May 2, 2010

Setting up Log4j for simple Java Web Applications + Tomcat 5/6

If you have developed Java based web applications you probably felt the need at some point to use log4j for better more efficient logging.

There are different ways to setup log4j for you web application. Here I will present 2 of ways to setup log4j, particularly aimed at simple java web applications (eg. plain servlets/jsp webapps).

First you can download the following basic log4j.properties file. Just replace <appname> with your application name (eg. FunkyWebApp).


log4j.logger.<appname>logger=DEBUG, C, fileappender

log4j.additivity.<appname>logger=false
log4j.appender.C=org.apache.log4j.ConsoleAppender
log4j.appender.C.layout=org.apache.log4j.PatternLayout
#basic pattern
log4j.appender.C.layout.ConversionPattern=[%c] [%d{dd MMM yyyy - hh:mm:ss}] %5p - %m %n
#advanced pattern (slow)
#log4j.appender.C.layout.ConversionPattern=[%c] [%d{dd MMM yyyy - hh:mm:ss}] %5p - %m - in %M() at line %L of class %C %n 

log4j.appender.fileappender=org.apache.log4j.RollingFileAppender
log4j.appender.fileappender.File=${appRootPath}WEB-INF/logs/<appname>.log
log4j.appender.fileappender.MaxFileSize=500KB

## Keep one backup file
log4j.appender.fileappender.MaxBackupIndex=3
log4j.appender.fileappender.layout=org.apache.log4j.PatternLayout
log4j.appender.fileappender.layout.ConversionPattern=%p %t %c - %m%n
#log4j.appender.C.layout.ConversionPattern=[%c] [%d{dd MMM yyyy - hh:mm:ss}] %5p - %m %n

Now use one of the methods below to add and enable Log4J in your web application

Method 1: Use Servlet to initialize log4j

Step 1: Put log4j.properties file in the right place

  • Place 'log4j.properties' into the root of your classpath. See an example web application layout here

    Tip: when web application is deployed it should be in /WEB-INF/classes/log4j.properties.

  • If using eclipse place 'log4j.properties' under your project_name/src directory

Step 2: Define the servlet mapping in web.xml

Add the following code to WEB-INF/web.xml

<servlet> 
     <servlet-name>log4j-init</servlet-name>
     <servlet-class>com.FunkyWebapp.servlets.Log4jInit</servlet-class> 
     <init-param>
       <param-name>log4j-init-file</param-name>
       <param-value>WEB-INF/classes/log4j.properties</param-value>
     </init-param>
     <load-on-startup>1</load-on-startup>
</servlet> 

Make sure to change the java class file path to be relevant to your project. 'com.FunkyWebapp.servlets.Log4jInit'

Step 3: Add the servlet you mapped in Step 2 to your application

Add the following servlet to your project


import javax.servlet.http.HttpServlet;
import org.apache.log4j.PropertyConfigurator;

public class Log4jInit extends HttpServlet {

 public void init()
 {
     String prefix =  getServletContext().getRealPath("/");
     String file = getInitParameter("log4j-init-file");
 
     // if the log4j-init-file context parameter is not set, then no point in trying
     if(file != null){
      PropertyConfigurator.configure(prefix+file);
      System.out.println("Log4J Logging started: " + prefix+file);
     }
     else{
      System.out.println("Log4J Is not configured for your Application: " + prefix + file);
     }     
 }
}

Make sure the <servlet-class> element in Step 2 matches the fully qualified name of your servlet. And make sure it's in the right package.

Step 4: Initialize the logger and start logging from other servlets in your web application


public class MyServlet extends HttpServlet {
...
private Logger log = Logger.getLogger("<appname>logger");
.
.
.
log.debug("Some string to print out");

}

Make sure the <appname> part matches with the line

log4j.logger.<appname>logger in the log4j.properties file

Notes:
When you initialize log4j in a servlet you will only be able to log from classes which are loaded after the servlet (eg. other servlets). You won't be able to do logging from a ServletContextListener for example.

Method 2: Initialize log4j in a ServletContextListener

Step 1: Put properties file in the right place

  • Place 'log4j.properties' into the root of your classpath. See an example web application layout here

    Tip: when web application is deployed it should be in /WEB-INF/classes/log4j.properties.

  • If using eclipse place 'log4j.properties' under your project_name/src directory

Step 2: Define a listener mapping in web.xml

Add the following servlet listener mapping in web.xml:


<listener>
  <listener-class>
   com.package.listeners.ApplicationServletContextListener
  </listener-class>
</listener>

Step 3: Add the SerlvetContextListener class to the application

public class ApplicationServletContextListener implements ServletContextListener
{
 public void contextInitialized(ServletContextEvent event) 
 { 
     ServletContext ctx = e.getServletContext();
   
  String prefix =  ctx.getRealPath("/");     
  String file = "WEB-INF"+System.getProperty("file.separator")+"classes"+System.getProperty("file.separator")+"log4j.properties";
          
     if(file != null) {
       PropertyConfigurator.configure(prefix+file);
       System.out.println("Log4J Logging started for application: " + prefix+file);
     }
     else
     {
      System.out.println("Log4J Is not configured for application Application: " + prefix+file);
     } 
       
     
 }

 public void contextDestroyed(ServletContextEvent event) 
 {
  
 }

}

Step 4: Define the logger and start logging from other servlets in your applications


public class MyServlet extends HttpServlet {
...
private Logger log = Logger.getLogger("<appname>logger");
.
.
.
log.debug("Some string to print out");

}

Notes:

  • Easier to implement that Method 1
  • All web application now has access to log4j (including listeners)
  • Placing log4j initialization in a ServletContextListener allows initialization of log4j when your web application is loaded for the first time.

Other resources about log4j

Log4j, configuring a Web App to use a relative path.