Adding Log4J on a Java Web Application

Logs on a web application make us easier to trace a flow of a process. Log is also become a tools for us to trace an error that might be happen on our web application, so we can trace where’s exactly the error happen by monitoring the stopped process. What kind of method or function that might be created based on wrong logic, or maybe other mistaken that we created when we arrange the code.

On java programming language, there’s a few library that we can use to adding log. Some of those libraries become a standard production of a web application. Practically, log made their own record file, this file is created in order to write all the process that we feel so important to tracing a data flow. Log recording on web application usually separated by the web application that we’ve made in order to make easier for us to trace data flow in each web application.

This time, we will try to add log on our web application, using the library that released by the Apache Foundation which is Log4J library. Just because we will need this library, so please download this library here, while in this sample project I will use log4j library version 1.2.8. if you want to use the latest library, go a head. And I will also use a Servlet Container Apache Tomcat 5.5 that I use very often to create a web application.

The important things that we have to understand when the Tomcat is started is Tomcat will read all the web application setting through a file called web.xml that exist on WEB-INF directory on each our web application folder. And all the libraries that we use in our web application, have to be put on WEB-INF/lib folder at each web application that we have made.

The scenario of adding log4j on a web application, based on understanding of a Servlet Container behavior above is: running out a servlet that containing a method to set the log4j. Just because the Tomcat will read web.xml file, so this log4j calling method will be placed in this web.xml, this calling method is a servlet that will run on the first load of tomcat. And don’t forget to put the libraries of this log 4j on a WEB-INF/lib folder on our web application.

Ok, let’s create a servlet that have a function to set this log4j platform. below is the source code of the servlet, let’s name this servlet with Log4JInitServlet name. Thise servlet is an extends of HttpServlet class, so we can override few methods belongs to HttpServlet class. 

 

package org.mojo.app.web.servlet;

import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class Log4JInitServlet extends HttpServlet{
    static Logger logger = Logger.getLogger(Log4JInitServlet.class.getName());
 public void init(ServletConfig sc) throws ServletException {
        super.init(sc);
        ServletContext context = getServletContext();
        //find out where this web application is located on machine and print it out
        String sPath = context.getRealPath("/");
        System.out.println("Application Path :" + sPath);

        //finding log4j configuration file on web.xml
        String sLogConfigFile = getInitParameter("log4j-init-file");
        System.out.println("LogConfig: " + sLogConfigFile);

        //configuring Log4J System using PropertyConfigurator Class
        PropertyConfigurator.configure(sLogConfigFile);
        logger.info("Logger has been initialized...");
    }

    public void destroy() {
        super.destroy();
        logger.info("Destroy");
    }

    protected void doPost(HttpServletRequest req, HttpServletResponse res)
       throws ServletException, IOException {
        logger.info("doPost()");
    }

    protected void doGet(HttpServletRequest req, HttpServletResponse res)
        throws ServletException, IOException {
        logger.info("doGet()");
    }
}

Let’s discuss code above before we go to the next step.

package org.mojo.app.web.servlet;

import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

In this block we describe the package of this servlet located, we also import some classes that we might be need it later. And then we will create codes to define this class and also static variable logger as a Logger that we will use. Here’s the code:

public class Log4JInitServlet extends HttpServlet {
    static Logger logger = Logger.getLogger(Log4JInitServlet.class.getName());
    ........

}

And then, we create a method that overriding a method from HttpServlet class which is Init method, on it’s super class this method have a public as it’s modifier access, and also have a parameter, and last but not least, it’s has a ServletException.throws. below is the code of the method.

public void init(ServletConfig sc) throws ServletException {
    .........
}

In this method we will put the setting of log4j configuration for our web application, and now let’s see the screen-shot of the code:

  super.init(sc);
  ServletContext context = getServletContext();
  //find out where this web application is located on machine and print it out
  String sPath = context.getRealPath("/");
  System.out.println("Application Path :" + sPath);

On the first line we call the method that inherited from the HttpServlet class, and then the second line of the code we define a variable named context which has a ServletContext as a\it’s data type, the third line is comments,. And then the fourth lines, we define a variable called String sPath that it’s value directly filled with the value that we took from the real-path of the context variable that we have define before, in order to print out to the console. Actually this lines is an option whether to use it or not, because the essence of this line is to figure out where is our web application located.

OK let’s take a look of the next code:

   //finding log4j configuration file on web.xml
   String sLogConfigFile = getInitParameter("log4j-init-file");
   System.out.println("LogConfig: " + sLogConfigFile);

   //configuring Log4J System using PropertyConfigurator Class
   PropertyConfigurator.configure(sLogConfigFile);
   logger.info("Logger has been initialized...");

On the first line there’s a comment tell us that the lines below will searching the configuration file on web.xml. It’s seen on the second line, we declare a variable called sLogConfigFile and the value direcly filled by the value that we took from a servlet parameter that we will configure later on web.xml file, the name of the parameter is “log4j-init-file”. Later on the web.xml file, we will add a lines like this <param name>log4j-init-file</param name>, and below of these line, we will add one line again contain <param value>…..</param value> where the blanks is value of the log4j-init-file parameter.

On the next lines there’s a comment too, that the meaning of the comment is about “Configuring the Log4J System by using propertyConfigurer”. In the code practically, to configure this log4j, we just call a method named configure that owned by PropertyConfigurator class. If the configuration configured successfully, then we just call the instance of log4j library with calling the method named info and fill the parameter with “Logger has beed initialized” string.

It’s highly need to remember that if this string is printed out on the log file, mean that we configured the log for our web application successfully, so for other method we only just call this info method. And also for other class that we will make later. We just call this info method to entering to the log which point we want to record. But don’t forget to declare the log variable first and located in the header of the class just like the sample shows us.

Practically, the log that we made will have two log records. The first one is containing normal log, and the second log is contains error log of the data flow. To call error method in order to fill out the error log, same as we call info method, but change the word info and replaced with the word error.

Besides that, in this servlet we also override another three method of the HttpServlet class whis is : do doPost, doGet, and destroy method, but I think I don’t have to explain this three methods, because these methods id not too important to explain in the relation of configuring this log4j platform. these method is also an option whether we will use or not.

By this explanation, we have finished creating a servlet that contains a method configuring the log4J platform for our web application. now let’s move out by look at the source code of the web.xml file below. This file we the guide of the tomcat Servlet Container in order to run out our web application.

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
          http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
           version="2.5">

    <servlet>
        <servlet-name>Log4JInitServlet</servlet-name>
        <servlet-class>org.mojo.app.web.servlet.Log4JInitServlet</servlet-class>
        <init-param>
            <description>This param and value is set to define where is configuration located</description>
            <param-name>log4j-init-file</param-name>
            <param-value>/java/mojo/web_app/macam-macam/config/macam-macam_log4j.properties</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

We can see on the web.xml source code above, that there’s a servlet configured on our web application, the servlet’s name is Log4JInitServlet. If we see on the <servlet>………</servlet> block, there’s a class call, which is Log4JInitServlet Servlet class that exist on org.mojo.app.web.servlet package, This is where the location of the servlet that we just made. This servlet declaration on this web.xml file has params, named log4j-init-file that we’ve created on the servlet, and we also can see that params has a value which is /java/mojo/web_app/macam-macam/config/macam-macam_log4j.properties. This servlet will also run automatically on the first time when the Tomcat boot up, marked by <load-on-startup>1</load-on-startup> blocks.

Please see on the param value line, there’s something that we should deeply understand here, related with the Tomcat behaviour. If Tomcat installed on our windows system on C:\Web\Tomcat_5.5, then the root of Tomcat will be start from that folder, while the system root will start from the C:\ drive. The relation with this param value is , if we use the “/” character on the first characted on the param value just like above , that means macam-macam_log4j.properties file will have to be put on path: C:\Java\mojo\web_app\macam-macam\config\.That is one of the Tomcat behaviour, if we use “/ ” on the first character of param value on the web.xml file, then Tomcat will start to read from system root. How about if we didn’t use the “/” character, Tomcat will start to read from the path instalation of Tomcat it self which is C:\Web\Tomcat_5.5.

Then the next step is, we will create a log 4j property file. To create this file we have to follow the API of this Log4j, here’s the log4j propery file.

# For the general syntax of property based configuration files see the
# documentation of org.apache.log4j.PropertyConfigurator.
# The root category uses two appenders called A1 and R. Since no priority is
# specified, the root category assumes the default priority for root
# which is DEBUG in log4j. The root category is the only category that
# has a default priority. All other categories need not be assigned a
# priority in which case they inherit their priority from the
# hierarchy.

#log4j.rootCategory=, R
# Root logger set to DEBUG using the A2 appender defined above.

log4j.rootLogger=, R, E, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

# Pattern to output the caller's file name and line number.
log4j.appender.stdout.layout.ConversionPattern=%d %5p [%F:%L] - %m%n

# R is the RollingFileAppender that outputs to a rolling log
# file called web_app.log.
log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=/java/mojo/web_app/macam-macam/logs/macam-macam.log
log4j.appender.R.Threshold=DEBUG

# Define a pattern layout for the file.
# For more information on conversion characters (i.e. d,p,t,c,l,m,n)
# please see the PatternLayout class of the Log4j API.
log4j.appender.R.layout=org.apache.log4j.PatternLayout

#log4j.appender.R.layout.ConversionPattern=%d [%c{1}] %-5p - %m%n
log4j.appender.R.layout.ConversionPattern=%d [%F:%L] %-5p - %m%n

# Set the max size of the file and the number of backup files
log4j.appender.R.MaxFileSize=2MB
log4j.appender.R.MaxBackupIndex=9

################################## Define Error File Log #########################################
# E is the ErrorFileAppender that outputs to a rolling log
# file called web_err.log.
log4j.appender.E=org.apache.log4j.RollingFileAppender
log4j.appender.E.File=/java/mojo/web_app/macam-macam/logs/macam-macam_err.log
log4j.appender.E.Threshold=ERROR

# Define a pattern layout for the file.
# For more information on conversion characters (i.e. d,p,t,c,l,m,n)
# please see the PatternLayout class of the Log4j API.

log4j.appender.E.layout=org.apache.log4j.PatternLayout
#log4j.appender.E.layout.ConversionPattern=%d [%c{1}] %-5p - %m%n
log4j.appender.E.layout.ConversionPattern=%d [%F:%L] %-5p - %m%n

# Set the max size of the file and the number of backup files
log4j.appender.E.MaxFileSize=100KB
log4j.appender.E.MaxBackupIndex=9

We will not discuss line by line of this log4j property file. I think it’s enough for us to focus on this line log4j.appender.R.File=/java/mojo/web_app/macam-macam/logs/macam-macam.log. This line is line where the logger will create a log called macam-macam.log. And we should focus on this line too log4j.appender.E.File=/java/mojo/web_app/macam-macam/logs/macam-macam_err.log. This line is a definition where we initialize the log for error.

As a last reference of deployment for this project, copy the log4j library on to your web application. Put this log4j library on your WEB-INF/lib folder, and then place the Servlet Class that we’ve created on the correct package. And then copy the log4j property file to correct location as it declared on the web.xml file. Don’t forget to create log folder where the logger will produce log files based on log4j property file.

That’s it, our discussion, go try with your own creativity, and i’m waiting here for your feed back of this article.

 

 

Hope this will helfull

 

Menteng, June 15th, 2008

 

Josescalia

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s