Tomcat and Log4jConfigListener don't mix

At least not if you want to load your log4j.properties with classpath:log4j.properties. What happens is that Tomcat internally uses commons-logging, which finds log4j on your classpath and thinks "Hey, I'll use log4j". Log4j then finds your log4j.properties and reads it before Log4jConfigListener ever gets instantiated.

The result?
log4j:ERROR setFile(null,true) call failed.
java.io.FileNotFoundException: /logs/spring.log (No such file or directory)
at java.io.FileOutputStream.openAppend(Native Method)
at java.io.FileOutputStream.(FileOutputStream.java:177)
at java.io.FileOutputStream.(FileOutputStream.java:102)
at org.apache.log4j.FileAppender.setFile(FileAppender.java:289)
at org.apache.log4j.FileAppender.activateOptions(FileAppender.java:163)
at org.apache.log4j.config.PropertySetter.activate(PropertySetter.java:256)
at org.apache.log4j.config.PropertySetter.setProperties(PropertySetter.java:132)
No worries, though; the application comes up just fine, and logs where you expect... If you're lucky and don't have a security manager.

With a security manager, you get a nice, fatal AccessControlException.


The fix is simple: move log4j.properties away from the classpath root, e.g. into /WEB-INF.

No comments: