My team was recently asked to provide a solution for externalizing session storage in order to support clustering within a web application deployed on JBoss. In order to do this we decided to create a model in which the standard Java session object would be replaced by a custom session object via a RequestWrapper. The type of session object returned would be determined by the session repository configured within the web container. We provided two types of session repositories: 1) An object grid repository that returns a session object that would be stored and persisted within an external database. This type of session object would support clustering and is intended to be used within a production environment 2) An in memory session repository that returns a session object stored within the web container’s memory. This type of session object does not support clustering and would be used for ease of development only.
In order to use a request wrapper, within the servlet filter, we initialized it and added it to the filter chain like this:
public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException {
final HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletRequestWrapper wrapper = new HttpServletRequestWrapper(httpRequest) {
chain.doFilter(wrapper, response);
}
The diagram below shows the flow used by the RequestWrapper to retrieve the custom session object.
By doing this there were other challenges that presented themselves such as not being able to detect session events such createSession and destroySession through the web container’s servlet filters. Possible solutions to this would be to explicitly create listeners for each CustomSession object and then initialize these listeners for each servlet filter subsequently created. In addition we would may lose valuable session management functionality made available by the web container in terms of the lifecycle and cleanup (i.e. session timeout, session expiry). In order to compensate we would need to implement this through our own custom design. This model, does however, allow for sessions to be maintained across a cluster.