JSF 2.x HttpSession bean upon login.. proper way to use it? - jsf-2

I've looked at some other threads here and I think I have the general idea of how to use a SessionScoped bean for maintaining a user's logged in state. However, as I am relatively new to JSF 2, I am trying to figure out the best way to use the bean during login and on subsequent pages to render a header/footer (using same page template, but different menus/links depending on login state and non-logged in state).
I have a typical JSF2 login form that calls a backing bean (request scoped) login() method. All of that works, and I am going to tie it in to the container security soon as I have a little more time to work on and figure that part out (realms, roles, etc).
In the old pre-JSF (jsp/struts) days, upon login, I'd add an object, usually a user ID Long value that would be easy to replicate across a cluster of sessions and restore a full user object from. This kept the httpsession data minimal (one Long value per user), and regardless of what server a user was routed, I could determine they were logged in and pull up their user object and go from there.
With JSF, I am not sure the right way to do this. I have a SessionScoped bean with a Long userid property. Upon the login() method succeeding, I use the ExternalContext to add the attribute of the SessionScoped object, something like:
User user = loginBean.login(username, password);
Session session = new Session();
session.setUserid(user.getId());
externalContext.getSessionMap().put("usersession", session);
externalContext.redirect(originalURL);
The Session is the SessionScoped bean, and it's CDI name is usersession. I hope that is the right way to stick the bean into the HttpSession so it can be used on pages, etc with EL.
The first thing I am not sure of is because the bean is SessionScoped, do I need to put it into the session after creating it in the above code? Or is that done automatically upon creation for me since it's scoped as session?
The second question is.. being picky that I am, I don't want a Session object in the session until the user logs in, even if the userid is null. So on a xhtml page, if I have something like:
<h:panelGroup render="#{usersession.loggedin}"...>
Will that create and put the Session bean into the session the first page that uses that? Or will that Session object not be put into the HttpSession until I do so with my code above? My guess is, if it gets put into the session upon creation, then the use of it on any page will create it and stick it in the session. I am less bothered by this..the object with just the Long property is very little memory use per user on the system, but like I said, I am being picky and more so wanted to understand exactly when a SessionScoped object gets stored into the session.
Thanks.

The first thing I am not sure of is because the bean is SessionScoped, do I need to put it into the session after creating it in the above code? Or is that done automatically upon creation for me since it's scoped as session?
The managed bean is autocreated in the given scope if referenced for the first time in EL by #{beanName} while it's not in the scope yet. So, no, you don't need to do it yourself. Just inject it as managed property in your login bean.
#ManagedProperty("#{usersession}")
private Session session;
// ...
User user = loginBean.login(username, password);
session.setUserid(user.getId());
externalContext.redirect(originalURL);
Will that create and put the Session bean into the session the first page that uses that? Or will that Session object not be put into the HttpSession until I do so with my code above?
It will do that once you reference it for the first time in EL by #{beanName}.
Unrelated to the concrete question, another way is
User user = loginBean.login(username, password);
externalContext.getSessionMap().put("user", user);
externalContext.redirect(originalURL);
and check for the logged-in user as follows
<h:panelGroup rendered="#{not empty user}">
See also:
Performing user authentication in Java EE / JSF using j_security_check

Related

Session scoped bean multiple constructor calls

I have a session scoped bean (I have checked the imports and they are correct for ManagedBean). There is a main page which checks if the user has been authenticated by calling one of the get methods of the session bean. Upon first view I see that the Session Bean is correctly constructed. If I attempt a login, I see that the correct method is called and the login succeeds. However, when the user is redirected back to the main page the constructor of the session bean is called again. Any ideas?

CDI bean List in datatable is null on submit from JSF

Please note: This question is about CDI scopes as we are using CDI scopes in the app and not JSF scopes.
1) Controller Bean (TestController.java) which is in RequestScoped (enterprise context) is called index_cut.xhtml, when we come for first time on this page.
2) On button “Load”, we load the following method to populate the sapFinancialPeriodList which works fine and displays the data
3) After changing the content on the page and submitting, the sapFinancialPeriodList appears as NULL in the following method –
Any suggestions?
Your bean is request scoped and you're loading the data model on action only instead of on (post)construction. When the HTTP response after the action which loaded the data is finished, then the bean is garbaged. The subsequent request would get a brand new instance of the bean with all properties set to default. However, as the same data model isn't been preserved during (post)construct, it remains empty.
In JSF2 you'd solve this with using #ViewScoped. This way the bean will live as long as you're interacting with the same view by postbacks (which return null or void).
In CDI you'd need to solve this using #ConversationScoped, which in turn requires some additional #Inject Conversation boilerplate, complete with begin() and end() calls at the right moments. For a concrete example, see also What scope to use in JSF 2.0 for Wizard pattern?.
An alternative is to pass the parameters responsible for creating the data model to the subsequent request via <f:param> in the command link/button as follows
<h:commandButton value="save" ...>
<f:param name="period" value="#{bean.period}" />
</h:commandButton>
and then recreate exactly the same data model in (post)constructor of the request scoped bean as follows
String period = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("period");
List<SapFinancialPeriod> sapFinancialPeriodList = someservice.list(period);
(the above is by the way nicer to solve with #ManagedProperty if you were using standard JSF; as far as I know CDI doesn't have an annotation which enables you to set a HTTP request parameter as a bean property)
See also:
How to choose the right bean scope?
Unrelated to the concrete problem, the upcoming JSF 2.2 solves this functional requirement in a nicer way using the new "Faces Flow" feature with the new #FlowScoped annotation and the new xmlns:j="http://java.sun.com/jsf/flow" tags.

jsf clearing the form

I need help. I'm new to JSF and im using JSF2 and richfaces in my project.
I want to clear the form for which I'm using <f:ajax render="#form"/> in refresh button. I have an ADD button on that screen which adds one record and I hit refresh then it's going to the default page. But when I once again go to enter a record then those values which I entered earlier remain in the form fields.
Can anyone please help me out with this issue?
Assuming that you mean the browser's refresh button when you say "I hit refresh", then that can happen if you've incorrectly placed the bean holding view scoped data in the session scope. You're then basically reusing the very same bean as the form is previously been submitted to. Putting the bean in the view scope instead of the session scope should fix this problem. The view scope ends when you navigate to a different page or fires a new request (as by hitting browser's refresh button).
See also:
How to choose the right bean scope?
Update if you're due to bad design restricted to using session scope, then you might want to hack this around by a
<f:event type="preRenderView" listener="#{sessionScopedBeanWhichShouldActuallyBeViewScoped.resetModel}" />
with
public void resetModel() {
if (!FacesContext.getCurrentInstance().isPostback()) {
model = null;
}
}
This will clear the model on every GET request. However, regardless of this hack, you'll still run into serious problems when the enduser opens the same view in a different browser tab/window within the same session.
The right solution is to put the bean in the view scope instead of the session scope, as said earlier.

Relogging a user in with different Spring Security Authorities programmatically

PreReq:
User logs in and is given roles got from the database using a custom implementation of userService. i.e.
authentication-provider user-service-ref="securityPolicyService"
The implemented method loadUserByUsername gets called and the roles are load for the user for the particular club they are logging into, Default one is loaded first time in.
The user then click on a different club from the UI and I call a method on a service that gets the new list of authorities for this club.
I then perform the following:
Object principle = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
SecureMember sm = (SecureMember) principle;
Authentication auth =
new UsernamePasswordAuthenticationToken(sm, null, newAuthories); <br><br>
SecurityContextHolder.getContext().setAuthentication(auth);<br>
request.getSession(false).invalidate();
SecureMember extends User from SpringFramework.
The problem is the SecureMember authorities are never updated with the new ones.
thanks
Gary
Spring Security won't store the security context if the HttpSession is null and was invalidated during the request, so if you set the context after invalidating the session (and don't create a new session), then it won't be stored.
You should see this log message if this is the case (and you have debug logging enabled).
Either create a new session or don't invalidate the original one.

viewParam and the request scoped bean

I tried to use view parameters in conjunction with a request scoped bean. I noticed that the model does get updated and when the page is rendered, the bean properties are set and are rendered with <h:outputText value="myBean.myParameter />. My question is, about the post back. I was under the impression that the view parameter values were retained as long as you don't post to a different view. I expected that the property would be set in the bean during the action method call automatically, but in practice I found this is not the case. Can someone explain why this is the case. I searched all around and I found many articles discussing viewParams but I couldn't find an explanation of exactly what the effect is (and why) in each scope. If anyone knows of an article that documents this already can you point me to it. Thanks in advance...
I was under the impression that the view parameter values were retained as long as you don't post to a different view.
This is only true when you're using a view scoped bean because they are remembered in the bean. The view scoped bean lives as long as you're interacting with the same view. I think that you're confusing the request scope with the view scope, given your impression.
A request scoped bean is trashed by end of the HTTP request/response cycle. So when the webbrowser is finished loading the page, the request scoped backing bean is already trashed for long. When you submit a form on that page, a new request scoped bean will be created, the <f:viewParam> will check if the to-be-set request parameters are available and if not, then just skip it (or validate; if you have required="true" set on them). As long as you don't retain view parameters by using <f:param> inside command links/buttons of the form on that page, then those parameters will get lost on subsequent requests and thus also in any involved request scoped bean.
See also:
Communication in JSF 2.0

Resources