<chapter id="Interceptors">
    <title>Filters and Interceptors</title>
    <para>&REST-API; has two different concepts for interceptions: Filters and Interceptors.  Filters are mainly used to
    modify or process incoming and outgoing request headers or response headers.  They execute before and after
    request and response processing.</para>
    <sect1>
        <title>Server Side Filters</title>
    <para>
        On the server-side you have two different types of filters.  ContainerRequestFilters
        run before your &REST-API; resource method is invoked.  ContainerResponseFilters run after your &REST-API; resource method
        is invoked.  As an added caveat, ContainerRequestFilters come in two flavors:  pre-match and post-matching.  Pre-matching
        ContainerRequestFilters are designated with the @PreMatching annotation and will execute before the &REST-API; resource
        method is matched with the incoming HTTP request.  Pre-matching filters often are used to modify request attributes
        to change how it matches to a specific resource method (i.e. strip .xml and add an Accept header).  ContainerRequestFilters can abort the request by calling ContainerRequestContext.abortWith(Response).  A filter
        might want to abort if it implements a custom authentication protocol.
    </para>
    <para>
          After the resource class method is executed, &REST-API; will run all ContainerResponseFilters.  These filters
        allow you to modify the outgoing response before it is marshalling and sent to the client.
        So given all that, here's some pseudo
        code to give some understanding of how things work.
    </para>
    <programlisting>
        // execute pre match filters
        for (ContainerRequestFilter filter : preMatchFilters) {
            filter.filter(requestContext);
            if (isAborted(requestContext)) {
               sendAbortionToClient(requestContext);
               return;
            }
        }
        // match the HTTP request to a resource class and method
        JaxrsMethod method = matchMethod(requestContext);

        // Execute post match filters
        for (ContainerRequestFilter filter : postMatchFilters) {
           filter.filter(requestContext);
           if (isAborted(requestContext)) {
              sendAbortionToClient(requestContext);
              return;
           }
        }

        // execute resource class method
        method.execute(request);

        // execute response filters
        for (ContainerResponseFilter filter : responseFilters) {
           filter.filter(requestContext, responseContext);
        }
    </programlisting>
    <sect2>
        <title id="Asynchronous_Filter">Asynchronous filters</title>
        <para>
            It is possible to turn filters into asynchronous filters, if you need to suspend execution of your filter
            until a certain resource has become available. This turns the request asynchronous, but requires no change
            to your resource method declaration. In particular, <link linkend="Asynchronous_HTTP_Request_Processing">synchronous
            and asynchronous resource methods</link> continue
            to work as specified, regardless of whether or not a filter turned the request asynchronous. Similarly,
            one filter turning the request asynchronous requires no change in the declaration of further filters.
        </para>
        <para>
            In order to turn a filter's execution asynchronous, you need to cast the <code>ContainerRequestContext</code> into
            a <code>SuspendableContainerRequestContext</code> (for pre/post request filters), or cast the <code>ContainerResponseContext</code> into
            a <code>SuspendableContainerResponseContext</code> (for response filters). 
        </para>
        <para>
            These context objects can turn the current filter's execution to asynchronous by calling the <code>suspend()</code>
            method. Once asynchronous, the filter chain is suspended, and will only resume after one of the following method
            is called on the context object:
        </para>
        <variablelist>
            <varlistentry>
                <term><code>abortWith(Response)</code></term>
                <listitem>Terminate the filter chain, return the given <code>Response</code> to the client (only for <code>ContainerRequestFilter</code>).</listitem>
            </varlistentry>
            <varlistentry>
                <term><code>resume()</code></term>
                <listitem>Resume execution of the filter chain by calling the next filter.</listitem>
            </varlistentry>
            <varlistentry>
                <term><code>resume(Throwable)</code></term>
                <listitem>
                    Abort execution of the filter chain by throwing the given exception. This behaves as if the filter were synchronous
                    and threw the given exception.
                </listitem>
            </varlistentry>
        </variablelist>
        <para>
            You can also do async processing inside your <code>AsyncWriterInterceptor</code> (if you are using
            <link linkend="Asynchronous_IO">Async IO</link>), which is the asynchronous-supporting equivalent to
            <code>WriterInterceptor</code>. In this case, you don't need to manually suspend or resume the request.
        </para>
    </sect2>
    </sect1>
    <sect1>
        <title>Client Side Filters</title>
        <para>
            On the client side you also have two types of filters: ClientRequestFilter and ClientResponseFilter.
            ClientRequestFilters run before your HTTP request is sent over the wire to the server.  ClientResponseFilters
            run after a response is received from the server, but before the response body is unmarshalled.  ClientRequestFilters
            are also allowed to abort the execute of the request and provide a canned response without going over the
            wire to the server.  ClientResponseFilters can modfiy the Response object before it is handed back to
            application code.  Here's some pseudo code to illustrate things.
        </para>
        <programlisting>
            // execute request filters
            for (ClientRequestFilter filter : requestFilters) {
               filter.filter(requestContext);
               if (isAborted(requestContext)) {
                  return requestContext.getAbortedResponseObject();
               }
            }

            // send request over the wire
            response = sendRequest(request);

            // execute response filters
            for (ClientResponseFilter filter : responseFilters) {
               filter.filter(requestContext, responseContext);
            }
        </programlisting>
    </sect1>
    <sect1>
        <title>Reader and Writer Interceptors</title>
        <para>
            While filters modify request or response headers, interceptors deal with message bodies.  Interceptors are executed
            in the same call stack as their corresponding reader or writer.  ReaderInterceptors
            wrap around the execution of MessageBodyReaders.  WriterInterceptors wrap around the execution of MessageBodyWriters.
            They can be used to implement a specific content-encoding.  They can be used to generate digital signatures or
            to post or pre-process a Java object model before or after it is marshalled.
        </para>
        <para>
            Note that in order to support Async IO, you can implement <code>AsyncWriterInterceptor</code>, which is a subtype of
            <code>WriterInterceptor</code>.
        </para>
    </sect1>
    <sect1>
        <title>Per Resource Method Filters and Interceptors</title>
        <para>
            Sometimes you want a filter or interceptor to only run for a specific resource method.  You can do this in two different
            ways:  register an implementation of DynamicFeature or use the @NameBinding annotation.  The DynamicFeature
            interface is executed at deployment time for each resource method.  You just use the Configurable interface
            to register the filters and interceptors you want for the specific resource method.  @NameBinding works a lot
            like CDI interceptors.  You annotate a custom annotation with @NameBinding and then apply that custom annotation
            to your filter and resource method. The custom annotation must use @Retention(RetentionPolicy.RUNTIME) in order for the
            attribute to be picked up by the RESTEasy runtime code when it is deployed.
        </para>
        <programlisting>
            @NameBinding
            @Retention(RetentionPolicy.RUNTIME)
            public @interface DoIt {}

            @DoIt
            public class MyFilter implements ContainerRequestFilter {...}

            @Path("/root")
            public class MyResource {

               @GET
               @DoIt
               public String get() {...}
            }
        </programlisting>
    </sect1>
    <sect1>
        <title>Ordering</title>
        <para>
            Ordering is accomplished by using the @BindingPriority annotation on your filter or interceptor class.
        </para>
    </sect1>

</chapter>
