Log4j2 shutdown problems in a servlet 3.0 application

When using log4j2 with a Servlet 3.0+ application, initialization and shutdown is supposed to be automatic. Unfortunately, if your application is still using its web.xml to define context listeners for other frameworks or libraries chances are good that you’ll run into thread leaks and other problems when undeploying your application or shutting down the application server (e.g. Tomcat).

This problem stems from the fact that log4-web component responsible for initializing log4j in a web application uses the Servlet 3.0 “web fragment” feature and a ServletContainerInitializer to add the necessary filter and servlet listener. The Servlet 3.0 spec states that:

If you have listeners which perform logging defined in your web.xml, you will run into problems during shutdown (and possibly startup):

In this example destroy will be called on the Log4jListener and Log4j will finish shutting down before destroy is called on Listener 2 or 1. If either of those listeners try to use logging during their own shutdown this will trigger log4j to start up again and leak threads.

Since this ordering is explicit in the spec, there is no way to properly use the log4j-web auto initialization feature if you still have context listeners that use logging in your web.xml.

Solution 1

Go back to explicitly configuring log4j in your web.xml to make sure it’s defined first:

<listener>
   <listener-class>org.apache.logging.log4j.web.Log4jServletContextListener</listener-class>
</listener>

<filter>
   <filter-name>log4jServletFilter</filter-name>
   <filter-class>org.apache.logging.log4j.web.Log4jServletFilter</filter-class>
</filter>
<filter-mapping>
   <filter-name>log4jServletFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

If you decide to do this you must disable the Log4jServletContainerInitializer. If you don’t the listener will be added twice, once in the wrong place. Either:

Solution 2

Move any listeners that use logging out of your web.xml and into fragments. The log4j-web fragment is configured to order itself before all other fragments so this will load your listeners in the correct order.

Comments