jtiger
jtiger

Reputation: 473

Jersey client not setting fields during XML deserialization

I'm working on setting up a Jersey JAX-RS client to deserialize XML provided by a .NET Web API service. I'm hitting a road block where I'm making a call to get a collection of objects. I'm able to receive the collection on the Jersey client, however, none of the fields on the objects are being set.

The XML:

<?xml version="1.0"?>
<ArrayOfEvent xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/TestApi.Models">
<Event>
    <Id>3</Id>
    <MeetingId>444</MeetingId>
    <Name>Jon's Meeting</Name>
</Event>
<Event>
    <Id>134</Id>
    <MeetingId>234</MeetingId>
    <Name>Super meeting</Name>
</Event>
<Event>
    <Id>43</Id>
    <MeetingId>9966</MeetingId>
    <Name>Test meeting!</Name>
</Event>
</ArrayOfEvent>

The client class:

@XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)
@XmlType(name="Event")
public class Event {
    public int Id;

    public int MeetingId;

    public String Name;

    @Override
    public String toString(){
        return String.format("%s, %s, %s", Id, MeetingId, Name);
    }
}

The client code:

 WebTarget target = client.target(baseUrl);

 target = target.path("Event");

 List<Event> events = target.request(MediaType.APPLICATION_XML).get(new GenericType<List<Event>>() {});
 for (Event e: events){
     System.out.println(e.toString());
 }

The result of print:

0, 0, null
0, 0, null
0, 0, null

I have tried adding @XmlElement to the properties and specifying the name with no luck. I've also reviewed these questions:

Jersey client xml collection

Jersey jax-rs client xml to java list deserialization

They seem straight forward enough, but I can't get the same results. From the first question, using XmlRootElement on the Event class throws an exception. The second question is what led me to correctly deserializing the collection, but missing the field data.

How do I set this up to correctly deserialize the fields?

Edit: I have also tried doing this using a root element.

The root element class:

@XmlRootElement(name="ArrayOfEvent", namespace="http://schemas.datacontract.org/2004/07/TestApi.Models")
@XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)
public class EventSearch {

    public List<Event> Events;
}

The client class:

WebTarget target = client.target(baseUrl);

target = target.path("Event");

EventSearch search = target.request(MediaType.APPLICATION_XML).get(EventSearch.class);

When I do it this way, the Events field on EventSearch is null, so I don't even get the collection deserialized.

Upvotes: 2

Views: 1283

Answers (1)

bdoughan
bdoughan

Reputation: 149017

By default JAXB will convert the field called Id to an element called id to get the element names you want you will need to use the @XmlElement annotation.

@XmlElement(name="Id")
public int Id;

You also need to map the namespace qualification. This is done using the package level @XmlSchema annotation. To do this add a source file called package-info.java in the same package as your model with the following content (modify the package to match your own).

@XmlSchema( 
    namespace = "http://schemas.datacontract.org/2004/07/TestApi.Models", 
    elementFormDefault = XmlNsForm.QUALIFIED) 
package your_package;

import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;

I have written more about JAXB and namespace qualification on my blog:

Upvotes: 2

Related Questions