Interface Context


  • public interface Context
    A context propagation mechanism which can carry scoped-values across API boundaries and between threads.

    A Context object can be set to the ContextStorage, which effectively forms a scope for the context. The scope is bound to the current thread. Within a scope, its Context is accessible even across API boundaries, through current(). The scope is later exited by Scope.close() closing} the scope.

    Context objects are immutable and inherit state from their parent. To add or overwrite the current state a new context object must be created and then attached, replacing the previously bound context. For example:

    
     Context withCredential = Context.current().with(CRED_KEY, cred);
     withCredential.wrap(new Runnable() {
       public void run() {
          readUserRecords(userId, CRED_KEY.get());
       }
     }).run();
     

    Notes and cautions on use:

    • Every makeCurrent() must be followed by a Scope.close(). Breaking these rules may lead to memory leaks and incorrect scoping.
    • While Context objects are immutable they do not place such a restriction on the state they store.
    • Context is not intended for passing optional parameters to an API and developers should take care to avoid excessive dependence on context when designing an API.
    • Attaching Context from a different ancestor will cause information in the current Context to be lost. This should generally be avoided.
    • Method Detail

      • current

        static Context current()
        Return the context associated with the current Scope.
      • root

        static Context root()
        Returns the root Context which all other Context are derived from.

        It should generally not be required to use the root Context directly - instead, use current() to operate on the current Context. Only use this method if you are absolutely sure you need to disregard the current Context - this almost always is only a workaround hiding an underlying context propagation issue.

      • with

        <V> Context with​(ContextKey<V> k1,
                         V v1)
        Returns a new context with the given key value set.
        
         Context withCredential = Context.current().with(CRED_KEY, cred);
         withCredential.wrap(new Runnable() {
           public void run() {
              readUserRecords(userId, CRED_KEY.get());
           }
         }).run();
         

        Note that multiple calls to with(ContextKey, Object) can be chained together.

        
         context.with(K1, V1).with(K2, V2);
         

        Nonetheless, Context should not be treated like a general purpose map with a large number of keys and values — combine multiple related items together into a single key instead of separating them. But if the items are unrelated, have separate keys for them.

      • makeCurrent

        @MustBeClosed
        default Scope makeCurrent()
        Makes this the current context and returns a Scope which corresponds to the scope of execution this context is current for. current() will return this Context until Scope.close() is called. Scope.close() must be called to properly restore the previous context from before this scope of execution or context will not work correctly. It is recommended to use try-with-resources to call Scope.close() automatically.
        
         Context prevCtx = Context.current();
         try (Scope ignored = ctx.makeCurrent()) {
           assert Context.current() == ctx;
           ...
         }
         assert Context.current() == prevCtx;