[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [equinox-dev] Question about uses constraints in a constellation involving fragments

What you describe should not be allowed.  The uses directive on the export of org.slf4j.impl from ch.qos.logback.slf4j should not allow bundle slf4j.api (id=927) from wiring to the logback version.  Running the osgi> command 'bundle 927' should give you the packages that bundle 927 is wired to.  That should tell us if it really is wired to the one from logback which is being hosted by orbit slf4j bundle.  Your analysis sounds correct for the IncombatibleClassChangeError, but I don't understand how it is getting wired to the logback version of the impl package.


From:        Andreas Sewe <andreas.sewe@xxxxxxxxxxxxxx>
To:        Equinox development mailing list <equinox-dev@xxxxxxxxxxx>
Date:        10/07/2014 11:22 AM
Subject:        [equinox-dev] Question about uses constraints in a constellation        involving fragments
Sent by:        equinox-dev-bounces@xxxxxxxxxxx


I've come across a weird constellation involving uses constraints and
fragments and need an OSGi expert to double-check my logic. I hope this
is the right mailing list. If not, please accept my apologies.

I've just had fun making sense of the following bug report [1] (which
exhibits similar symptoms as these other reports [2,3,4]).

>     java.lang.IncompatibleClassChangeError: Class ch.qos.logback.classic.LoggerContext does not implement the requested interface org.slf4j.ILoggerFactory
>     at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:270)
>     at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:281)

The situation in which this occurs seems to be like this:

> osgi> ss slf4j
> "Framework is launched."
> id    State       Bundle
> 5    RESOLVED    ch.qos.logback.slf4j_1.0.7.v20121108-1250
>                 Master=836
> 836    RESOLVED    org.slf4j.api_1.7.2.v20121108-1250
>                 Fragments=5
> 908    RESOLVED    jcl.over.slf4j_1.7.2
> 924    ACTIVE      org.sonar.ide.eclipse.slf4j.pde_3.4.0.20140404-0949-RELEASE
> 927    RESOLVED    slf4j.api_1.7.2

So, we have two SLF4J API bundles (836, 927). The former comes from
Orbit, the latter is shipped with the SonarQube Eclipse plugin. The
plugin from Orbit uses a neat implementation trick where a fragment (5)
is used to give the org.slf4j.api bundle (836) access to the package
org.slf4j.impl and thereby make it use Logback as an API implementation.

osgi> h 5
Bundle headers:
Bundle-Localization = fragment
Bundle-ManifestVersion = 2
Bundle-Name = Logback Native SLF4J Logger Module
Bundle-RequiredExecutionEnvironment = J2SE-1.5,JavaSE-1.6,JavaSE-1.7
Bundle-SymbolicName = ch.qos.logback.slf4j
Bundle-Vendor = Eclipse.org
Bundle-Version = 1.0.7.v20121108-1250
Eclipse-SourceReferences =
Export-Package = org.slf4j.impl;
Fragment-Host = org.slf4j.api;bundle-version="[1.7.2,1.7.3)"
Manifest-Version = 1.0
Require-Bundle =

Now, my explanation for the IncompatibleClassChangeError is that whoever
calls org.slf4j.LoggerFactory.getLogger(...) is for some reason wired to
the slf4j.api (927) shipped with SonarQube. Now, that bundle's manifest
looks like this:

> osgi> h 927
> Bundle headers:
>  Archiver-Version = Plexus Archiver
>  Build-Jdk = 1.6.0_23
>  Built-By = ceki
>  Bundle-Description = The slf4j API
>  Bundle-ManifestVersion = 2
>  Bundle-Name = slf4j-api
>  Bundle-RequiredExecutionEnvironment = J2SE-1.3
>  Bundle-SymbolicName = slf4j.api
>  Bundle-Vendor = SLF4J.ORG
>  Bundle-Version = 1.7.2
>  Created-By = Apache Maven
>  Export-Package = org.slf4j;version=1.7.2, org.slf4j.spi;version=1.7.2, org.slf4j.helpers;version=1.7.2
>  Implementation-Title = slf4j-api
>  Implementation-Version = 1.7.2
>  Import-Package = org.slf4j.impl;version=1.6.0
>  Manifest-Version = 1.0

And here's where I think things can go wrong. Instead of getting wired
to the org.slf4j.impl package from org.sonar.ide.eclipse.slf4j.pde
(924), the slf4j.api bundle (927) gets wired to the org.slf4j.api bundle
(836) + ch.qos.logback.slf4j fragment (5) from Orbit. And the
ch.qos.logback.classic.LoggerContext from the fragment of course
implements the interface org.slf4j.ILoggerFactory exported from its host
bundle, not from the conflicting slf4j.api bundle (927). Hence the

So far for my theory. There is one thing, however, that puzzles me. The
fragment dutifully exports org.slf4j.impl with a uses constraint:

> org.slf4j.impl; uses:="...,org.slf4j,...";version="1.7.2"

Shouldn't this constraint prevent the slf4j.api bundle (927) from wiring
to the org.slf4j.api bundle (836) + fragment in the first place? Or does
the fact that the slf4j.api bundle (927) itself *defines* the org.slf4j
package (rather importing another, conflicting instance) does not
constitute a *use* that would violate the constraint and hence prevent
the two bundles from being wired together?

Can someone more knowledgeable of OSGi please explain to me what's going
on? Is this a constellation where uses constraints just don't help? Or
is my theory simply wrong and there exists another possible wiring that
explains the IncompatibleClassChangeError?

Any help is greatly appreciated.

Best wishes,


[1] <
[3] <
[4] <

Codetrails GmbH
The knowledge transfer company

Robert-Bosch-Str. 7, 64293 Darmstadt
Phone: +49-6151-276-7092
Mobile: +49-170-811-3791

Managing Director: Dr. Marcel Bruch
Handelsregister: Darmstadt HRB 91940
equinox-dev mailing list
To change your delivery options, retrieve your password, or unsubscribe from this list, visit