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.
Client code,
Output:
Let's now try to return Integer.
Client code,
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.
Client code,
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
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