Binding JAX-RS Providers to Resource Methods

When you register providers (such as filters and interceptors) in your application they’re associated and applied to each resource method by default. In other words they’re bound globally. For most cases this approach is sufficient but sometimes, especially when you want to use your provider only with a few methods, it’s not enough. JAX-RS 2.0 brings a solution for this situation: Name and Dynamic Binding.

Name Binding

Name Binding is an annotation-driven (static) provider binding based on the JAX-RS meta-annotation @NameBinding. Custom binding annotations annotated with @NameBinding can be later used to decorate resource classes or resource methods as well as JAX-RS providers to define associations between them.

Let’s assume we have a logging filter (similar to LoggingFilter) responsible for logging incoming and outgoing communication (headers and/or entity) on our server:

Decorating this class with @Logged (name binding) annotation we transformed a globally-bound provider to a name-bound one. To bind this provider to a resource method we need to decorate the method with @Logged as well:

Name binding annotations can be applied to a resource method (as in our case), to a resource class (i.e. HelloWorldResource) or to an Application sub-class (a name-bound JAX-RS provider bound by the annotation will be applied to all (sub-)resource methods).

Finally to create a name binding annotation from @Logged just put @NameBinding on top of it:

Assigning multiple name-bound providers to a single resource method is also possible by decorating the method with all required name binding annotations. For example, if you want to use AuthenticationFilter:

with the previously mentioned HelloWorldResource.getHello() resource method decorate this method with @Authenticated as well. Now both AuthenticationFilter and LoggingFilter will be used when the resource method is being invoked.

Dynamic Binding

To bind post-matching providers more dynamically a new interface, DynamicFeature, has been introduced in JAX-RS 2.0. By implementing this interface you can assign particular providers programmatically to a subset of available resource methods.

Similar mechanism exists in Jersey 1. ResourceFilterFactory / ResourceFilter allows you to create request/response filters for a resource method. These classes has been replaced with DynamicFeature in Jersey 2.

The interface contains a callback method providing

The callback method is invoked once for every resource method, that exists in an application, to augment the set of filters and entity interceptors bound to this method.

Let’s take the example from the previous chapter and assign LoggingFilter to all resource methods from package my.package.admin that are listening to HTTP GET requests.

Now every HTTP GET request sent to a resource from my.package.admin package will be logged.

Implementations of DynamicFeature contract are still providers that need to be registered in your application before they can be used. Registering Resources and Providers in Jersey 2 discusses how to do that.

Further reading

Filters and Interceptors – Name Binding
Filters and Interceptors – Dynamic Binding

References

JAX-RS 2.0 specification

  • Cássio Mazzochi Molin

    Thanks for this article. It also works perfectly on RESTEasy.

  • Binh Thanh Nguyen

    Thanks, concise and nice post.

  • billy

    I’m trying to use @NameBinding to create a request authentication check filter with annotation named “AccessKeyRequired”. But i found that i could only place “AccessKeyRequired” on the Application subclass’s class level, while any attempt to put it on a resource class level or on a resource method level would result in a deployment failure reporting a java.lang.IllegalStateException. Is it a bug or what?
    Note that I’m using jersey 2.14 with glassfish 4.1 on windows 7.

    • Michal Gajdos

      Is your request filter also annotated with @PreMatching annotation? If so, this is not supposed to work, see JavaDoc:

      
      Any named binding annotations will be ignored on a component annotated with the @PreMatching annotation.
      

      However the IllegalStateException should not occur. I’ll fix that, thanks for filing an issue.

      • billy

        Ah, yes! I removed the @PreMatching annotation from my request filter, the exception no longer occured!

        Thanks a lot!