59.8. Dynamic Binding
Overview
The standard approach to binding container filters and container interceptors to resources is to annotate the filters and interceptors with the
@Provider
annotation. This ensures that the binding is global: that is, the filters and interceptors are bound to every resource class and resource method on the server side.
Dynamic binding is an alternative approach to binding on the server side, which enables you to pick and choose which resource methods your interceptors and filters are applied to. To enable dynamic binding for your filters and interceptors, you must implement a custom
DynamicFeature
interface, as described here.
DynamicFeature interface
The
DynamicFeature
interface is defined in the javax.ws.rx.container
package, as follows:
// Java package javax.ws.rs.container; import javax.ws.rs.core.FeatureContext; import javax.ws.rs.ext.ReaderInterceptor; import javax.ws.rs.ext.WriterInterceptor; public interface DynamicFeature { public void configure(ResourceInfo resourceInfo, FeatureContext context); }
Implementing a dynamic feature
You implement a dynamic feature, as follows:
- Implement one or more container filters or container interceptors, as described previously. But do not annotate them with the
@Provider
annotation (otherwise, they would be bound globally, making the dynamic feature effectively irrelevant). - Create your own dynamic feature by implementing the
DynamicFeature
class, overriding theconfigure
method. - In the
configure
method, you can use theresourceInfo
argument to discover which resource class and which resource method this feature is being called for. You can use this information as the basis for deciding whether or not to register some of the filters or interceptors. - If you decide to register a filter or an interceptor with the current resource method, you can do so by invoking one of the
context.register
methods. - Remember to annotate your dynamic feature class with the
@Provider
annotation, to ensure that it gets picked up during the scanning phase of deployment.
Example dynamic feature
The following example shows you how to define a dynamic feature that registers the
LoggingFilter
filter for any method of the MyResource
class (or subclass) that is annotated with @GET
:
// Java ... import javax.ws.rs.container.DynamicFeature; import javax.ws.rs.container.ResourceInfo; import javax.ws.rs.core.FeatureContext; import javax.ws.rs.ext.Provider; @Provider public class DynamicLoggingFilterFeature implements DynamicFeature { @Override void configure(ResourceInfo resourceInfo, FeatureContext context) { if (MyResource.class.isAssignableFrom(resourceInfo.getResourceClass()) && resourceInfo.getResourceMethod().isAnnotationPresent(GET.class)) { context.register(new LoggingFilter()); } }
Dynamic binding process
The JAX-RS standard requires that the
DynamicFeature.configure
method is called exactly once for each resource method. This means that every resource method could potentially have filters or interceptors installed by the dynamic feature, but it is up to the dynamic feature to decide whether to register the filters or interceptors in each case. In other words, the granularity of binding supported by the dynamic feature is at the level of individual resource methods.
FeatureContext interface
The
FeatureContext
interface (which enables you to register filters and interceptors in the configure
method) is defined as a sub-interface of Configurable<>
, as follows:
// Java package javax.ws.rs.core; public interface FeatureContext extends Configurable<FeatureContext> { }
The
Configurable<>
interface defines a variety of methods for registering filters and interceptors on a single resource method, as follows:
// Java ... package javax.ws.rs.core; import java.util.Map; public interface Configurable<C extends Configurable> { public Configuration getConfiguration(); public C property(String name, Object value); public C register(Class<?> componentClass); public C register(Class<?> componentClass, int priority); public C register(Class<?> componentClass, Class<?>... contracts); public C register(Class<?> componentClass, Map<Class<?>, Integer> contracts); public C register(Object component); public C register(Object component, int priority); public C register(Object component, Class<?>... contracts); public C register(Object component, Map<Class<?>, Integer> contracts); }