You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by Mickael Marrache <Mi...@xconnect.net> on 2012/10/12 11:44:21 UTC
XmlRootElement annotation and marshalling error
Hi,
I'm working on a REST web service. In my WADL, I've defined only one resource B where I define multiple possible operations on B (GET, PUT, DELETE...). I also import in my WADL, a XML schema where B is declared using a complexType but without defining a root element. After generating my code using WADL2Java plugin, I get the resource interface of B and the classes generated from my schema. As expected, the class B (corresponding to the complexType B) is not annotated with @XmlRootElement. So, when I call the GET method on a given resource of type B, I get an error since the resource can't be marshaled.
I've looked on the web for a solution and I've found this blog http://blog.bdoughan.com/2012/07/jaxb-and-root-elements.html. It seems that the solution is to create JAXBElement's that wrap my B instances. But, I don't understand how it works in the context of a REST service.
Here's my WADL:
<?xml version="1.0"?>
<application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://wadl.dev.java.net/2009/02 http://www.w3.org/Submission/wadl/wadl.xsd"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://wadl.dev.java.net/2009/02"
xmlns:srvcb="com:mycomp:service:base">
<grammars>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="com:mycomp:service:rest">
<import namespace="com:mycomp:service:base"
schemaLocation="schema.xsd" />
</schema>
</grammars>
<resources base="REPLACE_WITH_THE_BASE_URL">
<resource id="BResource" path="/B/{id}">
<method id="getB" name="GET">
<request>
<param name="id" style="template" type="xsd:string" />
</request>
<response status="200">
<representation mediaType="application/xml" element="srvcb:BType" />
</response>
</method>
</resource>
</resources>
</application>
I get the following interface:
@Path("/B/{id}")
public interface BResource {
@GET
@Produces("application/xml")
BType getB(@PathParam("id") String id);
}
I don't understand how can I create a JAXBElement that wraps my BType's instance and also, how all of this works in this context. The getB method returns an instance of BType, not a JAXBElement instance. I'm confused.
Thanks,
Mickael
Re: XmlRootElement annotation and marshalling error
Posted by Sergey Beryozkin <sb...@gmail.com>.
Hi
On 12/10/12 10:44, Mickael Marrache wrote:
> Hi,
>
> I'm working on a REST web service. In my WADL, I've defined only one resource B where I define multiple possible operations on B (GET, PUT, DELETE...). I also import in my WADL, a XML schema where B is declared using a complexType but without defining a root element. After generating my code using WADL2Java plugin, I get the resource interface of B and the classes generated from my schema. As expected, the class B (corresponding to the complexType B) is not annotated with @XmlRootElement. So, when I call the GET method on a given resource of type B, I get an error since the resource can't be marshaled.
>
> I've looked on the web for a solution and I've found this blog http://blog.bdoughan.com/2012/07/jaxb-and-root-elements.html. It seems that the solution is to create JAXBElement's that wrap my B instances. But, I don't understand how it works in the context of a REST service.
>
> Here's my WADL:
>
> <?xml version="1.0"?>
> <application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
> xsi:schemaLocation="http://wadl.dev.java.net/2009/02 http://www.w3.org/Submission/wadl/wadl.xsd"
> xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://wadl.dev.java.net/2009/02"
> xmlns:srvcb="com:mycomp:service:base">
>
> <grammars>
> <schema xmlns="http://www.w3.org/2001/XMLSchema"
> targetNamespace="com:mycomp:service:rest">
> <import namespace="com:mycomp:service:base"
> schemaLocation="schema.xsd" />
> </schema>
> </grammars>
>
> <resources base="REPLACE_WITH_THE_BASE_URL">
> <resource id="BResource" path="/B/{id}">
> <method id="getB" name="GET">
> <request>
> <param name="id" style="template" type="xsd:string" />
> </request>
> <response status="200">
> <representation mediaType="application/xml" element="srvcb:BType" />
> </response>
> </method>
> </resource>
> </resources>
> </application>
>
> I get the following interface:
>
> @Path("/B/{id}")
> public interface BResource {
>
> @GET
> @Produces("application/xml")
> BType getB(@PathParam("id") String id);
>
> }
>
> I don't understand how can I create a JAXBElement that wraps my BType's instance and also, how all of this works in this context. The getB method returns an instance of BType, not a JAXBElement instance. I'm confused.
>
At the moment, if you have @XmlType annotated classes in the signature,
then CXF JAXBElementProvider needs to be explicitly configured to be
marshalled (and unmarshalled) as JAXBElements, for example:
<bean id="jaxbProvider"
class="org.apache.cxf.jaxrs.provider.JAXBElementProvider">
<property name="marshalAsJaxbElement" value="true"/>
</bean>
...
<jaxrs:providers>
<ref bean="jaxbProvider"/>
</jaxrs:providers>
Glen has raised this issue recently and perhaps we should make
@XmlType-classes auto-wrapped. One potential problem with auto-wrapping
is that the representation is not guaranteed to match the schema.
For example, suppose you have
<xs:element name="theBar" type="tns:bar"/>
<xs:complexType name="bar">
...
</xs:complexType>
and
@GET
public Bar getBar() {}
There's no way auto-wrapping will guess that the name of the root
element has to be "theBar".
I think I've just convinced myself that we should not do auto-wrapping :-)
So, please configure JAXBElementProvider as suggested above, and
additionally, consider adding a jaxbElementClassNames map property
(class name: key, expected root element name - value) to make sure the
representation matches the schema.
Alternatively, update the schema to use anonymous types - that will get
@XmlRootElement added. Yet another option is to configure jaxb plugin to
do it - I think I saw someone doing it,
HTH, Sergey
> Thanks,
> Mickael
>
--
Sergey Beryozkin
Talend Community Coders
http://coders.talend.com/
Blog: http://sberyozkin.blogspot.com