16
Feb
13

Log4j2 Configuration with Multiple Web Apps


This page describes how to use the new Log4j 2 Framework within multiple web applications deployed to a single web container with a shared log4j jar.

Full downloadable source for this page is available here. Corrections and enhancements are welcome, fork, change and push back to GitHub.

Background

Historically Java Web Application WAR files have included their own copy of the log4j jar files. This allowed multiple applications to co exist and use their own log4j configuration. However as web applications get smaller and focused smaller tasks (possibly RESTful applications) you will find yourself deploying multiple WAR files to the same web container. It doesnt make too much sense to have each WAR contain its own copy of log4j.jar.

Ideally it would be nice to have one log4j.jar file at the container level that each application can share. However, its not as simple as moving it out of the WAR file because of the way log4j configures itself.

This page covers a method described in the log4j 2 homepage.

Place the logging jars in the container’s classpath and use the default ClassLoaderContextSelector. Include the Log4jContextListener in each web application. Each ContextListener can be configured to share the same configuration used at the container or they can be individually configured. If status logging is set to debug in the configuration there will be output from when logging is initialized in the container and then again in each web application.

Requirements

  • Java 5 or later
  • Maven 2 or later
  • Log4j 2
  • Apache Tomcat 6

Procedure

We will create 2 apps and deploy them on Tomcat and verify that they are both logging to the console as well as individual files specified in their configs.

Any one who worked with log4j 1.x knows that this was a pain to setup with multiple web applications. Log4j 2 makes it a lot easier.

  • web-log-test – outputs to SYSOUT and ${user.home}/APPBASE/logs/web-log-test.log
  • web-log-test2 – outputs to SYSOUT and ${user.home}/APPBASE/logs/web-log-test2.log

Project Configuration

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.test</groupId>
  <artifactId>web-log-test</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>

	<pluginRepositories>
	  <pluginRepository>
	    <id>numberformat-releases</id>
	    <url>https://raw.github.com/numberformat/20130213/master/repo</url>
	  </pluginRepository>
	</pluginRepositories>

  <dependencies>
  	<dependency>
  		<groupId>javax.servlet</groupId>
  		<artifactId>servlet-api</artifactId>
  		<version>2.5</version>
  		<scope>provided</scope>
  	</dependency>
  	<dependency>
  		<groupId>org.apache.logging.log4j</groupId>
  		<artifactId>log4j-core</artifactId>
  		<version>2.0-beta4</version>
  		<scope>provided</scope>
  	</dependency>
  	<dependency>
  		<groupId>org.apache.logging.log4j</groupId>
  		<artifactId>log4j-api</artifactId>
  		<version>2.0-beta4</version>
  		<scope>provided</scope>
  	</dependency>
  	<dependency>
  		<groupId>org.apache.logging.log4j.adapters</groupId>
  		<artifactId>log4j-web</artifactId>
  		<version>2.0-beta4</version>
  		<scope>provided</scope>
  	</dependency>
  	<dependency>
  		<groupId>org.apache.logging.log4j.adapters</groupId>
  		<artifactId>log4j-1.2-api</artifactId>
  		<version>2.0-beta4</version>
  		<scope>provided</scope>
  	</dependency>
  </dependencies>

	<build>
		<finalName>web-log-test</finalName>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>2.0.2</version>
				<configuration>
					<source>1.6</source>
					<target>1.6</target>
				</configuration>
			</plugin>
	 		<plugin>
	 			<groupId>github.numberformat</groupId>
	 			<artifactId>blog-plugin</artifactId>
	 			<version>1.0-SNAPSHOT</version>
	 			<configuration>
				<gitUrl>https://github.com/numberformat/20130216</gitUrl>
	 			</configuration>
	        <executions>
	          <execution>
	            <id>1</id>
	            <phase>site</phase>
	            <goals>
	              <goal>generate</goal>
	            </goals>
	          </execution>
	        </executions>
	 		</plugin>
		</plugins>
	</build>
</project>

Web Configuration

The following sets up the log4jContextListener by specifying the log4jConfiguration parameter pointing it to the location of your config.

You may specify a file in the classpath or an absolute location on your system. If you want to keep this file in your WEB-INF folder then you can extend the class and customize it to suit your requirement.

vi src/main/webapp/WEB-INF/web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	id="WebApp_ID" version="2.5">
	<display-name>Sample Web Application</display-name>

	<context-param>
	   <param-name>log4jConfiguration</param-name>
	   <param-value>log4j2.xml</param-value>
	</context-param>

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

</web-app>

Log4j Configuration

In log4j 2 the name of the config file should be log4j2.xml. For this page our configuration file is very simple. See the log4j 2 site for further details about other configuration options.

vi src/main/resources/log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration strict="true">
<!-- include this to enable log4j internal debug messages: status="debug" -->
<appenders>
	<appender type="Console" name="STDOUT">
		<layout type="PatternLayout" pattern="%d %-5p %c - %m%n"/>
	</appender>
	<appender type="File" name="File" fileName="${sys:user.home}/APPBASE/logs/web-log-test.log">
		<layout type="PatternLayout">
			<pattern>%d %-5p %c - %m%n</pattern>
		</layout>
	</appender>
</appenders>

<loggers>
	<logger name="org.apache.jsp" level="debug">
		<appender-ref ref="File"/>
	</logger>
	<root level="trace">
		<appender-ref ref="STDOUT"/>
	</root>
</loggers>

</configuration>

Test Page

We can test the application by using a simple jsp.

vi src/main/webapp/snoop.jsp

<HTML>
<HEAD>
	<TITLE>JSP snoop page</TITLE>
	<%@ page import="org.apache.log4j.*" %>
</HEAD>
<BODY>

<H1>WebApp JSP Log4j Test</H1>

<h3>Apache Log4j Logging</h3>

<%
Logger logger = Logger.getLogger(getClass());
if("submit".equals((String)request.getParameter("log"))) {
	String text = (String)request.getParameter("text");
	String level = (String)request.getParameter("level");
	logger.log(Level.toLevel(level), text);
}
%>

<form action="" method="GET">
<TABLE border="1">
<TR valign=top>
	<TH align=left>Level</TH>
	<TH align=left>Test Message</TH>
</TR>
<TR valign=top>
	<TD>
		<select name="level">
			<option value="ERROR">ERROR</option>
			<option value="WARN">WARN</option>
			<option value="INFO" selected="selected">INFO</option>
			<option value="DEBUG">DEBUG</option>
			<option value="TRACE">TRACE</option>
		</select>
	</TD>
	<TD>
		<input name="text" type="text" size="35" value="<%=new java.util.Date()%>">
		<input name="log" type="submit" value="submit">
	</TD>
</TR>
</TABLE>
</form>

</BODY>
</HTML>

Finally copy the following files to the “tomcat6/lib” folder. You may obtain these files from the .m2 folder after the project is built. Or you can get them from the apache download site. (at the time of this writing only beta4 was the latest available)

  • log4j-core-2.0.jar – core libarary.
  • log4j-api-2.0.jar – API Shell Classes to be used by your code
  • log4j-web-2.0.jar – Servlet Listener to initialize Logging
  • log4j-1.2-api-2.0.jar – log4j 1.x support for legacy code that still uses it.

Build and Run the Application

perform the build by typing:

mvn clean compile package

You will notice that the WAR file does not contain any log4j jars.

Copy the war file into your tomcat6/webapps folder.

navigate to: http://localhost:8080/web-log-test/snoop.jsp

Modify and Deploy the Second Application

For the second application we want to modify the log4j2.xml to write the log to ${user.home}/APPBASE/logs/web-log-test2.log

Rename the WAR file to web-log-test2.war deploy to the same server.

Restart and test.

Using a new TAB, navigate to: http://localhost:8080/web-log-test2/snoop.jsp

Verify that the logs are being written the console and to each file independently.

Appendix

log4j 1.x configuration available here

Full downloadable source for this page is available here.
Advertisements

2 Responses to “Log4j2 Configuration with Multiple Web Apps”


  1. May 15, 2014 at 10:53 am

    Excelent post numberformat!! Unfortunately, I cannot update from log4j to log4j2 in my project. You said in the article “Any one who worked with log4j 1.x knows that this was a pain to setup with multiple web applications. Log4j 2 makes it a lot easier.” Do you have some information about how to configure log4j with multiple web applications using log4j?? Thanks in advance


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


Enter your email address to subscribe to this blog and receive notifications of new posts by email.

Join 78 other followers

February 2013
S M T W T F S
« Jan   May »
 12
3456789
10111213141516
17181920212223
2425262728  

Blog Stats

  • 822,102 hits

%d bloggers like this: