ServletRequestAttributeListener | cannot create session after response has been committed
I recently completed some work for a client where I was tasked in addressing their ever-increasing number of error logs being reported in their production sites. My analysis was helped by the fact that a few years ago we installed JavaMelody on each of their production web servers. This allowed me to get an insight into their issues even though they have their log4j log levels set purely to ERROR.
One of the major issues that I started noticing was ‘cannot create session after response has been committed’. There were literally over 2 million instances of this error on one server alone.
The reason for the error was that the client had developed some code to integrated Spring Forms into the delivery stack. There’s nothing wrong with the Spring Forms per se but rather with the client’s custom logic used to pass form variables around in the session whilst trying to integrate into our delivery framework.
The logic worked and forms ran happily on the site. The problem was that for the bulk of the requests on the site, an unnecessary session was being created. The logic was using a ServletRequestAttributeListener to listen out for request scope attributes being added, edited and removed. It would then try initialize an object, populate it with the attribute key and value and then put the object in a session it retrieved from the request. Problem in point.
The ServletRequestAttributeEvent passed to the method in your ServletRequestAttributeListener has no access to the HttpServletResponse object and thus can’t tell if the response has already been committed. I’ve since remove all dependencies on them having to use a ServletRequestAttributeListener and things are running much smoother.
ServletRequestAttributeListener is powerful but with power comes great responsibility. My advice would be to make sure you do not create or work with session objects from within your request attribute listener. Also know that it’ll be called whenever any request scoped attribute is added, removed or updated. So if you have to use one then match against a specific url first. You don’t want to be processing incorrect urls unnecessarily.
As a refresher here’s a simple implementation of a ServletRequestAttributeListener:
public class ServletRequestAttributeListenerDemo implements ServletRequestAttributeListener
public void attributeAdded(ServletRequestAttributeEvent e)
System.out.println(e.getName()+" : Attribute added . .Value "+e.getValue());
public void attributeRemoved(ServletRequestAttributeEvent e)
System.out.println(e.getName()+" : Attribute removed . " );
public void attributeReplaced(ServletRequestAttributeEvent e)
System.out.println(e.getName()+" : Attribute replaced . .Value ");