tags:

views:

54

answers:

1

We are bundling Log4j 1.2.15 with our plain Swing application and load our own properties file from the file system at startup:

import org.apache.log4j.*;

...
System.setProperty("log4j.defaultInitOverride", "true");
...
File log4jPropertiesFile = ...
PropertyConfigurator.configure(log4jPropertiesFile.getAbsolutePath());
...

In logs we are getting from customers the output does not look like we have defined in the properties file and we are sure that not more than a very small minority edited the file themself.

Could it be that Log4j somehow overrides our settings if there is another configuration file somewhere present on the user's machine available? How we can prevent using that?

+3  A: 

There's a whole paragraph in the docs detailing how Log4j initializes itself:

The exact default initialization algorithm is defined as follows:

  1. Setting the log4j.defaultInitOverride system property to any other value then "false" will cause log4j to skip the default initialization procedure (this procedure).
  2. Set the resource string variable to the value of the log4j.configuration system property. The preferred way to specify the default initialization file is through the log4j.configuration system property. In case the system property log4j.configuration is not defined, then set the string variable resource to its default value "log4j.properties".
  3. Attempt to convert the resource variable to a URL.
  4. If the resource variable cannot be converted to a URL, for example due to a MalformedURLException, then search for the resource from the classpath by calling org.apache.log4j.helpers.Loader.getResource(resource, Logger.class) which returns a URL. Note that the string "log4j.properties" constitutes a malformed URL. See Loader.getResource(java.lang.String) for the list of searched locations.
  5. If no URL could not be found, abort default initialization. Otherwise, configure log4j from the URL. The PropertyConfigurator will be used to parse the URL to configure log4j unless the URL ends with the ".xml" extension, in which case the DOMConfigurator will be used. You can optionaly specify a custom configurator. The value of the log4j.configuratorClass system property is taken as the fully qualified class name of your custom configurator. The custom configurator you specify must implement the Configurator interface.

This is, admittedly, confusing as hell to understand. Basically, the simplest thing you can do is put log4j.properties on the classpath of your app, and it will be found. Everything else is... finesse. Personally, I sometimes explicitly call the BasicConfigurator class in my main, sometimes configuring (hard coded) some of the stuff that might otherwise appear in a file... whatever my circumstances call for. You can initialize log4j completely programmatically, and that would kind of make the question of the configuration file moot. Though it would also make your configuration completely less flexible.

Carl Smotricz
Correct - I would given the same answer +1
Romain Hippeau
Thanks for answering, Carl. We don't add the `log4j.properties` to the classpath, because the install location usually is read-only and I don't feel good adding our application's settings directory (where the log4j.properties is located) to the classpath.
mklhmnn
I notice a discrepancy between your code excerpt and the log4j documentation: `PropertyConfigurator` doesn't seem to have a `configure(File)` method! Can you explain this, and maybe give a little more detail?
Carl Smotricz
Would you be OK with your customers not being able to fiddle with the `log4j.properties` file at all? Then put it into the root of your `.jar` file! That's both on the classpath and pretty inaccessible.
Carl Smotricz
This would not be OK, because sometimes we have to tell customers to add one line or another to the file to increase logging details.
mklhmnn
@mklhmnn Then why not create an API for the client, which will alter the log4j configuration at runtime? Or will override the defaults in the log4j.xml that resides in the jar using command line parameters that your application will define?
Maxim Veksler
Command line parameters? Try to do that on OS X for an JavaApplicationStub application...
mklhmnn