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)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} |
Note: 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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public interface DynamicFeature { | |
public void configure(ResourceInfo resInfo, FeatureContext ctx); | |
} |
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@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); | |
} | |
} | |
} |
For more on JAX-RS 2.0 …
- Check out the specification doc
- One of the articles in the latest Java Magazine edition
Cheers!
Hi Abhishek, thanks for the article. I am new to REST and have limited exposure. By default interceptor and filters are applied on each request and response, so as you are saying if we use some custom annotation like you mention then we limit the calling of filter in each request/response. Only those methods which are having this annotation will be treated. Right?
LikeLike
Hey Tushar. Thanks for reading !
You’re correct. If you use the Named or Dynamic binding strategy, you can override the default behaviour and apply the filter/interceptor in a declarative/selective/criteria-driven manner
LikeLike
Thanks Abhishek for revert. Static binding is easy to understand but i am having hard time to understand Dynamic binding. Could you please explain little bit more about it?
LikeLike
Tushar, in the Dynamic binding case
Makes sense ?
LikeLike
Thanks Abhishek.. Actually, i am not aware of ResourceInfo and FeatureContext interface.. I will read them first and then get back to this article. I think then only it will make more sense to me.
LikeLike
Actually i have read it and it seems to be clear now… Thanks again..
LikeLike
Great article! Read and put it in practice already.
But I’m facing a problem.
When I use dynamic binding and my dynamic filter HeaderAdminValidatorFilter isn’t annotated (neither Provider or named binding @AdminAudited) it work very well, but when my HeaderAdminValidatorFilter is annotated with @Provider and @AdminAudited, other methods (which are filtered by other named binding filter) are being filtered too.
And if my other filte HeaderValidatorFilterr (which is named bindind @Audited) annotated with @PreMatching, my method (which is filtered by dynamic filter) is also being intercepted, so I had to replace the @PreMatching by @Priority in order to execute it before the other filter (HeaderAppendFilter).
I tested it in Wildfly 8.1 and 10.0, both FINAL.
Can you tell me if I did something wrong?
Here is the project: https://github.com/wesleyegberto/javaee_projects/tree/master/jaxrs-specification
Thank you!
LikeLike
Pingback: Sharing data between JAX-RS filters | Thinking in Java EE (at least trying to!)
Pingback: Sharing Data Between JAX-RS filters | Voxxed