blogger templates blogger widgets
This is part of a list of blog posts.
To browse the contents go to

JAX-RS: Sending/Receiving objects

Note that all primitive datatypes are converted to Wrapper classes. So all we need to discuss is how to send as a response or request to a REST application without doing any custom string/json/xml conversion.

First let's write a service that returns integer as string.
@Path("/hello")
public class HelloResource {
 private static String[] response = { "apple", "banana", "mango" };

 @Path("/fruit")
 @POST
 public String getFruit(String index) {
  System.out.println(index);
  return response[Integer.parseInt(index) % 3];
 }
}

Client code,
String lsUrl = "http://localhost:9080/RSServer/HelloApp/hello/fruit";
RestClient client = new RestClient();
Resource resource = client.resource(lsUrl);
ClientResponse result = resource.contentType(MediaType.TEXT_PLAIN).post("1");
System.out.println(result.getEntity(String.class));

Output:
1
banana


Let's now try to return Integer.

@Path("/hello")
public class HelloResource {
 private static String[] response = { "apple", "banana", "mango" };
 
 @Path("/fruit")
 @POST
 public Integer getFruit(int index) {
  System.out.println(index);
  return response[index % 3];
 }
}

Client code,
String lsUrl = "http://localhost:9080/RSServer/HelloApp/hello/fruit";
RestClient client = new RestClient();
Resource resource = client.resource(lsUrl);
//ClientResponse result = resource.contentType(MediaType.TEXT_PLAIN).post(1);
// cannot do like this
//java.lang.RuntimeException: A javax.ws.rs.ext.MessageBodyWriter implementation was not found for the class java.lang.Integer type and text/plain media type.

Couldn't find a workaround for this using Wink/IBM implementation but there seems to be a way to do it using jersy as explained here

Another approach is to represent a mime type corresponding to your data and create custom entity providers.
By adding a custom entity provider, you can de-serialize custom Java types from message bodies and serialize any media type as message bodies.

Let's say you have object of class MyObject.

import java.io.Serializable;

public class MyObject implements Serializable {
 public static final String MIME_TYPE = "application/myType";

 private int index;

 public MyObject() {
 }

 public MyObject(int index) {
  this.index = index;
 }

 public int getIndex() {
  return index;
 }

 public void setIndex(int index) {
  this.index = index;
 }
}

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;

import javax.ws.rs.Consumes;
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;

@Provider
@Consumes(MyObject.MIME_TYPE)
public class MyReader implements MessageBodyReader<myobject> {

 @Override
 public boolean isReadable(Class<?> type, Type type1, Annotation[] antns,
   MediaType mt) {
  return MyObject.class.isAssignableFrom(type);
 }

 @Override
 public MyObject readFrom(Class<myobject> type, Type type1,
   Annotation[] antns, MediaType mt,
   MultivaluedMap<String, String> mm, InputStream in)
   throws IOException, WebApplicationException {
  try {
   ObjectInputStream ois = new ObjectInputStream(in);
   return (MyObject) ois.readObject();
  } catch (ClassNotFoundException ex) {
   ex.printStackTrace();
  }
  return null;
 }
}

import java.io.IOException;
import java.io.ObjectOutputStream;
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;

@Provider
@Produces(MyObject.MIME_TYPE)
public class MyWriter implements MessageBodyWriter<myobject> {

 @Override
 public boolean isWriteable(Class<?> type, Type type1, Annotation[] antns,
   MediaType mt) {
  return MyObject.class.isAssignableFrom(type);
 }

 @Override
 public long getSize(MyObject t, Class<?> type, Type type1,
   Annotation[] antns, MediaType mt) {
  // As of JAX-RS 2.0, the method has been deprecated and the
  // value returned by the method is ignored by a JAX-RS runtime.
  // All MessageBodyWriter implementations are advised to return -1 from
  // the method.

  return -1;
 }

 @Override
 public void writeTo(MyObject t, Class<?> type, Type type1,
   Annotation[] antns, MediaType mt,
   MultivaluedMap<String, Object> mm, OutputStream out)
   throws IOException, WebApplicationException {
  ObjectOutputStream oos = new ObjectOutputStream(out);
  oos.writeObject(t);
 }
}


Client code,
//note that client needs access to Writer and Reader classes.
ClientConfig clientConfig = new ClientConfig();
Application app = new javax.ws.rs.core.Application() {
 public Set<Class<?>> getClasses() {
  Set<Class<?>> classes = new HashSet<Class<?>>();
  classes.add(MyReader.class);
  classes.add(MyWriter.class);
  return classes;
 }
};
clientConfig.applications(app);

String lsUrl = "http://localhost:9080/RSServer/HelloApp/hello/fruit";
RestClient client = new RestClient(clientConfig);
Resource resource = client.resource(lsUrl);
String result = resource.contentType(MyObject.MIME_TYPE).post(
  String.class, new MyObject(1));
System.out.println(result);

No comments:

Post a Comment