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]>
