I'm quoting Ceki's entire message here because I think he raises a number of
interesting and valid points.

But I think this misinterprets what (in my mind) is the main point of
commons-logging.

One can use commons-logging, as you state, as a implementation-independent
logging wrapper in hopes of reducing the cost of  switching between log4j
and JDK 1.4 (or logkit or whatever else comes along). But as you say, for
some changes the switching cost is already quite low.  (It's not clear to me
that the switching cost between, say, logkit and log4j is similarly low, but
maybe it is, I really don't know.)

But this isn't really the reason commons-logging was created.  Note that
most of the commons components are just that--tiny libraries meant to be
integrated/incorporated into larger frameworks and larger applications.
Some of these components need/want logging capabilities, or at least some
people need/want some components to have logging capabilities.  But it seems
a obtrusive for some tiny library to dictate the logging framework (if any)
that should be used by the larger application that contains it.  So the
component is stuck with a decision between not using logging at all, or
forcing some "standard" logging implementation upon the larger framework,
and the containing application is stuck with either converting everything to
this "standard" logging implementation (and hoping that each component
agrees on what that is) or having a heterogeneous set of logs and logging
implementations.  Search-and-replace code switching isn't really an option
for the commons components, or at least not a terribly good one.

Commons-Logging is meant to provide an alternative solution: create a
facade/adapter around an arbitrary logging API, use it at the common
component level, and allow the user (the containing application) to select
which specific logging implementation (if any) to use.  Then the same binary
works everywhere, and in many (most?) cases, the commons-logging will just
quietly do what you hope it would. (If you've got log4j, it uses it. If
you've got JDK 1.4, it uses that. If all else fails, it doesn't do
anything.)

An arbitrary application or system shouldn't feel compelled nor even
(necessarily) encouraged to use commons-logging. That's not what it's there
for.  It's there to allow the library components to delegate that decision
to the containing application.

 - Rod

-----Original Message-----
From: Ceki G�lc� [mailto:[EMAIL PROTECTED]]
Sent: Tuesday, March 26, 2002 10:11 PM
To: [EMAIL PROTECTED]
Subject: Comments on the commons-logging API



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