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; }
MessageBodyReaderInterceptor
s and MessageBodyWriterInterceptor
s 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.