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