Initialize Log4J in a web application with a ServletContextListener


Warning: Use of undefined constant user_level - assumed 'user_level' (this will throw an Error in a future version of PHP) in /homepages/12/d210716052/htdocs/javatastic/blog/wp-content/plugins/ultimate-google-analytics/ultimate_ga.php on line 524

While LogJj will self-initialize if it finds a file called log4j.properties or log4j.xml in the classpath, it will only read the file once at application startup.

I’ve often had the need to be able to change the logging level in a long-running application, such as a web application, so that I can switch logging to debug level as needed without requiring a restart.

Log4J provides configurator classes that will monitor a configuration file for changes and reload the configuration when the file changes. The implementation appears to spawn a background thread that sleeps for a specified interval, then wakes up and checks the configuration file for changes.

You can use this method by calling PropertyConfigurator.contigureAndWatch() or DOMConfigurator.configureAndWatch() methods. The challenge is that you should only call these methods once when your application starts up as each call to the above methods will result in a new thread to monitor the configuration file.

In many applications, it is a simple matter to call these methods only once. The question often comes up as to where to make the call to a ConfigureAndWatch method from within a web application. A collegue of mine once accidentally put this call in the main execution path of a high-traffic web application and brought the site down as the web application container couldn’t manage all the resulting threads.

I’ve seen several methods of ensuring that the ConfigureAndWatch method is only called once from within a web application, but I think the cleanest and simplest is to create a Context Listener to initialize Log4J.

The following example creates a ServletContextListener which will initialize Log4J when the application is loaded by the container, and will shut down logging for the application when it is unloaded.

package some.package;

import java.io.File;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.apache.log4j.PropertyConfigurator;
import org.apache.log4j.LogManager;
import org.apache.log4j.xml.DOMConfigurator;
/**
 * ServletContextListener to initialize Logging for the application
 */

public class Log4jConfigListener implements ServletContextListener
{
    private static long DEFAULT_INTERVAL = 300000;
    public void contextDestroyed(ServletContextEvent event)
    {
        //Turn off logging when the Servlet Context is destroyed
    	LogManager.shutdown();
    }

public void contextInitialized(ServletContextEvent event)
    {
        //Read configuration properties from web.xml
        String file = event.getServletContext().getInitParameter("LOG4J_CONFIG_LOCATION");
        String interval = event.getServletContext().getInitParameter("LOG4J_REFRESH_INTERVAL");
        long delay = DEFAULT_INTERVAL; //Default delay is 5 minutes

//Check for interval parameter
        if (interval != null && !"".equals(interval))
        {
            try
            {
                delay = Long.parseLong(interval);
            }
            catch(NumberFormatException e)
            {
                //Can't really log the error since we haven't initialized Log4J
                //Will use the default value
                delay = DEFAULT_INTERVAL;
            }
        }

//Check for file parameter
        if(file != null && !"".equals(file))
        {
            if(!(new File(file).exists()))
            {
                throw new IllegalArgumentException("Invalid 'LOG4J_CONFIG_LOCATION' parameter value '"
                                                                 + file + "'.");
            }
if(file.toLowerCase().endsWith(".xml"))
            {
                DOMConfigurator.configureAndWatch(file, delay);
            }
            else
            {
                PropertyConfigurator.configureAndWatch(file, delay);
            }
        }
    }
}

Once you add this class to your application, you need to configure the listener. This is done by adding the following to your web.xml file:

<!-- Log4j Initialization Parameters -->
<context-param>
  <!-- absolute path to log4j config file (*.properties or *.xml) -->
<param-name>LOG4J_CONFIG_LOCATION</param-name>
<param-value>
  ABSOLUTE_PATH_TO_YOUR_LOG4J_CONFIGURATION_FILE
  </param-value>
</context-param>
<context-param>
  <!-- number of milliseconds to wait before checking LOG4J_CONFIG_LOCATION for updates -->
  <param-name>LOG4J_REFRESH_INTERVAL</param-name>
  <param-value>(e.g. 300000)</param-value>
</context-param>

<listener>
  <listener-class>
    some.package.Log4jConfigListener
  </listener-class>
</listener>

4 thoughts on “Initialize Log4J in a web application with a ServletContextListener”

  1. Pingback:
    Warning: Use of undefined constant user_level - assumed 'user_level' (this will throw an Error in a future version of PHP) in /homepages/12/d210716052/htdocs/javatastic/blog/wp-content/plugins/ultimate-google-analytics/ultimate_ga.php on line 524
    Javatastic » Blog Archive » How Not to Initialize Log4J in an Application

  2. Warning: Use of undefined constant user_level - assumed 'user_level' (this will throw an Error in a future version of PHP) in /homepages/12/d210716052/htdocs/javatastic/blog/wp-content/plugins/ultimate-google-analytics/ultimate_ga.php on line 524
    ebeisswenger says:

    Warning: Use of undefined constant user_level - assumed 'user_level' (this will throw an Error in a future version of PHP) in /homepages/12/d210716052/htdocs/javatastic/blog/wp-content/plugins/ultimate-google-analytics/ultimate_ga.php on line 524

    Yes, indeed it is!

    Honestly speaking, I had to puzzle together nearly the same solution for exactly the same problem, before I found this post ;-), but I’m still happy finding a confirmation that I am not the only one going this way.


  3. Warning: Use of undefined constant user_level - assumed 'user_level' (this will throw an Error in a future version of PHP) in /homepages/12/d210716052/htdocs/javatastic/blog/wp-content/plugins/ultimate-google-analytics/ultimate_ga.php on line 524
    Nguyen Minh Quyet says:

    Warning: Use of undefined constant user_level - assumed 'user_level' (this will throw an Error in a future version of PHP) in /homepages/12/d210716052/htdocs/javatastic/blog/wp-content/plugins/ultimate-google-analytics/ultimate_ga.php on line 524

    Thanks for a nice article, I think i have found a way to config log4j in my later project!!!


  4. Warning: Use of undefined constant user_level - assumed 'user_level' (this will throw an Error in a future version of PHP) in /homepages/12/d210716052/htdocs/javatastic/blog/wp-content/plugins/ultimate-google-analytics/ultimate_ga.php on line 524
    Randy says:

    Warning: Use of undefined constant user_level - assumed 'user_level' (this will throw an Error in a future version of PHP) in /homepages/12/d210716052/htdocs/javatastic/blog/wp-content/plugins/ultimate-google-analytics/ultimate_ga.php on line 524

    Here’s another approach, but for WebLogic.
    Allows for dynamic configuration using JMX.
    With this method, you would not need to use the PropertyConfigurator, but can just load the properties in as part of your jar/war/ear and make adjustments as needed via JMX
    http://www.theserverlabs.com/blog/2010/04/22/dynamically-changing-log-level-with-weblogic-log4j-jmx-and-wlst/

Leave a Reply

Your email address will not be published. Required fields are marked *