Java – log4j.xml in current directory not found

javalog4j

I have a runnable jar file.

I have a log4j.xml file sitting in the same directory.

My classpath includes "."

env |grep CLASS
CLASSPATH=.;C:\Program Files (x86)\Java\jre6\lib\ext\QTJava.zip

But when I run java -jar myrunnable.jar I get the following message.

log4j:WARN No appenders could be found for logger (org.apache.commons.configuration.PropertiesConfiguration).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.

Oddly enough, if I wrap that jar in a launch4j executable, it sees the log4j.xml file and uses it.

I did go to the FAQ page mentioned in the error message. It reads as follows:

This occurs when the default configuration files log4j.properties and log4j.xml can not be found and the application performs no explicit configuration. log4j uses Thread.getContextClassLoader().getResource() to locate the default configuration files and does not directly check the file system. Knowing the appropriate location to place log4j.properties or log4j.xml requires understanding the search strategy of the class loader in use.

I am at a bit of a loss in understanding what I need to do in order for my runnable jar to see the log4j.xml short of adding the -Dlog4j.configuration=file:\\\\my\crazy\long\path\to\my\eclipse\workspace\target\directory\log4j.xml to the command line which is a PITA to type out.

If I try something like java -Dlog4j.debug -Dlog4j.configuration=.\\log4j.xml -jar myrunnable.jar

log4j: Trying to find [.\\log4j.xml] using context classloader sun.misc.Launcher $AppClassLoader@265f00f9.
log4j: Trying to find [.\\log4j.xml] using sun.misc.Launcher$AppClassLoader@265f00f9 class loader.
log4j: Trying to find [.\\log4j.xml] using ClassLoader.getSystemResource().
log4j: Could not find resource: [.\\log4j.xml].

same results for different combinations log4j.xml and ./log4j.xml

If it makes a difference, this is windows 7/java 7/64 bit using log4j via the standard slf4j-log4j binding.

Additional notes:

  • tried java -cp . unsuccessfully
  • tried java -cp .\\ as well
  • examined jar file META-INF\MANIFEST.MF and there is no classpath entry
  • this particular jar was generated by maven using the maven shade plugin.

Solution (sort of)

Per Dave Newton's answer below, I changed my MANIFEST.MF file to include the following line:

Class-Path: ./

With this in place, my log4j.xml file was seen appropriately. I'm using the Maven Shade Plugin to build the jar file, so adding the Class-Path entry was a matter of configuring the ManifestResourceTransformer.

<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
  <mainClass>my.runnable.Class</mainClass>
  <manifestEntries>
    <Class-Path>./</Class-Path>
  </manifestEntries>
</transformer>

I say "Sort of" resolved because although it does output logging information configured from my desired log4j.xml file, it means hardcoding that path into my jar and anybody using my jar has to have log4j.xml or log4j.properties in the installation directory. I wish there was a better solution that provided the standard and expected results (where the log4j.xml/log4j.properties file could be placed anywhere on your classpath), but with all the searching I've done today it does not seem to be the case.

I think I've run into yet another one of those frustrating issues where Java does not behave intuitively and anything beyond a very simple explanation of why it behaves the way it does involves reading an entire book.

Best Answer

When you use -jar the classpath is ignored.

You could add the config file to your manifest's Class-Path entry, but consider providing the path. It probably needs to be a file resource otherwise it'll probably try to find it on the jar's classpath value.