čtvrtek 21. května 2009

Java logging.properties in the Classpath

Java utils logging (JUL) has been included in Java since version 1.4. Since then, one does not need to ship an extra JAR (log4j) with an application. It is possible to initialize JUL by a standard properties file logging.properties. I do not like, that
  • the user of the application has to provide a "hard to remember" parameter -Djava.util.logging.config.file=logging.properties to the JRE
  • and some default logging.properties cannot be packed into the JAR of the application.
Compare it with a very flexible initialization of JNDI:
The JNDI automatically reads the application resource files from all components in the applications' classpaths and JAVA_HOME/lib/jndi.properties, ...

I have solved this issues with just a few lines of code. The code has to be invoked before the logging is first used in the application. So, the most suitable place for this code is in the static constructor (initializer) of the class, where is main() method. Then you may pack a default logging.properties file into the JAR with your application (the same JAR where is the class with this code). And the user may still use the -Djava.util.logging.config.file=logging.properties property to use her/his own logging configuration.
/**
 * Should be called before the first use of the JDK logging. The best place is
 * in the static initializer of the class, which has the {@code main()} method.
 */
static {
  String file = System.getProperty("java.util.logging.config.file");
  if (loggingfile == null || loggingfile.isEmpty()) {
    URL url = null;
    try {
      url = MyClass.class.getClassLoader().getResource("logging.properties");
      if (url == null) {
        System.err.println("Cannot find logging.properties.");
      } else {
      LogManager.getLogManager().readConfiguration(url.openStream());
      }
    } catch (Exception e) {
    System.err.println("Error reading logging.properties from '" + url + "': " + e);
    }
  }
}

public static void main(String[] args) { ... }
If you need something more robust, then look into the Java sources for the aforementioned JNDI initialization :-).