4

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.

Steve Kallestad
  • 3,484
  • 2
  • 23
  • 31

2 Answers2

2

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.

Dave Newton
  • 158,873
  • 26
  • 254
  • 302
  • But don't people distribute jars all the time where people run them via java -jar and have log output configured by log4j.xml or log4j.properties? And can't those people put the configuration file anywhere on their own user defined classpath? – Steve Kallestad Jun 20 '13 at 00:20
1

For Eclipse testing in Maven the easiest thing I've found to do is to put the log4j.xml in src/test/resources. It will be added to the classpath when running unit tests, etc. When we actually install our application at a customer site we place the file in /etc/... and specify it with -Dlog4j.configuration.

My best guess as to why the current directory part isn't working for you is that Eclipse is probably setting the current directory to something other than what you think it is. Try following the instructions here to print the current working directory and check it matches what you think.

UPDATE: Almost forgot. When you specify -jar the classpath options (-cp -classpath) are ignored.

-jar

Execute a program encapsulated in a JAR file. The first argument is the name of a JAR file instead of a startup class name. In order for this option to work, the manifest of the JAR file must contain a line of the form Main-Class: classname. Here, classname identifies the class having the public static void main(String[] args) method that serves as your application's starting point. See the Jar tool reference page and the Jar trail of the Java Tutorial for information about working with Jar files and Jar-file manifests. When you use this option, the JAR file is the source of all user classes, and other user class path settings are ignored.

Community
  • 1
  • 1
Pace
  • 41,875
  • 13
  • 113
  • 156
  • I've done that for my testing up to this point, but a bug popped up that doesn't show up while testing within eclipse. This is happening outside of eclipse from a command prompt. Within eclipse, I have no problem with log output strangely enough. – Steve Kallestad Jun 20 '13 at 00:23