Hi,
This has probably cropped up before? Correct me if I'm wrong (I'm always happy to get an earful about nonexisting problems) but...:
The gist:
"In some (most?) cases you cannot use a 'log4j.properties' file placed in your web application's WEB-INF/classes directory"
Who are you quoting? This is obviously wrong unless you are using a server that doesn't implement servlet-spec recommended class loading behavior such as is the default in JBoss (but configurable). Most every version of Tomcat does implement this class loading behavior (contrary to normal Java2 class loading behavior). As such, putting log4j.properties in WEB-INF/classes should work just fine..... more below....
...this goes counter to the Log4J's documentation, which says:
"The default log4j initialization is particularly useful in web-server environments. Under Tomcat 3.x and 4.x, you should place the log4j.properties under the WEB-INF/classes directory of your web-applications. Log4j will find the properties file and initialize itself. This is easy to do and it works."
So why doesn't it work?
Well, it works fine....as long as you *also* add log4j.jar to WEB-INF/lib. I bet you didn't do that, did you. :-)
-> When Tomcat starts up and one of its own classes and/or some classes in its "common" or "shared" classloaders use log4j (possibly indirectly through commons-logging), then:
-> Tomcat will initialize log4j logging through the relevant classloaders (named "StandardClassloader"). Unfortunately, whatever is in a Webapp is completely invisible to such a classloader. Thus, the file log4.properties in the WEB-INF/classes directory is irrelevant at this point.
True, WEB-INF/classes/log4j.properties is irrelevant to common/lib/log4j.jar. However, it is *entirely* relevant to WEB-INF/lib/log4j.jar. Because of the class loading behavior of webapps, any webapp with log4j.jar in its own WEB-INF/lib will run its default logger repository in an entirely self-contained environment completely separated from that of the server or other apps.
-> At the first request of a Servlet, the WebappClassloader could in principle start log4j initialization using the log4j.properties file because it is visible to it. Unfortunately, at that moment, the org.apache.log4j.LogManager class has already been loaded, its static initializer executed. And thus, initialization will not be done again.
This can be easily seen by switching LogLog logging on and by adding some test code to a servlet.
On Tomcat startup, we get the details of the classloaders. They are all called 'StandardClassLoader' and the last message is:
log4j: Trying to find [log4j.properties] using ClassLoader.getSystemResource().
log4j: Could not find resource: [null].
log4j:WARN No appenders could be found for logger (org.apache.commons.digester.Digester).
log4j:WARN Please initialize the log4j system properly.
Starting service Tomcat-Standalone
Apache Tomcat/4.1.24
As you can see, "org.apache.commons.digester.Digester" caused premature initialization.
The servlet, containing this code (essentially the same as the one called by LogManager):
Method method = Thread.class.getMethod("getContextClassLoader", null); ClassLoader ccl = (ClassLoader) method.invoke(Thread.currentThread(), null); URL url = ccl.getResource("log4j.properties"); LogLog.debug(url.toString() + " using " + ccl + ".");
will give this output:
log4j: setFile called: velocity.log, true
log4j: setFile ended
log4j: file:/C:/eclipse/workspace/log4jtest/WEB-INF/classes/log4j.properties using WebappClassLoader
available:
delegate: false
repositories:
/WEB-INF/classes/
required:
----------> Parent Classloader:
StandardClassLoader
available:
delegate: true
.....
I don't see that this problem is in any way solvable. Also, should it be? Wouldn't log-configuration from the webapp give the webapp too much power over Tomcat? It probably would.
If you put log4j.jar in common/lib, then add a log4j.properties or log4j.xml to common/classes. commons-logging, which is included in Tomcat, will use log4j preferentially over other logging api's if available. You will need to provide a config file for log4j to avoid the log4j warning. I simply provide a config file with a <root> logger using a console appender and set the level to INFO for normal use. Then each webapp also gets its own config file and log4j.jar.....or, I simply use a repository selector, in which case I can have a single log4j.jar in common/lib and still have each webapp logging in its own distinct logger repository, each with its own config file. See....
http://nagoya.apache.org/wiki/apachewiki.cgi?Log4JProjectPages/AppContainerLogging
The solution is of course to move the 'log4j.properties' file higher: ask the friendly BOFH to move it into the 'common-classes' for example. But that's another story.
No need. This is easily solved as explained above.
Best regards,
-- David Tonhofer M-PLIFY S.A.
Jake
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
