glassfish
  1. glassfish
  2. GLASSFISH-11748

JAXB does not work in vanilla OSGi bundle context

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Critical Critical
    • Resolution: Fixed
    • Affects Version/s: V3
    • Fix Version/s: 3.1
    • Component/s: web_services
    • Labels:
      None
    • Environment:

      Operating System: All
      Platform: All

    • Issuezilla Id:
      11,748

      Description

      I am deploying a vanilla OSGi bundle in GlassFish. This has nothing to do with
      any Java EE programming model. It tries to obtain a JAXBContext to do some XML
      unmarshalling, but gets NPE as the stack below shows:

      java.lang.NullPointerException
      at javax.xml.bind.ContextFinder.handleClassCastException(ContextFinder.java:95)
      at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:204)
      at javax.xml.bind.ContextFinder.find(ContextFinder.java:375)
      at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:618)
      at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:565)
      at sahoo.metainfservicetest.Activator.start(Activator.java:9)
      at
      org.apache.felix.framework.util.SecureAction.startActivator(SecureAction.java:640)
      at org.apache.felix.framework.Felix.activateBundle(Felix.java:1700)
      at org.apache.felix.framework.Felix.startBundle(Felix.java:1622)
      at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:915)
      at org.apache.felix.shell.impl.StartCommandImpl.execute(StartCommandImpl.java:114)
      at
      org.apache.felix.shell.impl.Activator$ShellServiceImpl.executeCommand(Activator.java:286)
      at org.apache.felix.shell.remote.Shell.run(Shell.java:109)
      at java.lang.Thread.run(Thread.java:619)

      To reproduce, use the attached test case. Run it like this:
      mvn package
      cp target/metainfservicetest-1.0-SNAPSHOT.jar domain1/autodeploy/bundles/
      See server.log

        Activity

        Hide
        Sanjeeb Sahoo added a comment -

        Created an attachment (id=4291)
        Test case. mvn package, cp jar to autodeploy/bundles/, see server.log

        Show
        Sanjeeb Sahoo added a comment - Created an attachment (id=4291) Test case. mvn package, cp jar to autodeploy/bundles/, see server.log
        Hide
        kumara added a comment -

        -> snajper

        Show
        kumara added a comment - -> snajper
        Hide
        Martin Grebac added a comment -

        There is supposed to be a code in GF osgi runtime which should shield the JDK
        api/impl from the runtime. It seems that code is not working properly for
        non-javaee bundles?

        Show
        Martin Grebac added a comment - There is supposed to be a code in GF osgi runtime which should shield the JDK api/impl from the runtime. It seems that code is not working properly for non-javaee bundles?
        Hide
        Sanjeeb Sahoo added a comment -

        How will the glassfish class loader magic come into play for non-javaee bundles?
        It can't and that's exactly why we have to fix JAXB and other web services
        bundles that rely on the magic. Thanks a lot for looking into it.

        Show
        Sanjeeb Sahoo added a comment - How will the glassfish class loader magic come into play for non-javaee bundles? It can't and that's exactly why we have to fix JAXB and other web services bundles that rely on the magic. Thanks a lot for looking into it.
        Hide
        ltouve added a comment -
            • Issue 11748 has been confirmed by votes. ***
        Show
        ltouve added a comment - Issue 11748 has been confirmed by votes. ***
        Hide
        Martin Grebac added a comment -

        Hi Sahoo, I'd really like to implement a solution. However, yet I didn't find
        any that would not require adding osgi-dependent code into JAXB api.
        Remember that jaxb api integrates into JDK, thus it is not acceptable. Any
        suggestions?

        Show
        Martin Grebac added a comment - Hi Sahoo, I'd really like to implement a solution. However, yet I didn't find any that would not require adding osgi-dependent code into JAXB api. Remember that jaxb api integrates into JDK, thus it is not acceptable. Any suggestions?
        Hide
        Sanjeeb Sahoo added a comment -

        Pl. look at http://wiki.glassfish.java.net/Wiki.jsp?page=JdkSpiOsgi
        If you follow the proposal, JAXB code will not have any dependency on OSGi APIs.
        It will get configured in runtime to look at OSGi bundles for providers.

        Show
        Sanjeeb Sahoo added a comment - Pl. look at http://wiki.glassfish.java.net/Wiki.jsp?page=JdkSpiOsgi If you follow the proposal, JAXB code will not have any dependency on OSGi APIs. It will get configured in runtime to look at OSGi bundles for providers.
        Hide
        Martin Grebac added a comment -

        Thanks, will look at it.

        Show
        Martin Grebac added a comment - Thanks, will look at it.
        Hide
        Martin Grebac added a comment -

        Hi Sahoo, could the ServiceLoader from http://wiki.glassfish.java.net/Wiki.jsp?page=JdkSpiOsgi contain
        one more method to obtain a classloader instance? The method would return osgi-based classloader
        extension (let's say e.g. OsgiClassLoader extends ClassLoader).
        The issue is that in JAXB api the META-INF services provider lookup is not the only way to lookup the
        implementation. There are other ways, like lookup the impl class through jaxb.properties file.
        The current proposed approach would help in META-INF/services lookup, but not in the other cases.

        Show
        Martin Grebac added a comment - Hi Sahoo, could the ServiceLoader from http://wiki.glassfish.java.net/Wiki.jsp?page=JdkSpiOsgi contain one more method to obtain a classloader instance? The method would return osgi-based classloader extension (let's say e.g. OsgiClassLoader extends ClassLoader). The issue is that in JAXB api the META-INF services provider lookup is not the only way to lookup the implementation. There are other ways, like lookup the impl class through jaxb.properties file. The current proposed approach would help in META-INF/services lookup, but not in the other cases.
        Hide
        Martin Grebac added a comment -

        As we discussed, because JAXB uses slightly modified service lookup mechanism, osgiutil shall provide
        method which does not check isAssignable on service provider instances. I'll post the updated jaxb api
        code once such method is ready.

        Show
        Martin Grebac added a comment - As we discussed, because JAXB uses slightly modified service lookup mechanism, osgiutil shall provide method which does not check isAssignable on service provider instances. I'll post the updated jaxb api code once such method is ready.
        Hide
        Sanjeeb Sahoo added a comment -

        Martin,

        Has JAXB been changed to use the new ServiceLoader? AFAIK, I added the necessary
        methods to meet your requirements and I have also released osgi-resource-locator
        module version 1.0.0.

        I just received a request from a user who is facing this exact problem.

        Sahoo

        Show
        Sanjeeb Sahoo added a comment - Martin, Has JAXB been changed to use the new ServiceLoader? AFAIK, I added the necessary methods to meet your requirements and I have also released osgi-resource-locator module version 1.0.0. I just received a request from a user who is facing this exact problem. Sahoo
        Hide
        egarcia_sms added a comment -

        I'm the user Sahoo was referring to.

        As almost all our products depends on this (parsing XML using JAXB, as we have lot of classes) it will be
        nice to know the status of the bug, because I'm now experiencing side issues related to this one (not being
        able to load a class inside a WAR using JAXB)

        Thank you in advance.

        �ngel Eduardo

        Show
        egarcia_sms added a comment - I'm the user Sahoo was referring to. As almost all our products depends on this (parsing XML using JAXB, as we have lot of classes) it will be nice to know the status of the bug, because I'm now experiencing side issues related to this one (not being able to load a class inside a WAR using JAXB) Thank you in advance. �ngel Eduardo
        Hide
        Martin Grebac added a comment -

        The OSGi based loading of JAXB Context depending on Sahoo's utility classes has been integrated to GF so
        marking this as fixed.

        Show
        Martin Grebac added a comment - The OSGi based loading of JAXB Context depending on Sahoo's utility classes has been integrated to GF so marking this as fixed.
        Hide
        aaronjwhiteside added a comment -

        I am still seeing this error with Glassfish 3.1.2 and an OSGi bundle..

        The bundle is Apache Camel, and the corresponding code is, it seems that GlassFish fails to find the ContextFactory if a ClassLoader is supplied. This same code works under other OSGi containers Servicemix and JBoss 7..

                    // must use classloader from CamelContext to have JAXB working
                    jaxbContext = JAXBContext.newInstance(Constants.JAXB_CONTEXT_PACKAGES, CamelContext.class.getClassLoader());
        

        Stacktrace below...

        [#|2013-01-10T16:51:01.480-0500|INFO|glassfish3.1.2|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=224;_ThreadName=Thread-2;|ERROR [EclipseGeminiBlueprintExtenderThread-42] com.mm.gateway.messaging.routing.RouteDeployer - An error occurred while trying to load the routing file: /tmp/routes/hello.xml
        javax.xml.bind.JAXBException: Provider com.sun.xml.internal.bind.v2.ContextFactory not found
        	at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:148) ~[jaxb-api-osgi.jar:na]
        	at javax.xml.bind.ContextFinder.find(ContextFinder.java:361) ~[jaxb-api-osgi.jar:na]
        	at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:446) ~[jaxb-api-osgi.jar:na]
        	at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:409) ~[jaxb-api-osgi.jar:na]
        	at com.mm.gateway.messaging.routing.RouteLoader.load(RouteLoader.java:61) ~[routing-engine-1.0-SNAPSHOT.jar:1.0-SNAPSHOT]
        	at com.mm.gateway.messaging.routing.RouteDeployer.loadRoutes(RouteDeployer.java:266) [routing-engine-1.0-SNAPSHOT.jar:1.0-SNAPSHOT]
        	at com.mm.gateway.messaging.routing.RouteDeployer.loadExistingRoutes(RouteDeployer.java:106) [routing-engine-1.0-SNAPSHOT.jar:1.0-SNAPSHOT]
        	at com.mm.gateway.messaging.routing.RouteDeployer.start(RouteDeployer.java:79) [routing-engine-1.0-SNAPSHOT.jar:1.0-SNAPSHOT]
        	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.7.0_09]
        	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) ~[na:1.7.0_09]
        	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.7.0_09]
        	at java.lang.reflect.Method.invoke(Method.java:601) ~[na:1.7.0_09]
        	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeCustomInitMethod(AbstractAutowireCapableBeanFactory.java:1612) [org.springframework.beans-3.2.0.RELEASE.jar:3.2.0.RELEASE]
        	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1553) [org.springframework.beans-3.2.0.RELEASE.jar:3.2.0.RELEASE]
        	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1483) [org.springframework.beans-3.2.0.RELEASE.jar:3.2.0.RELEASE]
        	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:524) [org.springframework.beans-3.2.0.RELEASE.jar:3.2.0.RELEASE]
        	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461) [org.springframework.beans-3.2.0.RELEASE.jar:3.2.0.RELEASE]
        	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295) [org.springframework.beans-3.2.0.RELEASE.jar:3.2.0.RELEASE]
        	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223) [org.springframework.beans-3.2.0.RELEASE.jar:3.2.0.RELEASE]
        	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292) [org.springframework.beans-3.2.0.RELEASE.jar:3.2.0.RELEASE]
        	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194) [org.springframework.beans-3.2.0.RELEASE.jar:3.2.0.RELEASE]
        	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:607) [org.springframework.beans-3.2.0.RELEASE.jar:3.2.0.RELEASE]
        	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932) [org.springframework.context-3.2.0.RELEASE.jar:3.2.0.RELEASE]
        	at org.eclipse.gemini.blueprint.context.support.AbstractDelegatedExecutionApplicationContext.access$1600(AbstractDelegatedExecutionApplicationContext.java:60) [gemini-blueprint-core-1.0.2.RELEASE.jar:1.0.2.RELEASE]
        	at org.eclipse.gemini.blueprint.context.support.AbstractDelegatedExecutionApplicationContext$4.run(AbstractDelegatedExecutionApplicationContext.java:325) [gemini-blueprint-core-1.0.2.RELEASE.jar:1.0.2.RELEASE]
        	at org.eclipse.gemini.blueprint.util.internal.PrivilegedUtils.executeWithCustomTCCL(PrivilegedUtils.java:85) [gemini-blueprint-core-1.0.2.RELEASE.jar:1.0.2.RELEASE]
        	at org.eclipse.gemini.blueprint.context.support.AbstractDelegatedExecutionApplicationContext.completeRefresh(AbstractDelegatedExecutionApplicationContext.java:290) [gemini-blueprint-core-1.0.2.RELEASE.jar:1.0.2.RELEASE]
        	at org.eclipse.gemini.blueprint.extender.internal.dependencies.startup.DependencyWaiterApplicationContextExecutor$CompleteRefreshTask.run(DependencyWaiterApplicationContextExecutor.java:137) [gemini-blueprint-extender-1.0.2.RELEASE.jar:1.0.2.RELEASE]
        	at java.lang.Thread.run(Thread.java:722) [na:1.7.0_09]
        Caused by: java.lang.ClassNotFoundException: com.sun.xml.internal.bind.v2.ContextFactory not found by org.apache.camel.camel-core [286]
        	at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1460) ~[na:na]
        	at org.apache.felix.framework.BundleWiringImpl.access$400(BundleWiringImpl.java:72) ~[na:na]
        	at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:1843) ~[na:na]
        	at java.lang.ClassLoader.loadClass(ClassLoader.java:356) ~[na:1.7.0_09]
        	at javax.xml.bind.ContextFinder.safeLoadClass(ContextFinder.java:573) ~[jaxb-api-osgi.jar:na]
        	at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:145) ~[jaxb-api-osgi.jar:na]
        	... 28 common frames omitted
        |#]
        
        Show
        aaronjwhiteside added a comment - I am still seeing this error with Glassfish 3.1.2 and an OSGi bundle.. The bundle is Apache Camel, and the corresponding code is, it seems that GlassFish fails to find the ContextFactory if a ClassLoader is supplied. This same code works under other OSGi containers Servicemix and JBoss 7.. // must use classloader from CamelContext to have JAXB working jaxbContext = JAXBContext.newInstance(Constants.JAXB_CONTEXT_PACKAGES, CamelContext.class.getClassLoader()); Stacktrace below... [#|2013-01-10T16:51:01.480-0500|INFO|glassfish3.1.2|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=224;_ThreadName= Thread -2;|ERROR [EclipseGeminiBlueprintExtenderThread-42] com.mm.gateway.messaging.routing.RouteDeployer - An error occurred while trying to load the routing file: /tmp/routes/hello.xml javax.xml.bind.JAXBException: Provider com.sun.xml.internal.bind.v2.ContextFactory not found at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:148) ~[jaxb-api-osgi.jar:na] at javax.xml.bind.ContextFinder.find(ContextFinder.java:361) ~[jaxb-api-osgi.jar:na] at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:446) ~[jaxb-api-osgi.jar:na] at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:409) ~[jaxb-api-osgi.jar:na] at com.mm.gateway.messaging.routing.RouteLoader.load(RouteLoader.java:61) ~[routing-engine-1.0-SNAPSHOT.jar:1.0-SNAPSHOT] at com.mm.gateway.messaging.routing.RouteDeployer.loadRoutes(RouteDeployer.java:266) [routing-engine-1.0-SNAPSHOT.jar:1.0-SNAPSHOT] at com.mm.gateway.messaging.routing.RouteDeployer.loadExistingRoutes(RouteDeployer.java:106) [routing-engine-1.0-SNAPSHOT.jar:1.0-SNAPSHOT] at com.mm.gateway.messaging.routing.RouteDeployer.start(RouteDeployer.java:79) [routing-engine-1.0-SNAPSHOT.jar:1.0-SNAPSHOT] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.7.0_09] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) ~[na:1.7.0_09] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.7.0_09] at java.lang.reflect.Method.invoke(Method.java:601) ~[na:1.7.0_09] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeCustomInitMethod(AbstractAutowireCapableBeanFactory.java:1612) [org.springframework.beans-3.2.0.RELEASE.jar:3.2.0.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1553) [org.springframework.beans-3.2.0.RELEASE.jar:3.2.0.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1483) [org.springframework.beans-3.2.0.RELEASE.jar:3.2.0.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:524) [org.springframework.beans-3.2.0.RELEASE.jar:3.2.0.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461) [org.springframework.beans-3.2.0.RELEASE.jar:3.2.0.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295) [org.springframework.beans-3.2.0.RELEASE.jar:3.2.0.RELEASE] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223) [org.springframework.beans-3.2.0.RELEASE.jar:3.2.0.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292) [org.springframework.beans-3.2.0.RELEASE.jar:3.2.0.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194) [org.springframework.beans-3.2.0.RELEASE.jar:3.2.0.RELEASE] at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:607) [org.springframework.beans-3.2.0.RELEASE.jar:3.2.0.RELEASE] at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932) [org.springframework.context-3.2.0.RELEASE.jar:3.2.0.RELEASE] at org.eclipse.gemini.blueprint.context.support.AbstractDelegatedExecutionApplicationContext.access$1600(AbstractDelegatedExecutionApplicationContext.java:60) [gemini-blueprint-core-1.0.2.RELEASE.jar:1.0.2.RELEASE] at org.eclipse.gemini.blueprint.context.support.AbstractDelegatedExecutionApplicationContext$4.run(AbstractDelegatedExecutionApplicationContext.java:325) [gemini-blueprint-core-1.0.2.RELEASE.jar:1.0.2.RELEASE] at org.eclipse.gemini.blueprint.util.internal.PrivilegedUtils.executeWithCustomTCCL(PrivilegedUtils.java:85) [gemini-blueprint-core-1.0.2.RELEASE.jar:1.0.2.RELEASE] at org.eclipse.gemini.blueprint.context.support.AbstractDelegatedExecutionApplicationContext.completeRefresh(AbstractDelegatedExecutionApplicationContext.java:290) [gemini-blueprint-core-1.0.2.RELEASE.jar:1.0.2.RELEASE] at org.eclipse.gemini.blueprint.extender.internal.dependencies.startup.DependencyWaiterApplicationContextExecutor$CompleteRefreshTask.run(DependencyWaiterApplicationContextExecutor.java:137) [gemini-blueprint-extender-1.0.2.RELEASE.jar:1.0.2.RELEASE] at java.lang. Thread .run( Thread .java:722) [na:1.7.0_09] Caused by: java.lang.ClassNotFoundException: com.sun.xml.internal.bind.v2.ContextFactory not found by org.apache.camel.camel-core [286] at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1460) ~[na:na] at org.apache.felix.framework.BundleWiringImpl.access$400(BundleWiringImpl.java:72) ~[na:na] at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:1843) ~[na:na] at java.lang. ClassLoader .loadClass( ClassLoader .java:356) ~[na:1.7.0_09] at javax.xml.bind.ContextFinder.safeLoadClass(ContextFinder.java:573) ~[jaxb-api-osgi.jar:na] at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:145) ~[jaxb-api-osgi.jar:na] ... 28 common frames omitted |#]
        Hide
        aaronjwhiteside added a comment -

        So after more digging it turns out that it will load correctly when using the current threads context ClassLoader but not the actual bundle's class loader (where the classes are actually located).

        The bundle ClassLoader should be able to find the ContextFactory too.

        Show
        aaronjwhiteside added a comment - So after more digging it turns out that it will load correctly when using the current threads context ClassLoader but not the actual bundle's class loader (where the classes are actually located). The bundle ClassLoader should be able to find the ContextFactory too.
        Hide
        Sanjeeb Sahoo added a comment - - edited

        There are three things I would like to highlight:
        1. It seems you are passing your bundle class loader to JAXBContext.newInstance.
        In such a case JAXB seems to be searching available service provider using that class loader only.
        Since your bundle does not have a dependency on a JAXB implementation bundle,
        JAXB API is not able to locate a provider.

        I am assuming you are not trying to locate a specific JAXB provider. Any provider is good for for you.
        In that case, why do you pass a classloader argument? If you leave it unspecified, I am sure
        JAXB can locate the default provider. So, I think you should change your code to leave it unspecified.

        2. Coming to the issue of JAXB not being able to locate the default behavior.
        I am hesitant to call it a bug, but I definitely call it a poor implementation.
        I can't call it a bug because the javadocs for JAXBContext [1] only recommends the API to locate the default provider.
        The wordings from javadocs [1] is produced below verbatim:

        "Finally, if all the steps above fail, then the rest of the look up is unspecified.
        That said, the recommended behavior is to simply look for some hard-coded platform default JAXB implementation.
        This phase of the look up is so that JavaSE can have its own JAXB implementation as the last resort."

        It does not mandate as you can see from the above wording. By no means, I am defending their behavior.

        3. Finally coming to the issue of why JAXBContext.newInstance succeeds when you pass it a classloader that's
        same as Thread's context classloader. Without knowing what's set as Thread's context classloader, it is difficult
        to say why it works. There is one thing I would like to highlight is the following code in FactoryFinder:

        if (getContextClassLoader() == classLoader) {
        Class factory = lookupUsingOSGiServiceLoader("javax.xml.bind.JAXBContext");
        if (factory != null)

        { logger.fine("OSGi environment detected"); return newInstance(contextPath, factory, classLoader, properties); }

        }

        I definitely don't endorse the "if (getContextClassLoader() == classLoader)" check here.
        This may explain why you code behaved differently when you passed TCL as the argument.
        I am not the author of this class and my experience says that it will take a long time
        to get this fixed. So, the simple thing to do would be to do what I asked you to do in #1.

        Thanks,
        Sahoo

        [1] http://docs.oracle.com/javaee/6/api/javax/xml/bind/JAXBContext.html

        Show
        Sanjeeb Sahoo added a comment - - edited There are three things I would like to highlight: 1. It seems you are passing your bundle class loader to JAXBContext.newInstance. In such a case JAXB seems to be searching available service provider using that class loader only. Since your bundle does not have a dependency on a JAXB implementation bundle, JAXB API is not able to locate a provider. I am assuming you are not trying to locate a specific JAXB provider. Any provider is good for for you. In that case, why do you pass a classloader argument? If you leave it unspecified, I am sure JAXB can locate the default provider. So, I think you should change your code to leave it unspecified. 2. Coming to the issue of JAXB not being able to locate the default behavior. I am hesitant to call it a bug, but I definitely call it a poor implementation. I can't call it a bug because the javadocs for JAXBContext [1] only recommends the API to locate the default provider. The wordings from javadocs [1] is produced below verbatim: "Finally, if all the steps above fail, then the rest of the look up is unspecified. That said, the recommended behavior is to simply look for some hard-coded platform default JAXB implementation. This phase of the look up is so that JavaSE can have its own JAXB implementation as the last resort." It does not mandate as you can see from the above wording. By no means, I am defending their behavior. 3. Finally coming to the issue of why JAXBContext.newInstance succeeds when you pass it a classloader that's same as Thread's context classloader. Without knowing what's set as Thread's context classloader, it is difficult to say why it works. There is one thing I would like to highlight is the following code in FactoryFinder: if (getContextClassLoader() == classLoader) { Class factory = lookupUsingOSGiServiceLoader("javax.xml.bind.JAXBContext"); if (factory != null) { logger.fine("OSGi environment detected"); return newInstance(contextPath, factory, classLoader, properties); } } I definitely don't endorse the "if (getContextClassLoader() == classLoader)" check here. This may explain why you code behaved differently when you passed TCL as the argument. I am not the author of this class and my experience says that it will take a long time to get this fixed. So, the simple thing to do would be to do what I asked you to do in #1. Thanks, Sahoo [1] http://docs.oracle.com/javaee/6/api/javax/xml/bind/JAXBContext.html

          People

          • Assignee:
            Martin Grebac
            Reporter:
            Sanjeeb Sahoo
          • Votes:
            2 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: