59.4. Client Request Filter
Overview
This section explains how to implement and register a client request filter, which is used to intercept an outgoing request message on the client side. Client request filters are often used to process headers and can be used for any kind of generic request processing.
ClientRequestFilter interface
The
javax.ws.rs.client.ClientRequestFilter
interface is defined as follows:
// Java package javax.ws.rs.client; ... import javax.ws.rs.client.ClientRequestFilter; import javax.ws.rs.client.ClientRequestContext; ... public interface ClientRequestFilter { void filter(ClientRequestContext requestContext) throws IOException; }
By implementing the
ClientRequestFilter
, you can create a filter for the ClientRequest
extension point on the client side, which filters the request message before sending the message to the server.
ClientRequestContext interface
The
filter
method of ClientRequestFilter
receives a single argument of type javax.ws.rs.client.ClientRequestContext
, which can be used to access the outgoing request message and its related metadata. The ClientRequestContext
interface is defined as follows:
// Java ... package javax.ws.rs.client; import java.io.OutputStream; import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.net.URI; import java.util.Collection; import java.util.Date; import java.util.List; import java.util.Locale; import java.util.Map; import javax.ws.rs.core.Configuration; import javax.ws.rs.core.Cookie; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.Response; import javax.ws.rs.ext.MessageBodyWriter; public interface ClientRequestContext { public Object getProperty(String name); public Collection<String> getPropertyNames(); public void setProperty(String name, Object object); public void removeProperty(String name); public URI getUri(); public void setUri(URI uri); public String getMethod(); public void setMethod(String method); public MultivaluedMap<String, Object> getHeaders(); public abstract MultivaluedMap<String, String> getStringHeaders(); public String getHeaderString(String name); public Date getDate(); public Locale getLanguage(); public MediaType getMediaType(); public List<MediaType> getAcceptableMediaTypes(); public List<Locale> getAcceptableLanguages(); public Map<String, Cookie> getCookies(); public boolean hasEntity(); public Object getEntity(); public Class<?> getEntityClass(); public Type getEntityType(); public void setEntity(final Object entity); public void setEntity( final Object entity, final Annotation[] annotations, final MediaType mediaType); public Annotation[] getEntityAnnotations(); public OutputStream getEntityStream(); public void setEntityStream(OutputStream outputStream); public Client getClient(); public Configuration getConfiguration(); public void abortWith(Response response); }
Sample implementation
To implement a client request filter for the
ClientRequest
extension point (that is, where the filter is executed prior to sending the request message), define a class that implements the ClientRequestFilter
interface.
For example, the following code shows an example of a simple client request filter that gets installed in the
ClientRequest
extension point, with a priority of 20:
// Java package org.jboss.fuse.example; import javax.ws.rs.client.ClientRequestContext; import javax.ws.rs.client.ClientRequestFilter; import javax.annotation.Priority; @Priority(value = 20) public class SampleClientRequestFilter implements ClientRequestFilter { public SampleClientRequestFilter() { System.out.println("SampleClientRequestFilter starting up"); } @Override public void filter(ClientRequestContext requestContext) { System.out.println("ClientRequestFilter.filter() invoked"); } }
Aborting the invocation
It is possible to abort a client-side invocation by implementing a suitable client request filter. For example, you might implement a client-side filter to check whether a request is correctly formatted and, if necessary, abort the request.
The following test code always aborts the request, returning the
BAD_REQUEST
HTTP status to the client calling code:
// Java package org.jboss.fuse.example; import javax.ws.rs.client.ClientRequestContext; import javax.ws.rs.client.ClientRequestFilter; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; import javax.annotation.Priority; @Priority(value = 10) public class TestAbortClientRequestFilter implements ClientRequestFilter { public TestAbortClientRequestFilter() { System.out.println("TestAbortClientRequestFilter starting up"); } @Override public void filter(ClientRequestContext requestContext) { // Test filter: aborts with BAD_REQUEST status requestContext.abortWith(Response.status(Status.BAD_REQUEST).build()); } }
Registering the client request filter
Using the JAX-RS 2.0 client API, you can register a client request filter directly on a
javax.ws.rs.client.Client
object or on a javax.ws.rs.client.WebTarget
object. Effectively, this means that the client request filter can optionally be applied to different scopes, so that only certain URI paths are affected by the filter.
For example, the following code shows how to register the
SampleClientRequestFilter
filter so that it applies to all invocations made using the client
object; and how to register the TestAbortClientRequestFilter
filter, so that it applies only to sub-paths of rest/TestAbortClientRequest
.
// Java ... import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.Invocation; import javax.ws.rs.client.WebTarget; import javax.ws.rs.core.Response; ... Client client = ClientBuilder.newClient(); client.register(new SampleClientRequestFilter()); WebTarget target = client .target("http://localhost:8001/rest/TestAbortClientRequest"); target.register(new TestAbortClientRequestFilter());