3

I've been pulling my hair out for a week trying to figure out what I'm doing wrong here, including trying to find solutions on this site and through Google, but I think maybe I don't know what I'm searching for. Any help is greatly appreciated!

My goal is to use log4j 1.2.17 in a Maven 2 Java project which I created in Eclipse Kepler. I've recreated the problem from the Maven archetype: quickstart, then added the log4j dependency in pom.xml like so...

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

so that running 'maven package' builds happily...

import org.apache.log4j.Logger;
import org.apache.log4j.LogManager;
import org.apache.log4j.BasicConfigurator;

public class App 
{
    private static Logger logger = 
            LogManager.getLogger( App.class );

    public static void main( String[] args )
    {
        BasicConfigurator.configure();
        logger.debug( "Entering the main class" );

    System.out.println( "Hello World!" );
    }
}

But running 'java -cp target/dc-0.1.jar DC.dc.App' on the command line after a maven build results in this:

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/log4j/LogManager
at DC.dc.App.<clinit>(App.java:14)
Caused by: java.lang.ClassNotFoundException: org.apache.log4j.LogManager
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 1 more

I'm complying with the Maven directory structure and log4j.properties is stored in /src/main/resources. This is the log4j file.

log4j.appender.consoleAppender = org.apache.log4j.ConsoleAppender
log4j.appender.consoleAppender.layout = org.apache.log4j.PatternLayout
log4j.appender.consoleAppender.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
log4j.rootLogger = DEBUG, consoleAppender
Furlong
  • 63
  • 1
  • 1
  • 7

3 Answers3

3

After spelling it out, the solution was much easier to find. I added the following to pom.xml :

<build>
  <plugins>
    <plugin>
      <artifactId>maven-assembly-plugin</artifactId>
      <configuration>
        <archive>
          <manifest>
            <mainClass>fully.qualified.MainClass</mainClass>
          </manifest>
        </archive>
        <descriptorRefs>
          <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
      </configuration>
    </plugin>
  </plugins>
</build>

Then ran mvn clean compile assembly:single Then ran the application java -cp target/dc-0.1-jar-with-dependencies.jar DC.dc.App

And everything was happy. I found the solution at how-can-i-create-an-executable-jar-with-dependencies-using-maven.

Community
  • 1
  • 1
Furlong
  • 63
  • 1
  • 1
  • 7
1

The log4j jar is missing from the java classpath. If you know the location of the log4j jar on your file system you can append it to your -cp classpath argument.

You could look into using the maven-dependency-plugin if you want to copy or bundle your dependencies, refer to the usage. Lots of alternatives discussed on this SO post.

Another way to test your jar project and have maven build the runtime classpath would be to via a maven unit or integration test.

Community
  • 1
  • 1
Drew MacInnis
  • 8,267
  • 1
  • 22
  • 18
  • I receive the proper output when I run the app without maven in Eclipse so it must be a problem with my pom.xml file, but I have the log4j file listed there. if you would, please elaborate on that specifically? I've read through the maven dependency plugin usage page and believe I'm using it correctly, so the problem must be specifically how I'm listing log4j as a plugin in the pom file. – Furlong Aug 29 '13 at 15:33
1

I like the answer provided by Furlong. If it does not work for any reason, you can try this solution below.

I think you need to use the following maven plugin:

This plugin provides the capability to package the artifact in an uber-jar, 
including its dependencies and to shade - 
i.e. rename - the packages of some of the dependencies.

You can find it here

When you have the plugin and execute the following:

mvn package

It will build a so called uberjar. It contains the content of all the dependent jar files as a singe big fat jar file.

So it will contain the org.apache.log4j.LogManager class, too.

Denim Datta
  • 3,740
  • 3
  • 27
  • 53
jseteny
  • 412
  • 1
  • 6
  • 10