28.7. Interceptor Ordering and Precedence
Some interceptors are sensitive to the order in which they are invoked. For example, your security interceptor should always be invoked first. Other interceptors' behavior can be triggered by an interceptor that adds a header. By default, you have no control over the order in which registered interceptors are invoked, but you can specify interceptor precedence.
Interceptor precedence is not specified by listing interceptor classes. Instead, a particular interceptor class is associated with a precedence family with the
@org.jboss.resteasy.annotations.interception.Precedence
annotation. Specifying precedence through a family structure protects the built-in interceptors that are sensitive to ordering and simplifies configuration.
The families are listed here in execution order:
SECURITY HEADER_DECORATOR ENCODER REDIRECT DECODER
Any interceptor not associated with a precedence family will be invoked last.
SECURITY
usually includes PreProcessInterceptor
s. These should be invoked first so that as little as possible occurs prior to authorization. HEADER_DECORATOR
s are interceptors that add headers to a response or an outgoing request. These are next in precedence because the added headers may affect the behavior of other interceptors. ENCODER
interceptors change the OutputStream
. For example, the GZIP interceptor creates a GZIPOutputStream
to wrap the real OutputStream
for compression. REDIRECT
interceptors are usually used in PreProcessInterceptor
s because they can reroute the request and bypass the JAX-RS method. DECODER
interceptors wrap the InputStream
. For example, the GZIP interceptor decoder wraps the InputStream
in a GzipInputStream
instance.
To associate your custom interceptors with a particular family, annotate it with
@org.jboss.resteasy.annotations.interception.Precendence annotation
.
@Provider @ServerInterceptor @ClientInterceptor @Precedence("ENCODER") public class MyCompressionInterceptor implements MessageBodyWriterInterceptor {...}
There are convenience annotations in the
org.jboss.resteasy.annotations.interception
package to provide complete type safety: @DecoredPrecedence
, @EncoderPrecedence
, @HeaderDecoratorPrecedence
, @RedirectPrecedence
, and @SecurityPrecedence
. Use these instead of the @Precedence
annotation
28.7.1. Custom Precedence
You can define your own precedence families and apply them with the
@Precedence
annotation.
@Provider @ServerInterceptor @Precedence("MY_CUSTOM_PRECEDENCE") public class MyCustomInterceptor implements MessageBodyWriterInterceptor {...}
You can create your own convenience annotation by using
@Precedence
as a meta-annotation.
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Precedence("MY_CUSTOM_PRECEDENCE") public @interface MyCustomPrecedence {}
You must register your custom precedence, or RESTEasy will show an error at deployment time. You can register your custom precendence with the context parameters:
resteasy.append.interceptor.precedence resteasy.interceptor.before.precedence resteasy.interceptor.after.precedence
resteasy.append.interceptor.precedence
appends the precedence family to the list. resteasy.interceptor.before.precedence
lets you specify a family for your precendence to fall ahead of. resteasy.interceptor.after.precedence
lets you specify a family for your precedence to follow after. For example:
<web-app> <display-name>Archetype RestEasy Web Application</display-name> <!-- testing configuration --> <context-param> <param-name>resteasy.append.interceptor.precedence</param-name> <param-value>END</param-value> </context-param> <context-param> <param-name>resteasy.interceptor.before.precedence</param-name> <param-value>ENCODER : BEFORE_ENCODER</param-value> </context-param> <context-param> <param-name>resteasy.interceptor.after.precedence</param-name> <param-value>ENCODER : AFTER_ENCODER</param-value> </context-param> <context-param> <param-name>resteasy.servlet.mapping.prefix</param-name> <param-value>/test</param-value> </context-param> <listener> <listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class> </listener> <servlet> <servlet-name>Resteasy</servlet-name> <servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class> </servlet> <servlet-mapping> <servlet-name>Resteasy</servlet-name> <url-pattern>/test/*</url-pattern> </servlet-mapping> </web-app>
In this
web.xml
file, we have defined three new precedence families: END
, BEFORE_ENCODER
, and AFTER_ENCODER
. With this configuration, the family order would look like this:
SECURITY HEADER_DECORATOR BEFORE_ENCODER ENCODER AFTER_ENCODER REDIRECT DECODER END