Asynchronous method invocation and RequestScoped beans

The problem

This week I ran into a problem with asynchronous method invocation and a RequestScoped bean. Consider the following situation.

I have a JAX-WS web service with a SOAPHandler handling the authentication. In the SOAPHandler an object (let’s call it RequestContext) is filled with parameters specific to the request like the user and customer information) This object is a regular class, annotated with the @RequestScoped annotation, so it lives during the handling of the SOAP request.

As defined, the @RequestScoped object is available in EJBs which get called by the JAX-WS implementation class. However, when in one of the EJBs an @Asynchronous method gets invoked, the RequestScope gets reinitialized. So far I haven’t found any spec yet documenting this behaviour, but in a way I think it makes sense. The @Asynchronous method may outlive the actual SOAP request, and I figure that’s why RequestScoped beans get reinitialized.

Although the async method won’t outlive the SOAP request in my case, I’ve constructed a workaround. Instead of injecting the RequestScoped bean, I’m passing a Callable<V> to the async method. See the following examples.

The code

The code explained

As I outlined in the comment of TestService, the injected requestContext needs to be cloned. If you pass in the injected requestContext, you’re actually passing a proxy to the original requestContext. If you call clone() on the proxy, you’ll get the actual clone and so a plain non-CDI object. The Callable will exist for as long as the async method exists, because the async method holds a reference to it.

This is probably not the best way to do it, and there are obvious downsides to it. It’s not possible to modify the request context in the async method, but I guess it’s not a good idea to do such modifications in scoped beans from async methods anyway.

Conclusion

When you need this kind of a construct, this may be a way to do it. If you have better ways of doing this, please tell me so in the comments 🙂