tags:

views:

40

answers:

2

My java application uses log4j for logging. Using ant the project builds successfully, but I am unable to run it. The error I get is

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/logging/Log
.........
Caused by: java.lang.ClassNotFoundException: org.apache.commons.logging.Log

My classpath contains the log4j jar.

[echo] ..../apache-log4j-1.2.15/log4j-1.2.15.jar: .....

My ant version is 1.7.1. What am I missing?

[Edit] My application is referencing another project which required the commons logging jar. So I tried creating an executable jar of the referenced project so that all the dependencies are carried over. The ant task to create the executable jar is as follows:

<target name="executablejar" depends="compile">
        <delete file="${dist}/app.jar" />

        <javac debug="true" srcdir="${src}" destdir="${classes}" classpath="${javac.classpath}"/>

        <copy todir="classes" flatten="true">
            <path>
                  <pathelement path="${javac.classpath}"/>
                </path>
        </copy>
        <jar jarfile="${dist}/app.jar" basedir="${classes}" />
</target>

However the error still persists. Am I creating the executable jar correctly?

A: 

You'll have add apache commons logging to your classpath. The package org.apache.commons.logging is not part of log4j.

Andreas_D
@Andreas_D: yes, please see the edited question.
athena
+1  A: 

You may have inadvertently imported a class from org.apache.commons.logging and now, as you might expect, the JVM is expecting to find the class definition on your classpath at runtime.

I'd recommend looking for usages of the commons-logging package in your code.

RonU
@RonU: Yes. Please see the edited question
athena
@athena You say you created a jar of the supporting project, but that does not bundle up and bring along that project's dependencies (these are called transitive dependencies). If your other project uses Commons-Logging, and you in turn must use this supporting project, then when executing, you're going to need to have the Commons-Logging jar on the classpath.
RonU
@RonU: I thought that creating an executable jar would bundle up *all* the dependencies. Then is there a way to bundle up *all* the dependencies and create jar?
athena
@athena An executable jar really just means there is a Main-Class entry in the manifest, meaning you can invoke the jar without having to specify a startup class. Traditionally, a J2SE app distribution is an archive (like a zip) containing the application jar you developed and a supporting library folder with jars on which your app depends. Often there's also a script to kick things off and set up the classpath. Jars themselves cannot actually nest other jars, however.
RonU
@RonU: Thanks for the clarification. Can you give me pointers to help create such a script? Is it better than just including the project jar and all its dependencies(jars) in the classpath in ant?
athena
Let's make an important distinction between your *compile-time* classpath and *runtime* classpath. At compile-time, you're using Ant to build, and you've told it what jars you need to compile. At runtime, by some means (like a script), you have to set the classpath for your invocation of the JVM so it has class definitions to load when your code references third-party classes.
RonU
I don't really have a good tutorial handy, I'm afraid, but I recommend doing some research to understand the classpath. See http://java.sun.com/developer/Books/javaprogramming/JAR/basics/run.html, which talks about invoking Java and setting the classpath. Depending on your platform, you can script this up (Windows BAT file, Linux/Solaris shell script, etc.). Java Web Start is also a popular launching mechanism worth reading about.
RonU