Hello all,

Given that log4j is such a low-level library, most organizations are
suspicious to tie their code to log4j, especially considering the new
logging API in JDK 1.4.

Before going forward, it is appropriate to mention that these two APIs
are very similar.  The classical usage pattern for log4j is:

---------------------------------------------------------------

import org.apache.log4j.Logger;

public class MyClass {
   final static Logger logger = Logger.getLogger("some.name");

    public void foo1() {
      logger.debug("Hello world.");
    }

    public void foo2() {
      logger.info("Another message.");
      logger.error("Stop that!", new Exception("The earth is getting 
warmer."));
    }
}
---------------------------------------------------------------

As you are well aware by now, one of the important benefits of log4j
is that it can be configured at run time using configuration scripts.
You can have hundreds or thousands of log statement but only one or
two lines of code to configure log4j.

The usage pattern for the JDK 1.4 logging API is:

---------------------------------------------------------------
import java.util.logging.Logger;

public class MyClass {
    final static Logger logger = Logger.getLogger("test");

    public void foo1() {
      logger.debug("Hello world.");
    }

    public void foo2() {
      logger.info("Another message.");
      logger.error("Stop that!", new Exception("The earth is getting 
warmer."));
    }
}
---------------------------------------------------------------

Do you notice anything similar? The JDK 1.4 logging API also admits
configuration scripts. Being part of the JDK, the common guess that
this API will supplant log4j some time in the future.

It is not so easy to write a complete logging API. Users
come to realize they need the features present in log4j but absent in
JDK 1.4 logging API.  Moreover, log4j runs with JDK 1.1 or later whereas
the JDK 1.4 logging API, requires, well, JDK 1.4.  Most users can't
afford to tie their code to JDK 1.4.

But they need logging and they need it now. A common strategy for
protecting against future changes and at the same time to benefit from
existing log4j features is to *wrap* log4j with a custom logging
API. Log4j actually has support to facilitate such wrappers.

It turns out that such wrappers are not that trivial to write. I frequently
receive email where a user runs into a problem with their wrapper and
requests help. More often than not, these wrappers are of poor quality
such that the cost of inactive (or disabled) logging statements is
multiplied by a factor of 1'000.

Of course, not all wrappers are of poor quality. For example, the
commons-logging API is rather well implemented. Obviously, there is
still a cost for the wrapping but it won't be of a huge factor.

The commons-logging API will try to use the JDK 1.4 API if present, or
the log4j API. The *current* preference is log4j I believe. Neat!

Now, it just happens that the part where most users have difficulty is the
initialization of the log4j API. Where should the log4j.jar go? Where
do I put the log4j.properties files?  Can I have different
web-applications have different log4j configurations?  How do I
initialize log4j in an application server?  Although there is ample
literature on the subject, much confusion remains.

The commons-logging API as it wraps multiple logging APIs such
as Avalon's LogKit, log4j, JDK 1.4 has its own "discovery process".
Things were confusing before, they will be even more when
commons-logging API enters "common" usage. With some effort, it might
start making sense to you. However, your users will not show the same
perseverance nor enthusiasm.

There will be also unexpected interactions between log4j and the
commons-logging API. For example, log4j 1.2alpha1 through alpha4 had a
very subtle bug which caused client code compiled with log4j version
1.1.3 to throw exceptions when ran with log4j 1.2alpha. Inversely,
code compiled with 1.2alpha would crash when ran using log4j 1.1.3.
This problem was fixed in log4j beta.

It is now sufficient for client code to be compiled with 1.1.x and to
run with 1.2 beta without problems and vice versa. Of course if
commons-logging compiled with log4j 1.2alpha the problem would be
sticky. It would not go away by compiling client code but only by replacing
the commons-logging API.

In the recent weeks I have also started to receive disturbing bug reports
where components using commons-logging API behave strangely.

http://nagoya.apache.org/bugzilla/show_bug.cgi?id=7484
http://nagoya.apache.org/bugzilla/show_bug.cgi?id=6764

I suspect that these problems will only worsen in the future. The
commons-logging developers will suspect a log4j bug and we will
suspect a commons-logging API bug. By increasing the number of
components required for logging you have doubled the probability of
bugs while the difficulty of resolving them has increased by a higher
multiple.

Remember that the initial goal of introducing a wrapper API was to
protect our coding investment. If for whatever reason you decide to
drop log4j in favor of JDK 1.4 (or the other way around) a simple
string search-and-replace operation will do. Most IDEs support
search-and-replace operations on multiple files. All you have to do is
to replace "import org.apache.log4j.Logger" with "import
java.util.logging.Logger".

I believe the saying is "a penny today is worth a promise of a nickel
tomorrow." By adopting a wrapper API, you are trading "a nickel of
today for a promise of a penny tomorrow."

As long as you are aware that the supposedly free-lunch may turn out
to be an expensive and not so tasty meal after all...


--
Ceki
My link of the month: http://java.sun.com/aboutJava/standardization/


--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to