> On 13 May 2014, at 21:13, michaelw@... wrote:
>
> > I ran wadl2java 1.1.6 to generate JavaBeans from WADL and used the
> > beans in my Jersey 2.7 client. There are no problems unmarshalling
an
> > XML response using the generated beans. However, if a request body
> > content is XML, marshalling fails with an exception:
> >
> >
org.glassfish.jersey.message.internal.WriterInterceptorExecutor$Termina
> > lWriterInterceptor aroundWriteTo
> > SEVERE: MessageBodyWriter not found for media type=application/xml,
> > type=class com.ltree.airportweather.AirportInfo,
> > genericType=class com.ltree.airportweather.AirportInfo.
> >
> > If I manually add @XmlRootElement to the generated bean, the
request
> > succeeds.
>
> Can you show me the code snippet you use to invoke the service using
the
> client
> as you did below? And also the body of the client method it is
calling.
Here's my code:
String driverPostString =
AirportWeatherRestClient.weather()
.postXmlAsTextPlain(airportInfoBean,
String.class);
And here's the method generated by wadl2java:
public<T >T postXmlAsTextPlain(Object input, GenericType<T>
returnType) {
UriBuilder localUriBuilder = _uriBuilder.clone();
WebTarget resource =
_client.target(localUriBuilder.buildFromMap(
_templateAndMatrixParameterValues));
javax.ws.rs.client.Invocation.Builder resourceBuilder =
resource.request("text/plain");
Response response;
response = resourceBuilder.build("POST", Entity.entity(input,
"application/xml")).invoke();
if (response.getStatus()>= 400) {
throw new
AirportWeatherRestClient.WebApplicationExceptionMessage(response);
}
return response.readEntity(returnType);
}
> > I get the same result when sending requests from the generated
custom
> > class (i.e., the generated JAX-RS client with methods for all the
> > requests in the WADL).
> >
> > Here's my code:
> >
> > AirportInfo airportInfoBean = new AirportInfo(); // generated by
> > wadl2java
> > ...
> > Client client = ClientBuilder.newClient();
> > String responseFromPost =
> > client.target(BASE_URL)
> > .request(MediaType.TEXT_PLAIN)
>
> > .post(Entity.xml(airportInfoBean), String.class);
>
> This is an odd formulation, why are you using Entity.xml,
I'm following examples in the Java EE 7 tutorial, e.g. section
30.1.1.4:
TrackingNumber trackingNumber =
myResource.request(MediaType.APPLICATION_XML)
.post(Entity.xml(order), TrackingNumber.class);
I checked the source, and Entity.xml(obj) is a wrapper for new
Entity.entity(obj, MediaType.APPLICATION_XML_TYPE). Is there a better
way? I'm new to JAX-RS, so any suggestions for good practices are
welcome.
> I suspect that give your model you will need to use:
>
> .post(new JAXBElment(new QName(….), AirportInfoBean.class,
> airportInfoBean),String.class);
>
> The problem here is that the AirportInfo object in a @XmlType and you
need to
> provide the specific name in order to map this to a xml element / or
just
> just the XmlRootElement annotation on it as you did above if the
names match.
Ok, I added a JAXBElement to the call, and the marshalling to XML
succeeds:
JAXBElement<AirportInfo> airportInfoElement =
new JAXBElement<>(new QName("airportInfo"), AirportInfo.class,
airportInfoBean);
String responseFromXml =
webTarget.request(MediaType.TEXT_PLAIN)
.post(Entity.xml(airportInfoElement), String.class);
However, if I replace Entity.xml() with Entity.json(), the client
throws this exception:
SEVERE: MessageBodyWriter not found for media type=application/json,
type=class javax.xml.bind.JAXBElement,
genericType=class javax.xml.bind.JAXBElement.
If I add @XmlRootElement to the generated bean, the JSON request
succeeds (without the JAXBElement).
Here's the relevant portion of the schema generated by wadl2java:
<xs:schema version="1.0" xmlns:xs="
http://www.w3.org/2001/XMLSchema">
<xs:element name="airportInfo" type="airportInfo"/>
<xs:complexType name="airportInfo">
<xs:sequence>
<xs:element name="airportCode" type="xs:string" minOccurs="0"/>
<xs:element name="associatedCity" type="xs:string"
minOccurs="0"/>
<xs:element name="elevation" type="xs:double" minOccurs="0"/>
<xs:element name="latitude" type="xs:decimal" minOccurs="0"/>
<xs:element name="longitude" type="xs:decimal" minOccurs="0"/>
<xs:element name="name" type="xs:string" minOccurs="0"/>
</xs:sequence>
</xs:complexType>