Say that in general your session time out works fine for you, but you have a couple of screens where you expect that users might hang around a bit longer than that. For instance on a page where people can submit their Resumes.
A good solution is to do what gmail or wordpress do: save drafts for your user and enable them to go on with these drafts at a later stage. If your session gets expired or you lose your browser or something, at least your user won’t have lost everything.
What you can also do, as an alternative or in addition to, is create a component that pings back to the server every once in a while to keep the session alive. Here is how you could do that.
The component we’ll be creating is a custom text area; that’s probably where you will need it for anyway.
public class KeepAliveTextArea extends TextArea {
public KeepAliveTextArea(String id) {
super(id);
add(new KeepAliveBehavior());
}
public KeepAliveTextArea(String id, IModel model) {
super(id, model);
add(new KeepAliveBehavior());
}
That’s the start. We just extend TextArea and override it’s two constructors. Those constructors in turn add a behavior that does the real work:
private static class KeepAliveBehavior extends AbstractDefaultAjaxBehavior {
@Override
protected void respond(AjaxRequestTarget target) {
// prevent wicket changing focus
target.focusComponent(null);
} @Override
public void renderHead(IHeaderResponse response) {
super.renderHead(response);
response.renderOnLoadJavascript(
"setInterval(function() { " +
" wicketAjaxGet('" + getCallbackUrl() + "', null, null, null); " +
"}, 600000);");
}
}
If you are familiar with Wicket, you probably already know that behaviors are a great way to extend the capabilities of components using composition rather than inheritance.
The first purpose of this Ajax behavior is to be a bucket for calls, which are received through the respond event method. Receiving a call will be enough for the application server to reset the session time out counter, which is the thing we’re after here.
Then, the Ajax behavior does a header contribution in the body of overridable method renderHead. It calls renderOnLoadJavascript on the header response, which will make Wicket register a script that is to be executed right after the page is loaded. The script creates a loop that calls wicketAjaxGet every ten minutes (600,000 miliseconds). That wicketAjaxGet function comes from Wicket’s standard Ajax support, which is automatically available for anything that extends AbstractDefaultAjaxBehavior or it’s subclasses.
The last interesting thing to note here is the call:getCallbackUrl()
This gives the URL to the Ajax behavior itself. This is what the loop calls every ten minutes,, and it results in the respond method being called on the behavior.
[update]
Al is right, it’s much easier to just extend AbstractAjaxTimerBehavior for this. I ripped the code for this post from a component that was doing much more than this, and in simplifying that, I didn’t think about the last step. Anyway, here it is, and using Duration makes it much nicer as well.
private static class KeepAliveBehavior extends AbstractAjaxTimerBehavior {
public KeepAliveBehavior() {
super(Duration.minutes(10));
}
@Override
protected void onTimer(AjaxRequestTarget target) {
// prevent wicket changing focus
target.focusComponent(null);
}
}