Question

I understand the concept of OSGi complaining about multiple dependency chains - a package is available more than once and when the importing bundle doesn't specify exactly which version it needs, so the OSGi container can run into the trouble of not knowing what to provide.

Unfortunately I ran into such a problem this week, but both involved bundles are third party bundles, so I can't really influence their imports and exports. Here are the two error messages I get:

org.osgi.framework.BundleException: Uses constraint violation. Unable to resolve bundle revision org.hibernate.core [28.0] because it is exposed to package 'javax.xml.stream' from bundle revisions com.springsource.javax.xml.stream [23.0] and org.apache.felix.framework [0] via two dependency chains.

Chain 1:
  org.hibernate.core [28.0]
    import: (osgi.wiring.package=javax.xml.stream)
     |
    export: osgi.wiring.package=javax.xml.stream
  com.springsource.javax.xml.stream [23.0]

Chain 2:
  org.hibernate.core [28.0]
    import: (osgi.wiring.package=javax.xml.transform.stax)
     |
    export: osgi.wiring.package=javax.xml.transform.stax; uses:=javax.xml.stream
    export: osgi.wiring.package=javax.xml.stream
  org.apache.felix.framework [0]
    at org.apache.felix.framework.Felix.resolveBundleRevision(Felix.java:3824) 
    at org.apache.felix.framework.Felix.startBundle(Felix.java:1868)
    at org.apache.felix.framework.Felix.setActiveStartLevel(Felix.java:1191)
    at org.apache.felix.framework.FrameworkStartLevelImpl.run(FrameworkStartLevelImpl.java:295)
    at java.lang.Thread.run(Thread.java:724)



org.osgi.framework.BundleException: Uses constraint violation. Unable to resolve bundle revision org.hibernate.core [28.0] because it is exposed to package 'javax.xml.stream' from bundle revisions org.apache.felix.framework [0] and com.springsource.javax.xml.stream [23.0] via two dependency chains.

Chain 1:
  org.hibernate.core [28.0]
    import: (osgi.wiring.package=javax.xml.stream)
     |
    export: osgi.wiring.package=javax.xml.stream
  org.apache.felix.framework [0]

Chain 2:
  org.hibernate.core [28.0]
    import: (osgi.wiring.package=org.dom4j.io)
     |
    export: osgi.wiring.package=org.dom4j.io; uses:=javax.xml.stream
  com.springsource.org.dom4j [27.0]
    import: (&(osgi.wiring.package=javax.xml.stream)(version>=1.0.1)(!(version>=2.0.0)))
     |
    export: osgi.wiring.package=javax.xml.stream
  com.springsource.javax.xml.stream [23.0]
    at org.apache.felix.framework.Felix.resolveBundleRevision(Felix.java:3824)
    at org.apache.felix.framework.Felix.startBundle(Felix.java:1868)
    at org.apache.felix.framework.Felix.setActiveStartLevel(Felix.java:1191)
    at org.apache.felix.framework.FrameworkStartLevelImpl.run(FrameworkStartLevelImpl.java:295)
    at java.lang.Thread.run(Thread.java:724)

When I try and remove com.springsource.javax.xml.stream from installed bundles, com.springsource.org.dom4j complains about missing package javax.xml.stream.

I checked the MANIFEST.MF file of org.apache.felix.framework because I was really astonished of Felix apparently exporting javax.xml.stream, but it contains no such entry. Also the dom4j bundle does not reexport the streaming package according to it's manifest.

I'd be really grateful for any tips that could get me closer to answer the question where this dependency chain problem comes from. From my point of view I couldn't find a bundle besides com.springsource.javax.xml.stream exporting said package-

Was it helpful?

Solution

It is often an issue if a package is available in a bundle and also in the bpot classpath (JDK). It is even a bigger issue if that package is wired from another JDK package and also from a bundle directly. In your case the problem is the following:

  • javax.xml.transform.stax is available only on the boot classpath (JDK) so hibernate.core wires to that package.
  • As javax.xml.transform.stax comes from the boot classpath, it can wire to another package on the boot classpath. It needs javax.xml.stream so it will wire to the package that comes from JDK

We have the chain:

hibernate.core -> javax.xml.transform.stax -> javax.xml.stream

On the other hand, hibernate.core wires to javax.xml.stream directly. Probably it even uses a version in the Import-Package section so it cannot wire to the package that comes from JDK.

We have the chain:

hibernate.core -> javax.xml.stream

This generates a conflict. As hibernate.core uses the javax.xml.stream API with the help of javax.xml.transform.stax, hibernate.core and javax.xml.transform.stax should use the same classes of javax.xml.stream. However, they do not.

You have a couple of options to solve your problem:

You can install a bundle that contains javax.xml.transform.stax package. That package will be able to wire to the javax.xml.stream package that comes from the bundle and also hibernate.core can wire to the bundle that contains javax.xml.transform.stax. You can pray that the wirings will be always OK.

In my experience, the wires are good after the framework is started. As the package versions are higher in the bundles, they will be preferred when the package is imported from other bundles. However, when the bundles are updated and refreshed at runtime, the wiring often goes wrong. I do not know why, it just happens.

To avoid every issue, I normally exclude those packages from the boot classpath that are also available in bundles.

Your next issue might be that these APIs often use factory classes. When someone uses such a factory, the classloader of the factory class must see the implementation classes, too. I created a bundle that contains all of the xmlcommons packages. It contains all of the xml-apis classes and implementation for them (xerces, xalan, etc). It might be helpful for you. If this bundle solves your problem, please let me know. In that case, I will take the time finally to collect all necessary data (licensing into the pom, sources) and release it to maven-central so it can help others as well.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top