3
votes

I' m trying to access an OSGI Bundle from my main application. But if a class in the bundle is accessed that uses javax.xml.* package. A NoClassDefFoundError is thrown.

java.lang.NoClassDefFoundError: javax/xml/transform/Source
    at de.foo.bar.test.Builder.<init>(Builder.java:46) ~[test-bundle-1.4.0.jar:1.4.0]
    at de.foo.bar.test.request.Factory.createRequest(Factory.java:99) ~[?:?]
    at de.foo.bar.test.request.Request.prepareRequest(Request.java:93) ~[?:?]
    at de.foo.bar.test.request.Request.process(Request.java:60) ~[?:?]
    at de.foo.bar.test.TestClass.execute(TestClass.java:74) ~[?:?]
    at de.foo.bar.test.TestClass.execute(TestClass.java:1) ~[?:?]
    at de.foo.bar.service.system.OsgiTransactionHandler.handleTransaction(OsgiTransactionHandler.java:71) ~[bin/:?]
    at de.foo.bar.service.system.TransactionRequestService.processTransaction(TransactionRequestService.java:110) ~[bin/:?]
    at de.foo.bar.service.system.TransactionRequestService.runService(TransactionRequestService.java:72) ~[bin/:?]
    at de.foo.bar.service.model.InfiniteService.run(InfiniteService.java:57) ~[bin/:?]
    at com.google.common.util.concurrent.AbstractExecutionThreadService$1$2.run(AbstractExecutionThreadService.java:60) [guava-16.0.1.jar:?]
    at com.google.common.util.concurrent.Callables$3.run(Callables.java:93) [guava-16.0.1.jar:?]
    at java.lang.Thread.run(Thread.java:662) [?:1.6.0_43]
Caused by: java.lang.ClassNotFoundException: javax.xml.transform.Source not found by test-bundle [1]
    at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1532) ~[org.apache.felix.framework-4.2.1.jar:?]
    at org.apache.felix.framework.BundleWiringImpl.access$400(BundleWiringImpl.java:75) ~[org.apache.felix.framework-4.2.1.jar:?]
    at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:1955) ~[org.apache.felix.framework-4.2.1.jar:?]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247) ~[?:1.6.0_43]
    ... 13 more

I've checked the imported packages in the MANIFEST.MF and can see, that the package javax.xml.transform is stated (I've shortend it a bit):

Import-Package: com.fasterxml.jackson.core;resolution:=optional,com.fast
 ...
 500;resolution:=optional,javax.servlet;resolution:=optional,javax.sql;r
 esolution:=optional,javax.swing;resolution:=optional,javax.xml.bind;res
 olution:=optional,javax.xml.bind.annotation;resolution:=optional,javax.
 xml.bind.annotation.adapters;resolution:=optional,javax.xml.parsers;res
 olution:=optional,javax.xml.transform;resolution:=optional,javax.xml.tr
 ansform.stream;resolution:=optional,javax.xml.validation;resolution:=op
 tional,org.bson;resolution:=optional,org.lightcouch;resolution:=optiona
 l,org.osgi.framework;resolution:=optional;version="[1.5,2)",org.osgi.fr
 amework.wiring;resolution:=optional,org.w3c.dom;resolution:=optional,or
 g.xml.sax;resolution:=optional,sun.misc;resolution:=optional

I'm using apache felix in version 4.2.1 as an embedded framework and the maven-bundle-plugin is configured as follows:

<plugin>
    <groupId>org.apache.felix</groupId>
    <artifactId>maven-bundle-plugin</artifactId>
    <extensions>true</extensions>
    <configuration>
        <instructions>
            <Bundle-Name>Test Bundle</Bundle-Name>
            <Bundle-Activator>de.foo.bar.test.activator.TestActivator</Bundle-Activator>
            <Service-Component>OSGI-INF/component.xml</Service-Component>
            <Export-Package>de.foo.bar.test</Export-Package>
            <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
            <Import-Package>*;resolution:=optional</Import-Package>
            <Embed-Transitive>true</Embed-Transitive>
            <Embed-Dependency>*;scope=compile|runtime;inline=false;artifactId=!org.osgi.core</Embed-Dependency>
            <_failok>true</_failok>
            <_nouses>true</_nouses>
            <_nodefaultversion>true</_nodefaultversion>
            <_snapshot>${osgi-version-qualifier}</_snapshot>
        </instructions>
    </configuration>
</plugin>

I tried to export the missing packages by using FRAMEWORK_SYSTEMPACKAGES_EXTRA property. But that seems to result in exporting all Java packages. I've stopped it on the 7th package.

Is there a way to provide these java standard packages without exporting them explicitly?

1
Interesting question. All I can suggest is that you have a quick look at jboss, AS7+ uses OSGi for everything, also the base packages, perhaps you can see how they did it. - nablex
Equinox has profiles for the standard JREs so that the system bundle exports the typical packages. I would have though Felix had a similar mechanism. - BJ Hargrave
@BJHargrave Do you have a link to a site where these Equinox profiles are documented? - sebastian
The link above is perfect. In short, explicit exports of these packages should not be necessary, and even explicit imports can be avoided with boot delegation. However, as you already have explicit imports, you are doing it right and something else is going on. Why are all your package imports optional? This is a great way to avoid the benefits of OSGi and defer all your class loading problems to runtime, old-Java style, rather than failing fast and explicitly on bundle startup. - Holly Cummins

1 Answers

0
votes

The cause of this problem was located in the framework configuration. Based on an online tutorial I had added following parameter to my config:

config.put(Constants.FRAMEWORK_SYSTEMPACKAGES, "org.osgi.framework; version=1.5.0");

This caused that the default system packages have been replaced and only org.osgi.framework has been available besides the extra packages I exported.

After I'd removed this line the default packages where available again and so javax.xml.transform.