Enterprise Java

JAX-RS 2.0 : Server side Processing Pipeline

The inspiration for this post was the Processing Pipeline section in the JAX-RS 2.0 specification doc (Appendix C). I like it because of the fact that it provides a nice snapshot of all the modules in JAX-RS – in the form of a ready to gulp capsule !
 
 
 
 
 
 
 
 

Courtesy – JAX-RS 2.0 Specification Document
Courtesy – JAX-RS 2.0 Specification Document

So I thought of using this diagram to provide a brief overview of the different JAX-RS components and how they orchestrate with each other.

What’s covered ?

  • Filters (Request and Response)
  • Method matching
  • Injection
  • Interceptors (Request and Response)
  • Entity Providers (Request and Response)

Note: what’s discussed here is the server side processing pipeline i.e. the sequence of actions which are triggered after the client sends an HTTP request (GET, POST, PUT etc)

It all begins when the client (browser or custom REST client) sends an HTTP request to your awesome RESTful service!

Request Filters (chain)

req-filters

The client request is handled by JAX-RS Filters. They are applicable on both the server and client side (we are going to look at server side filters – both request and response based)

  • Filters are optional components and you can write one by simply implementing the ContainerRequestFilter interface. They need to be annotated using @Provider annotation for automatic detection by the JAX-RS run time
  • One can mutate the instance of ContainerRequestContext and change attributes like headers, cookies, URI etc. Filters do not allow you to access the HTTP request body/message payload (that’s something which Interceptors can do)
  • Can be used to implement logging, authentication etc
  • If the filter implementation class needs to be executed before the resource method matching, use the @PreMatching annotation on the implementation class.
  • Filters can be bound to ALL JAX-RS methods (globally) or selectively by using @NamedBinding annotation or an implementation of the DynamicFeature interface
  • The @Priority annotation can be used to determine the order of execution of multiple filters – a sequential chain.

Method matching

After (successful) filter execution, the JAX-RS run time initiates the resource method matching process

  • The exact method to be invoked is based on the algorithm outlined by the specification (although JAX-RS providers are not bound by it)
  • It’s determined by a combination of below mentioned annotations
  • @GET, @PUT, @POST, @DELETE etc – these are the annotations which should match up to the actual HTTP operation (the mapping of the annotation to the HTTP verb is rather obvious)
  • @Path – its value (relative to the context root) is used to map the request URI e.g. /tweeters/all
  • @Consumes – its values should match the Content-Type header value sent in the HTTP request
  • @Produces – its values should match the Accept header value sent in the HTTP request

HTTP components injection

After the method matching is complete, the required HTTP components get injected into JAX-RS Resource classes (if configured) by the the JAX-RS run time. All we need to do is use the appropriate annotation

HTTP URI parameters

Other HTTP components

JAX-RS makes it easy to access (inject) HTTP request components like headers, cookies and even HTTP form data

  • @HeaderParam – extracts headers of a request. You can also use @Context annotation to inject an instance of HttpHeaders
  • @CookieParam – used to inject HTTP cookies from a HTTP request
  • @FormParam – can help inject values from attributes sent via a HTML Form using the HTTP POST request
  • @BeanParam – Can help use all the above injection related annotations on the instance variables of a custom domain class rather than using these to inject values into individual method parameters

Request Interceptors (chain)

req-interceptors-entityproviders

Interceptors are applicable on both the server and client side (we are going to look at server side interceptors only – both request and response based)

  • Interceptors help allow mutation of the HTTP request payload before it is processed
  • Request Interceptors are invoked only when a MessageBodyReader (see next topic) implementation is registered with the JAX-RS run time.
  • Interceptors for incoming server requests are handled by implementations of the ReaderInterceptor interface and need to be annotated using @Provider annotation for automatic detection by the JAX-RS run time
  • The ReaderInterceptorContext instance is passed by the JAX-RS run time and it has access to the HTTP body in the form of java.io.InputStream
  • Interceptors can be bound to ALL JAX-RS methods (globally) or selectively by using @NamedBinding annotation or an implementation of the DynamicFeature interface
  • Interceptors can be chained and prioritized (using @Priority) and calling the proceed method of the ReaderInterceptorContext automatically invokes the next interceptor in the chain or the MessageBodyReader implementation itself
  • A ReaderInterceptor acts as a wrapper around the MessageBodyReader (invokes it internally)

Entity Providers (converting HTTP request payload to Java type)

Entity Providers help in conversion of HTTP message payload to its appropriate Java type (for injection into the method parameters of JAX-RS resource classes) and vice versa

  • The conversion of HTTP request payload to its corresponding Java type is done by a concrete class implementing the MessageBodyReader interface
  • The readFrom method of the MessageBodyReader implementation is where the action takes place. The JAX-RS run time passes in all the contextual information including the payload itself (in the form of an InputStream) which can then be introspected and converted into the appropriate Java type.
  • JAX-RS spec mandates that an implementation should contain out-of-of-the-box implementations of MessageBodyReader interface for certain Java types like String, InputStream, File etc

Response Filter (chain)

resp-filters

Response Filters are similar to their Request-centric counterpart discussed previously.

  • Response Filters are optional components and you can write one by simply implementing the ContainerResponseFilter interface.
  • These type of filters are used to modify the response headers, add cookies etc. One can mutate the instance of ContainerResponseContext and change attributes like to achieve this. Filters do not allow you to access the HTTP response body/message payload (that’s something which Interceptors can do)
  • They need to be annotated using @Provider annotation for automatic detection by the JAX-RS run time
  • Filters can be bound to ALL JAX-RS methods (globally) or selectively by using @NamedBinding annotation or an implementation of the DynamicFeature interface
  • The @Priority annotation can be used to determine the order of execution of multiple filters – a sequential chain.

Response Interceptors (chain)

resp-interceptors-entityproviders1

  • They are invoked only when a MessageBodyWriter (see next topic) is registered to handle outgoing HTTP payload
  • Interceptors for outgoing server responses are handled by implementations of the class WriterInterceptor and need to be annotated using @Provider annotation for automatic detection by the JAX-RS run time
  • Interceptors can be chained and prioritized (using @Priority) and calling the proceed method of the WriterInterceptorContext automatically invokes the next interceptor in the chain or the MessageBodyWriter implementation itself
  • A WriterInterceptor acts as a wrapper around the MessageBodyWriter (invokes it internally)

Entity Providers (converting Java object to HTTP response payload)

  • The conversion of a Java object returned by the application code to HTTP response payload is done by a concrete class implementing the MessageBodyWriter interface
  • The writeTo method of the MessageBodyWriter implementation is where the action takes place. The JAX-RS run time passes in all the contextual information along with the OutputStream to which the which the response stream can be written to after conversion from its Java type
  • JAX-RS spec mandates that an implementation should contain out-of-of-the-box implementations of MessageBodyWriter interface for certain Java types like String, InputStream, File etc

Alright then ! This was a rather brief overview of how server side request processing works in JAX-RS and which components come into play. Thanks for reading. Cheers !

References

Reference: JAX-RS 2.0 : Server side Processing Pipeline from our JCG partner Abhishek Gupta at the Object Oriented.. blog.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button