I'm trying to integrate ExtJS with JAX-RS. I setup Jersey with POJOMappingFeature and it works fine. But I want to get rid of the glue code. Every class looks now like this:
@Path("/helloworld")
public class A {
@POST
@Produces(MediaType.APPLICATION_JSON)
public final ExtJsRestOutput createAction(ExtJsRestInput<B> toCreate) {
try {
final B created = toCreate.getData();
// logic
return new ExtJsRestDataOutput<B>(created);
} catch (Exception e) {
return new ExtJsRestFailure();
}
}
@GET
@Produces(MediaType.APPLICATION_JSON)
public final ExtJsRestOutput readCollectionAction() {
try {
final List<B> readCollection;
//logic
return new ExtJsRestDataOutput<List<B>>(readCollection);
} catch (Exception e) {
return new ExtJsRestFailure();
}
}
@PUT
@Path("{id}")
@Produces(MediaType.APPLICATION_JSON)
public final ExtJsRestOutput updateAction(ExtJsRestInput<B> toUpdate) {
try {
final B udpated = toUpdate.getData();
// logic
return new ExtJsRestDataOutput<B>(udpated);
} catch (Exception e) {
return new ExtJsRestFailure();
}
}
@GET
@Path("{id}")
@Produces(MediaType.APPLICATION_JSON)
public final ExtJsRestOutput readAction(@PathParam("id") Integer id) {
try {
final T read;
// logic
return new ExtJsRestDataOutput<B>(read);
} catch (Exception e) {
return new ExtJsRestFailure();
}
}
@DELETE
@Path("{id}")
@Produces(MediaType.APPLICATION_JSON)
public final ExtJsRestOutput deleteActi开发者_StackOverflow中文版on(@PathParam("id") Integer id) {
try {
// logic
return new ExtJsRestSuccess();
} catch (Exception e) {
return new ExtJsRestFailure();
}
}
}
I tried to resolve this with inheritance, and it turned it to something like that:
public abstract class ExtJsRestAction<T> {
@GET
@Path("{id}")
@Produces(MediaType.APPLICATION_JSON)
public final ExtJsRestOutput readAction(@PathParam("id") Integer id) {
try {
final T read = read(id);
return new ExtJsRestDataOutput<T>(read);
} catch (Exception e) {
LOG.error("blad wywolania read", e);
return new ExtJsRestFailure("FAIL");
}
}
abstract public T read(Integer id) throws Exception;
// ... similar for the other methods
}
This makes the extending classess clean and ExtJS agnostic:
@Path("/helloworld")
public class BAction extends ExtJsRestAction<B> {
B create(B toCreate){
// logic
}
B read(Integer id){
// logic
}
// and so on...
}
This would be quite good, but there are problems when the path looks like this:
@Path("/helloworld/{anotherId}")
There is no (simple) way to access the anotherId.
I don't know were should I look for a solution. Is there any way to write an interceptor class instead of this base class that would pack/unpack the objects for ExtJS? Or maybe you could recommend a better solution to integrate ExtJS with Java. I was using Struts 2 and it worked quite well with JSON when I added a custom interceptor, but I was hoping I will be able to use the JAX-RS API to do it better.
If I understand the question, you need to get to the path param.
You can do so using a class level path param variable in your sub-class like:
@Path("/helloworld/{anotherId}")
public class SubClass {
@PathParam("anotherId")
private String anotherId;
@GET
public String hello() {
return anotherId;
}
}
If for some REST method you need to read extra parameters, then you might add to your base class field
@Context protected HttpServletRequest request;
or
@Context protected UriInfo uriInfo;
and get required value from path, e.g. from request.getPathInfo(). You'll need to parse path by yourself, which is not particularly nice piece of code, but this way you can make your base abstract class very generic.
精彩评论