5

How can I set up an aop MethodInterceptor to work with Jersey resources?

Here is what I've tried, following this documentation:

Step 1 - InterceptionService

public class MyInterceptionService implements InterceptionService
{
    private final Provider<AuthFilter> authFilterProvider;

    @Inject
    public HK2MethodInterceptionService(Provider<AuthFilter> authFilterProvider)
    {
        this.authFilterProvider = authFilterProvider;
    }

    /**
     * Match any class.
     */
    @Override
    public Filter getDescriptorFilter()
    {
        return BuilderHelper.allFilter();
    }

    /**
     * Intercept all Jersey resource methods for security.
     */
    @Override
    @Nullable
    public List<MethodInterceptor> getMethodInterceptors(final Method method)
    {
        // don't intercept methods with PermitAll
        if (method.isAnnotationPresent(PermitAll.class))
        {
            return null;
        }

        return Collections.singletonList(new MethodInterceptor()
        {
            @Override
            public Object invoke(MethodInvocation methodInvocation) throws Throwable
            {
                if (!authFilterProvider.get().isAllowed(method))
                {
                    throw new ForbiddenException();
                }

                return methodInvocation.proceed();
            }
        });
    }

    /**
     * No constructor interception.
     */
    @Override
    @Nullable
    public List<ConstructorInterceptor> getConstructorInterceptors(Constructor<?> constructor)
    {
        return null;
    }
}

Step 2 - Register the service

public class MyResourceConfig extends ResourceConfig
{
    public MyResourceConfig()
    {
        packages("package.with.my.resources");

        // UPDATE: answer is remove this line
        register(MyInterceptionService.class);

        register(new AbstractBinder()
        {
            @Override
            protected void configure()
            {
                bind(AuthFilter.class).to(AuthFilter.class).in(Singleton.class);

                // UPDATE: answer is add the following line
                // bind(MyInterceptionService.class).to(InterceptionService.class).in(Singleton.class);
            }
        });
    }
}

However this doesn't appear to work because none of my resource methods are being intercepted. Could this be because I use @ManagedAsync with all of my resources? Any ideas?

Also, please do not suggest a ContainerRequestFilter. See this question for why I can't use one to handle security.

Community
  • 1
  • 1
Alden
  • 6,553
  • 2
  • 36
  • 50

1 Answers1

5

I think that rather than calling register(MyInterceptionService.class) you might want to instead add into your configure() statement:

bind(MyInterceptionService.class).to(InterceptionService.class).in(Singleton.class)

I am not sure it will work as I have not tried it myself so your results may vary lol

jwells131313
  • 2,364
  • 1
  • 16
  • 26
  • Oh good call! I had also tried doing this in configure(), but I did `bind(MyInterceptionService.class).in(Singleton.class)` which is definitely incorrect. Trying it now... – Alden Mar 09 '14 at 03:01
  • This works! Not sure if you've read my other question that I've linked above, but I now have an `AsyncContainerRequestFilter extends ContainerRequestFilter` in my project, and a generic way to register them, which I'm pretty excited about :) – Alden Mar 09 '14 at 06:01
  • 2
    For a more detailed example with GUICE + jersey have a look here https://github.com/mycom-int/jersey-guice-aop – Ronan Quillevere Jul 21 '14 at 16:34
  • Wow, what a gr8 page. Would you mind if we pointed to it from the hk2 documentation on the guice/hk2 bridge? – jwells131313 Jul 21 '14 at 21:32
  • Sure please feel free to do so. – devlearn Nov 06 '14 at 08:48