问题
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-
回答1:
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.
来源:https://stackoverflow.com/questions/23495147/dependency-chain-conflicts-for-hibernate-and-apache-felix