Skip to content

ContextManager library in Java to propagate context across threads.

License

Notifications You must be signed in to change notification settings

hanson76/context-propagation

 
 

Repository files navigation

Build Status Coverage Status Maven Version

Context propagation library

Standardized context propagation in concurrent systems.

Provides a standardized way to create snapshots from various supported ThreadLocal-based Context types that can be reactivated in another thread.

How to use this library

Capturing a snapshot of ThreadLocal context values

Just before creating a new thread, capture a snapshot of all ThreadLocal context values:

ContextSnapshot snapshot = ContextManagers.createContextSnapshot();

In the code of your background thread, activate the snapshot to have all ThreadLocal context values set as they were captured:

try (Context<Void> reactivation = snapshot.reactivate()) {
    // All ThreadLocal values from the snapshot are available within this block
}

Threadpools and ExecutorService

If your background threads are managed by an ExecutorService acting as a threadpool, you can use the ContextAwareExecutorService instead of your usual threadpool.
This automatically takes a new context snapshot when submitting new work and reactivates this snapshot in the background threads.
The ContextAwareExecutorService can wrap any ExecutorService for the actual thread execution:

// private static final ExecutorService THREADPOOL = Executors.newCachedThreadpool();
private static final ExecutorService THREADPOOL = 
        new ContextAwareExecutorService(Executors.newCachedThreadpool());

It will automatically create a snapshot and reactivate it in the background thread when started.
The ThreadLocal values from the calling thread will therefore be available in the background thread as well.

Supported contexts

The following ThreadLocal-based contexts are currently supported out of the box by this context-propagation library:

Adding your own Context type is not difficult.

Custom contexts

It is easy to add a custom Context type to be propagated:

  1. Implement the ContextManager interface.
    Create a class with a default constructor that implements initializeNewContext and getActiveContext methods.
  2. Create a service file called /META-INF/services/nl.talsmasoftware.context.ContextManager containing the qualified class name of your ContextManager implementation.
  3. That's it. Now the result from your getActiveContext method is propagated into each snapshot created by the ContextManagers.createSnapshot() method. This includes all usages of the ContextAwareExecutorService.

An example of a custom context implementation:

public class DummyContextManager implements ContextManager<String> {
    public Context<String> initializeNewContext(String value) {
        return new DummyContext(value);
    }

    public Context<String> getActiveContext() {
        return DummyContext.current();
    }
    
    public static Optional<String> currentValue() {
        return Optional.ofNullable(DummyContext.current()).map(Context::getValue);
    }
    
    private static final class DummyContext extends AbstractThreadLocalContext<String> {
        private DummyContext(String newValue) {
            super(newValue);
        }
        
        private static Context<String> current() {
            return AbstractThreadLocalContext.current(DummyContext.class);
        }
    }
}

Caching

By default the ContextManagers class caches the context manager instances it finds per context classloader. Since the cache is per classloader, this should work satisfactory for applications with simple classloader hierarchies (e.g. spring boot, dropwizard etc) and complex hierarchies (JEE and the like).

Disable caching

If however, you wish to disable caching of the context manager instances, you can set either:

  • the java system property talsmasoftware.context.caching, or
  • the environment variable TALSMASOFTWARE_CONTEXT_CACHNG

to the values false or 0.

Performance metrics

No library is 'free' with regards to performance. Capturing a context snapshot and reactivating it in another thread is no different. For insight, the library tracks the overall time used creating and reactivating context snapshots along with time spent in each individual ContextManager.

Logging performance

On a development machine, you can get timing for each snapshot by turning on logging for nl.talsmasoftware.context.Timing at FINEST or TRACE level (depending on your logger of choice). Please do not turn this on in production as the logging overhead will most likely have a noticable impact to the context management itself.

Dropwizard metrics

If your project happens to use dropwizard metrics, adding the context propagation metrics module to your classpath will automatically configure various timers in the default metric registry of your application.

License

Apache 2.0 license

About

ContextManager library in Java to propagate context across threads.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Java 100.0%