On 10.10.2012 15:42, Mark Struberg wrote:

Hi Mark,

> Hi!

> Here are a few basic observations about slf4j.  slf4j really rocks for
> end user applications, but when it comes to deep container core stuff
> you must take care about classloader clashes much more than within an
> end-user project. We just don't know what a user defined in his
> <plugin> sections...
>
> If we like to use slf4j as maven logging api and export it in the core
> classloader then we might probably face the following problematic
> spots
>
> 1.) slf4j-api <=1.5 and >=1.6 are not fully binary compatible
> afaik. Ceki, is this correct? Afair there have been a few minor
> changes between those versions. They do not always cause problems but
> I've seen those in the wild already.

The method signatures of classes in the org.slf4j package such as
Logger, LoggerFactory, Marker, MDC, etc. are the same since 2005.
Client code which only imports the Logger, LoggerFactory, Marker, MDC
classes will run fine with any version of slf4j-api, 1.0.x onwards.

SLF4J bindings such as slf4j-simple, slf4j-log4j etc import classes
from the org.slf4j.spi and org.slf4j.helpers packages which offer
lesser guarantees with respect to stability of method signatures. For
instance, as you mentioned, a method signature in the
org.slf4j.spi.LocationAwareLogger class changed between 1.5 and
1.6. Assuming a "major.minor.maintenance" versioning scheme, this
means that the minor version of the SLF4J binding must match that of
the slf4j-api. The "maintenance" number is unimportant.

As a client only importing from the org.slf4j package, you don't have
to worry about the version of the slf4j-api with which some other
dependency was compiled with.

> 2.) if you use slf4j, then ALL the funnels and logging backends must
> have the very same version number than the slf4j-api. Otherwise you
> are pretty much doomed. Ceki, is this correct as well?

I would not go as far as "doomed". For example, the following
combination will work fine: slf4j-api-1.7.2.jar,
sfl4j-simple-1.6.5.jar, log4j-over-slf4j-1.6.2.jar,
jcl-ocer-slf4j-1.7.1.jar and jul-to-slf4j-1.6.0.jar. In other words,
you can freely mix artifacts in the 1.6.x and 1.7.x families.

> 3.) if we would provide a sfl4j funnel (e.g. log4j-over-slf4j) and a
> plugin brings his own log4j.jar then we will have class path clashes
> as well.

There is no need for Maven to provide slf4j bridges (or funnels as you
say) to plugins, is there?

> I'm happy if someone tells me the above observations are wrong and I
> just failed to setup the stuff properly. If not, then we still can use
> slf4j for maven BUT we need to isolate it really well via
> classworlds. And of course that would mean that we miss maven logging
> for those 'isolated' plugins, right?

Most plugins should be able to see org.slf4j.* classes exported by
maven-core.  For the rare few plug-ins which declare their own version
of slf4j artifacts, isolating the org.slf4j.* classes makes
sense. Such isolation would serve two purposes. 1) it would avoid any
version mismatch problem 2) it would isolate the plugin's logging from
the logging in Maven core probably as intended by the plugin author.

> I'll first sum up the problems which will occur if the upper
> assumptions are correct.

> ad 1.) maven provides slf4j-api-1.6 but a plugin uses slf4j-api-1.5,
> 1.4, etc  This might cause class cast exceptions ("Cannot cast class
> Logger to class Logger") by having different versions of the slf4j-api
> classes in different ClassLoaders

This problem is independent of the version of the slf4j-api
used. According to Section 4.3.4 of the Java Language Specification,
two classes loaded by different class loaders are considered distinct
and hence incompatible.

> ad 2.) we provide slf4j-simple-1.6 and user provides
> slf4j-xxx-1.4. This will most probably end up in a big *boom*. And we
> do not know all slf4j-** as any user might easily add his own backend.

If I understand correctly, by default maven uses a "self-first" class
loading strategy. Plugin's class loader will load slf4j classes
defined in the plugin and everything may/should work seamlessly for
legacy plugins. For non legacy plugins requesting slf4j logger
injection via annotations and simultaneously declaring dependencies to
slf4j classes, class cast exceptions are likely to be thrown.

> ad 3.) We will face class path clashes since a few slf4j funnels are
> not fully binary compatible with the original impls. So funneling is
> hard to do in maven. If others think it is possible, then please point
> out a way to do this properly, thanks!

As mentioned earlier, I don't think Maven should use, declare or
export any slf4j bridges.

> Now for the workaround we could implement:
>

> While discussing this topic with Stephen he had the idea to scan
> whether a plugin uses slf4j by unzipping all plugin dependencies and
> do some checks. E.g. check whether there is a
> org.slf4j.impl.StaticLoggerBinder.class If we detect this or any slf4j
> with a version != the version used in maven-core, then we must isolate
> away slf4j provided by the maven core via ClassWorlds.

Sounds good. I would recommend isolation regardless of the version of
the discovered slf4j dependency. The plugin author probably wishes
logging isolation. Maven should let the plugin have its own separate
logging environment distinct from Maven's own logging.

I hope you find the above helpful.

--
Ceki
65% of statistics are made up on the spot

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@maven.apache.org
For additional commands, e-mail: dev-h...@maven.apache.org

Reply via email to