[slf4j-dev] Consolidating the LoggerFactory / A better plugin mechanism

Eric Crahen eric.crahen.lists at gmail.com
Thu Feb 15 22:32:39 CET 2007


Please read the Service API docs.
http://java.sun.com/javase/6/docs/api/java/util/ServiceLoader.html

The benefit over the current mechanism is that you have a type safe plugin
implementation & a clean separation between interface and implementation.

Today, including the LoggerFactory in each implementation jar; it works only
because the author of all the LoggerFactory classes happened to use the same
signature, there was no strong connection - just careful coding. The
compiler is able to help you whereas with the current approach it cannot.

With the Service API, you include and code against LoggerFactory that
delegates to one of several implementations of a LoggerFactoryService
interface. This is the class pImpl idiom. The benefit is that is very easy
to plugin in new service implementations, and its easier to write them since
you are only implementing and interface and not trying to go line for line
with some other file trying to match the correct signature of a class. The
compiler is able to help you whereas with the static binding approach it
cannot.

The current method is called static binding, but that is actually not what
is happening - were it a static binding you would have compiled a reference
to a specific class into the LoggerFactory and that is not what has
happened. This still is a runtime binding.

On 2/15/07, Boris Unckel <boris.unckel.mlg at gmx.net> wrote:
>
> > ......
> >     factory = f;
> >     if(f == null) {
> >       // TODO: Should there be a simple fall back on a System.outlogger?
> >       // TODO: Perhaps the simple loggers is included with SLF4J-API and
> >       // TODO: Is selected always, unless another implementation is
> > provided
> >     }
>
> please do not do that: Put in an RuntimeException with a clear error
> message what is missing.


That is why this is labeled as a TODO, I'm not sure this is the right thing
to do.

Saying this makes someone "too stupid" to use the system is an ignorant
statement that is in no way objective.

Realizing that you have the *option* to deal with this error by defaulting
to a simple logger that prints to stderr. With the current implementation
you have a dead stop and thats it. Its not by design, thats a consequence of
the static binding approach we are using.

Many people place a great deal of value on having a working system out of
the box, and including a fallback to stderr in the case of 0 configuration
(deploying the correct jar *is* a kind of configuration) is one way to get
that. There are various reasons that you might want to do this, and there
are reasons you might not want to do this. I think falling back on the
system.err logger as a default is a sane option if you value a 0
configuration solution. If you haven't read the docs and just want a working
logger this is a good experience, if you haven't read the docs and it
doesn't work outright that is a bad experience. If, like yourself, you have
read the docs and *want* a dead-stop because you take it to mean there was a
deployment error, perhaps you set a system property to prevent the default
from kicking in.

This is especially valuable in a situation where you migrate people away
from log4j. Inevitably, when you are moving people away from what they are
familiar with - there are comparisons. So in the case of migrating people
away from log4j, when they forget to configure the system correctly, there
is a stderr default. If they make the same error in slf4j there is an error
and the program halts, the first thing I'm bound to hear in this situation
is, "Log4j wouldn't have done that". However much you may disagree with
log4j's approach, the comparison is inevitable, and I have first hand
experience to back this claim up.

Again, this is an option that you have, I'm not demanding it

In other words:
> The change of the implementation is done by replacing the implementation
> jar,


Still true for what I proposed!

The whole point of using the Service API is that you provide 1 core jar with
LoggerFactory who loads the services from the additional implementation jar
that you deploy.

Please read the Service API docs.
http://java.sun.com/javase/6/docs/api/java/util/ServiceLoader.html

The next user comes with a proposal: Please put in a property, I want to
> deliver all implementations just in my war, the
> customer should use a property when he wants to use my application.
> Next one: My ugly application server offers "shared" or "common"
> libraries. I have put this jar in path xy and that jar
> in the application, it does not work? Could you offer a diagnostic
> function?


I don't understand your question/statement here; but with the ServiceLoader
API, a customer is able to provide thier own sl4f implementations inside
thier WAR file. As long as you don't deploy slf4j implementations in the
application servers shared classpath, then there is no conflict - again,
this is not different than the current behavior.

If you are talking about someone installing a webserver with all slf4j
implementations's installed and a system property lets a webapps select
which is loaded, then I don't think that makes a whole lot of sense. The
webapp is going to want to configure where the log goes, and you have a
deployment/configuration dependency on some slf4j implementation. This is
closer to a policy decision I don't think is relevant to slf4j.

-- 

- Eric
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://qos.ch/pipermail/slf4j-dev/attachments/20070215/fb82a860/attachment.htm>


More information about the slf4j-dev mailing list