The main context-propagation
module implements the core concepts
of propagating contexts.
The main use case is taking a snapshot
of ThreadLocal
values from the calling thread
and reactivating it in another thread.
The terms Context, Context Manager and Context Snapshot are crucial to understanding this library.
A context can be anything that needs to be maintained on the 'current thread' level.
Implementations are typically maintained with a static ThreadLocal variable. Contexts have a life-cycle that is simply defined as: they can be created and closed, within a single thread. A well-behaved Context restores the original value when it is closed.
An abstract implementation is available that takes care of nested contexts and restoring the 'previous' context state. It contains safeguards for concurrency and out-of-sequence closing of contexts, although technically these use cases are not appropriate.
Manages contexts by initializing and maintaining an active context value.
Normally it is not necessary to interact directly with individual context managers. The api detects available context managers and lets you capture a snapshot of all active contexts at once.
A context snapshot is captured by the ContextSnapshot' capture()
method.
The snapshot contains active context values from all known ContextManager implementations.
Once created, the captured values in such context snapshot will not change anymore,
even when the active context is later modified.
The values in this snapshot can be reactivated all at once in another thread.
They stay active until the reactivation is closed again (or are overwritten by new values).
Closing the reactivated object is mandatory (from the thread where the reactivation was called).
-
Create a context manager.
Implement thenl.talsmasoftware.context.ContextManager
interface.
Make sure your class has a public default constructor. -
Register your context manager.
Add a service file to your application called/META-INF/services/nl.talsmasoftware.context.ContextManager
.
It should contain the fully qualified classname of your implementation.
public class DummyContextManager implements ContextManager<String> {
public Context<String> initializeNewContext(String value) {
return new DummyContext(value);
}
public Context<String> getActiveContextValue() {
DummyContext current = DummyContext.current();
return current != null ? current.getValue() : null;
}
private static final class DummyContext extends AbstractThreadLocalContext<String> {
private DummyContext(String newValue) {
super(newValue);
}
private static Context<String> current() {
return AbstractThreadLocalContext.current(DummyContext.class);
}
}
}