Maven

Log4j Maven example

In this article we are going to explain how to use Maven and Log4j in a Java project.

All examples in this article have been implemented using Java version 8 update 5, Maven version 3.2.2 and Log4j version 1.2.17 (all for and under Windows 64b). This Log4j version is the last one supported in the maven repositories at the moment of writing this article.

First of all, we are going to explain briefly what Maven and Log4j are. Maven is a tool for building Java based project that offers several benefits and options by making build processes powerful, easy and understandable. Maven takes care of downloading all necessary dependencies and including them correctly in the project. Log4j is a Java based logging API that offers many log related functionalities like configuring different log levels, separate them by class or package, appending logs to different outputs, etc. Both are part of the Apache Software Foundation.

For more information about these technologies please go to the official apache sites: http://maven.apache.org/index.html http://logging.apache.org/log4j

Download Maven

First of all, we have to download maven from the following links http://maven.apache.org/download.cgi. As I mentioned before, we are going to use the version 3.2.2.

Maven installation on Windows

In order to install Maven on Windows we should unzip the archive apache-maven-3.2.2-bin.zip to the desired directory. These instructions assume you chose C:\Program Files\Apache Software Foundation. The subdirectory apache-maven-3.2.2 will be created from the archive.

Afterwards, you should add following environment variables to your system:

  • M2_HOME = C:\Program Files\Apache Software Foundation\apache-maven-3.2.2
  • M2 = %M2_HOME%\bin
  • update Path = %M2%
  • make sure JAVA_HOME exists and it is pointing to a correct JDK, not a JRE; e.g. C:\Program Files\Java\jdk1.8.0_25.
  • make sure %JAVA_HOME%\bin is in your Path environment variable.

In order to check that everything went fine, go to a command prompt and type mvn --version , the output should show your maven basic configuration.

For more information about the installation of maven in other platforms please visit http://maven.apache.org/download.cgi#Installation.

Maven usage

Now that we have Maven installed in our system, we are going to generate our first Java project using Maven.

We go to the directory where we want to create our projects and we type:

mvn archetype:generate -DgroupId=com.danibuiza.firstexample -DartifactId=firstexample -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

this creates a project with a source and a test directories that include just a small unit test class and a hello world program, nothing special though. The only “new” thing here is the file called pom.xml (Project Object Model). That file contains the configuration of the project in XML format: its name, the dependencies to other projects and libraries and the build instructions and processes needed to build (and other tasks) it. Even if we are not going to see it in this article, it is good to mention that larger projects normally have several POM files that are managed by a “super” POM, so POM files can be included and concatenated.

Here is the generated POM for our default project:

  <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/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.danibuiza.maven.firstexample</groupId>
  <artifactId>firstexample</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>firstexample</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

As we can see in the POM above, this project only has one dependency to junit, this dependency is solved by maven and we do not need to take care of it. We just have created the project basic structure that we can change if we want to implement something.

So we are going to make some changes in the main class and in the unit tests. I am just creating some static methods with some computations and calling them from the main method of the App class. Then I am verifying these methods using Junit. Here are the changes in the source code:

		public static int addition(int first, int second) {
			return first + second;
		}

		public static double divide(int first, int second) {
			if (second != 0) {
				return (double) first / (double) second;
			}
			return 0;
		}

and the test changes in order check that Maven is executing them:

	
		public void testAppAddition() {
			assertEquals(7, App.addition(3, 4));
		}

		public void testAppDivide() {
			assertEquals(8.0, App.divide(80, 10));
		}

These changes are not really interesting but show us a little bit how Maven works. If we build the project now using Maven, we just go to the directory where we created our project before (where the pom.xml is located) and we type:

mvn package

this creates a jar file containing the project, folders containing the .class files with the Bytecode of our code and test reports using surefire. Also all unit tests are executed and the results are shown:

		...
		-------------------------------------------------------
		 T E S T S
		-------------------------------------------------------
		Running com.danibuiza.maven.firstexample.AppTest
		Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.017 sec

		Results :

		Tests run: 3, Failures: 0, Errors: 0, Skipped: 0
		...
		[INFO] ------------------------------------------------------------------------
		[INFO] ------------------------------------------------------------------------
		[INFO] Total time: 5.491 s
		[INFO] BUILD SUCCESS
		[INFO] Finished at: 2014-07-10T10:24:58+02:00
		[INFO] Final Memory: 9M/312M
		[INFO] ------------------------------------------------------------------------
		...

we can see in the output produced by Maven that the tests were successfully executed and the project was properly build. If the tests failed or some problem occurred during the build process Maven would have informed us.

Maven created a jar file with the content of the project. In order to execute our first example, type:

		java -cp target/firstexample-1.0-SNAPSHOT.jar com.danibuiza.maven.firstexample.App

and the output would be

	
		Hello World!
		3
		0.5

so we have implemented already our first project that uses Maven.

Integrate Log4j in the maven Build options

Now, we are going to see how to integrate Log4j in our java project using Maven.

First of all indicate Maven that we need Log4j in our project by adding a Log4j dependency in our pom.xml file:

    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency> 

just with this change you would be able to use Log4j in your code. Maven will take care of properly download and insert the dependencies in your project. We can print out our Hello World using Log4j now by configuring a basic logger in our main class and printing a debug message, for example, hello world!. So we change our main class:

		//Configure logger
                BasicConfigurator.configure();
                logger.debug("Hello World!");
		logger.info("Info");
		logger.warn("warning!");
		logger.error("error");

and build the project again:

		mvn package

we execute it like before

		java -cp target/firstexample-1.0-SNAPSHOT.jar com.danibuiza.maven.firstexample.App

and the results:

		NoClassDefFoundError!!!!

Ups, we have a problem here!! The problem is that we the dependencies used by Maven to build the project and create the jar file are not accessible for Java while executing the jar. So we have to indicate Maven to include these dependencies into the jar file that is going to be generated. This can be done by using the shade maven plug-in:

  <build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>2.1</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                    <configuration>
                        <transformers>
                            <transformer
                                implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                <mainClass>com.danibuiza.maven.firstexample.AppWithLog4j</mainClass>
                            </transformer>
                        </transformers>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

This plug-in “copies” all the content of the dependencies into the jar file, for sure this is just an option, you can execute your code in several ways and resolve the dependencies in runtime differently. In the configuration shown above we are also indicating maven what class is the main one in our project. In order to execute now our code we can type:

		java -jar target\firstexample-1.0-SNAPSHOT.jar

and we get the following output:

	
		2014-07-10 10:39:44 DEBUG AppWithLog4j:21 - Hello World!
		2014-07-10 10:39:44 INFO  AppWithLog4j:22 - Info
		2014-07-10 10:39:44 WARN  AppWithLog4j:23 - warning
		2014-07-10 10:39:44 ERROR AppWithLog4j:24 - error

we can see in the output shown above the different log levels.

It is also possible to just copy the needed dependencies to your project structure, this can be done by the copy-dependencies options of the maven dependency plug-in, just add to the POM:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <version>2.8</version>
    <executions>
      <execution>
        <id>copy-dependencies</id>
        <phase>package</phase>
        <goals>
          <goal>copy-dependencies</goal>
        </goals>
        <configuration>
          <outputDirectory>${project.build.directory}/alternateLocation</outputDirectory>
          <overWriteReleases>false</overWriteReleases>
          <overWriteSnapshots>false</overWriteSnapshots>
          <overWriteIfNewer>true</overWriteIfNewer>
        </configuration>
      </execution>
    </executions>
</plugin>

this creates a folder called dependency where the needed libraries are stored. It is also possible to create an eclipse project using Maven, just type:

		mvn eclipse:eclipse

and a project with the proper .project file that can be opened with eclipse will be created.

There are many other options and plugins available while using maven, but they are not in the scope of this article.

Playing with Log4j a bit

So we are able to include Log4j in our project and to use it to print something out in the console.

First of all, we are going to see how to log using different log levels:

		logger.debug("Hello World!");
		logger.info("Info");
		logger.warn("warning!");
		logger.error("error");

so we are logging debug information, warnings, errors, etc. Now we are going to see how to create an Appender that is an output destination for our log messages. In our examples we are using the BasicConfigurator.configure() that internally creates a ConsoleAppender, which is an Appender that logs to the standard console. If we want to change that and use advanced Log4j properties we can indicate Log4j what properties file to use:

	PropertyConfigurator.configure("log4j.properties");

Actually this is not needed if the Log4j configuration indicates that the configuration properties are located in a file called like that (what is the standard), but I prefer to do it in order to be more independent and control better my code. In the log4j.properties file we indicate the Log4j options that we desire, for example:

		# Root logger option
		log4j.rootLogger=WARN, file, stdout
		 
		# Direct log messages to a log file
		log4j.appender.file=org.apache.log4j.RollingFileAppender
		log4j.appender.file.File=.\\logging.log
		log4j.appender.file.MaxFileSize=10MB
		log4j.appender.file.MaxBackupIndex=10
		 
		# Direct log messages to stdout
		log4j.appender.stdout=org.apache.log4j.ConsoleAppender
		log4j.appender.stdout.Target=System.out	

this configuration shown above is indicating that Log4j should log messages in a file called logging.log (log4j.appender.file=org.apache.log4j.RollingFileAppender) and in the standard console at the same time (log4j.rootLogger=WARN, file, stdout), the messages that are going to be stored in the file logging.log should be WARN or above level ones and the messages to be printed out to the console all of them, without level restrictions. We are also indicating Log4j that the appender file maximum size should be 10MB (log4j.appender.file.MaxFileSize=10MB) and it should create a maximum of 10 backups (log4j.appender.file.MaxBackupIndex=10, rolling). Note: the Log4j configuration can be also done via xml files. There are several ways and options to use and configure Log4j in a project, this article is just an example of all this potential with the aim to explain briefly how to build and create a project using Maven with a Log4j dependency.

Summary

In this article we saw how to use Maven and Log4j in a Java project. We created with Maven a vanilla Java project from scratch and we show some output using Log4j. We also played around with Log4j using different log levels and printing the output to different appenders. We changed the appenders configuration and their log levels. We also showed how to use Maven to produce jar files with different content by adding different maven plug-ins.

Note: As commented in this article, it is possible to configure maven to run on your desired IDE like Eclipse, Netbeans or whatever you are using. It is quite easy to do it. For more information about how to integrate maven into eclipse, please visit http://www.eclipse.org/m2e/. Basically, you just need to install the proper eclipse plug in and run the build files from Eclipse.

You can download all examples in this article from the following link: maven_log4j

Dani Buiza

Daniel Gutierrez Diez holds a Master in Computer Science Engineering from the University of Oviedo (Spain) and a Post Grade as Specialist in Foreign Trade from the UNED (Spain). Daniel has been working for different clients and companies in several Java projects as programmer, designer, trainer, consultant and technical lead.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Back to top button