[JAX-RS] Implementing custom MessageBodyWriter for serialization

Say you want to serialize your object in a custom format. For XML you can use JAXB, for JSON you can use Jackson. But in case you have your own specific format, you need to implement your own MessageBodyWriter.

1. Maven web application – pom.xml (here jersey 1.19, feel free to upgrade):

 

2. Application class. Note that besides the actual resource class, you need to also add your custom writer.
package com.vvirlan;

import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.ApplicationPath;
import com.vvirlan.resources.CustomerResource;
import com.vvirlan.resources.MyCustomWriter;

@ApplicationPath(“rest”)
public class Application extends javax.ws.rs.core.Application{
@Override
public Set<Class<?>> getClasses() {
Set<Class<?>> classes = new HashSet<Class<?>>();
classes.add(CustomerResource.class);
classes.add(MyCustomWriter.class);
return classes;
}
}

 

3. The resource class (CustomerResource):
package com.vvirlan.resources;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path(“customers”)
@Produces(MediaType.TEXT_PLAIN)
public class CustomerResource {
@GET
@Path(“c”)
@Pretty
public Customer getCustomer() {
return new Customer(“A”,2,2);
}
}

4. The Customer object:
package com.vvirlan.resources;

//My custom annotation (makes it eligible for my serialization)
@MyContent
public class Customer {

private String name;
private int age;
private int size;

//Mandatory
public Customer() {

}

public Customer(String name, int age, int size) {
this.name = name;
this.age = age;
this.size = size;
}

// Getters and setters
}

5. My MyContent annotation

package com.vvirlan.resources;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyContent {

}

6. The actual custom body writer:

package com.vvirlan.resources;

import java.io.IOException;
import java.io.OutputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;

import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlRootElement;

@Provider
@Produces(MediaType.TEXT_PLAIN)
public class MyCustomWriter implements MessageBodyWriter<Customer> {

public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
boolean present = type.isAnnotationPresent(MyContent.class);
return present;
}

public long getSize(Customer t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
// Leave it to Jersey to put content-length
return -1;
}

public void writeTo(Customer t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream)
throws IOException, WebApplicationException {

// Here reflection may be used to get the custom serialization
StringBuilder sb = new StringBuilder();
sb.append(“Name: ” + t.getName() + ” Age: ” + t.getAge() + ” Size: ” + t.getSize());

entityStream.write(sb.toString().getBytes());

}
}

7. Accessing the application at:
http://localhost:8080/yourprojectname/rest/customers/c/

And you will see:
Name: A Age: 2 Size: 2

Leave a Reply

Your email address will not be published. Required fields are marked *