Creating Custom JAX-RS MessageBodyReader
You can use a JAX-RS MessageBodyReader
to deserialize an entity on the server or client. Jersey already provides default deserializers like json and xml. This is just a demonstration how you can build your own deserializer.
JAX-RS MessageBodyReader
We consume a User
entity in xml representation.
package com.memorynotfound.jaxrs.chunked;
import javax.ws.rs.*;
@Path("/users")
public class UserResource {
@POST
@Consumes("application/xml")
public void getUser(User user){
System.out.println(user);
}
}
Here is the JAX-B mapping of the entity we are consuming.
package com.memorynotfound.jaxrs.chunked;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class User {
private Integer id;
private String name;
public User() {
}
public User(Integer id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
We create our deserializer by implementing the MessageBodyReader
interface and override the appropriate methods. The isReadable
method inspects if the deserializer is able to process the entity. The readFrom()
method does the real deserialization into a java object.
package com.memorynotfound.jaxrs.chunked;
import javax.ws.rs.Consumes;
import javax.ws.rs.ProcessingException;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.Provider;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import java.io.*;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
@Provider
@Consumes("application/xml")
public class UserMessageBodyReader implements MessageBodyReader<User> {
@Override
public boolean isReadable(Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
return type == User.class;
}
@Override
public User readFrom(Class<User> type, Type genericType, Annotation[] annotations,
MediaType mediaType, MultivaluedMap<String, String> httpHeaders,
InputStream entityStream) throws IOException, WebApplicationException {
try {
JAXBContext jaxbContext = JAXBContext.newInstance(User.class);
return (User) jaxbContext.createUnmarshaller().unmarshal(entityStream);
} catch (JAXBException e) {
throw new ProcessingException("Error deserializing user.", e);
}
}
}
Demo
When make a HTTP POST with the following xml message body to the resource: http://localhost:8081/jaxrs-message-body-reader/api/users.
<user>
<id>1</id>
<name>John Doe</name>
</user>
We print the following output to the console, indicating that the request is successfully parsed.
User{id=1, name='John Doe'}