Returning complex data types in @WebResult

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Returning complex data types in @WebResult

Cedric Hurst
I'm working on a tutorial for EJB3 and JAX-WS generation and I'm running into a problem returning any non-primitive result.  In this example, I have an @Entity called Customer, and I'm exposing a @WebMethod called findCustomerByName which takes a String and returns a List of Customers whose names match that String.  See implementation here:

http://svn2.assembla.com/svn/d5Z24gWSer3lvHabIlDkbG/ComplexDataTypeWSExampleEJB/ejbModule/com/gmail/at/cedrichurst/complexDataTypeWSExampleEJB/ejb/CustomerSearchBean.java

When I call this method, I get the following error:

17:51:44,890 INFO  [Transaction] TX Required: Started transaction org.apache.geronimo.transaction.manager.TransactionImpl@5c985c98
17:51:44,906 ERROR [OpenEJB] The bean instances business method encountered a system exception: javax.xml.bind.MarshalException
 - with linked exception:
[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:378)
        at org.apache.geronimo.axis2.Axis2WebServiceContainer.doService2(Axis2WebServiceContainer.java:248)
        at org.apache.geronimo.axis2.Axis2WebServiceContainer.doService(Axis2WebServiceContainer.java:205)
        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:104)
        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:261)
        at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:581)
        at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
        at java.lang.Thread.run(Thread.java:801)
Caused by:
javax.xml.bind.MarshalException
 - with linked exception:
[javax.xml.bind.JAXBException: java.util.List is not known to this context]
        at com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:295)
        at com.sun.xml.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:148)
        at org.apache.axis2.jaxws.message.databinding.impl.JAXBBlockImpl$2.run(JAXBBlockImpl.java:402)
        ... 46 more


Of course, I can see why Axis2 would have a problem returning a java.util.List, but I need to be able to return multiple results somehow.  Any suggestions?
Reply | Threaded
Open this post in threaded view
|

Re: Returning complex data types in @WebResult

Dain Sundstrom
FWIU, JaxWS requires that all complex type be annotated with JaxB  
annotations (this is why the root most exception is a JAXBException).  
These annotations tell JaxWS how to convert between XML and the Java  
Object.

I think (and I'm not JaxWS expert) you only need to add @XmlType or  
@XmlRootElement to your Customer class, but you may want to check the  
Axis2 docs.

-dain

On Jan 26, 2008, at 3:57 PM, Cedric Hurst wrote:

>
> I'm working on a tutorial for EJB3 and JAX-WS generation and I'm  
> running into
> a problem returning any non-primitive result.  In this example, I  
> have an
> @Entity called Customer, and I'm exposing a @WebMethod called
> findCustomerByName which takes a String and returns a List of  
> Customers
> whose names match that String.  See implementation here:
>
> http://svn2.assembla.com/svn/d5Z24gWSer3lvHabIlDkbG/ComplexDataTypeWSExampleEJB/ejbModule/com/gmail/at/cedrichurst/complexDataTypeWSExampleEJB/ejb/CustomerSearchBean.java
>
> When I call this method, I get the following error:
>
> 17:51:44,890 INFO  [Transaction] TX Required: Started transaction
> org.apache.geronimo.transaction.manager.TransactionImpl@5c985c98
> 17:51:44,906 ERROR [OpenEJB] The bean instances business method  
> encountered
> a system exception: javax.xml.bind.MarshalException
> - with linked exception:
> [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:378)
> at
> org
> .apache
> .geronimo
> .axis2
> .Axis2WebServiceContainer.doService2(Axis2WebServiceContainer.java:
> 248)
> at
> org
> .apache
> .geronimo
> .axis2
> .Axis2WebServiceContainer.doService(Axis2WebServiceContainer.java:205)
> 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:104)
> 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:
> 261)
> at
> org
> .apache.coyote.http11.Http11Processor.process(Http11Processor.java:
> 844)
> at
> org.apache.coyote.http11.Http11Protocol
> $Http11ConnectionHandler.process(Http11Protocol.java:581)
> at org.apache.tomcat.util.net.JIoEndpoint
> $Worker.run(JIoEndpoint.java:447)
> at java.lang.Thread.run(Thread.java:801)
> Caused by:
> javax.xml.bind.MarshalException
> - with linked exception:
> [javax.xml.bind.JAXBException: java.util.List is not known to this  
> context]
> at
> com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:
> 295)
> at
> com
> .sun.xml.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:
> 148)
> at
> org.apache.axis2.jaxws.message.databinding.impl.JAXBBlockImpl
> $2.run(JAXBBlockImpl.java:402)
> ... 46 more
>
> Of course, I can see why Axis2 would have a problem returning a
> java.util.List, but I need to be able to return multiple results  
> somehow.
> Any suggestions?
> --
> View this message in context: http://www.nabble.com/Returning-complex-data-types-in-%40WebResult-tp15114306p15114306.html
> Sent from the OpenEJB User mailing list archive at Nabble.com.
>

Reply | Threaded
Open this post in threaded view
|

Re: Returning complex data types in @WebResult

Cedric Hurst
Thanks for the suggestion, Dain.

I tried adding the @XmlType annotation:

http://trac2.assembla.com/d5Z24gWSer3lvHabIlDkbG/browser/ComplexDataTypeWSExampleEJB/ejbModule/com/gmail/at/cedrichurst/complexDataTypeWSExampleEJB/domain/Customer.java?rev=24

...but referencing the object in the @WebReturn resulted in a classloading error for geronimo's wsgen tool (the jar for "javax.xml.bind" is included but the jar for "javax.xml.bind.annotation" is not).  I'm pretty sure that is a Geronimo-specific issue because I ran into a similar problem generating WSDL files which return @Entity classes.  So, I'll take that issue to the Geronimo mailing list or open a JIRA.

In the meantime, there still seems to be an issue returning any kind of java.util.List in a @WebService.  To test this out, I replaced the return type of List<Customer> with List<String>

http://trac2.assembla.com/d5Z24gWSer3lvHabIlDkbG/browser/ComplexDataTypeWSExampleEJB/ejbModule/com/gmail/at/cedrichurst/complexDataTypeWSExampleEJB/ejb/CustomerSearchBean.java?rev=23

And I'm still getting the "java.util.List is not known to this context" error.

However, I have noticed that if I return a String[]:

http://trac2.assembla.com/d5Z24gWSer3lvHabIlDkbG/browser/ComplexDataTypeWSExampleEJB/ejbModule/com/gmail/at/cedrichurst/complexDataTypeWSExampleEJB/ejb/CustomerSearchBean.java?rev=24

...it seems to work just fine.  So that will probably do for now.

Dain Sundstrom wrote
FWIU, JaxWS requires that all complex type be annotated with JaxB  
annotations (this is why the root most exception is a JAXBException).  
These annotations tell JaxWS how to convert between XML and the Java  
Object.

I think (and I'm not JaxWS expert) you only need to add @XmlType or  
@XmlRootElement to your Customer class, but you may want to check the  
Axis2 docs.

-dain
Reply | Threaded
Open this post in threaded view
|

Re: Returning complex data types in @WebResult

Cedric Hurst
Update: I was able to get around Geronimo's wsgen error by using @XmlRootElement instead of @XmlType:

http://trac2.assembla.com/d5Z24gWSer3lvHabIlDkbG/browser/ComplexDataTypeWSExampleEJB/ejbModule/com/gmail/at/cedrichurst/complexDataTypeWSExampleEJB/domain/Customer.java?rev=25

But now, if I change the return type to Customer[] on my session bean:

http://trac2.assembla.com/d5Z24gWSer3lvHabIlDkbG/browser/ComplexDataTypeWSExampleEJB/ejbModule/com/gmail/at/cedrichurst/complexDataTypeWSExampleEJB/ejb/CustomerSearchBean.java?rev=25

...I get the following error:

[javax.xml.bind.JAXBException: [Lcom.gmail.at.cedrichurst.complexDataTypeWSExampleEJB.domain.Customer; is not known to this context]
        at com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:295)
        at com.sun.xml.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:148)
        at org.apache.axis2.jaxws.message.databinding.impl.JAXBBlockImpl$2.run(JAXBBlockImpl.java:402)
        ... 46 more



There must be something else I'm missing.
Reply | Threaded
Open this post in threaded view
|

Re: Returning complex data types in @WebResult

Dain Sundstrom
Sounds like Geronimo or Axis2 is not properly setting up the JaxB  
context.  I've used CXF and lists worked for me.

-dain

On Jan 26, 2008, at 11:02 PM, Cedric Hurst wrote:

>
> Update: I was able to get around Geronimo's wsgen error by using
> @XmlRootElement instead of @XmlType:
>
> http://trac2.assembla.com/d5Z24gWSer3lvHabIlDkbG/browser/ComplexDataTypeWSExampleEJB/ejbModule/com/gmail/at/cedrichurst/complexDataTypeWSExampleEJB/domain/Customer.java?rev=25
>
> But now, if I change the return type to Customer[] on my session bean:
>
> http://trac2.assembla.com/d5Z24gWSer3lvHabIlDkbG/browser/ComplexDataTypeWSExampleEJB/ejbModule/com/gmail/at/cedrichurst/complexDataTypeWSExampleEJB/ejb/CustomerSearchBean.java?rev=25
>
> ...I get the following error:
>
> [javax.xml.bind.JAXBException:
> [Lcom
> .gmail.at.cedrichurst.complexDataTypeWSExampleEJB.domain.Customer; is
> not known to this context]
> at
> com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:
> 295)
> at
> com
> .sun.xml.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:
> 148)
> at
> org.apache.axis2.jaxws.message.databinding.impl.JAXBBlockImpl
> $2.run(JAXBBlockImpl.java:402)
> ... 46 more
>
>
>
> There must be something else I'm missing.
> --
> View this message in context: http://www.nabble.com/Returning-complex-data-types-in-%40WebResult-tp15114306p15116554.html
> Sent from the OpenEJB User mailing list archive at Nabble.com.
>

Reply | Threaded
Open this post in threaded view
|

Re: Returning complex data types in @WebResult

Cedric Hurst
I tested with CXF and List<String> seems to work.  However, I'm getting a "not known to this context" error for returns of type Customer[].  Do I need to do something else to add my Customer class to the JaxB context?

Dain Sundstrom wrote
Sounds like Geronimo or Axis2 is not properly setting up the JaxB  
context.  I've used CXF and lists worked for me.

-dain