Fork me on GitHub

October 30, 2009

Log4J Logging without Log4J

Post moved to

As time goes by, ridiculous challenges might arise to a J2EE developer. This one starts with a third party web application that needed to be part of an enterprise application (running on WebLogic). The war was closed source, with business classes obfuscated in a jar inside WEB-INF/lib, and as many out there using LOG4J as it's logging facility (with commons-logging as a cherry on top due to some dependencies).
So far so good, now what if the root logger name is chosen unwisely and it interferes with your application server's logger categories.

At first the solution seemed obvious, the WEB-INF classes and libraries should be loaded first by the servlet container, thus having a separate LOG4J configuration created from the web application's class path. WebLogic 10.3 likes to prefer its own system jars by default, thus an (optional) step for the lucky ones :

That was easy, but what if ... LOG4J's runtime reconfiguration ("watch dog") is involved and You can't or don't want to turn it off. Well than this might just get messy, especially if other applications within the same ear, or the server itself, use LOG4J for logging.

I won't go into any more details here, some things tend to get a little noisy in the Java world.
Anyway, I had no meaningful option left than to get somehow rid of LOG4J from the war, obviously that would break the application wouldn't it ? Sure, but what if one could emulate the org.apache.log4j.Logger API.
The one here wouldn't be me, I do prefer others doing the dirty work, in this case Simple Logging Facade for Java (SLF4J) to the rescue !

The SLF4J distribution contains several jars, here's what we need :
  • slf4j-api.jar - SLF4J's own logging API
  • log4j-over-slf4j.jar - log4j compatible API that delegates to SLF4J
  • jcl-over-slf4j.jar - (optional) commons-logging compatible API that delegates to SLF4J
Don't forget to delete log4j.jar and commons-logging.jar, once the SLF4J jars were added.
Finally, we should pick a SLF4J logging implementation, I've chosen LOGBack here, as I wasn't into rewriting the by hand, thus add these :
  • logback-core.jar
  • logback-classic.jar
Once all those fancy new jars are in place (WEB-INF/lib) and configuration was translated into logback.xml (save it into WEB-INF/classes), restart and bone appetite !

Of course, it wouldn't be a WebLogic if it went smoothly, but don't worry those scary red system console outputs :

SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [zip:/weblogic/domains/.../war/WEB-INF/lib/logback-classic-0.9.17.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [zip:/weblogic/domains/.../war/WEB-INF/lib/logback-classic-0.9.17.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See for an explanation.

are caused by a ClassLoader bug reported here, but it's not fatal and SLF4J can live with it.

No comments:

Post a Comment