I am using JAX-RS 2.0 with Jersey 2.6. I was wondering if it was possible to have something like this:
@GET
@Path("/get/{id}")
@MapTo(type = MyObjectDTO.class)
public MyObject getMyObject(@PathParam("id") String id){
MyObject o = ...
return o;
}
In the method above I am returning an instance of MyObject
. However, I have defined the MapTo
annotation to indicate that I want to map this object to MyObjectDTO
. The way I was thinking this could work is to process the response early in a ContainerResponseFilter
, detect the annotation MapTo
and, assuming no error occurred, replace the entity in the response with an instance of MyObjectDTO
created appropriately from the existing entity (of type MyObject
).
However, I couldn't find a way to get the Method
in the resource that was just called after the request came in, ie, the getMyObject
method, so that I can scan for the MapTo
annotation.
Is there a way to achieve this in a JAX-RS-y kind of way?
Is this some serious reason you cannot return dto object? Sounds very strange...You can probably use AOP but I guess it would be bad practive Here the Spring AOP example http://docs.spring.io/spring/docs/2.5.4/reference/aop.html
I think I found a solution by reading this SO . I created a class that looks like this:
@Provider // or register in the configuration...
public class DTOMapperFeature implements DynamicFeature {
@Override
public void configure(ResourceInfo resourceInfo, FeatureContext context) {
for (Annotation annotation : resourceInfo.getResourceMethod().getAnnotations()) {
if (annotation instanceof MapTo) {
MapTo mapTo = (MapTo) annotation;
// Note: additional validation (return type shouldn't be void,
// collections are out etc.) is required before creating this,
// or should be pushed in the DTOMapperFilter.
// You get the gist: this filter will map the entity to an instance
// of the specified class (using a constructor in this case).
context.register(new DTOMapperFilter(
resourceInfo.getResourceMethod().getReturnType(),
mapTo.getResponseType());
}
}
}
@Priority(/* appropriate priority here! */)
public final static class DTOMapperFilter implements ContainerResponseFilter {
public DTOMapperFilter(Class<?> declaredReturnType, Class<?> responseType) {
// implementation omitted: find DTO constructor etc.
// throw if responseType does NOT have a constructor that takes an instance
// of declaredReturnType: catch errors at application bootstrap!
}
@Override
public void filter(
ContainerRequestContext requestContext,
ContainerResponseContext responseContext) throws IOException {
// implementation omitted: create instance of DTO class using constructor
}
}
}
Given sensible exceptions will be thrown from either the constructor of DTOMapperFilter
or the configure
method above, this should be pretty robust and errors detectable at test time.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.