Tomcat 5.x, Commons Logging and Log4J

by Dejan Bosanac

First of all, I never use Jakarta Commons Logging (JCL) directly in my applications (Log4J is my tool of choice for logging tasks), but as you probably know many frameworks and libraries do all of their logging through JCL. In most cases you will want to catch some of these log messages, so that you can better monitor your application. For example, you will probably want to log all SQL queries that Hibernate issues, at least in the early development phase, so that you can have a better perspective of what is going on.

I usually don't have a problem with JCL since it finds a Log4J implementation in the classpath, get my configuration and all works fine. Except when it doesn't.

In this particulair case, I had a Spring-Hibernate based web application that I needed to deploy on the Tomcat 5 server. After deploying an application, commons logging couldn't find a log4j implemantation and all logs were redirected to the standard Tomcat log file.

17 Comments

Oran Kelly
2006-08-29 04:08:10
Have you checked out http://www.slf4j.org/ yet? IMHO, it's the way to go for projects that want to use "generic" logging.


oran

Kenneth Lee
2006-08-29 05:08:49
See also http://www.qos.ch/logging/classloader.jsp, in case you haven't come across it.

2006-08-29 05:15:38
This is a known problem for working with IBM WebSphere years ago.


See the following link for the cause and solution:
http://www-1.ibm.com/support/docview.wss?uid=swg27004610


It's also the fact that the server uses JCL itself.


2006-08-29 08:07:15
We put the log4j.jar in WEB-INF/lib and log4j.properties in WEB-INF/classes on Tomcat 5.0.28. Works just fine.
Henrik
2006-08-29 08:45:29
Classloading is a top gotcha for J2EE development. The Tomcat site has a nice description of how it works. Basicly the various 'lib' directories are managed by separate loaders.


The problem arrises for library pairs such as JCL+log4j or Tapestry+HiveMind. As one manipulates the other they need to be loaded with the same class loader.


Your fix may work, but its bad practice to meddle with the containers private jar's. Instead just put commons-logging.jar & log4j.jar in WEB-INF/lib, and it will work just fine. Make sure that they are not in shared/lib or common/lib.


Additionally you need a snipped in a context listener to ensure that JCL releases it's references when you redeploy your webapp. Otherwise you get a memory leak.

Robert Cooper
2006-08-29 20:13:56
I completely sympathize here. JCL and JUL annoy me to no end. Log4J was a perfectly good solution, and even if you accept it as an "implementation" for the other specs, they always have some kind of "ism" that annoys me to no end.
Grzegorz Grzybek
2006-08-29 23:56:07
My solution is to leave commons-logging-api.jar in bin/ folder and to put:
- log4j.jar and commons-logging.jar to common/lib/ folder
- log4j.properties (tomcat logging properties) to common/classes/

Now there are two choices:
- when web app doesn't have commons-logging.jar in WEB-INF/lib, it uses server-wide JCL+Log4J configuration
- when web app wants to use its own JCL config, it has to have commons-logging.jar, log4j.jar in WEB-INF/lib AND log4j.xml in WEB-INF/classes.

This configuration uses the fact, that Log4J static{} configuration first looks up log4j.xml and then log4j.properties.

In my opinion this is better approach then to use e.g. Spring's Log4jConfigListener, because it works immediately after creating web-app class loader by Tomcat.

Grzegorz Grzybek

Jilles van Gurp
2006-08-29 23:57:15
The whole point of commons.logging is that it doesn't create an unnecessary dependency on log4j or the jdk logging api. You should distinguish between functionality for logging messages and for configuring the logging. These are two things. Use commons.logging for the first and whatever suits best you for the latter.


Personally I get really annoyed when I need to use some library or component that insists on using log4j because it breaks the jdk logging api configuration I have set up in my container. In general this is not an issue because libraries shouldn't log anything (at least not above FINE level) but sadly some do insist on spoiling my logs with pointless information and then make matters worse by forcefeeding me log4j. E.g. hibernate lacks a STFU option and seems to be bundled with log4j.


What most log4j users don't understand is that logging configuration should be taken care of at the container level and not at the library or application level. In other words, if you are depending on log4j at the application level you are probably messing with stuff that is better done elsewhere. Your application is a source and not a consumer of logging information.

bluedolphincp
2006-10-09 20:29:58
It seems putting commons-logging.jar and log4j.jar in your-webapp/WEB-INF/lib and putting log4j.xml in your-webbapp/WEB-INF/classes is a recommended way. Yet i encounted a problem.


i created log/netmsg folder under my-webapp/WEB-INF, and here is part of my log4j.xml:


I intended to log to my-webapp/WEB-INF/log/netmsg/msgserver.log.


When i started tomcat, it throws exception:
log4j:ERROR setFile(null,true) call failed.
java.io.FileNotFoundException: ..\log\netmsg\msgserver.lo
But if i created log/netmsg folder under tomcat-home folder, this exception won't be thrown. So it seems like commons-logging-api.jar in the bin folder will try to read my log4j.xml, and configure the logging setting according to it.


obvious it's not what i want. can somebody please help me?

Victor Ott
2007-01-29 13:29:48
Dejan, you saved my day!


Situation: Tomcat 5.5.20, log4j.jar only in our WEB-INF/lib. Today a new application component required commons-logging-1.1.jar in WEB-INF/lib, so we added it => low level Tomcat debug messages everywhere, immediately suffocating any useful application output. I knew it's about JCL, but haven't even dreamed of replacing the original bin\commons-logging-api.jar (1.0.4) to our version (1.1).


It helped, Thanks!

Venkat
2007-03-22 08:18:23
Hi ,


i have application in tomcat clarityweb/web-inf/lib i have all jar i have removed log4j.properties from my tomcat folder even though it is picking up from some other place even i have searched the file through out the folder but no use , its picking up by some other place am unable to notice that culprit. plz hgelp me out from this


thanks
venkat

trama
2007-04-11 09:31:43
Ich erklare meinen Freunden uber diese Seite. Interessieren!
imparare
2007-04-15 01:37:34
Interesting comments.. :D
Fan
2007-12-01 19:02:14
Same problem when deploying axis2 into Tomcat 5.5.25. Axis2 did not pickup any log4j stuff which it has a denpendy on. I have actually tried the same tactics of renaming my commons-logging-1.1.jar into commons-logging.api.jar and placed it under Tomcat-5.5.25\bin folder. But the axis2 did not work out for me. Any suggestions. (JDK1.6_03, Axis2 1.3)
Andriy Zhurba
2008-02-05 03:04:30
it works with log4j as described in the Apache Tomcat documentation. My problem I have to fight with is going further. We use our own logging framework, which is distributed as a component and resides in a web app. We have upgraded to the new FOP 0.94, which now uses commons logging. The challenge is to catch the log output from FOP and redirect it to our own logger - and make it on the application level. Attempts to set the logging implementation in the app fails with "Call too late" error, because Tomcat configures commons logging on start-up. I would not be willing to place own components in common\libs as, how logging is performed is a matter of the web app. How would you guys solve the problem?
Mark
2008-07-02 12:43:33
Thank you!
Debadatta
2008-07-03 03:30:18
I have tried the steps. Now i am able to start the server. However i am not able to see the log messages in the console, as it is giving a warning message as below.


log4j:WARN No appenders could be found for logger (org.apache.catalina.startup.ClassLoaderFactory).
log4j:WARN Please initialize the log4j system properly.


I have kept my log4j.properties under commons/classes folder. Please let me know if i am missing something.


Regards..
Debadatta