Chapter 28. Interceptors

RESTEasy can intercept JAX-RS invocations and route them through listener-like objects called interceptors. There are four interception points on the server side:
  • wrapping around MessageBodyWriter invocations
  • wrapping around MessageBodyReader invocations
  • through pre-processors, which intercept the incoming request before unmarshaling occurs
  • through post-processors, which are invoked immediately after the JAX-RS method finishes
You can also intercept MessageBodyReader, MessageBodyWriter, and the remote invocation to the server on the client side.

28.1. MessageBodyReader/Writer Interceptors

MessageBodyReader and MessageBodyWriter interceptors wrap around the invocation of MessageBodyReader.readFrom() or MessageBodyWriter.writeTo(). They are used to wrap the Output or InputStream. For example, RESTEasy GZIP support contains interceptors that create and override the default Output and InputStream with a GzipOutputStream or GzipInputStream so that GZIP encoding can work. You can also use interceptors to append headers to the response (or, on the client side, the outgoing request).
To use an interceptor, implement the org.jbos.resteasy.spi.interception.MessageBodyReaderInterceptor or MessageBodyWriterInterceptor.
public interface MessageBodyReaderInterceptor
{
   Object read(MessageBodyReaderContext context) throws IOException, WebApplicationException;

}

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

}
Interceptors are driven by the MessageBodyWriterContext or MessageBodyReaderContext. They are invoked together in a Java call stack. You must call MessageBodyReaderContext.proceed() or MessageBodyWriterContext.proceed() to add subsequent interceptors. When there are no more interceptors to invoke, call the readFrom() or writeTo() method of the MessageBodyReader or MessageBodyWriter. This wrapping lets you modify objects before they reach the Reader or Writer, and clean up when proceed() returns. The Context objects also possess methods that modify the parameters sent to the Reader or Writer.
public interface MessageBodyReaderContext
{
   Class getType();

   void setType(Class type);

   Type getGenericType();

   void setGenericType(Type genericType);

   Annotation[] getAnnotations();

   void setAnnotations(Annotation[] annotations);

   MediaType getMediaType();

   void setMediaType(MediaType mediaType);

   MultivaluedMap<String, String> getHeaders();

   InputStream getInputStream();

   void setInputStream(InputStream is);

   Object proceed() throws IOException, WebApplicationException;
}

public interface MessageBodyWriterContext
{
   Object getEntity();

   void setEntity(Object entity);

   Class getType();

   void setType(Class type);

   Type getGenericType();

   void setGenericType(Type genericType);

   Annotation[] getAnnotations();

   void setAnnotations(Annotation[] annotations);

   MediaType getMediaType();

   void setMediaType(MediaType mediaType);

   MultivaluedMap<String, Object> getHeaders();

   OutputStream getOutputStream();

   public void setOutputStream(OutputStream os);

   void proceed() throws IOException, WebApplicationException;
}
MessageBodyReaderInterceptors and MessageBodyWriterInterceptors can be use on the server or the client side. They must be annotated with @org.jboss.resteasy.annotations.interception.ServerInterceptor or @org.jboss.resteasy.annotations.interception.ClientInterceptor so that RESTEasy adds them to the correct interceptor list. If your interceptor classes are not annotated with one or both of these annotations, a deployment error will occur. Interceptors should also be annotated with @Provider, like so:
@Provider
@ServerInterceptor
public class MyHeaderDecorator implements MessageBodyWriterInterceptor {

    public void write(MessageBodyWriterContext context) throws IOException, WebApplicationException
    {
       context.getHeaders().add("My-Header", "custom");
       context.proceed();
    }
}
This is a server-side interceptor that adds a header value to the response. It is annotated with @Provider and @ServerInterceptor. It must modify the header before calling context.proceed(), because the response may be committed after the MessageBodyReader runs.

Important

You must call context.proceed(), or your invocation will not occur.