Search code examples
javajvmosgiclassloaderapache-felix

Java Class cast exception, Classloader error on using javax xml providers?


I get the following error when I switched from OSGI Equinox to OSGI Karaf runtime.

Earlier the com.sun implementation was working fine, but now I need an apache implementation to run in one environment and com.sun in the older.

I know that OSGI has different class loading mechanism when compared to Java Class loading.

We are providing the javax packages as a part of the rt.jar which contains the Provider interface.

The implementation is coming from com.sun.xml

com.sun.xml.internal.ws.spi.ProviderImpl cannot be cast to javax.xml.ws.spi.Provider (loaded by org.apache.felix.framework.BundleWiringImpl$BundleClassLoader@0x0000000100162fd8) (found matching super class javax.xml.ws.spi.Provider loaded by , but needed loader org.apache.felix.framework.BundleWiringImpl$BundleClassLoader@0x0000000100162fd8)
            at javax.xml.ws.spi.Provider.provider(Provider.java:43)
            at javax.xml.ws.Service.<init>(Service.java:35)
            at javax.xml.ws.Service.create(Service.java:126)

When I look at the logs, both class loaders seem to have the same ID, then why get a class cast exception?

javax.xml.ws.spi.Provider (loaded by org.apache.felix.framework.BundleWiringImpl$BundleClassLoader@0x0000000100162fd8) (found matching super class javax.xml.ws.spi.Provider loaded by , but needed loader org.apache.felix.framework.BundleWiringImpl$BundleClassLoader@0x0000000100162fd8)

As of now, I am using a hack to get around this in two different environments

private static final String PROVIDER_CXF = "org.apache.cxf.jaxws.spi.ProviderImpl";
private static final String PROVIDER_DEFAULT = "com.sun.xml.internal.ws.spi.ProviderImpl";

private String setProvider() {
    log.debug("set default provider");
    System.setProperty(PROVIDER, PROVIDER_DEFAULT);
    try {
        Service.create(new QName(null, ""));
        return PROVIDER_DEFAULT;
    } catch (Exception e) {
        log.debug("setting cxf provider");
        System.setProperty(PROVIDER, PROVIDER_CXF);
        return PROVIDER_CXF;
    }
}

Solution

  • You may need to set -Dorg.osgi.framework.bootdelegation=com.sun.*. See https://osgi.org/specification/osgi.core/7.0.0/framework.module.html#framework.module.parentdelegation. It is possible Equinox provides a common, useful default for boot delegation while Karaf does not.