Jersey Async ContainerRequestFilter

僤鯓⒐⒋嵵緔 提交于 2019-11-29 04:01:30
Alden

This is not built in to Jersey as of 2.7.

@ManagedAsync is useless if you have any filters or interceptors that do any serious work (like hit a remote authorization service). They may add the ability to run filters asynchronously in the future, but for now you're on your own.

UPDATE - there are other ways...

After a long and perilous journey, I have found a very hacky solution that I'm using in the short term. Here is a rundown of what I tried and why it failed/worked.

Guice AOP - failed

I use Guice for DI (getting Guice injection to work with Jersey is a feat in itself!), so I figured I could use Guice AOP to get around the issue. Though Guice injection works, it is impossible to get Guice to create resource classes with Jersey 2, so Guice AOP cannot work with resource class methods. If you are trying desperately to get Guice to create resource classes with Jersey 2, don't waste your time because it will not work. This is a well-known problem.

HK2 AOP - RECOMMENDED SOLUTION

HK2 just recently released an AOP feature, see this question for details on how to get it working.

Monitoring - also worked

This is not for the faint of heart, and it is completely discouraged in the Jersey docs. You can register and ApplicationEventListener and override onRequest to return a RequestEventListener that listens for RESOURCE_METHOD_START and calls an authentication/authorization service. This event is triggered from the @ManagedAsync thread, which is the whole goal here. One caveat, the abortWith method is a no-op, so this won't work quite like a normal ContainerRequestFilter. Instead, you can throw an exception if auth fails instead, and register an ExceptionMapper to handle your exception. If someone is bold enough to give this a try, let me know and I'll post code.

shahshi15

I am not sure if this is what you were looking for but, have you looked into Spring's OncePerRequestFilter? I am currently using it for my authorization layer where each request goes through some filter that extends this OncePerRequestFilter depending on how my filters are mapped to the URLs. Here's a quick overview of how I am using it:

Authentication/Authorization of a resource in Dropwizard

I am not very clear on the async dispatch parts of these filters but I hope this link atleast sheds some light to what you are trying to achieve!

We use Spring security for authentication/authorization. I worked around the problem using a sub-resource locator with empty path as shown below:

@Path("/customers")
public class CustomerResource {
    @Inject
    private CustomerService customerService;

    @Path("")
    public CustomerSubResource delegate() {
        final Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        return new CustomerSubResource(auth);
    }

    public class CustomerSubResource {
        private final Authentication auth;           

        public CustomerSubResource(final Authentication auth) {
            this.auth = auth;
        }

        @POST
        @Path("")
        @Produces(MediaType.APPLICATION_JSON)
        @Consumes(MediaType.APPLICATION_JSON)
        @ManagedAsync
        public void createCustomer(final Customer customer, @Suspended final AsyncResponse response) {
            // Stash the Spring security context into the Jersey-managed thread
            SecurityContextHolder.getContext().setAuthentication(this.auth);

            // Invoke service method requiring pre-authorization
            final Customer newCustomer = customerService.createCustomer(customer);

            // Resume the response
            response.resume(newCustomer);
        }
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!