Custom Method Annotation using Jersey's AbstractHttpContextInjectable not Working
annotations, dropwizard, java, jersey
Solution
If you don't want to use AOP, I think you can do this by implementing ResourceMethodDispatchProvider and ResourceMethodDispatchAdapter.
public class CustomDispatchProvider implements ResourceMethodDispatchProvider {
ResourceMethodDispatchProvider provider;
CustomDispatchProvider(ResourceMethodDispatchProvider provider)
{
this.provider = provider;
}
@Override
public RequestDispatcher create(AbstractResourceMethod abstractResourceMethod) {
System.out.println("creating new dispatcher for " + abstractResourceMethod);
RequestDispatcher defaultDispatcher = provider.create(abstractResourceMethod);
if (abstractResourceMethod.getMethod().isAnnotationPresent(Secure.class))
return new DispatcherDecorator(defaultDispatcher);
else
return defaultDispatcher;
}
@Provider
public static class CustomDispatchAdapter implements ResourceMethodDispatchAdapter
{
@Override
public ResourceMethodDispatchProvider adapt(ResourceMethodDispatchProvider provider) {
return new CustomDispatchProvider(provider);
}
}
public static class DispatcherDecorator implements RequestDispatcher
{
private RequestDispatcher dispatcher;
DispatcherDecorator(RequestDispatcher dispatcher)
{
this.dispatcher = dispatcher;
}
public void dispatch(Object resource, HttpContext context) {
if (context.getRequest().isSecure())
{
System.out.println("secure request detected");
this.dispatcher.dispatch(resource, context);
}
else
{
System.out.println("request is NOT secure");
throw new RuntimeException("cannot access this resource over an insecure connection");
}
}
}
}
In Dropwizard, add the provider like this: environment.addProvider(CustomDispatchAdapter.class);
Problem
I want to restrict some methods if they are being accessed in a non-secure manner. I'm creating a @Secure annotation that checks whether or not the request was sent over secure channels. However, I cannot create a method injectable that captures the HttpContext of the request. ``` @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) public @interface Secure { } public class SecureProvider<T> implements InjectableProvider<Secure, AbstractResourceMethod> { @Override public ComponentScope getScope() { return ComponentScope.PerRequest; } @Override public Injectable<?> getInjectable(ComponentContext componentContext, Secure annotation, AbstractResourceMethod method) { return new SecureInjectable(); } } public class SecureInjectable<T> extends AbstractHttpContextInjectable<T> { @Override public T getValue(HttpContext context) { // validation here return null; } } ``` I'm using the Dropwizard framework, so initialization of the Providers should be as easy as: ``` environment.addProvider(new SessionRestrictedToProvider<>(new SessionAuthenticator(), "MySession")); environment.addProvider(new SecureProvider<>()); environment.setSessionHandler(new SessionHandler()); ``` Usage: ``` @Resource @Path("/account") public class AccountResource { @GET @Path("/test_secure") @Secure public Response isSecure() { return Response.ok().build(); } } ``` At this point I'm assuming that a HttpContext Injectable doesn't work on a method, but I'm at a loss as to what other options I could utilize to implement this annotation.