Closed jesse-gallagher closed 1 year ago
The trouble looks to come from @Context private Application application
being null
when used to populate a client request. It looks like this is indeed specific to async use: the trouble doesn't arise when used in a single thread.
I put some null guards in there to avoid the immediate trouble, but the true fix would be to propagate the Application to the new thread.
This is an odd one. There's a class responsible for ferrying context between threads in the core RESTeasy already - RestEasyContext
- that works in a way similar to Concurrency API extensions.
Though it should already be present, I also added in a "true" Concurrency participant to wrap it. I can see it working - it captures and pushes a contextual Map
that contains the Application
class. However, by the time the JsonBindingProvider
is called, that map has been replaced by another one (or trimmed) containing only a Providers
implementation.
What makes this all the more odd is that the test passes when it's the only one executed and fails when run in the full suite, so something must be poisoning it. To my knowledge, nothing in this project intentionally called this before now, so it must be some odd interaction or an effect of, say, the MicroProfile additions.
Internally, the context map is stored in a stack structure, so presumably what's happening is that the right data is being pushed in, but then something else pushes a lesser map in for some reason. I'm not sure why or what that'd be, though.
I decided to check the theory that perhaps something in there was pushing another map to the stack and the "good" one was below. Unfortunately, that doesn't seem to be the case: in the two instances where the application object is null, the stack size is 1
. Conversely, there's a case where it is 2
, but the application object isn't null.
At this point, I suspect the problem may lie in the messiness of bootstrapping the JAX-RS Client. With incoming JAX-RS requests, things can be cleanly set up, but it's possible that running clients in threads don't find the context one way or another - if the thread spawner didn't see the active app and thus the default context propagator, maybe that's the trouble. The inconsistency of it makes it tough to be sure, though.
This was observed when the request was made via a Concurrency task, but I'm not sure if that is related, but it is readily reproducible with code like:
This results in a stack trace of: