In my application I have created some locking / unlocking functionality based on the current page that the user is viewing. A user can view a page and will acquire a lock which is stored in my database, when they navigate away the lock is released and the database is updated.
I am trying to handle the situation when the user closes the browser window without logging out. They will still be holding the lock and I need that to be released and a database call needs to occur.
Is there a way to handle this in a JSF application using Spring or something else?
I know the javascript function onbeforeunload but I need to call a java method that will enable me to update the database.
The unload and beforeunload events aren't going to help you here since it's not by the specification guaranteed that any ajax request which is fired within those events is ever going to successfully hit the server. More than often, this won't.
The most reliable way is to keep the server side session lifetime very short, e.g. 1 minute and introduce an ajax poller on the page which polls within the same session to the server every minute (minus a few seconds) until the user is been inactive for more than the actual maximum session timeout. The user activity can be tested by listening on JavaScript keyboard (keyup) and mouse (click) events.
I am currently working on a two window application and needed to detect when a window is closed.
My JSF application uses ICEfaces. It provides an #WindowDisposed annotation for ViewScoped beans. With this annotation, the ViewScoped bean's #PreDestroy method will be called when the window is closed.
I have included an h:inputHidden tag in my page bound to the viewScoped bean and this works in terms of detecting the window closing and executing server side code.
Related
I have a basic question about JSF ManagedBeans for which I can't find a answer.
Suppose I have a bean MyBean with two methods method1 and method2 and a JSF page with a command link
<h:commandLink action="#{myBean.method1}">
</h:commandLink>
Is it possible for someone to analyse the source code of the page and call method2 instead of method1?
Answer
No, this is not possible by design.
Reasoning
Technically the client can only tell the server "The user clicked a html element with a certain id".
This event is then processed by JSF on the server-side, the component with the corresponding id is looked up and in this case the method "#{myBean.method1}" is executed.
As you can see, the client can not[!] tell the server what to do with this event.
Sources
JSF 2.2 Spec - 3.4 Event and Listener Model
Caveat
JSF is stateful and there are multiple ways to hold this state. The default is to hold state information server-side (e.g. in the users HttpSession).
Another option is to transfer (encrypted) state to and from the client. This is still conceptionally secure, but there *might* be bugs with client side state saving. Such a bug *could* be exploitable to do something like you described.
Yes, it is always possible to modify code (or markup-language) on the client-side. Your "action" will be called through some forms and/or Javascript-Methods - everything visible to experienced users.
But that's not an issue of JSF-2 only - this applies for every language which allows insights from the client side.
You shouldn't apply "security through obscurity" (https://en.wikipedia.org/wiki/Security_through_obscurity) but rather make sure, that you can handle this on the server-side.
If a user, who has access to two urls modifies url1 to url2 - that's fine, why not? (Could be bookmarked) - But YOU should take care of the modified request, if he is not allowed to access url2.
If I'm informed correctly, every request for/from a XPage is processed in a new thread in the JVM on the Domino server.
Hence, all objects stored in the applicationScope which might be modified concurrently by different users should be thread-safe. However, all the articles about thread safety I have read so far never say anything about the necessity of using thread-safe objects in the sessionScope.
A user could, for example, run the same XPage (which modifies a sessionScope object) in two different browser tabs at the same time.
In my opinion, that sessionScope object has to be thread-safe too, or did I get something wrong?
In general, whenever there is more than one thread trying to access the same object and at least one of them tries to modify the state of the object it needs to be threadsafe.
So in this case if two browser tabs try to access same xpage or different xpages but trying to access the same session scope object and at least one of them trying to modify that object, we need to ensure it is threadsafe.
As #Tiny commented regarding the view scoped beans, "According to the JSF specification, AJAX requests made from the same view are queued on the client side. Therefore, the possibility of concurrent access in a view scoped bean is zero. A view scoped bean is not shared across different tabs / windows of the same browser".
Refer to Section 13.3.2 of jsf 2.0 specification.
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.
I have a JSF 2 app that uses RichFaces 4 and Spring Security 3.1 running on Tomcat 6 (also tested on Tomcat 7). Spring Security handles the session timeout and redirects user to the login page. That works perfectly.
The problem is that AJAX calls don't seen to have the effect of extending the session lifetime the say that ordinary navigation calls do.
I've read other articles suggesting that AJAX calls don't behave the same as ordinary navigation calls and that this is why the session isn't extended (unfortunately, none of them provide a clear explanation as to why this is).
This thread suggests that a call to getSession() will do the trick. However, this is not working for me.
Instead of writing my own jquery poller I used the PrimeFaces idlemonitor as suggested here. The bean method called by the idle monitor reset calls getSession().
For testing I set the session timeout period to 4 minutes. Even though the AJAX method with getSession() is being called after two minutes the session still expires exactly 4 minutes after I navigate to that page.
Any idea what I'm doing wrong? More importantly, how would you debug this situation?
Thanks
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.