Marshal / Un Marshal List of objects in Jersey JAX-RS using JAXB
Good morning. This morning as I go through the Jersey Entity providers MessageBodyReader
and MessageBodyWriter
I am facing the following problem.
I want to write a resource method and client that returns a list of custom objects and the media type is application/xml
. So I would like to use JAXB (I'm new to JAXB). I was able to achieve this by writing my own extended MessageBodyReader
and MessageBodyWriter
. But I am afraid of the way I follow. Just see how I have implemented:
Resource method:
@Path("productlist/xml")
@GET
public RetObjects getProductsXml(){
List<Product> pList = new ArrayList<Product>();
pList.add(new Product("1","Dell latitude E6000",2900,500));
pList.add(new Product("2","Xperia Z2",549,400));
RetObjects obj = new RetObjects();
obj.setObject(pList);
return obj;
}
My custom objects:
@Entity
@Table (name="PRODUCT")
@XmlRootElement(name="product")
public class Product {
@Id
@Column(name = "CODE")
private String code;
...
// rest of the fields, constructors, getters and setters
}
The object that wraps my custom object list:
@XmlRootElement(name = "products")
@XmlAccessorType (XmlAccessType.FIELD)
public class RetObjects {
@XmlElement(name = "product")
private List<Product> object = null;
public List<Product> getObject() {
return object;
}
public void setObject(List<Product> object) {
this.object = object;
}
}
MessageBodyReader/Writer
are straight forward using Jaxb unmarshaller and marshaller over the object RetObjects
.
With this implementation, it works fine as expected and I can get RetObjects
the Product listing completion perfectly fine on the client.
My question here is that instead of my product list in an intermediate object, RetObjects
in my case, I could not marshal and redirect the product list right away. If I want to write another service that returns a list of orders, I need to wrap this with another intermediate object. What is the correct approach to achieve this? How could I do this without intermediate objects?
source to share
The first
You don't need yours MessageBodyWriter/Reader
. Jersey / JAX -RS alread has standard support for this. I would stick with the default unless you have a really good reason to hack.
Second
We don't need a shell, you can just return it GenericEntity
. This will automatically wrap items in a multiple wrapper element, i.e. <product>
→ <products>
.
List<Product> list = new ArrayList<>();
GenericEntity<List<String>> entity = new GenericEntity<List<Product>>(list) {};
Response response = Response.ok(entity).build();
To accept a body in a resource method, you just need to accept it List<Product>
as an argument. He will accept<products><product/><product/></products>
UPDATE
To get List<Product>
client side, we have to use GenericType
. Se this post .
Jersey 1
WebResource resource = client.resource("...");
List<Product> products = resource.get(new GenericType<List<Product>>(){});
Jersey 2 / JAX-RS 2
Response response = ...
List<Product> products = response.readEntity(new GenericType<List<Product>>(){});
source to share