While working on the JAX-RS 2.1 implementation in Liberty, a colleague of mine discovered some inconsistent behavior related to the reactive client's CompletionStage with regard to executors. He wrote me:
When a ManagedExecutorService is used as the default asynchronous execution facility for a CompletionStage created by a JAX-RS client's CompletionStageRxInvoker, the specification is currently unclear as to exactly when thread context should be captured for propagation to the CompletionStage and its dependent stages.
The ambiguity similarly exists when ManagedExecutorService is explicitly specified in any of the *Async methods. For example, completionStage.thenRunAsync(runnable, executor).
In discussions within our team, we have come to the conclusion that it makes sense for thread context capture to always (and only) be done at the point in time where CompletionStageRxInvoker.<method> is invoked to create the CompletionStage and at each point where CompletionStage.*Async is invoked to create a dependent stage.
Let's consider a scenario where code running as user1 uses the JAX-RS client to create a CompletionStage, and a subsequent block of code running as user2 adds a dependent stage, followed by another block of code running as user3, which adds another dependent stage.
This could be shown as:
Code running as user1 invokes: stage1 = clientBuilder.executorService(managedExecService).build().target(uri).request().rx().method(...);
Code running as user2 invokes: stage2 = stage1.handleAsync(function2);
Code running as user3 invokes: stage3 = stage2.handleAsync(function3);
With our proposal, the spec would guarantee that function2 always runs as user2 and function3 always runs as user3, which we believe to best match the intent of the user. Note that, lacking this behavior as proposed, it seems wrong to allow user2 or user3 to be able to add dependent stages that run as user1. Therefore, we would not want thread context capture to be done at alternate points, such as at the end of the execution of the previous stage. We would like to see the spec updated to state this guarantee about thread context capture and transfer when using the JAX-RS client builder with ManagedExecutorService, such that users will be able to rely on a predictable and useful behavior.
Would it be possible to clarify this in the spec - perhaps as part of a maintenance release? If it would help, I could draft up some text and submit a pull request.
Thanks in advance for your review,
J. Andrew McCright
IBM WebSphere Development
+1 507 253 7448