# JAX-RS Providers Part II

Let's continue exploring different JAX-RS providers and dive into

* **Filters**: one of the foremost components of the JAX-RS request processing chain
* **Interceptors**: work in tandem with (intercept) Message Body [Readers](#mbr) and [Writers](#mbw)

## Filters

Filters provide _AOP_ (Aspect Oriented Programming) like capabilities within JAX-RS applications and allow developers to implement cross cutting application specific concerns which ideally should not be sprinkled all over the business logic e.g. authentication, authorization, request/response validation etc. The AOP-based programming model involves interposing on methods of JAX-RS resource classes and dealing with (or mutating) components of HTTP request/response - headers, request URIs, the invoked HTTP method (GET, POST etc)

![JAX-RS filters](https://306641893-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M3y20skOpa1fn2NwAFz%2F-M3y21RiL2z2imUMTDD-%2F-M3y24Z8pa41rk8zMlBa%2Fjaxrs-filters.jpg?generation=1585883942760885\&alt=media)

### Server side Request filter

Server side request filters act on incoming HTTP requests from the clients and provide an opportunity to act on/make decisions based on certain characteristics of the HTTP request. In order to implement a server side request filter, one needs to implement the `javax.ws.rs.container.ContainerRequestFilter` interface (which is an extension provided by JAX-RS). An instance of the `javax.rs.ws.ContainerRequestContext` interface is seamlessly injected by the container into the filter method of `ContainerRequestFilter`. It is a mutable object (on purpose) and exposes methods to access and modify HTTP request components

A JAX-RS request processing pipeline involves dispatching a HTTP request to the appropriate Java method in the resource classes based on matching algorithm implemented by the JAX-RS provider. Filters take this into account and are divided into _pre_ and _post_ matching filters

#### Pre-matching filters

As the name indicates, Pre-matching filters are executed before the incoming HTTP request is mapped/dispatched to a Java method. Use the `javax.ws.rs.container.PreMatching` annotation on the filter implementation class

```
//Server side Pre Matching filter

@Provider
@PreMatching
public class PreMatchingAuthFilter{
 public void filter(ContainerRequestContext crc) 
 throws IOException{
  if(crc.getHeaderString("Authorization") == null){
   crc.abortWith(Response.status(403).build());
   }else{ //check credentials.... }
  }
}
```

#### Post-matching filters

A Post-matching filter is executed by the JAX-RS container only after the completion of method dispatch/matching process. Unlike, pre-matching filters, these filters do not need an explicit annotation i.e. filter classes without the `@PreMatching` annotation are assumed to be post-matching by default

```
//Server side Post Matching filter

@Provider
public class PostMatchingFilterExample{
 public void filter(ContainerRequestContext crc)
 throws IOException{
  System.out.println("Referrer: "+ 
  crc.getHeaderString("referrer"));
  System.out.println("Base URI: "+ 
  crc.getUriInfo().getBaseUri());
  System.out.println("HTTP Request method: "+ 
  crc.getMethod());
  }
}
```

> A JAX-RS application can have multiple filters (in a _chain_ like structure) which are executed as per user defined order (more on this later) or a default one (container driven). However, it possible to break the chain of processing by throwing an exception from the filter implementation logic or by calling the `abortWith` method. In either cases, the other request filters in the chain are not invoked and the control is passed on to the Response Filters (if any).

### Server side Response filter

A server side Response filter is invoked by the runtime after a response (or an exception) is generated by the JAX-RS resource method (before dispatching the same to the caller/client). Response filters are similar to their counterparts (Request filters) in terms of their utility (read/mutate aspects of the response e.g. HTTP headers) and programming model (executed as a chain in a user defined or default order) Setting up a server side response filter is as simple as providing an implementation for the `javax.ws.rs.container.ContainerResponseFilter` interface. The injection of `ContainerResponseContext` into the filter method of the `ContainerResponseFilter` interface is taken care of by the JAX-RS runtime

> Response filters also need to be annotated with the `javax.ws.rs.ext.Provider` annotation in order for the JAX-RS runtime to recognize it automatically.

```
//Server side Response filter

@Provider
public class CustomerHeaderResponseFilter{
 public void filter(ContainerRequestContext crc,
 ContainerResponseContext resCtx) 
 throws IOException{
  System.out.println("Request URI: "+ 
  crc.getUriInfo().getAbsolutePath().toString());
  //adding a custom header to the response
  resCtx.getHeaders().add("X-Search-ID",
  "qwer1234-tyuio5678-asdfg9876");
  }
}
```

### Client side Request filter

Client side request filters are invoked after the HTTP request creation before it is dispatched to the server. They can be to mutate/make decisions based on the properties of the HTTP request (Headers, Cookies etc) In order to implement a client side request filter, one needs to implement the extension interface provided by JAX-RS - `javax.ws.rs.client.ClientRequestFilter`

```
//Client side Request filter

public class ClientRequestHTTPMethodFilter {
 public void filter(ClientRequestContext crc) 
 throws IOException{
  String method = crc.getMethod();
  if(method.equalsIgnoreCase("DELETE")){
   //Return HTTP 405 - Method Not Allowed
   crc.abortWith(Response.status(405).build());
   }
  }
}
```

### Client side Response filters

Client side response filters are invoked after the HTTP response has been received from the server end but before it is dispatched to the caller/client. It provides an opportunity to mutate the properties of the HTTP response (Headers, Cookies etc) In order to implement a client side response filter, one needs to implement the extension interface provided by JAX-RS - `javax.ws.rs.client.ClientResponseFilter`

```
//Client side Response filter

public class ClientResponseLoggerFilter {
 public void filter(ClientRequestContext reqCtx, 
 ClientResponseContext resCtx) throws IOException{
  System.out.println("Response status: "+
  resCtx.getStatus());
 }
}
```

#### Sharing data between JAX-RS filters

JAX-RS API enables sharing of user-defined data amongst filters associated with a particular request

* It is abstracted in the form of a Map (pretty natural choice) via the [ContainerRequestContext](https://docs.oracle.com/javaee/7/api/javax/ws/rs/container/ContainerRequestContext.html) interface
* Get all the custom properties using the `getPropertyNames()` method
* The value of a specific property can be fetched (from the `Map`) using `getProperty(String name)`
* Overwrite an existing property or a add a new one using `setProperty(String name, Object val)`

> The same capability is available in the _Client side_ JAX-RS filters as well. The only difference is that you would be interacting with an instance of the [ClientRequestContext](https://docs.oracle.com/javaee/7/api/javax/ws/rs/client/ClientRequestContext.html)

{title="",lang=java}

```
public class ReqFilter_1 implements ContainerRequestFilter {

  @Override
  public void filter(ContainerRequestContext cReqCtx) throws IOException {
    cReqCtx.setProperty("prop1", "value1");
  }
}

public class ReqFilter_2 implements ContainerRequestFilter {

  @Override
  public void filter(ContainerRequestContext cReqCtx) throws IOException {
    String val1 = (String) cReqCtx.getProperty("prop1");
    cReqCtx.setProperty("prop1", "value1");
    cReqCtx.setProperty("prop2", "value2");
  }
}

public class ReqFilter_3 implements ContainerRequestFilter {

  @Override
  public void filter(ContainerRequestContext cReqCtx) throws IOException {
    String val1 = (String) cReqCtx.getProperty("prop1");
    String val2 = (String) cReqCtx.getProperty("prop2");
    Collection<String> customProperties = cReqCtx.getPropertyNames();
  }
}
```

```
//Sharing contextual data b/w Request and Response filters

@Priority(Priorities.AUTHENTICATION)
public class ReqFilter_1 implements ContainerRequestFilter {

  @Override
  public void filter(ContainerRequestContext cReqCtx) throws IOException {
    //generated and used internally
    cReqCtx.setProperty("random-token", "token-007"); 
  }
}

public class ResponseFilter implements ContainerResponseFilter {

  @Override
  public void filter(ContainerRequestContext cReqCtx, ContainerResponseContext cRespCtx) throws IOException {
       //get the property
    String responseToken = (String) cReqCtx.getProperty("random-token"); 
    if(responseToken!=null){
      //set it to HTTP response 
      cRespCtx.getHeaders.put("random-token-header" , responseToken); header
    }
  }
}
```

## Interceptors

Interceptors are similar to filters in the sense that they are also used to mutate HTTP requests and responses, but the major difference lies in the fact that Interceptors are primarily used to manipulate HTTP message payloads. They are divided into two categories - `javax.ws.rs.ext.ReaderInterceptor` and `javax.ws.rs.ext.WriterInterceptor` for HTTP requests and responses respectively.

> The same set of interceptors are applicable on the client side as well (unlike filters)

![JAX-RS interceptors](https://306641893-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M3y20skOpa1fn2NwAFz%2F-M3y21RiL2z2imUMTDD-%2F-M3y24ZGPC78JUxXGOEO%2Fjaxrs-interceptors.jpg?generation=1585883943751138\&alt=media)

### Reader Interceptor

A `ReaderInterceptor` is a contract (extension interface) provided by the JAX-RS API. On the server side, a Reader Interceptor acts on HTTP payloads sent by the client while the client side reader interceptors are supposed to act on (read/mutate) the request payload prior to it being sent to the server

### Writer Interceptor

On the server side, a `WriterInterceptor` act on HTTP payloads produced by the resource methods while the client side writer interceptors are supposed to act on (read/mutate) the payload sent by the server prior to it being dispatched to the caller

> Interceptors are invoked in a chain like fashion (similar to filters). They are only triggered when entity providers (`MessageBodyReader`and `MessageBodyWriter`) are required to convert HTTP message to and from their Java object representations. Both `ReaderInterceptor` and `WriterInteceptor` wrap around `MessageBodyReader` and `MessageBodyWriter` respectively and hence executed in the same call stack.

## Binding strategies for JAX-RS filters and interceptors

JAX-RS 2.0 defines multiple ways using which _server side_ filters and interceptors can be bound to their target components.

* Global Binding
* Named Binding
* Dynamic Binding

### Global Binding

By default, JAX-RS filters and interceptors are bound to _all_ the methods of resource classes in an application. That is, both request (pre and post) and response filters will be invoked whenever any resource method is invoked in response to a HTTP request by the client. This convention can be overridden using named binding or dynamic binding.

### Named Binding

Filters and interceptors scoping can be handled in a fine-grained manner (based on per resource class/method)

**Configuring Named Binding**

```
//Step 1: Define a custom annotation with the @NamedBinding annotation

@NameBinding
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(value = RetentionPolicy.RUNTIME)
public @interface Audited { }

//Step 2: Apply the custom annotation on the filter or interceptor

@Provider
@Audited
public class AuditFilter implements ContainerRequestFilter {
    //filter implementation....
}

//Step 3: Apply the same annotation to the required resource class or method

@GET
@Path("{id}")
@Produces("application/json")
@Audited
public Response find(@PathParam("id") String custId){
//search and return customer info
}
```

> If it is applied to a class, the filter/interceptor will be bound to all its resource methods

### Dynamic Binding

JAX-RS provides the `DynamicFeature` interface to help bind filters and interceptors dynamically at runtime. They can be used in tandem with the more static way of binding made possible using `@NamedBinding`. The injected instance of the `ResourceInfo` interface helps you choose the resource method in dynamic fashion by exposing various methods and the `FeatureContext` interface allows us to register the filter or interceptor once the resource method has been selected.

```
//Dynamic Binding sample

@Provider
public class AuthFilterDynamic implements DynamicFeature {
    @Override
    public void configure(ResourceInfo resInfo, FeatureContext ctx) {
        if (UserResource.class.equals(resInfo.getResourceClass()) && 
           resInfo.getResourceMethod().getName().contains("PUT")) {
              ctx.register(AuthenticationFilter.class);
           }
      }
}
```
