How to check if is user logged in? - jsf

I want do display a login link when the user isn't logged in and a logout link when the user is logged in. I'm using container managed security as defined in web.xml.
How can I achieve this?

The username of the logged-in user is available by ExternalContext#getRemoteUser() which delegates under the covers to HttpServletRequest#getRemoteUser(). Both are available in EL by #{facesContext.externalContext.remoteUser} and #{request.remoteUser} respectively. If it is null, then it means that the user is not logged in.
So, in your view you can check it in the rendered attribute as follows:
<h:form rendered="#{not empty request.remoteUser}">
<h:commandLink value="Logout" action="#{auth.logout}" />
</h:form>
<h:link value="Login" outcome="login" rendered="#{empty request.remoteUser}" />
See also:
Conditionally displaying JSF components

This depends on your definition of "logged in". Usually you can login an user in your application by implementing your own login mechanism. Otherwise you are using some container dependent mechanism which your server will take care of.
For the container managed method you can usually check FacesContext with its ExternalContext.
FacesContext.getExternalContext().getRemoteUser();
You can put that method into a helper bean and check it with the rendered attribute of your link component.
If you implement your own system its totally up to you.

You may check session to know whether one is logged in or not (if you are using session to manage login information). Assuming you stored user information with the key user,here is an example:
<%
String page = "login.jsp";
String linkName = "Login";
if (session.getAttribute("user") != null) {
page = "logout.jsp";
linkName = "Logout";
}
%>
<%=linkName %>

Related

How to pass objects from one page to another page in JSF without writing a converter

first of all sorry for my english. I have two pages in JSF2, one to list Passengers and another one to create/update passengers. I have also two #ViewScoped beans, one with the list of passengers and one for hold in pageB the selected passenger. I see the ways to pass the passenger through viewParam or #ManagedProperty but i don´t want to write a converter.
What i want to know if there is a way to pass the object from pageA to pageB without passing the id of the passenger and write a converter or without passing the id and then go to the DB to retrieve the passenger.
What i do and works is the following. I set in flash scope through setPropertyActionListener the selected object and navigate to pageB, in the #PostConstruct of the viewScopedBean i get the flashScope and retrieve the object. As i said, this works but i don´t know if it is correct. Here is the code
Page A:
<p:column width="10" style="text-align: center;">
<p:commandButton icon="ui-icon-pencil" action="editClientes?faces-redirect=true">
<f:setPropertyActionListener target="#{flash.pax}" value="#{row}"/>
</p:commandButton>
</p:column>
#PostConstruct of pageB bean
#PostConstruct
private void initBean(){
this.pax = (Passenger) JSFUtils.getFlashScope().get("pax");
if(this.pax == null){
this.pax = new Passenger();
}
}
Is this correct, or the correct way is to write a converter?
Thanks.
Depends on whether you want the /editClientes request to be idempotent ("bookmarkable") or not.
The flash approach is not idempotent. It's not possible to link/share/bookmark the /editClientes URL in order to edit a specific client. When the enduser copies this URL for sharing/bookmarking and re-executes the request on it (even though it's just pressing [enter] in browser's address bar), all the enduser would face is an empty edit form for a new client instead of the one the enduser initially selected via flash scope.
The request parameter approach is idempotent. The enduser is able to get exactly the same response everytime the enduser re-executes the request.
It's not our decision whether your /editClientes page should be idempotent or not. It's yours.
See also:
How to navigate in JSF? How to make URL reflect current page (and not previous one)

Navigate to previous page with JSF

I use a backing bean where I can save a form and navigate to this page.
public String saveHere() {
return Faces.getViewId() + "?faces-redirect=true&includeViewParams=true";
}
How do I navigate to the previous page with OmniFaces?
My save action should result in the page where I have the "edit" button.
Typically a list-view (with edit-button next to very item)
or another page with (with edit-button to this item)
Thanks!
You need the page id you're navigating from somewhere. At first look, keeping it in Session seems to be a good idea, however, this could remain in coflict if you're navigating in multi-tab (sharing same Http Session through different browser tabs).
Having said that, the most proper solution for your case is to pass a view param to your edition view telling where you're coming from. That should be as easy as this:
<h:button outcome="edit" value="Edit registry">
<f:param name="pageFrom" value="#{view.viewId}" />
</h:button>
After that, in your edition view bind this param to your bean:
<f:metadata>
<f:viewParam name="pageFrom" value="#{editBean.pageFrom}" />
</f:metadata>
And just redirect to that view in your EditBean.java after saving, supposing it is #ViewScoped:
public String saveHere() {
//save here
return pageFrom + "?faces-redirect=true&includeViewParams=true";
}
That's the most straight forward way to achieve what you ask for. However, you must take into account the page where you're coming from remains to be a view parameter, so the end user could type what he wants there. With this behaviour, he could achieve being redirected to some other page rather than the one expected. If you want to avoid that, go with the flash scope instead of view parameters.
See also:
Get current page programmatically

Passing an object stored in a session managed bean in a JSF creation form

I am working in Java EE application which supports authentication and managing some simple objects
After the user has been logged in I store it as an object in a session scoped managed bean. The logged in user can Create a new UNIT object which must be visible only to him. I am doing this using a JSF form. My problem is that I am not being able to pass the current user as the owner of the created unit.
I was trying to do something like this with the inputHidden tag in the JSF Create unit form
<h:inputHidden binding="#{unitController.selected.user}" value="#{loginController.checkedUser}"/>
but it is not working.
I also tried to add a User object as parameter in the CreateUnit method, but I was not sure how to call this method using the Java Expression Language.
Basically,
<p:commandButton value="Save Unit" action="#{unitController.create(#{loginController.checkedUser})}" update="createUnitForm :growlCreateUnit"/>
but still is not working.
Can somebody help please?
Replace
<p:commandButton value="Save Unit"
action="#{unitController.create(#{loginController.checkedUser})}"
update="createUnitForm :growlCreateUnit"/>
with:
<p:commandButton value="Save Unit"
action="#{unitController.create(loginController.checkedUser)}"
update="createUnitForm :growlCreateUnit"/>
EL expressions cannot be nested.

How do I update a menu bar in a calling template

As an exercise I want to have a menu bar which is disabled until the user logs in. When he logs in I want to call something which will trigger an update. The menu bar is in the master.xhtml template file
<h:form >
<p:menubar id="masterMenuBar">
<p:menuitem disabled="#{backing.disableMenu}" value="List users" />
</p:menubar>
</h:form>
As part of the login I have code to refresh the form
public void refreshForm() {
RequestContext context = RequestContext.getCurrentInstance();
context.update("form1");
context.update("masterMenuBar");
}
I tried my luck with calling a context update to my defined label of masterMenuBar but the RequestContext apparently doesn't include my calling template form (which sounds reasonable enough).
Is there some other context I can call which will include a context update to my menu bar? Perhaps I am on the wrong path, and there is a better way to achieve the same thing?
I did notice that even resizing the browser wasn't reason enough to call again to my backing.disableMenu bean. Apparently I need something fairly strong to cause it to reach my bean a second time.
You need to pass the absolute client ID, not the relative client ID. If you rightclick and view source in browser, then you'll see that the masterMenuBar element has the (autogenerated) ID of its form prefixed.
You need to give the form where the menu is sitting in a fixed ID
<h:form id="menuForm">
<p:menubar id="masterMenuBar">
...
and pass the absolute client ID instead.
context.update("menuForm:masterMenuBar");
Update: sorry, it shouldn't start with : in contrary to the update attribute of <p:commandButton>.

whats the practice to write a review page in JSF?

I have a JSF Page which gets few inputs from the User, I want to show a review page to the user - as what he has given as inputs in the previous page. I am using h:OutputText in the review page to show all the inputs the User had given - but when the user has reviewed and if the user wants to save them - I have a commandButton which is bound to an action method in the backing bean - which will not submit any values as the outputTexts are not submitted. What are the options do I have to show a review page at the same time get the values at the server side - I dont want to have the bean session-scoped.
I am using Apache My faces Implementation of JSF 1.2 without any component libs.
You can use h:inputHidden to retain data for the subsequent POST request. E.g.
<h:outputText value="#{bean.property}" />
<h:inputHidden value="#{bean.property}" />
When you don't have an aversion against component libraries, I'd have suggested Tomahawk's t:saveState for this. This way you don't need to specify every property separately in a hidden field.
<t:saveState value="#{bean}" />
When you're already on JSF 2.0, just putting the bean in the view scope would have been sufficient (assuming that you're conditionally rendering input form and review form in the same view). This way it lives as long as you're interacting with the same view.
#ManagedBean
#ViewScoped
public class Bean {
// ...
}

Resources