curiousmind curiousmind - 2 months ago 24
Java Question

How to exclude some url from jersey filter?

I've used jersey to create webservices. I've created request filter using

ContainerRequestFilter
. I've gone through Jersey Request Filter only on certain URI question but I want to exclude filter for some urls only.

@Provider
public class AuthFilter implements ContainerRequestFilter{

@Override
public void filter(ContainerRequestContext requestContext) throws IOException {

// business logic

}
}

Answer

Name binding filters

Instead of excluding URIs from a global filter, you could consider using a name binding filter to select the endpoints your filter will be bound to. For more details, have a look here.

Also check this answer for some examples with name binding filters.

Global filters

If you are still happy with the global filter approach, you could consider using the UriInfo interface to get details about the requested URI. Use one of the following approaches to get an instance of UriInfo:

  1. Using the @Context annotation:

    @Provider
    public class AuthFilter implements ContainerRequestFilter {
    
        @Context
        private UriInfo info;
    
        @Override
        public void filter(ContainerRequestContext requestContext) throws IOException {
            ...
        }
    }
    
  1. Getting it from the ContainerRequestContext:

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {
        UriInfo info = requestContext.getUriInfo();
        ...
    }
    

Once you have the UriInfo instance, you'll have access to a bunch of methods that may be useful:

For more details, check the UriInfo documentation.

If the requested URI does not match the URIs you want to apply the filter to, simply use a return instruction:

@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
    UriInfo info = requestContext.getUriInfo();
    if (!info.getPath().contains("secured")) {
        return;
    }
}

Dynamic binding

Another approach is dynamic binding. It allows you to assign filters and interceptors to the resource methods in a dynamic manner. Name binding, mentioned above, uses a static approach and changes to binding require source code change and recompilation. With dynamic binding you can implement code which defines bindings during the application initialization time.

The following example extracted from the Jersey documentation shows how to implement dynamic binding:

@Path("helloworld")
public class HelloWorldResource {

    @GET
    @Produces("text/plain")
    public String getHello() {
        return "Hello World!";
    }

    @GET
    @Path("too-much-data")
    public String getVeryLongString() {
        String str = ... // very long string
        return str;
    }
}
// This dynamic binding provider registers GZIPWriterInterceptor
// only for HelloWorldResource and methods that contain
// "VeryLongString" in their name. It will be executed during
// application initialization phase.
public class CompressionDynamicBinding implements DynamicFeature {

    @Override
    public void configure(ResourceInfo resourceInfo, FeatureContext context) {
        if (HelloWorldResource.class.equals(resourceInfo.getResourceClass())
                && resourceInfo.getResourceMethod().getName().contains("VeryLongString")) {
            context.register(GZIPWriterInterceptor.class);
        }
    }
}

The binding is done using the provider which implements the DynamicFeature interface. The interface defines one configure method with two arguments, ResourceInfo and FeatureContext.

ResourceInfo contains information about the resource and method to which the binding can be done. The configure method will be executed once for each resource method that is defined in the application. In the example above the provider will be executed twice, once for the getHello() method and once for getVeryLongString() (once the resourceInfo will contain information about getHello() method and once it will point to getVeryLongString()).

If a dynamic binding provider wants to register any provider for the actual resource method it will do that using provided FeatureContext which extends JAX-RS Configurable API. All methods for registration of filter or interceptor classes or instances can be used. Such dynamically registered filters or interceptors will be bound only to the actual resource method. In the example above the GZIPWriterInterceptor will be bound only to the method getVeryLongString() which will cause that data will be compressed only for this method and not for the method getHello().

Note that filters and interceptors registered using dynamic binding are only additional filters run for the resource method. If there are any name bound providers or global providers they will still be executed.


For more details, check the Jersey documentation about filters and interceptors.