JSF User Management - jsf-2

Im building a few JSF interfaces that im going to embedd into a website. I want though to allow the user to log into the website inorder to view another JSF interface where they can update details about the services the website will offer.
What I want to know is, do I need to implemented a Login/Registration facility from scratch or is there an existing system already out there that I can easily use. The db im using is a derby db and the application runs on a GF server.
Or can someone recommend some good resources on building a custom user site using JSF?
Sorry if this question has been asked before and I missed it in my searches before.
P

All the textbooks seem to mention container-managed security but I have always stayed away from it. In every application I have done so far I have implemented application-managed authentication, which gives you much more flexibility with regard to how authentication is done. The price of course is you will have to allocate a couple of days to implementing and fiddling with it.
The key to making it easy is to 1) incorporate the authentication right in your Facelets template that all pages use so you always have it, and 2) have a #SessionScoped bean which holds the state of the user login. In the application I am working on now the top part of the template looks like this:
<div id="top" class="top" style="min-height: 40px">
<h:form id="formLogout" style="float: right"
rendered="#{userSession.loggedIn}">
<h:outputText
value="Logged In As: #{userSession.sysUser.handle} "
rendered="#{userSession.loggedIn}" />
<p:commandLink value="Logout"
ajax="false"
action="#{userSession.logoutUser}" />
</h:form>
<h:panelGrid style="float: right" rendered="#{!userSession.loggedIn}" >
<h:form id="formLogin">
<h:outputLabel value="User Handle: " />
<p:inputText size="16" value="#{userSession.loginHandle}" />
<h:outputLabel value=" Password: " />
<p:password value="#{userSession.loginPassword}" />
<p:commandButton value="Login"
ajax="false"
action="#{userSession.login}" />
<h:link outcome="/newUser" value=" New User" />
<h:commandLink action="#{userSession.loginAlan}" value="A" />
</h:form>
</h:panelGrid>
<h:link outcome="/index" value="MyWebApp v#{wisApp.ver}" />
<h:outputText value=" " />
</div>
I'll not bore you with the UserSession bean since it should be pretty obvious. The sysUser property is actually a JPA entity fetched from the Derby data base.
(Note the extra h:commandLink value="A". That's a link that automatically logs me in so I don't have to type my username and password over and over again while developing.)
That should probably be what you need.

Related

Display JSF element only if specific h:message is being displayed

I have a h:form with several inputs and each of them got its own h:message and I'm looking for a way to show (using render or assigning some styleClass) some other element only when specific h:message is being shown (and hide when that h:message is not being displayed).
Here a code snippet
<li>
<h:panelGroup id="current_password_wrapper">
<p:password value="#{myBean.myCurrPass}" id="current_password" required="true"
styleClass="required_field" />
</h:panelGroup>
<h:message for="current_password"/>
</li>
<li>
<h:panelGroup id="new_password_wrapper">
<p:password value="#{myBean.myNewPass}" id="new_password" required="true"/>
</h:panelGroup>
<h:message for="new_password"/>
<h:commandLink value="my value"/>
</li>
I want to make the h:commandLink visible only when the <h:message for="new_password"/> is being displayed
So far I couldn't find anything...
If your environment supports EL 2.2, then you could check if FacesContext#getMessageList() isn't empty for the particular client ID.
<p:password binding="#{new_password}" ... />
<h:commandLink ... rendered="#{not empty facesContext.getMessageList(new_password.clientId)}" />
If the message is being shown as result of a validation error, then you could also just check the UIInput#isValid() state of the component associated with the message.
<p:password binding="#{new_password}" ... />
<h:commandLink ... rendered="#{not new_password.valid}" />
Note that manually adding a faces message to the context won't mark the input component invalid. Therefor either a true Validator should be used which throws a ValidatorException, or an explicit input.setValid(false) call has to be done programmatically.
I think with the answer to this question you requirement can be archived:
How to number JSF error messages and attach number to invalid component
I think you can do something like this:
<h:outputText value="output text" rendered="#{bean.messageIndexes['form:input1'] > 0}" />

Authorization in JSF2 components

In our project we have JSF2 pages used in internal network of a company. But we are going to open those pages to Internet. So pages will be available to everybody. But some fields will not be rendered if a user comes from Internet.
I know it is possible to write a rendered attribute for each component such as "userIsInRole". But additional "rendered" control doesn't seem to be efficient and elegant method. So I plan to mark the components which are going to be rendered online by using a custom attribute as shown below:
<h:inputText context="internet" />
...
In the renderer of the inputText or component code:
if(user is from Internet && context = "internet") {
return true; // or render... whatever
}
If a component is not marked as Internet, then it means it will be available (rendered) only from inside of the company.
Is it possible implement authorization by using JSF2 components according to a given attribute? Is there any better options? Or should I design separate pages for internet users?
We use: PrimeFaces + Spring in our project.
Thank you
This is ridiculous. What's the difference in effort of ultimately using
<h:inputText context="internet" />
versus
<h:inputText rendered="#{intranet}" />
?
If your sole problem is that you need to repeat the whole condition everytime ending up in ugly code like so
<h:inputText rendered="#{not (user.hasRole('internet') and context eq 'internet')}" />
<h:inputText rendered="#{not (user.hasRole('internet') and context eq 'internet')}" />
<h:inputText rendered="#{not (user.hasRole('internet') and context eq 'internet')}" />
...
then just refactor the condition to a single request scoped variable
<c:set var="intranet" value="#{not (user.hasRole('internet') and context eq 'internet')}" scope="request" />
...
<h:inputText rendered="#{intranet}" />
<h:inputText rendered="#{intranet}" />
<h:inputText rendered="#{intranet}" />
...

ignoreValidationFailed doesn´t work inside ui:repeat

I´m using o:ignoreValidationFailed, but it doesn´t work inside the ui:repeat. When I do the same outside, it works! I tried with mojarra ans MyFaces... I´m using primefaces. If there is another way to skip the validations only for one button...
<o:form id="rateplanEditByPeriod" prependId="false">
<p><p:messages id="mensagensDlg"/></p>
<p:tabView id="tabs">
<p:tab title="Cancelamento" id="tabCanc">
<h:panelGrid id="cancelationsTable" columns="2" cellpadding="10px" columnClasses="alignTop,alignTop">
<ui:repeat id="repeat" var="rest" value="#{rateplanByPeriodManaged.rateplanByPeriod.restriction.restTypeCancelation.restTypeCanConfs}" >
<h:panelGrid columns="8">
<p:inputText id="penaltyValue_#{loop.index}" value="#{rest.penalityValue}" style="width:28px" label="Valor" title="Valor" disabled="#{rest.noCancel}" required="true"/>
<p:commandLink id="add_#{loop.index}" actionListener="#{rateplanByPeriodManaged.addCancConf}" update=":rateplanEditByPeriod:tabs:cancelationsTable" partialSubmit="true" process=":rateplanEditByPeriod:tabs:cancelationsTable" value="+">
<o:ignoreValidationFailed />
</p:commandLink>
<p:commandLink actionListener="#{rateplanByPeriodManaged.removeCancConf(rest)}" value="-" update=":rateplanEditByPeriod:tabs:cancelationsTable" partialSubmit="true" process=":rateplanEditByPeriod:tabs:cancelationsTable">
<o:ignoreValidationFailed />
</p:commandLink>
</h:panelGrid>
</ui:repeat>
</h:panelGrid>
</p:tab>
</p:tabView>
<p:commandLink styleClass="button" onclick="dlgEdit.hide()" immediate="true" update=":msgsPanel">#{msgs['inventory.editByPeriod.cancel']}</p:commandLink>
<p:commandLink styleClass="button" actionListener="#{rateplanByPeriodManaged.editByPeriod(loginManaged.hotelSelected)}" oncomplete="if (!args.validationFailed) {dlgEdit.hide(); updateAllSearches(); updateAllNotifications();}" update="mensagensDlg, tabs" >#{msgs['inventory.editByPeriod.confirm']}</p:commandLink>
</o:form>
I have faced the same issue but with p:datatable
I solved it with
1- add a condition to the required field to know if the ajax come from submit button or not
as #Camilla said.
required="#{!empty param['trans_desc_form:savetransid']}"/>
trans_desc_form is the entire form id and savetransid is the submit button save id
2- I removed #NotNull from my JPA entity which force the validation
#JoinColumn(name = "ITEMNO", referencedColumnName = "ITEMNO")
#ManyToOne(optional = false, fetch = FetchType.LAZY)
//#NotNull
private Item item;
I have created a question for this issue
ignoreValidationFailed doesn´t work inside p:dataTable
I don´t know if it´s the best aproach but it worked for me...
<h: inputText id="text1" value="" required="#{!empty param['formName:btnSave']}" />
This is not the right way to have a "Cancel" button.
Just put process="#this" in the <p:commandLink>, or if you don't need to do any business logic, make it a normal <h:link> which reloads the page (and thus implicitly recreates the request/view scoped bean).
As to <o:ignoreValidationFailed> the failure in <ui:repeat> on its own, please create an issue.

Constructor of a viewScoped class invoked twice

I've been struggling with this for two days with no success and I think it's already time to ask for your help. But first of all, this is what I'm using:
JSF 2 Mojara 2.1.1
Primefaces 3.4.2
Netbeans 7.1.1
Tomcat 7.0.37
And now, the problem: I have a main page which is composed by several other pages using several <ui:include .. /> tags, like this:
<ui:composition template="/resources/templates/template1.xhtml">
<ui:define name="appData">
<p:panelGrid columns="1" id="contenidoAplicacion" styleClass="noborder">
<h:form id="fNewPerson">
<p:panel header="New employee" style="min-height:40em">
<ui:include src="./forms/personal.xhtml" />
<p:accordionPanel styleClass="noborder" activeIndex="3">
<p:tab id="tabSomeData" title="Identidad profesional" >
<ui:include src="./forms/formSomeData.xhtml" />
</p:tab>
....
....
</ui:define>
</ui:composition>
The personal.xhtm file looks like this:
<p:panelGrid>
<p:row>
<p:column >
<h:outputLabel value="Field1"/>
<p:inputText label="Field1" id="field1" value="#{dataBacking.selectedPerson.field1}" tabindex="1"
required="true" size="10" >
<f:convertNumber for="field1" integerOnly="true" groupingUsed="false"/>
</p:inputText>
<p:inputText id="field2" value="#{dataBacking.selectedPerson.field2}" tabindex="2" required="true" size="1" maxlength="1" >
<p:ajax event="keyup" listener="#{dataBacking.check}"
process="field1 field2" partialSubmit="true"
update="field1 field2 photo"/>
</p:inputText>
</p:column>
<p:column rowspan="5" >
<p:graphicImage id="photo" value="#{dataBacking.selectedPerson.photo}" width="90" />
</p:column>
</p:row>
...
</p:panelGrid>
The check() method in the dataBacking class is irrelevant because it only checks if the field1 and the field2 meet some rules and it works properly. The problem comes when the main page is loaded for the first time. In that case, the <p:ajax /> component in personal.xhtml doesn't work. I have to reload the page (simply by pressing the F5 key) and this time it works as it would be expected.
I've been changing some attributes of the component, but nothing seems to work. I really don't know what else to do. Any kind of help will be apreciated.
EDITED. After one more day, I think the problem has nothing to do with Primefaces ajax component, as the title of the question suggested. I've come to this conclusion through these two facts:
The behaviour with the <f:ajax .../> component remains the same.
I've figured out that the view relative to the first time I load the page is not persisted. I'll try to explain myself.
The DataBacking class has defined its scope as view so that the page can "see" all the attributes and methods during the time it's been shown to the user. However, I've noticed that the constructor is called twice: the first time the page is loaded (and then, none of the methods of the class are successfully invoked) and when I refresh the page. In this last case, the behaviour of both the page and the class is the expected one.

actionListener not called inside <c:if>

I have the following code, Using jsf2.2, primefaces 3.2.
My requirement is to update the Project depending on the updateFlag.
when i use c:if (xmlns:c="http://java.sun.com/jsp/jstl/core") like the following code the action Listener for the Update commandButton is not called. but if i use < p:panel rendered="#{projectBean.updateFlag}" > instead of < c:if > it works. Please help i dint get it, i think i should use c:if but its not working.
<p:dialog widgetVar="projectUpdate" id="projectUpdatePanel" modal="false" >
<p:panel>
<c:if test="#{projectBean.updateFlag == false}">
<h:outputText value="Project Title" />
<p:inputText disabled="true" value="#{projectBean.selectedProjectDo.projectTitle}" />
<p:commandButton value="Update" disabled="true" />
<p:commandButton value="Cancel" actionListener="#{projectBean.cancelUpdate}" />
</c:if>
<c:if test="#{projectBean.updateFlag == true}">
<h:outputText value="Project Title"/>
<p:inputText value="#{projectBean.selectedProjectDo.projectTitle}" />
<p:commandButton value="Update" actionListener="#{projectBean.updateProject}" />
<p:commandButton value="Cancel" actionListener="#{projectBean.cancelUpdate}" />
</c:if>
</p:panel>
</p:dialog>
You better just use it the following way (put a condition on the disabled attribute)
<p:panel>
<h:outputText value="Project Title"/>
<p:inputText disabled="#{not projectBean.updateFlag}"
value="#{projectBean.selectedProjectDo.projectTitle}" />
<p:commandButton disabled="#{not projectBean.updateFlag}" value="Update"
actionListener="#{projectBean.updateProject}" />
<p:commandButton value="Cancel" actionListener="#{projectBean.cancelUpdate}" />
</p:panel>
In general : don't use JSTL tags unless you really need them...
This is a classic example of non-DRY code, which is bad. Daniel shows perfectly how to make it DRY, however he didn't explain the cause of your problem.
Based on the problem symptoms, this will happen when #{projectBean} is a view scoped bean. View scoped beans are stored in the JSF view state. So, view scoped beans are only available after restore view phase. However, JSTL tags runs during restore view phase, while the view scoped beans are not available yet. This causes creation of a brand new view scoped bean instance, which is then later replaced by the real view scoped bean which was stored in the restored JSF view state. The brand new and separate view scoped bean which is used by JSTL will have all its properties set to default and thus the block which has updateFlag=false will always be invoked.
See also:
JSTL in JSF2 Facelets... makes sense?

Resources