I have a Jersey REST API and am using a ContainerRequestFilter
to handle authorization. I'm also using @ManagedAsync
on all endpoints so that my API can serve thousands of concurrent requests.
My authorization filter hits a remote service, but when the filter is run, Jersey hasn't yet added the current thread to it's internal ExecutorService
, so I'm completely losing the async benefits.
Can I tell Jersey that I want this ContainerRequestFilter
to be asynchronous?
@Priority(Priorities.AUTHORIZATION)
public class AuthorizationFilter implements ContainerRequestFilter
{
@Inject
private AuthorizationService authSvc;
@Override
public void filter(ContainerRequestContext requestContext) throws IOException
{
String authToken = requestContext.getHeaderString(HttpHeaders.AUTHORIZATION);
// HITS A REMOTE SERVER
AuthorizationResponse authResponse = authSvc.authorize(authToken);
if (!authResponse.isAuthorized())
{
requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED)
.entity("unauthorized!")
.build());
}
}
}
And here's an example resource:
@Path("/stuff")
@Produces(MediaType.APPLICATION_JSON)
public class StuffResource
{
@GET
@Path("/{id}")
@ManagedAsync
public void getById(@PathParam("id") long id, @Suspended final AsyncResponse ar)
{
Stuff s;
// HIT THE DATABASE FOR STUFF
ar.resume(s);
}
}
UPDATE Just heard back from the Jersey guys, and this is not possible as of 2.7. Only the resource method itself is invoked asynchronously, not filters. Any suggestions for proceeding still welcome.
See Question&Answers more detail:os