user2268507
user2268507

Reputation:

Jersey Client to save response from REST Call into custom object

My REST service outputs @Produces(MediaType.APPLICATION_XML). This is converted from:

ArrayList<CoffeeOrder> orders = new ArrayList<CoffeeOrder>();

GenericEntity<ArrayList<CoffeeOrder> > entity = new GenericEntity<ArrayList<CoffeeOrder> >(orders) {};

 ....

return Response.status(Response.Status.OK).entity(entity).build();  

Example:

<coffeeOrders>
  <coffeeOrder>
    <id>2</id>
    <links>http://localhost:9080/cs9322.ass2/rest/coffee/2</links>
    <links>http://localhost:9080/cs9322.ass2/rest/payment/2</links>
  </coffeeOrder>
<coffeeOrder>
  <id>1</id>
  <links>http://localhost:9080/cs9322.ass2/rest/coffee/1</links>
  <links>http://localhost:9080/cs9322.ass2/rest/payment/1</links>
</coffeeOrder>

In my client, I want to call this service and save the response as an ArrayList<CoffeeOrder>.

CoffeeOrder looks something like this:

public class CoffeeOrder {

   private String id;

   private ArrayList<String> links = new ArrayList<String>();

   ...
}

Is there a way that I can fill this object with the response from the REST request?

Thank you for your help!

Upvotes: 0

Views: 1317

Answers (1)

Paul Samsotha
Paul Samsotha

Reputation: 208944

My suggestion is to use JAXB annotations. As noted from Jersey Tutorial, " Jersey contains default support for entity providers that can serialize JAXB beans into XML"

So you could create a CoffeeOrders class, that holds a List<CoffeeOrder>. Something like

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class CoffeeOrders {

    @XmlElement(name = "coffeOrder")
    protected List<CoffeeOrder> coffeeOrders;

    // GETTER and SETTERS

    public void addCoffeeOrder(CoffeeOrder coffeeOrder) {
        if (coffeeOrders == null) {
            coffeeOrders = new ArrayList<>();
        }
        coffeeOrders.add(coffeeOrder);
    }
}

Your response could simply be

CoffeeOrders orders = new CoffeeOrders();
// add CoffeeOrder(s) to list in orders
return Response.ok(orders).build();

As far as the <links> go, it seems you are trying to implements some HATEOAS format. I'd suggest maybe using the Link class to create links. You can have a List<Link> in the CoffeeOrder class.

@XmlAccessorType(XmlAccessType.FIELD)
public class CoffeeOrder {

    @XmlElement
    protected String id;

    @XmlElement(name = "link")
    @XmlJavaTypeAdapter(Link.JaxbAdapter.class)
    protected List<Link> links;

    // GETTERS and SETTERS
}

And (not so great) example of a response could be something like

@Path("/coffee")
public class CoffeeResource {

    @GET
    @Produces(MediaType.APPLICATION_XML)
    public Response getCoffeOrders(@Context UriInfo uriInfo) {
        UriBuilder builder = uriInfo.getBaseUriBuilder();
        CoffeeOrders orders = new CoffeeOrders();

        CoffeeOrder order = new CoffeeOrder();
        order.setId("1");

        List<Link> links = new ArrayList<>();
        URI coffee = builder.clone().path("coffee").path("1").build();
        Link coffeeLink = Link.fromUri(coffee).rel("coffee1")
                .type(MediaType.APPLICATION_XML).build();
        links.add(coffeeLink);

        URI payment = builder.clone().path("payment").path("1").build();
        Link paymentLink = Link.fromUri(coffee).rel("payment1")
                .type(MediaType.APPLICATION_XML).build();
        links.add(coffeeLink);

        order.setLinks(links);
        orders.addCoffeeOrder(order);

        return Response.ok(orders).build();
    }
}

Receiving the Response might look something like

@Test
public void testGetIt() throws Exception {
    Response response = target.path("coffee").request().get();
    CoffeeOrders order = response.readEntity(CoffeeOrders.class);
    response.close();
    JAXBContext context = JAXBContext.newInstance(CoffeeOrders.class);
    Marshaller marshaller = context.createMarshaller();
    marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
    marshaller.marshal(order, System.out);
}

And the result

<coffeeOrders>
    <coffeOrder>
        <id>1</id>
        <link href="http://localhost:8080/myapp/coffee/1" rel="coffee1" type="application/xml"/>
        <link href="http://localhost:8080/myapp/coffee/1" rel="coffee1" type="application/xml"/>
    </coffeOrder>
</coffeeOrders>

To receive a POST with the CoffeeOrders object, just use the same xml accept type. The Jersey runtime will parse the xml for you, based on the JAXB annotations you provided.


Some resources:

Upvotes: 1

Related Questions