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

Reply via email to