HttpSession expires on page refresh - jsf

I'm new to JSF and I was doing some research about Scopes and Http session lifecycles, but one thing was not clear to me.
I know that is possible to store variables using sessionMap from ExternalContext, and it used to work very fine for what I needed. I also know that when the session is invalidated all the data stored on the map is lost.
However, what I don't know is: when the page is refreshed the session is invalidated?
My problem appeared when I had to put a download request on one of the buttons from my web application. Apparently download requests cannot be made via Ajax, so the entire page have to be refreshed. The download proceed normaly, but after that, all the data stored on the map is gone, including all the managed beans. The user data itself is not that important as I can store it and then put it again on the new session map. But what about the managed beans? How should I proceed?

Assuming that it's not the webbrowser who misbehaved, this can only happen if the server side code is actually by itself invalidating the session by calling ExternalContext#invalidateSession() or HttpSession#invalidate().
If you can't seem to nail it down, then create a HttpSessionListener and put a debug breakpoint on sessionDestroyed() method and investigate the call stack who initiated it and why.

Related

How to keep Session Alive beyond its MaxInactive interval

I am Switching between two different Dynamic web application through Links.But if i am working on one application for long time then others application session expires and i got redirected to login page, Is there any method to keep session alive beyond maxInactive time interval while i am working on other application page
There are two options-
If both applications requires single sign on feature (like we login to gmail, then all google services are accessible), you can use tomcat clustering and share session accross cluster. Both your apps will be part of the cluster.
A simple work aroud would be to set a heartbeat ajax request in each application. Use JavaScript's timeout function and send ajax request to servlet after a fix interval.
You can anyway update MaxInactiveInterval of server at runtime, there is this method setMaxInactiveInterval available for HTTPsession class object.
Hope this helps. :)
I can think of one option here that is to manage your own Session Pool. You can save the session object in ArrayList<HttpSession> whenever you create new session. And send that session id to your another application. When you return to previous app, you send back session id. And if you find session dead then find that session in your Session Pool by session id and create new session. In new session set attributes of the previous session object.
Hope this might be useful.

How to survive viewscoped beans/viewmap after session destroy (using client side saving)?

I'm using Myfaces 2.2 with Client-side state saving. I see that the ViewScoped beans & data stored in viewmap is lost after the user session is destroyed.
I came to know, not sure if it is correct, that this is the expected behavior but then what's the way to avoid view expired exceptions after session destroy?
My problem is that I destroy the user session pretty quickly after some inactivity period(like after 20 minutes) but I want the viewscope data to survive even after that(when using client saving) so that when the user comes back after session destroy, he doesn't need to do a page refresh. I dont know why & how this is so implemented but It is very normal that the user may be busy reading some section of website or be away for 20 minutes, & as he comes back & interacts with opened pages, how would I make that work without the state ?
I think this is a common requirement for any public websites.
I think the internally used jsf viewstate is not lost, if I use client side state saving(as my pages still work), but then why are those viewscoped beans scoped that were also serialized to page along with the viewstate.
If this the designed behavior, Is there any way I could make the view scoped data survive session expiration ?
An answer that I got from the myfaces users mailing list:
viewRoot.getAttributes() map could be used to persist the viewscoped values even after session destroys. Thus instead of storing values to viewRoot.getViewMap(), store in the map returned by viewRoot.getAttributes(). However care should to be taken to ensure that the stored values are serializable.

JSF force URL rewriting

I use JSF and I want to avoid a same session sharing 2 tabs in my browser. I think an easy way is to force url rewriting instead of using cookies.
Can anyone tell me how I can force the url rewriting with JSF?
Thanks.
Stéphane
I want to avoid a same session sharing 2 tabs in my browser
Sorry, but this makes no sense. This is not something which you can control from the server side on. All browsers use the same session in all opened tabs/windows (expect of anonymized tabs/windows like Chrome Ingognito via Ctrl+Shift+N). That's just how all browsers work and completely beyond your control.
If you're having a problem with it, then you should absolutely solve it differently than attempting to disable session sharing in multiple browser tabs/windows (which simply isn't possible). It sounds much like as if you're incorrectly storing request or view scoped data in a session scoped bean. You should not do that. You should store request scoped data in a request scoped bean and view scoped data in a view scoped bean. The session scope should only be used for session scoped data, such as the logged-in user and its preferences like language settings.
I think the view scope is actually what you're looking for; it lives as long as you're interacting with the very same view (read: the very same browser window/tab) by postbacks and it it not shared in other browser windows/tabs.
See also:
How to choose the right bean scope?

j_security_check not redirecting to welcome page - successful login event listener?

For ages I've been puzzled about why after login I sometimes don't directed to the application welcome page. I've finally figured it out (years after everyone else):
I login successfully via j_security_check and go to the welcome page
wait for session timeout
click on h:link which sends a GET request
because it's a GET and not a POST my custom ViewExpiredException
handler doesn't kick in
container security redirects to the login page because the session
has timed out. Because of the session timeout+container security the
get request (from h:link) isn't seen by the application, in either a phase listener
or filter.
I successfully login again
j_security_check redirects me to the page which triggered the
authentication, in this case the target of the GET request.
The last bit I'd not understood, I assumed it would always go to the welcome page.
My problem is that my current design requires that after login I always show the welcome page. The welcome page has a preRenderView event which sets up some context information in a session scoped bean after login and increments a few counters etc...
This context information is required by backing bean code for other pages, and presently if I don't go through the welcome page first there'll be an exception.
In terms of fixing it I've looked at the following options:
Ideally there'd be an #PostLogin method that could be called, which would cleanly solve all my problems. I use JSF (Mojarra) with Myfaces CODI but I don't see anything which does what I want.
I could add some more code to my filter, but I need to persist some data (i.e. login count), it doesn't look like a nice option. Maybe I'm wrong.
I make all the preRenderView methods of potential targets of j_security_check (pages called with GET) handle the case where they are called directly from j_seecurity_check. I can see this being what I have to do but it seems like a lot of hassle.
Write a Server Authentication Module for glassfish to override j_security_check behavior.
How is this normally handled? I've started hitting this problem after moving to GETs for simple navigation cases after years of abusing POSTs, and the custom exception handler doesn't work. If anyone has any guidance on this issue I'd appreciate it, at least I know what's going on now. Hopefully I've missed something obvious!
Thanks
O/S
Ideally there'd be an #PostLogin method that could be called, which would cleanly solve all my problems. I use JSF (Mojarra) with Myfaces CODI but I don't see anything which does what I want.
There is indeed no such thing.
I could add some more code to my filter, but I need to persist some data (i.e. login count), it doesn't look like a nice option. Maybe I'm wrong.
That would indeed be the "easiest" way. Basically:
UserPrincipal user = request.getUserPrincipal();
HttpSession session = request.getSession();
if (user != null && session.getAttribute("user") == null) {
session.setAttribute("user", user);
// First-time login. You can do your intercepting thing here.
response.sendRedirect(request.getContextPath() + "/welcome.xhtml");
}
I make all the preRenderView methods of potential targets of j_security_check (pages called with GET) handle the case where they are called directly from j_seecurity_check. I can see this being what I have to do but it seems like a lot of hassle.
That's not DRY.
Write a Server Authentication Module for glassfish to override j_security_check behavior.
Can't answer that as I've never done that.

JSF - set STATE_SAVING_METHOD per-page

I would like to set a particular page (one that does not require a user to sign in to use) to have a STATE_SAVING_METHOD of client rather than server while the rest of the pages use server. Is there a way to set it on a per-page basis?
I would like to do this to get around the dreaded ViewExpiredException.
There is no way. This is however been requested as new feature. See also JSF spec issue 1056.
To solve the particular ViewExpiredException issue, you need to look for alternative ways. You can just ask a new question here about specifically the issue you have. There are always ways to go around it.
The state saving method is set once in web.xml and is there for the whole app. If you don't want that particular view to expire you could do an ajax poll that "pings" the page in a specific interval of time and thus avoiding view expired exception. Kinda workaround but this is the way with stateful frameworks.

Resources