Filters provide extended functionality such as logging and authentication. Interceptors provide extended functions such as entity compression. In this section, we will discuss the support for filters at specific extension points in JAX-RS 2.0 implementation. The two types of filters are provided in JAX-RS 2.0: client filters and container filters. The client filters are on the client side and the container filters are on the container side. Interfaces corresponding to the client filters are included in the Client API and are javax.ws.rs.client.ClientRequestFilter
and javax.ws.rs.client.ClientResponseFilter
. Interfaces for the container filters, which are included in the Server API, are javax.ws.rs.container.ContainerRequestFilter
and javax.ws.rs.container.ContainerResponseFilter
. To be discovered by the JAX-RS runtime, filters implementing the interfaces must be annotated with the @Provider
annotation. Create Java classes LoggingFilter
(for the container filter example), and ClientFilter
(for the client filter example), as shown in Project Explorer.
Before we discuss the client and container filters, we need to discuss the junctions at which the filters intercept communication between the client and the server:
ClientRequestFilter
intercepts communication before the client HTTP request is sent over to the server.ContainerRequestFilter
intercepts after the client is sent over to the server but before the JAX-RS resource method is invoked.ContainerResponseFilter
intercepts after the JAX-RS resource method is invoked but before the response is sent back to the client.ClientResponseFilter
is invoked after the server HTTP response is sent over to the client but before the response is unmarshalled.The junctions of request/response interception are illustrated in the following diagram:
First, we will discuss the client filters with an example. The ClientRequestFilter
is run in the invocation pipeline before the HTTP request is delivered to the network. The ClientRequestFilter
should be annotated by @Provider
, which is the marker that is discovered by the JAX-RS runtime during the scanning phase. The ClientResponseFilter
is run after the response is received from the server and before the control is returned to the application. Make the ClientFilter
class implement the ClientRequestFilter
and ClientResponseFilter
interfaces. Add implementation for the filter(ClientRequestContext arg0)
and filter(ClientRequestContext arg0, ClientResponseContext arg1)
methods. In the ClientRequestFilter
implementation method filter(ClientRequestContext arg0)
, output some headers using the getHeaderString(String)
method of ClientRequestContext
. For example, the Accept-Charset
and Accept-Encoding
headers give out the following output:
System.out.println("Accept-Charset: " + arg0.getHeaderString("Accept-Charset")); System.out.println("Accept-Encoding: " + arg0.getHeaderString("Accept-Encoding"));
Set a new resource URI using the setUri(URI)
method as follows:
arg0.setUri(new URI("http://localhost:8080/jboss-resteasy/rest/helloworld/text/Smith,John"));
The
ClientFilter
class is listed as follows:
package org.jboss.resteasy.rest; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import javax.ws.rs.client.ClientRequestContext; import javax.ws.rs.client.ClientRequestFilter; import javax.ws.rs.client.ClientResponseContext; import javax.ws.rs.client.ClientResponseFilter; import javax.ws.rs.core.Response; import javax.ws.rs.ext.Provider; @Provider public class ClientFilter implements ClientRequestFilter, ClientResponseFilter { @Override public void filter(ClientRequestContext arg0, ClientResponseContext arg1) throws IOException { } @Override public void filter(ClientRequestContext arg0) throws IOException { System.out.println("Entity Class: " + arg0.getEntityClass()); System.out.println("Accept: " + arg0.getHeaderString("Accept")); System.out.println("Accept-Charset: " + arg0.getHeaderString("Accept-Charset")); System.out.println("Accept-Encoding: " + arg0.getHeaderString("Accept-Encoding")); System.out.println("Accept-Language: " + arg0.getHeaderString("Accept-Language")); System.out.println("Accept-Ranges: " + arg0.getHeaderString("Accept-Ranges")); System.out.println("Allow: " + arg0.getHeaderString("Allow")); System.out.println("Authorization: " + arg0.getHeaderString("Authorization")); System.out.println("Cache-Control: " + arg0.getHeaderString("Cache-Control")); System.out.println("Content-Encoding: " + arg0.getHeaderString("Content-Encoding")); System.out.println("Content-Location: " + arg0.getHeaderString("Content-Location")); System.out.println("Accept-Encoding: " + arg0.getHeaderString("Accept-Encoding")); System.out.println("Content-Type: " + arg0.getHeaderString("Content-Type")); System.out.println("Host: " + arg0.getHeaderString("Host")); System.out.println("Pragma: " + arg0.getHeaderString("Pragma")); System.out.println("Server: " + arg0.getHeaderString("Server")); System.out.println("User-Agent: " + arg0.getHeaderString("User-Agent")); try { arg0.setUri(new URI( "http://localhost:8080/jboss-resteasy/rest/helloworld/text/Smith,John")); } catch (URISyntaxException e) { // TODO Auto-generated catch block e.printStackTrace(); } //arg0.abortWith(Response.notAcceptable(null).build()); } }
For a client filter issue that could occur, refer to the section Fixing a Common Issue
at the end of this chapter. In the client class, RESTEasyClient
registers the client filter with the client:
client.register(ClientFilter.class);
We will use the following root resource class HelloWorldResource
to test the client filter:
package org.jboss.resteasy.rest; import javax.ws.rs.GET; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.Path; @Path("/helloworld") public class HelloWorldResource { @GET @Produces("text/plain") @Path("/text/{name}") public String getClichedMessage(@PathParam("name") String name) { return "Hello " +name; } }
The client class RESTEasyClient
to test the client filter with is listed as follows:
package org.jboss.resteasy.rest; import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.WebTarget; import javax.ws.rs.core.*; public class RESTEasyClient { public static void main(String[] args) { Client client = ClientBuilder.newClient(); client.register(ClientFilter.class); String response = client.target("http://localhost:8080/jboss-resteasy/rest/helloworld/text/John Smith").request("text/plain").get(String.class); System.out.println("Text response "+ response); } }
Redeploy the jboss-resteasy
application. To redeploy, right-click on pom.xml
in Project Explorer and select Run As | Maven clean, and subsequently, right-click on pom.xml
and select Run As | Maven install. Run the RESTEasyClient.java
class to generate the following output in the Console screen shown as follows:
As we modified the resource URI in the client filter, the response message is not for John Smith as specified in the client class, but for Smith, John.
The filter chain processing may be aborted and response is returned to the client with the abortWith(Response response)
method. The client response filters get applied before the client gets the response. As an example, break the filter chain and return a notAcceptable(null)
response:
arg0.abortWith(Response.notAcceptable(null).build());
Keep RESTEasyClient
and HelloWorldResource
the same and redeploy the jboss-restaesy
application. Rerun the RESTEasyClient
class to generate the following output, which includes a NotAcceptableException
shown as follows:
3.147.47.144