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