I have a Java Spring Service with a RestController that calls an async method:
@RestController
public class SomeController {
@Autowired
//this is the service that contains the async-method
OtherService otherService;
@GetMapping
public void someFunctionWithinTheMainRequestThread() {
otherService.asyncMethod(RequestContextHolder.getRequestAttributes());
}
}
That async method needs to use the RequestContextAttributes because it is building Links with linkTo(...). The problem is that no matter how I pass the RequestAttributes to the method, I always get the error
java.lang.IllegalStateException: Cannot ask for request attribute - request is not active anymore!
This is the annotation on the async method:
public class OtherService {
@Async
@Transactional(readOnly = true)
public void asyncMethod(RequestAttributes context) {
RequestContextHolder.setRequestAttributes(context);
//doing a lot of stuff that takes a while
linkTo(methodOn(...)) //-> here the error occurs
}
What I tried:
- Passing RequestAttributes manually as a Parameter (as seen in the code-snippets above)
- Using the context-aware-pool executor described in this answer: How to enable request scope in async task executor - which basically seems to do the same as if I pass the context as a variable only that is is configured globally
- Updating the servlet config and setting ThreadContextInheritable to true
- Assigning the RequestAttributes to a final variable to try to get a copy of the original object which is marked as inactive by the main thread
No matter what I do, the request always seems to finish before my async method and I apparently never have a deep copy of the Attributes so they always get marked as inactive by the main thread before the async method is finished and then I can't use them anymore -> at least that is my understanding of the error.
I just want to be able to get the requestAttributes needed for the linkTo method in my async method even after the main thread finished the request, can someone point me in the right direction?
I found a solution that does work and removes the error. Since I don't think this is really clean I am hoping for more answers but in case it helps someone:
First I added this class. It creates a custom and very simple RequestAttributes-Implementation that enables us to keep the Attributes active for longer than they normally would be:
Then in the RestController before the async method is called:
And then in the async function: