Interface ThreadContext


public interface ThreadContext
This interface offers various methods for capturing the context of the current thread and applying it to various interfaces that are commonly used with completion stages and executor services. This allows you to contextualize specific actions that need access to the context of the creator/submitter of the stage/task.

Example usage:

 ThreadContext threadContext = ThreadContext.builder()
     .propagated(ThreadContext.SECURITY, ThreadContext.APPLICATION)
     .cleared(ThreadContext.TRANSACTION)
     .unchanged(ThreadContext.ALL_REMAINING)
     .build();
 ...
 CompletableFuture<Integer> stage2 = stage1.thenApply(threadContext.contextualFunction(function));
 ...
 Future<Integer> future = executor.submit(threadContext.contextualCallable(callable));
 
 

This interface is intentionally kept compatible with ContextService, with the hope that its methods might one day be contributed to that specification.

  • Field Details

    • ALL_REMAINING

      static final String ALL_REMAINING

      Identifier for all available thread context types which are not specified individually under cleared, propagated, or unchanged.

      When using this constant, be aware that bringing in a new context provider or updating levels of an existing context provider might change the set of available thread context types.

      See Also:
    • APPLICATION

      static final String APPLICATION
      Identifier for application context. Application context controls the application component that is associated with a thread. It can determine the thread context class loader as well as the set of resource references that are available for lookup or resource injection. An empty/default application context means that the thread is not associated with any application.
      See Also:
    • CDI

      static final String CDI
      Identifier for CDI context. CDI context controls the availability of CDI scopes. An empty/default CDI context means that the thread does not have access to the scope of the session, request, and so forth that created the contextualized action. For example, consider the following @RequestScoped resource:
      
          @RequestScoped
          public class MyRequestScopedBean {
              public String getState() {
                // returns some request-specific information to the caller
              }
          }
          
      CDI context propagation includes request, session and conversation contexts. When CDI context is propagated, all of the above mentioned contexts that are currently active will be available to the contextualized task with preserved state.
      
          ManagedExecutor exec = ManagedExecutor.builder()
              .propagated(ThreadContext.CDI, ThreadContext.APPLICATION)
              .build();
          
          @Inject
          MyRequestScopedBean requestBean;
          
          @GET
          public void foo() {
              exec.supplyAsync(() -> {
                  String state = reqBean.getState();
                  // do some work with the request state
              }).thenApply(more -> {
                  // request state also available in future stages
              });
          }
          
      If CDI context is 'cleared', currently active contexts will still be available to the contextualized task, but their state will be erased. If CDI context is 'unchanged', access to CDI bean's contextual state will be non-deterministic. Namely, context may be missing, or context from a different task may be applied instead. This option is discouraged, and only should be used if CDI context is not used in an application.
      See Also:
    • NONE

      static final String[] NONE
      An empty array of thread context. This is provided as a convenience for code that wishes to be more explicit. For example, you can specify builder.propagated(ThreadContext.NONE) rather than builder.propagated(new String[0]) or builder.propagated(), all of which have the same meaning.
    • SECURITY

      static final String SECURITY
      Identifier for security context. Security context controls the credentials that are associated with the thread. An empty/default security context means that the thread is unauthenticated.
      See Also:
    • TRANSACTION

      static final String TRANSACTION
      Identifier for transaction context. Transaction context controls the active transaction scope that is associated with the thread. Implementations are not expected to propagate transaction context across threads. Instead, the concept of transaction context is provided for its cleared context, which means the active transaction on the thread is suspended such that a new transaction can be started if so desired. In most cases, the most desirable behavior will be to leave transaction context defaulted to cleared (suspended), in order to prevent dependent actions and tasks from accidentally enlisting in transactions that are on the threads where they happen to run.
      See Also:
  • Method Details

    • builder

      static ThreadContext.Builder builder()
      Creates a new ThreadContext.Builder instance.
      Returns:
      a new ThreadContext.Builder instance.
    • currentContextExecutor

      Executor currentContextExecutor()

      Creates an Executorthat runs tasks on the same thread from which executeis invoked but with context that is captured from the thread that invokes currentContextExecutor.

      Example usage:

       Executor contextSnapshot = threadContext.currentContextExecutor();
       ...
       // from another thread, or after thread context has changed,
       contextSnapshot.execute(() -> obj.doSomethingThatNeedsContext());
       contextSnapshot.execute(() -> doSomethingElseThatNeedsContext(x, y));
       

      The returned Executor must raise IllegalArgumentException if an already-contextualized Runnable is supplied to its execute method.

      Returns:
      an executor that wraps the execute method with context.
    • contextualCallable

      <R> Callable<R> contextualCallable(Callable<R> callable)

      Wraps a Callable with context that is captured from the thread that invokes contextualCallable.

      When call is invoked on the proxy instance, context is first established on the thread that will run the call method, then the call method of the provided Callable is invoked. Finally, the previous context is restored on the thread, and the result of the Callable is returned to the invoker.

      Type Parameters:
      R - callable result type.
      Parameters:
      callable - instance to contextualize.
      Returns:
      contextualized proxy instance that wraps execution of the call method with context.
      Throws:
      IllegalArgumentException - if an already-contextualized Callable is supplied to this method.
    • contextualConsumer

      <T, U> BiConsumer<T,U> contextualConsumer(BiConsumer<T,U> consumer)

      Wraps a BiConsumer with context that is captured from the thread that invokes contextualConsumer.

      When accept is invoked on the proxy instance, context is first established on the thread that will run the accept method, then the accept method of the provided BiConsumer is invoked. Finally, the previous context is restored on the thread, and control is returned to the invoker.

      Type Parameters:
      T - type of first parameter to consumer.
      U - type of second parameter to consumer.
      Parameters:
      consumer - instance to contextualize.
      Returns:
      contextualized proxy instance that wraps execution of the accept method with context.
      Throws:
      IllegalArgumentException - if an already-contextualized BiConsumer is supplied to this method.
    • contextualConsumer

      <T> Consumer<T> contextualConsumer(Consumer<T> consumer)

      Wraps a Consumer with context that is captured from the thread that invokes contextualConsumer.

      When accept is invoked on the proxy instance, context is first established on the thread that will run the accept method, then the accept method of the provided Consumer is invoked. Finally, the previous context is restored on the thread, and control is returned to the invoker.

      Type Parameters:
      T - type of parameter to consumer.
      Parameters:
      consumer - instance to contextualize.
      Returns:
      contextualized proxy instance that wraps execution of the accept method with context.
      Throws:
      IllegalArgumentException - if an already-contextualized Consumer is supplied to this method.
    • contextualFunction

      <T, U, R> BiFunction<T,U,R> contextualFunction(BiFunction<T,U,R> function)

      Wraps a BiFunction with context that is captured from the thread that invokes contextualFunction.

      When apply is invoked on the proxy instance, context is first established on the thread that will run the apply method, then the apply method of the provided BiFunction is invoked. Finally, the previous context is restored on the thread, and the result of the BiFunction is returned to the invoker.

      Type Parameters:
      T - type of first parameter to function.
      U - type of second parameter to function.
      R - function result type.
      Parameters:
      function - instance to contextualize.
      Returns:
      contextualized proxy instance that wraps execution of the apply method with context.
      Throws:
      IllegalArgumentException - if an already-contextualized BiFunction is supplied to this method.
    • contextualFunction

      <T, R> Function<T,R> contextualFunction(Function<T,R> function)

      Wraps a Function with context that is captured from the thread that invokes contextualFunction.

      When apply is invoked on the proxy instance, context is first established on the thread that will run the apply method, then the apply method of the provided Function is invoked. Finally, the previous context is restored on the thread, and the result of the Function is returned to the invoker.

      Type Parameters:
      T - type of parameter to function.
      R - function result type.
      Parameters:
      function - instance to contextualize.
      Returns:
      contextualized proxy instance that wraps execution of the apply method with context.
      Throws:
      IllegalArgumentException - if an already-contextualized Function is supplied to this method.
    • contextualRunnable

      Runnable contextualRunnable(Runnable runnable)

      Wraps a Runnable with context that is captured from the thread that invokes ContextualRunnable.

      When run is invoked on the proxy instance, context is first established on the thread that will run the run method, then the run method of the provided Runnable is invoked. Finally, the previous context is restored on the thread, and control is returned to the invoker.

      Parameters:
      runnable - instance to contextualize.
      Returns:
      contextualized proxy instance that wraps execution of the run method with context.
      Throws:
      IllegalArgumentException - if an already-contextualized Runnable is supplied to this method.
    • contextualSupplier

      <R> Supplier<R> contextualSupplier(Supplier<R> supplier)

      Wraps a Supplier with context captured from the thread that invokes contextualSupplier.

      When supply is invoked on the proxy instance, context is first established on the thread that will run the supply method, then the supply method of the provided Supplier is invoked. Finally, the previous context is restored on the thread, and the result of the Supplier is returned to the invoker.

      Type Parameters:
      R - supplier result type.
      Parameters:
      supplier - instance to contextualize.
      Returns:
      contextualized proxy instance that wraps execution of the supply method with context.
      Throws:
      IllegalArgumentException - if an already-contextualized Supplier is supplied to this method.
    • withContextCapture

      <T> CompletableFuture<T> withContextCapture(CompletableFuture<T> stage)

      Returns a new CompletableFuture that is completed by the completion of the specified stage.

      The new completable future is backed by a ThreadContext rather than a ManagedExecutor. Therefore, the new stage and all dependent stages created from it, and so forth, have no default asynchronous execution facility and must raise UnsupportedOperationException for all *Async methods that do not specify an executor. For example, thenRunAsync(Runnable).

      When dependent stages are created from the new completable future, thread context is captured and/or cleared as described in the documentation of the ManagedExecutor class, except that this ThreadContext instance takes the place of the default asynchronous execution facility in supplying the configuration of cleared/propagated context types. This guarantees that the action performed by each stage always runs under the thread context of the code that creates the stage, unless the user explicitly overrides by supplying a pre-contextualized action.

      Invocation of this method does not impact thread context propagation for the supplied completable future or any dependent stages created from it, other than the new dependent completable future that is created by this method.

      Type Parameters:
      T - completable future result type.
      Parameters:
      stage - a completable future whose completion triggers completion of the new completable future that is created by this method.
      Returns:
      the new completable future.
    • withContextCapture

      <T> CompletionStage<T> withContextCapture(CompletionStage<T> stage)

      Returns a new CompletionStage that is completed by the completion of the specified stage.

      The new completion stage is backed by a ThreadContext rather than a ManagedExecutor. Therefore, the new stage and all dependent stages created from it, and so forth, have no default asynchronous execution facility and must raise UnsupportedOperationException for all *Async methods that do not specify an executor. For example, thenRunAsync(Runnable).

      When dependent stages are created from the new completion stage, thread context is captured and/or cleared as described in the documentation of the ManagedExecutor class, except that this ThreadContext instance takes the place of the default asynchronous execution facility in supplying the configuration of cleared/propagated context types. This guarantees that the action performed by each stage always runs under the thread context of the code that creates the stage, unless the user explicitly overrides by supplying a pre-contextualized action.

      Invocation of this method does not impact thread context propagation for the supplied stage or any dependent stages created from it, other than the new dependent completion stage that is created by this method.

      Type Parameters:
      T - completion stage result type.
      Parameters:
      stage - a completion stage whose completion triggers completion of the new stage that is created by this method.
      Returns:
      the new completion stage.