12.9. RESTEasy Interceptors

12.9.1. Intercept JAX-RS Invocations

Summary

RESTEasy can intercept JAX-RS invocations and route them through listener-like objects called interceptors. This topic covers descriptions of the four types of interceptors.

Example 12.3. MessageBodyReader/Writer Interceptors

MessageBodyReaderInterceptors and MessageBodyWriterInterceptors can be used on the either the server or client side. They are annotated with @Provider, as well as either @ServerInterceptor or @ClientInterceptor so that RESTEasy knows whether or not to add them to the interceptor list.
These interceptors wrap around the invocation of MessageBodyReader.readFrom() or MessageBodyWriter.writeTo(). They can be used to wrap the Output or Input streams.
RESTEasy GZIP support has interceptors that create and override the default Output and Input streams with a GzipOutputStream or GzipInputStream so that gzip encoding can work. They can also be used to append headers to the response, or the outgoing request on the client side.
public interface MessageBodyReaderInterceptor
  {
     Object read(MessageBodyReaderContext context) throws IOException, WebApplicationException;

  }

public interface MessageBodyWriterInterceptor
  {
     void write(MessageBodyWriterContext context) throws IOException, WebApplicationException;

  }

The interceptors and the MessageBodyReader or Writer is invoked in one big Java call stack. MessageBodyReaderContext.proceed() or MessageBodyWriterContext.proceed() is called in order to go to the next interceptor or, if there are no more interceptors to invoke, the readFrom() or writeTo() method of the MessageBodyReader or MessageBodyWriter. This wrapping allows objects to be modified before they get to the Reader or Writer, and then cleaned up after proceed() returns.
The example below is a server side interceptor, that adds a header value to the response.
@Provider
@ServerInterceptor
public class MyHeaderDecorator implements MessageBodyWriterInterceptor {

    public void write(MessageBodyWriterContext context) throws IOException, WebApplicationException
    {
       context.getHeaders().add("My-Header", "custom");
       context.proceed();
    }
}

Example 12.4. PreProcessInterceptor

PreProcessInterceptors run after a JAX-RS resource method is found to invoke on, but before the actual invocation happens. They are annotated with @ServerInterceptor, and run in sequence.
These interfaces are only usable on the server. They can be used to implement security features, or to handle the Java request. The RESTEasy security implementation uses this type of interceptor to abort requests before they occur if the user does not pass authorization. The RESTEasy caching framework also uses this to return cached responses to avoid invoking methods again.
public interface PreProcessInterceptor
    {
       ServerResponse preProcess(HttpRequest request, ResourceMethod method) throws Failure, WebApplicationException;
    }

If the preProcess() method returns a ServerResponse then the underlying JAX-RS method will not get invoked, and the runtime will process the response and return to the client. If the preProcess() method does not return a ServerResponse, the underlying JAX-RS method will be invoked.

Example 12.5. PostProcessInterceptors

PostProcessInterceptors run after the JAX-RS method was invoked, but before MessageBodyWriters are invoked. They are used if a response header needs to be set when a MessageBodyWriter may not be invoked.
They can only be used on the server side. They do not wrap anything, and are invoked in sequence.
public interface PostProcessInterceptor
  {
    void postProcess(ServerResponse response);
  }

Example 12.6. ClientExecutionInterceptors

ClientExecutionInterceptors are only usable on the client side. They wrap around the HTTP invocation that goes to the server. They must be annotated with @ClientInterceptor and @Provider. These interceptors run after the MessageBodyWriter, and after the ClientRequest has been built on the client side.
RESTEasy GZIP support uses ClientExecutionInterceptors to set the Accept header to contain "gzip, deflate" before the request goes out. The RESTEasy client cache uses it to check to see if its cache contains the resource before going over the wire.
public interface ClientExecutionInterceptor
{
  ClientResponse execute(ClientExecutionContext ctx) throws Exception;
}

public interface ClientExecutionContext
{
  ClientRequest getRequest();

  ClientResponse proceed() throws Exception;
}