Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jersey JAXRS filter that provides unmarshalled entity before hitting resource (web service)

Is there an elegant way (filters, hooks) to intercept an unmarshalled entity (and its annotations) in Jersey before it hits the web service resource methods - those annotated with @POST, @PUT.

I really need the entity itself and any annotations it has on it and then perform validation on that entity using properties of the validator annotation (looks like JSR 303 but we don't annotate the entire bean with metadata). From an implementation perspective of a resource, my goal is to be able to just type this in a resource method:

@Path("/people")
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public class PeopleService {
        @POST
        public Response createPerson(@CustomValidator("personValidator") Person person) throws URISyntaxException {
            String uri = someService.createPerson(person);
            return Response.created(new URI(uri)).entity(uri).build();
        }
    }

I started down the path of writing a custom MessageBodyReader, and I managed to get JSON working completely because I just delegate to the ObjectMapper to deserialize JSON. Other than that, I am handed the annotations of the parameter and things work perfectly. However, things fell apart when I needed to deserialize the XML. I have no idea how to go about getting the original deserializer that Jersey would have used and delegating to that. I also feel like I'm unnecessarily rewriting pieces of Jersey and would prefer to stop using MessageBodyReader as a hacky integration point if jersey has a layer after MessageBodyReader and before the implementation calls the web resource service that would allow itself to be extended such that I could add custom behavior to the flow.

Ultimately, does Jersey have any extension points where it can hand me the unmarshalled entity and any of it's parameter anntotations and allow me to do custom handling? Or do I have to figure out how to unmarshal entities on my own (Using JAXBContext or what not)? Possibly resort to AOP? Inject the validator into the resource class and give up on that annotation idea?

Jersey version: 1.5

like image 812
Lo-Tan Avatar asked Dec 13 '12 19:12

Lo-Tan


1 Answers

Ultimately, does Jersey have any extension points where it can hand me the unmarshalled entity and any of it's parameter anntotations and allow me to do custom handling?

Yes there's an SPI in Jersey 1.x where you can supply your own method invoker. I haven't ever implemented the SPI but it's my understanding that it's called after any MessageBodyReaders or filters. Take a look at ResourceMethodCustomInvokerDispatchProvider. From the Javadocs:

An implementation (a service-provider) identifies itself by placing a provider-configuration file (if not already present), "com.sun.research.ws.rest.spi.invoker.ResourceMethodCustomInvokerDispatchProvider" in the resource directory META-INF/services, and including the fully qualified service-provider-class of the implementation in the file.

This interface is similar to ResourceMethodDispatchProvider, but allows to use a custom JavaMethodInvoker instance, which will be used to make the final Java method call.

If you implement ResourceMethodCustomInvokerDispatchProvider you should be able to provide your own JavaMethodInvoker which will have access to the resource method being invoked, including all of its parameters and annotations.

Note that everything above applies to Jersey 1.x. In Jersey 2, ResourceMethodInvocationHandlerProvider provides similar functionality.

like image 93
John R Avatar answered Oct 20 '22 19:10

John R