14
Feb
16

Log4j configuration with Java CDI (Contexts and Dependency Injection)


This page describes how to configure log4j in a Java CDI stand-alone application.

All of us seen code that looks like this over and over again.

private Logger logger = Logger.getLogger(this.getClass().getName());

We will use Java Contexts and Dependency Injection to create a custom log4j Logger for a service class.

Modify the pom.xml

vi 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>log4jCDI</artifactId>
	<version>20160214</version>

	<pluginRepositories>
		<pluginRepository> <!-- Ignore this repository. Its only used for document publication. -->
			<id>numberformat-releases</id>
			<url>https://raw.githubusercontent.com/numberformat/wordpress/master/20130213/repo/</url>
		</pluginRepository>
	</pluginRepositories>
	
	<dependencies>
		<dependency>
			<groupId>javax.enterprise</groupId>
			<artifactId>cdi-api</artifactId>
			<version>1.2</version>
		</dependency>
		<dependency>
			<groupId>org.jboss.weld.se</groupId>
			<artifactId>weld-se</artifactId>
			<version>2.2.6.Final</version>
		</dependency>
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.17</version>
		</dependency>

		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.8.2</version>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>2.3.2</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
		
			<plugin> <!-- Ignore this plugin. Its only used for document publication. -->
				<groupId>github.numberformat</groupId>
				<artifactId>blog-plugin</artifactId>
				<version>1.0-SNAPSHOT</version>
				<configuration>
					<gitUrl>https://github.com/numberformat/wordpress/tree/master/${project.version}/${project.artifactId}</gitUrl>
				</configuration>
				<executions>
					<execution>
						<id>1</id>
						<phase>site</phase>
						<goals>
							<goal>generate</goal>
						</goals>
					</execution>
				</executions>
			</plugin>
		</plugins>
	</build>

</project>

Setup the log4j configuration files. We will be using a very basic file that outputs to the console.
vi src/main/resources/log4j.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
   
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
    <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
        <param name="Target" value="System.out"/>
        <param name="Threshold" value="INFO" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d %-5p %c - %m%n"/>
        </layout>
    </appender>
    <logger name="com.test" additivity="true">
        <level value="DEBUG"/>
    </logger>
    <root>
        <level value="ERROR"/>
        <appender-ref ref="CONSOLE"/>
    </root> 
</log4j:configuration>

Producer (Factory)

The following CDI Producer creates a log4j Logger whenever it encounters a @Inject. Java keeps track of all the methods that are annotated with @Producer. If it comes across an inject
that requires a type produced by one of these producers then it calls the producer method to get this instance. The producer method here accepts a InjectionPoint metadata object that helps identify the location of where the injection is occuring. We will use this information to create a log4j logger custom to the class where its being injected into.

vi src/main/java/com/test/LoggerProducer.java

package com.test;

import javax.enterprise.inject.Produces;
import javax.enterprise.inject.spi.InjectionPoint;

import org.apache.log4j.Logger;

public class LoggerProducer {
	@Produces
	public Logger produceLogger(InjectionPoint injectionPoint) {
		return Logger.getLogger(injectionPoint.getMember().getDeclaringClass().getName());
	}
}

Service Class

The following service class is responsible for printing out the different levels of log messages.

vi src/main/java/com/test/TestLogger.java

package com.test;

import javax.inject.Inject;

import org.apache.log4j.Logger;

public class TestLogger {	
	@Inject
	private transient Logger logger;
	
	private static final String THIS_IS = "Method: ";
	
	public void writeLogAllLevels() {
		logger.fatal(THIS_IS + new Object(){}.getClass().getEnclosingMethod().getName());
		logger.error(THIS_IS + new Object(){}.getClass().getEnclosingMethod().getName());
		logger.warn(THIS_IS + new Object(){}.getClass().getEnclosingMethod().getName());
		logger.info(THIS_IS + new Object(){}.getClass().getEnclosingMethod().getName());
		logger.debug(THIS_IS + new Object(){}.getClass().getEnclosingMethod().getName());
	}
}

Junit Test Case

Finally test the logging with a simple junit test case.

vi src/test/java/log4jCDI/TestApp.java

package log4jCDI;

import org.jboss.weld.environment.se.Weld;
import org.jboss.weld.environment.se.WeldContainer;
import org.junit.Test;

import com.test.TestLogger;

public class TestApp {
	static WeldContainer weld=null;
	static {
        weld = new Weld().initialize();
	}
	@Test
	public void test() {
        TestLogger testLogger = weld.instance().select(TestLogger.class).get();
        testLogger.writeLogAllLevels();
	}

}

Log4j xml file

This bare bones log4j file will print all log levels to the console.

vi src/main/resources/log4j.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
   
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
    <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
        <param name="Target" value="System.out"/>
        <param name="Threshold" value="INFO" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d %-5p %c - %m%n"/>
        </layout>
    </appender>
    <logger name="com.test" additivity="true">
        <level value="DEBUG"/>
    </logger>
    <root>
        <level value="ERROR"/>
        <appender-ref ref="CONSOLE"/>
    </root> 
</log4j:configuration>

beans.xml

Finally create a blank beans.xml file in your src/main/java/META-INF folder.

Run the Junit Test Case

At this time you will see output of each of the messages to the console similar to this:

2016-02-14 15:58:18,840 FATAL com.test.TestLogger - Method: writeLogAllLevels
2016-02-14 15:58:18,841 ERROR com.test.TestLogger - Method: writeLogAllLevels
2016-02-14 15:58:18,841 WARN  com.test.TestLogger - Method: writeLogAllLevels
2016-02-14 15:58:18,841 INFO  com.test.TestLogger - Method: writeLogAllLevels
Full downloadable source for this page is available here. Corrections and enhancements are welcome, fork, change and push back to GitHub.
Advertisements

0 Responses to “Log4j configuration with Java CDI (Contexts and Dependency Injection)”



  1. Leave a Comment

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 74 other followers

February 2016
S M T W T F S
« Dec   Mar »
 123456
78910111213
14151617181920
21222324252627
2829  

Blog Stats

  • 800,977 hits

%d bloggers like this: