|
If you've seen a warning message like the following, this document will be of interest to you.
/***************************************************************************\ * * * Protomatter Syslog Classloader Warning * * -------------------------------------- * * * * Protomatter Syslog has been loaded by a classloader other than * * the system classloader. This indicates that the Syslog libraries * * are not in the system CLASSPATH. Usually this is because Syslog * * is being used in an application server and the Syslog libraries * * are in the "lib" directory for a WebApp or EAR, etc. * * * * ClassLoader: sun.misc.Launcher$AppClassLoader@7fdcde * * * * Syslog may not work as you might expect if it is not loaded by * * the system classloader. Under some circumstances, users may want * * to take advantage of features of this kind of configuration. If * * this is the case, you can disable this warning message by setting * * the "Syslog.classloader.warning" system property to "off". In * * most cases, though, you don't want to do that. * * * * For more information on this behavior and the logic behind it, * * please see the documentation at the following address: * * * * http://protomatter.sourceforge.net/1.1.7/javadoc/ * * com/protomatter/syslog/classloader-warning.html * * * \**************************************************************************/ |
So, what's the deal? Fundamentally, the issue is that static member variables in Java are only really unique within their classloader and any "child" classloaders of that loader.
Syslog keeps its configuration information in static member variables on the Syslog class, meaning that Syslog is what is known as a Singleton (see the book Design Patterns by Gamma, et al).
What can happen is that multiple copies of the Syslog classes can get loaded, each with its own configuration, etc. Let's say that the application server you're using uses a hierarchy of classloaders to do its job. For instance, it could have one loader for each EAR being deployed, and then one child loader for each EJB jar and each WAR being deployed inside that EAR. If Syslog appears in the lib directory of more than one WAR file, and they are all loading the same configuration, you can get corrupted log files.
Generally, what people want is one Syslog instance, with one grand-unified configuration file for everything. If this is the case, you want to make sure that Syslog is loaded from the system classloader, so that there is only one instance of Syslog's "guts" for the entire JVM.
That being said, sometimes it pays to be fancy. If you're a hosting provider (or just a large IT shop), it may make sense to allow each application being hosted by the server to manage its own Syslog configuration. This will also ensure that there is no "cross talk" between applications in log files. To accomplish this, you need to make sure that a different copy of Syslog is loaded by each EAR.
The Jar file manifest specification for JDK 1.3 (see JDK 1.3 JavaDoc) includes the Class-Path: manifest attribute. This is a common way of addressing physical packaging issues with 3rd party software in J2EE applications. You may want to read EJB 2 and J2EE Packaging or part two of the series from OnJava.com by Tyler Jewell.
To use this feature, simply add the following to the META-INF/MANIFEST.MF file in the EAR that is being deployed:
Class-Path: lib/protomatter-1.1.7.jar |
Then place the protomatter-1.1.7.jar file into the lib directory directly under the root of the EAR file. This will instruct the server to include the that file in the CLASSPATH of things loaded for that EAR file.
At this point, we're ready to get Syslog configured for each of those EAR apps being deployed. The most server-agnostic method of doing this is by using the SyslogInitServlet to configure syslog when a WebApp is "booted" by the web container.
In your particular WebApp or in a new one, follow the instuctions in this JavaDoc to configure the WebApp so that the SyslogInitServlet is registered and configured to initialize when the WebApp is loaded by the container.
Now what we've got is a different instance of Syslog for each EAR being loaded by the app server. Each application can maintain its own Syslog configuration and there will never be any cross-talk on log channels between those applications. Care should be taken to make sure that the configurations aren't writing to the same log files, etc, or file corruption and general confusion can ensue.
There are roumers that a future release of the J2EE specification will include some kind of startup/shutdown hook in EAR file application.xml descriptors. That would remove the need for the (somewhat hackish) SyslogInitServlet to configure syslog. At that point, support for that feature would be integrated into Syslog.