Geronimo
  1. Geronimo
  2. GERONIMO-3793

"Not Known To This Context" JAXBException when attempting to return complex data type from a @WebMethod

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Critical Critical
    • Resolution: Fixed
    • Affects Version/s: 2.0.x, 2.1
    • Fix Version/s: 2.1.3, 2.2
    • Component/s: webservices
    • Security Level: public (Regular issues)
    • Labels:
      None
    • Environment:

      Windows XP x86-32, IBM J9 1.5.0 SR5, Geronimo w/ Tomcat+OpenEJB+Axis2

      Description

      I'm attempting to return a @XmlRootElement annotated object called "Customer" from a @WebMethod. When calling the service, I get the following error in the server log:

      javax.xml.bind.JAXBException: [Lcom.gmail.at.cedrichurst.complexDataTypeWSExampleEJB.domain.Customer; is not known to this context
      at com.sun.xml.bind.v2.runtime.XMLSerializer.reportError(XMLSerializer.java:223)
      at com.sun.xml.bind.v2.runtime.XMLSerializer.reportError(XMLSerializer.java:238)
      at com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl$1.serializeBody(ElementBeanInfoImpl.java:85)
      at com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl$1.serializeBody(ElementBeanInfoImpl.java:127)
      at com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl.serializeBody(ElementBeanInfoImpl.java:244)
      at com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl.serializeRoot(ElementBeanInfoImpl.java:251)
      at com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl.serializeRoot(ElementBeanInfoImpl.java:33)
      at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:461)
      at com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:292)
      ... 48 more

      From what I understand, the return type should be added to the JaxB context automatically.

      Just to make sure I wasn't doing something wrong in my Customer class, I added another method to my bean that returned a java.util.List of Strings. When calling this method, I also got the same sort of error:

      [javax.xml.bind.JAXBException: java.util.List is not known to this context]
      javax.xml.ws.WebServiceException: javax.xml.bind.MarshalException

      • with linked exception:
        [javax.xml.bind.JAXBException: java.util.List is not known to this context]
        at org.apache.axis2.jaxws.ExceptionFactory.createWebServiceException(ExceptionFactory.java:174)
        at org.apache.axis2.jaxws.ExceptionFactory.makeWebServiceException(ExceptionFactory.java:69)
        at org.apache.axis2.jaxws.ExceptionFactory.makeWebServiceException(ExceptionFactory.java:127)
        at org.apache.axis2.jaxws.message.databinding.impl.JAXBBlockImpl$2.run(JAXBBlockImpl.java:405)
        at org.apache.axis2.java.security.AccessController.doPrivileged(AccessController.java:76)
        at org.apache.axis2.jaxws.message.databinding.impl.JAXBBlockImpl.marshalByType(JAXBBlockImpl.java:321)
        at org.apache.axis2.jaxws.message.databinding.impl.JAXBBlockImpl._outputFromBO(JAXBBlockImpl.java:209)
        at org.apache.axis2.jaxws.message.impl.BlockImpl.outputTo(BlockImpl.java:327)
        at org.apache.axis2.jaxws.message.impl.BlockImpl.serialize(BlockImpl.java:252)
        at org.apache.axiom.om.impl.llom.OMSourcedElementImpl.internalSerializeAndConsume(OMSourcedElementImpl.java:599)
        at org.apache.axiom.om.impl.llom.OMElementImpl.internalSerialize(OMElementImpl.java:785)
        at org.apache.axiom.om.impl.llom.OMElementImpl.internalSerializeAndConsume(OMElementImpl.java:814)
        at org.apache.axiom.om.impl.llom.OMElementImpl.internalSerialize(OMElementImpl.java:785)
        at org.apache.axiom.om.impl.llom.OMElementImpl.internalSerializeAndConsume(OMElementImpl.java:814)
        at org.apache.axiom.soap.impl.llom.SOAPEnvelopeImpl.serializeInternally(SOAPEnvelopeImpl.java:237)
        at org.apache.axiom.soap.impl.llom.SOAPEnvelopeImpl.internalSerialize(SOAPEnvelopeImpl.java:225)
        at org.apache.axiom.om.impl.llom.OMElementImpl.internalSerializeAndConsume(OMElementImpl.java:814)
        at org.apache.axiom.om.impl.llom.OMNodeImpl.serializeAndConsume(OMNodeImpl.java:421)
        at org.apache.axis2.transport.http.SOAPMessageFormatter.writeTo(SOAPMessageFormatter.java:68)
        at org.apache.axis2.transport.http.CommonsHTTPTransportSender.sendUsingOutputStream(CommonsHTTPTransportSender.java:294)
        at org.apache.axis2.transport.http.CommonsHTTPTransportSender.invoke(CommonsHTTPTransportSender.java:211)
        at org.apache.axis2.engine.AxisEngine.send(AxisEngine.java:396)
        at org.apache.geronimo.axis2.ejb.EJBInterceptor.intercept(EJBInterceptor.java:94)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:615)
        at org.apache.openejb.core.interceptor.ReflectionInvocationContext$Invocation.invoke(ReflectionInvocationContext.java:146)
        at org.apache.openejb.core.interceptor.ReflectionInvocationContext.proceed(ReflectionInvocationContext.java:129)
        at org.apache.openejb.core.interceptor.InterceptorStack.invoke(InterceptorStack.java:73)
        at org.apache.openejb.core.stateless.StatelessContainer.invokeWebService(StatelessContainer.java:263)
        at org.apache.openejb.core.stateless.StatelessContainer._invoke(StatelessContainer.java:199)
        at org.apache.openejb.core.stateless.StatelessContainer.invoke(StatelessContainer.java:165)
        at org.apache.geronimo.axis2.ejb.EJBMessageReceiver.receive(EJBMessageReceiver.java:88)
        at org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:145)
        at org.apache.axis2.transport.http.HTTPTransportUtils.processHTTPPostRequest(HTTPTransportUtils.java:275)
        at org.apache.geronimo.axis2.Axis2WebServiceContainer.processPOSTRequest(Axis2WebServiceContainer.java:395)
        at org.apache.geronimo.axis2.Axis2WebServiceContainer.doService2(Axis2WebServiceContainer.java:265)
        at org.apache.geronimo.axis2.Axis2WebServiceContainer.doService(Axis2WebServiceContainer.java:204)
        at org.apache.geronimo.axis2.Axis2WebServiceContainer.invoke(Axis2WebServiceContainer.java:167)
        at org.apache.geronimo.tomcat.TomcatEJBWebServiceContext$EJBWebServiceValve.invoke(TomcatEJBWebServiceContext.java:180)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
        at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:563)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:263)
        at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:584)
        at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
        at java.lang.Thread.run(Thread.java:801)

      According to a thread in the OpenEJB mailing list:

      http://www.nabble.com/Returning-complex-data-types-in-%40WebResult-tc15114306.html

      ...it doesn't seem that these errors should be happening.

      I attempted to test this under CXF, but ran into another issue which is outlined in another JIRA.

      EAR file and geronimo.log attached.

      1. geronimo.log
        41 kB
        Cedric Hurst
      2. G3793 -r680814.patch
        0.7 kB
        Manu T George
      3. ComplexDataTypeWSExampleEAR.ear
        6 kB
        Cedric Hurst

        Activity

        Hide
        Jarek Gawor added a comment -

        Committed similar patch with additional tests to trunk (revision 682575) and branches/2.1 (revision 682576).

        Added a org.apache.geronimo.jaxws.wsgen.addToClassPath system property to control whether the wsgen generated classes should be added to the module classpath. By default, the generated classes will be added to the module classpath. To prevent the generated classes from being added to the module classpath pass -Dorg.apache.geronimo.jaxws.wsgen.addToClassPath=false system property.

        Show
        Jarek Gawor added a comment - Committed similar patch with additional tests to trunk (revision 682575) and branches/2.1 (revision 682576). Added a org.apache.geronimo.jaxws.wsgen.addToClassPath system property to control whether the wsgen generated classes should be added to the module classpath. By default, the generated classes will be added to the module classpath. To prevent the generated classes from being added to the module classpath pass -Dorg.apache.geronimo.jaxws.wsgen.addToClassPath=false system property.
        Hide
        Manu T George added a comment -

        Verified with jetty-cxf/tomcat-axis also on linux. Please review and commit if appropriate

        Show
        Manu T George added a comment - Verified with jetty-cxf/tomcat-axis also on linux. Please review and commit if appropriate
        Hide
        Manu T George added a comment -

        Patch Tested with both POJO and EJB Web Services with geronimo-tomcat-axis2
        Not tested with jetty yet as geronimo jetty is throwing some NIO related exception in my windows machine and not starting. Will test it if in linux later for geronimo-jetty-cxf

        Show
        Manu T George added a comment - Patch Tested with both POJO and EJB Web Services with geronimo-tomcat-axis2 Not tested with jetty yet as geronimo jetty is throwing some NIO related exception in my windows machine and not starting. Will test it if in linux later for geronimo-jetty-cxf
        Hide
        Manu T George added a comment -

        Finally Some light on the issue. It seems the generated classes are placed in a randomly generated directory and that directory is not looked into by the application classloader. Adding that directory to the application classloaders URLs does the trick.

        Show
        Manu T George added a comment - Finally Some light on the issue. It seems the generated classes are placed in a randomly generated directory and that directory is not looked into by the application classloader. Adding that directory to the application classloaders URLs does the trick.
        Hide
        Manu T George added a comment -

        In case of this issue. I added a package-info.class in each of the packages and still axis was unable to even find the package-info class. Another observation here is that the algorithm to find the packages to search for jaxb classes doesn't find the generated classes or even the Customer class in this case both of which are in different packages. I was unable to figure out how to the option to make wsgen generate an ObjectFactory for each
        package.I also see that the generated classes are in a different package than the one their namespace specifi

        Show
        Manu T George added a comment - In case of this issue. I added a package-info.class in each of the packages and still axis was unable to even find the package-info class. Another observation here is that the algorithm to find the packages to search for jaxb classes doesn't find the generated classes or even the Customer class in this case both of which are in different packages. I was unable to figure out how to the option to make wsgen generate an ObjectFactory for each package.I also see that the generated classes are in a different package than the one their namespace specifi
        Hide
        Cedric Hurst added a comment -

        I've tried to deploy the sample EAR on Geronimo 2.1.1 from trunk and the issue appears to still exist.

        Show
        Cedric Hurst added a comment - I've tried to deploy the sample EAR on Geronimo 2.1.1 from trunk and the issue appears to still exist.
        Hide
        Jarek Gawor added a comment -

        This is actaully more convoluted that I initially thought.

        OpenEJB creates a URLClassLoader initialized with a temporary file created during deployment (OpenEJB_Generated_*). That URLClassLoader has the parent set to the application classloader. When the EJB WS is invoked the URLClassLoader is set on the thread. The test fails when the context classloader is set to the URLClassLoader but works fine when it is set to application classloader.
        Now, becuase there is no ObjectFactory.java or package-info.java classes present, Axis2 tries to discover the classes to include in the JAXBContext by scanning the jar files. To get the list of jar files to scan, it calls URLClassLoader.getURLs(). The OpenEJB generated URLClassLoader will return only one jar file that points to that temporary file. And since the file is empty in this case, the discovery will fail and no files will be included in the JAXB context. That explains why the test passes and fails with different context classloaders.

        So possible solutions/ideas are to:

        1) Create ObjectFactory.java, package-info.java classes to help Axis2 add classes to JAXB context
        2) Force for WS-calls, the application classloader instead of the OpenEJB generated one. But I'm afraid this will cause problems in some other cases.
        3) Improve Axis2 class finding algorithm to consider parents classloaders. Looks like should be fairly easy to do but not sure about the effort since this problem does not exist in 2.1-SNAPSHOT.
        4) ???

        Show
        Jarek Gawor added a comment - This is actaully more convoluted that I initially thought. OpenEJB creates a URLClassLoader initialized with a temporary file created during deployment (OpenEJB_Generated_*). That URLClassLoader has the parent set to the application classloader. When the EJB WS is invoked the URLClassLoader is set on the thread. The test fails when the context classloader is set to the URLClassLoader but works fine when it is set to application classloader. Now, becuase there is no ObjectFactory.java or package-info.java classes present, Axis2 tries to discover the classes to include in the JAXBContext by scanning the jar files. To get the list of jar files to scan, it calls URLClassLoader.getURLs(). The OpenEJB generated URLClassLoader will return only one jar file that points to that temporary file. And since the file is empty in this case, the discovery will fail and no files will be included in the JAXB context. That explains why the test passes and fails with different context classloaders. So possible solutions/ideas are to: 1) Create ObjectFactory.java, package-info.java classes to help Axis2 add classes to JAXB context 2) Force for WS-calls, the application classloader instead of the OpenEJB generated one. But I'm afraid this will cause problems in some other cases. 3) Improve Axis2 class finding algorithm to consider parents classloaders. Looks like should be fairly easy to do but not sure about the effort since this problem does not exist in 2.1-SNAPSHOT. 4) ???
        Hide
        Jarek Gawor added a comment -

        I can replicate this problem with 2.0.3-SNAPSHOT but not 2.1-SNAPSHOT.

        After a little debugging it looks like the something (maybe in OpenEJB) is changing the ClassLoader that is associated with the current thread of execution. And since the classloader gets changed to some other classloader, JAXB is unable to load/find the classes in the ejb jar file causing these exceptions.

        Show
        Jarek Gawor added a comment - I can replicate this problem with 2.0.3-SNAPSHOT but not 2.1-SNAPSHOT. After a little debugging it looks like the something (maybe in OpenEJB) is changing the ClassLoader that is associated with the current thread of execution. And since the classloader gets changed to some other classloader, JAXB is unable to load/find the classes in the ejb jar file causing these exceptions.
        Hide
        Daniel Kulp added a comment -

        Cedric,

        Can you send the full stack trace?

        Also, can you try adding an @XmlType annotation with a name attribute in addition to the XmlRootElement? That may allow it to work OK as their will be a type in addition to the global element.

        Show
        Daniel Kulp added a comment - Cedric, Can you send the full stack trace? Also, can you try adding an @XmlType annotation with a name attribute in addition to the XmlRootElement? That may allow it to work OK as their will be a type in addition to the global element.
        Hide
        Cedric Hurst added a comment - - edited

        Running with the Sun JDK allowed me to test CXF. CXF successfully returned List<String>, but also throws a "javax.xml.bind.JAXBException" when attempting to return an array of objects annotated with @XmlRootElement.

        Show
        Cedric Hurst added a comment - - edited Running with the Sun JDK allowed me to test CXF. CXF successfully returned List<String>, but also throws a "javax.xml.bind.JAXBException" when attempting to return an array of objects annotated with @XmlRootElement.
        Hide
        Cedric Hurst added a comment -

        EAR file and geronimo.log

        Show
        Cedric Hurst added a comment - EAR file and geronimo.log

          People

          • Assignee:
            Jarek Gawor
            Reporter:
            Cedric Hurst
          • Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development