Archive for the ‘GWT RPC’ Category

Working with GWT has a number of benefits but in the other hand we could get some cons and troubles that you’ll need to solve by yourself. That’s the case for a user Session Timeout, for example. While in an ordinary JSP servlet you could have total control of a user session and its actions, due to the client resident feature of GWT, things turns a bit complicated….

Last Friday I was working on a Session Timeout feature for Turmeric, an eBay Open Source platform. In the next lines I’m gonna show you how I did it , anyways you can surf these updates at my git-hub home.

Based on GWT RPC call mechanism and a few timers, I added a new service into Policy Admin UI (the web project to manage policies in Turmeric), called SessionServiceImpl, which implements RemoteServiceServlet and extends my service. This servlet instance, as usual will reside in the server side of my app.  Then I added the two interfaces needed for RPC calls, SessionInterface and SessionInterfaceAsync, and its implementation.

public class SessionServiceImpl extends RemoteServiceServlet implements
SessionInterface {

private static final long serialVersionUID = 1L;

private int timeout;

@Override
public Integer getUserSessionTimeout() {

timeout = getThreadLocalRequest().getSession().getMaxInactiveInterval() * 1000;
return timeout;
}

@Override
public Boolean isSessionAlive() {

return new Boolean((System.currentTimeMillis() - getThreadLocalRequest().getSession()
.getLastAccessedTime()) < timeout);
}

@Override
public void ping() {

}

}

This Servlet has its own time counters for user logged. Why I had to create a specific time member instead of using the HTTPSession ones? Since  of GWT genned code resides on client machines, the server session is not updated until a new RPC call be made by user, ie FindByXXXX, createXXX methods and so on… So, in the user does some clicks on the left side tree menu, the last accessed time at HTTPSession will not be automatically updated. Now since in our GWT  app a common dispatcher should be the selectPresenter method under the Controller, I preferred to use it as a common entry point to notify the session updates, just calling to a ping method. .

the SessionService interface:


public interface SessionInterface extends RemoteService {
Integer getUserSessionTimeout();
Boolean isSessionAlive();
void ping();
}
<pre>

the asyncronous one, at your client side. Our  code will call the sessionService but it will not wait for a reply as in synch way. The response will came later…who knows…

public interface SessionInterfaceAsync  {
void getUserSessionTimeout(AsyncCallback<Integer> callback);
void isSessionAlive(AsyncCallback<Boolean> callback);
void ping(AsyncCallback callback);
}

Later, since GWT 1.6, if I recall correctly, you could add your servlets into your *.gwt.xml file instead of your web.xml file. I’m on GWT 2.2 so I added these lines into our PolicyAdminUI.gwt.xml file:

<servlet path="/sessionService" class="org.ebayopensource.turmeric.policy.adminui.server.SessionServiceImpl"/>

and finally in the web.xml a new property to set the timeout configurable:

<!--  session timeout in minutes -->
<session-config>
    <session-timeout>15</session-timeout>
 </session-config>

and here is how my appController looks like:

//this method is called when the controller starts and bind...
private void initSessionTimers() {
sessionService.getUserSessionTimeout(new AsyncCallback<Integer>() {
public void onSuccess(Integer timeout) {
timeoutCicle = timeout;
sessionTimeoutResponseTimer = new Timer() {
@Override
public void run() {
isSessionAlive();
}
};
sessionTimeoutResponseTimer.schedule(timeout);
}

public void onFailure(Throwable caught) {
               //throw custom errors
}
});

}

private void isSessionAlive() {
sessionService.isSessionAlive(new AsyncCallback<Boolean>() {
public void onSuccess(Boolean alive) {
if (alive.booleanValue()) {
sessionTimeoutResponseTimer.cancel();
sessionTimeoutResponseTimer.scheduleRepeating(timeoutCicle);
} else {
displaySessionTimedOut();
}

}

public void onFailure(Throwable caught) {
//throw custom errors
}
});

}

private void displaySessionTimedOut() {
Window.alert(PolicyAdminUIUtil.messages
.expiredSession());
Window.Location.reload();

}

private void updateSessionLastAccessedTime() {
sessionService.ping(new AsyncCallback<Object>() {
public void onSuccess(Object paramT) {
//do nothing
}

public void onFailure(Throwable caught) {
//throw custom errors
}

});

}

that’s all folks,
hope it helps somebody….