18 January 2011

Spring remote and IceFaces sessions

The application I am currently working on is using Spring security, IceFaces and an applet that is communicating with the back end using the Spring remote HTTP invokers.

An interesting problem (or side effect, depends on the point of view) with this configuration is that the IceFaces session would always expire while the user is only using the applet. Obviously a solution had to be implemented, that would monitor the user activity in the applet and then send periodic requests to the back end in order to keep the session alive.

While the monitoring itself was not such a challenge (the java.awt.Toolbox allowed for detecting global mouse and keyboard events) the major difficulty came from the fact that a Spring remote bean would not have the FacesContext initialized. I've noticed that the IceFaces provides API's that could be used to touch the monitor responsible, but it requires the current HttpSession and extracting it proved to be more problematic than I initially expected. I was surprised though that the answer was more obvious than I've expected - one could simply inject the session to a session scoped bean using the @Autowired annotation.


So as a result the solution is simple:

On the applet level:
- a global AWTListener that would monitor for the user interactions - example
- a Timer that would execute on a scheduled period (shorter than the timeout period set up in the server) - example
- a TimerTask that would check if the last user action was taken in the same timer cycle and if so then it would call the backend

On the server layer:
- a HTTP remote bean that would receive these requests - example
- this bean should be with a session scope so we can inject the HttpSession object
- the actual code that touches the session would be

@Autowired
private HttpSession session;

...

public void touchSession(){
    SessionDispatcher.Monitor.lookupSessionMonitor(session).touchSession();
}