Currently in 1.0 Jersey doesn't have a generic type parameter for the Response element so you are forced to use:
@GET
@Produces(MediaType.APPLICATION_JSON)
public JResponse<List<Bean>> get() {
Stock stock = new Stock();
stock.setQuantity(3);
return Response.ok(
new GenericEntity<List<Stock>>(Lists.newArrayList(stock)){}).build();
}
This is of course a hack of the JDK that creates a new inner class, Jersey has a subclass or Response, JResponse, which takes a generic parameter. So you are able instead to this this notation:
@GET
@Produces(MediaType.APPLICATION_JSON)
public JResponse<List<Bean>> get() {
Stock stock = new Stock();
stock.setQuantity(3);
return JResponse.<List<Bean>>ok(Lists.newArrayList(stock)).build();
}
This is much cleaner and probably faster, this also means that they type of the reponse can be know to the WADL XSD Schema generator without the user having to use extra annotations. There is one enhancement for this builder, any method that takes an entity currently just returns a builder of the same type. Ideally it should return JResponseBuilder<Entity> this would further simplify the code to be as follows:
@GET
@Produces(MediaType.APPLICATION_JSON)
public JResponse<List<Bean>> get() {
Stock stock = new Stock();
stock.setQuantity(3);
return JResponse.<List<Bean>>ok(Lists.newArrayList(stock)).build();
} }
There is a limitation in the JResponse API in that the return type from methods such as ok and entity don't transmute the generic parameter, it should be possible with the right parameters to just be able to type:
@GET
@Produces(MediaType.APPLICATION_JSON)
public JResponse<List<Bean>> get() {
Stock stock = new Stock();
stock.setQuantity(3);
return JResponse.ok(Lists.newArrayList(stock)).build();
}
Here is some code to show how the API would look:
package webservice;
import com.sun.jersey.api.JResponse;
import java.util.List;
public class Test {
public JResponse<List<String>> get() {
List<String> list = null;
return JResponse.<List<String>>ok(list).build();
}
public GResponse<List<String>> get2() {
List<String> list = null;
return GResponse.ok(list).build();
}
public GResponse<List<String>> get3() {
List<String> list = null;
return GResponse.ok()
.entity(list)
.build();
}
public static class GResponse<Type> {
public static GResponseBuilder<?> ok() {
return new GResponseBuilder();
}
public static <Param> GResponseBuilder<Param> ok(Param type) {
return new GResponseBuilder<Param>();
}
}
public static class GResponseBuilder<Type> {
Type entity;
public <Param> GResponseBuilder<Param> entity(Param type) {
@SuppressWarnings("unchecked") GResponseBuilder<Param> builder = (GResponseBuilder<Param>)this;
builder.entity = type;
return builder;
}
public GResponse<Type> build() {
return null;
}
}
}
One solution would be to make Request/Response generic. I am however worried that often Req/Resp are used to produce/consume arbitrary types based on the program flow, message header content or status code. Introducing generics would make such universal code more complicated IMO and would go against the spirit of Request/Response as a type-indifferent components.
Thoughts?