JAX-RS - Filter Priorities

[Updated: Jul 17, 2017, Created: Jul 17, 2017]

If there are more than one Filters in our application, then we may want to have them executed in a particular order.

An order can be specified by using @Priority annotation. This annotation accepts an integer parameter.

If @Priority annotation is used properly, the providers are sorted in ascending order; the lower the number the higher the priority.

Let's see an example how to use @Priority for filter.

Example

Implementing Filter

This filter will record the time taken for executing a resource method.

@Priority(1)
@Provider
public class TimeFilter implements ContainerRequestFilter, ContainerResponseFilter {

  @Override
  public void filter(ContainerRequestContext reqContext) throws IOException {
      System.out.println("-- TimeFilter request --");
      reqContext.setProperty("start-time", System.currentTimeMillis());
  }

  @Override
  public void filter(ContainerRequestContext reqContext,
                     ContainerResponseContext resContext) throws IOException {

      System.out.println("-- TimeFilter response --");

      long startTime = (long) reqContext.getProperty("start-time");
      System.out.printf("Time taken for request %s:  %s milli secs%n",
              reqContext.getUriInfo().getPath(),
              System.currentTimeMillis() - startTime
      );
  }
}

A log filter:

@Priority(2)
@Provider
public class LogFilter implements ContainerRequestFilter, ContainerResponseFilter {

  @Override
  public void filter(ContainerRequestContext reqContext) throws IOException {
      System.out.println("-- req headers --");
      log(reqContext.getUriInfo(), reqContext.getHeaders());

  }

  @Override
  public void filter(ContainerRequestContext reqContext,
                     ContainerResponseContext resContext) throws IOException {
      System.out.println("-- res headers --");
      log(reqContext.getUriInfo(), resContext.getHeaders());


  }

  private void log(UriInfo uriInfo, MultivaluedMap<String, ?> headers) {
      System.out.println("Path: " + uriInfo.getPath());
      headers.entrySet().forEach(h -> System.out.println(h.getKey() + ": " + h.getValue()));
  }
}

A JAX-RS resource

@Path("/")
public class MyResource {

  @GET
  @Path("{path:.*}")
  public String getResponse(@PathParam("path") String path) {
      System.out.printf("creating response for '%s'%n", path);
      return "dummy-response for " + path;
  }
}

To try examples, run embedded tomcat (configured in pom.xml of example project below):

mvn tomcat7:run-war

Output

Using HTTPie to access the resource:

Output on the server console:

-- TimeFilter request --
-- req headers --
Path: customers
host: [localhost:8080]
connection: [keep-alive]
accept-encoding: [gzip, deflate]
accept: [*/*]
user-agent: [HTTPie/0.9.9]
creating response for 'customers'
-- res headers --
Path: customers
Content-Type: [text/plain]
-- TimeFilter response --
Time taken for request customers:  13 milli secs

As seen in above output, TimeFilter ran before LogFilter. Reversing the priories will reverse the execution order of the filters as well.

Example Project

Dependencies and Technologies Used :

  • jersey-server 2.25.1: Jersey core server implementation.
  • jersey-container-servlet 2.25.1: Jersey core Servlet 3.x implementation.
  • JDK 1.8
  • Maven 3.3.9

JAX-RS - @Priority On filters Example Select All Download
  • filter-priorities
    • src
      • main
        • java
          • com
            • logicbig
              • example

See Also