Interface ContextService
java.lang.reflect.Proxy
).
ContextService also creates proxy objects for functional interfaces
(such as Function
) that can be used as
completion stage actions. Proxy objects run with
the addition of context typically associated with applications executing in a
Jakarta™ EE environment.
Examples of such context are classloading, namespace, security, etc.
The proxy objects follow the same rules as defined for the
java.lang.reflect.Proxy
class with the following additions:
- The proxy instance will retain the context of the creator's thread.
- The proxy instance will implement all of the interfaces specified on the
createContextualProxy
methods. - The object to have a proxy instance created for should not be a component managed by the Jakarta EE Product Provider, such as a web component or a Jakarta Enterprise Bean.
- All interface method invocations on a proxy instance run in the
creator's context with the exception of
hashCode
,equals
,toString
and all other methods declared inObject
. - The proxy instance must implement
Serializable
if the proxied object instance is serializable. - The proxied object instance must implement
Serializable
if the proxy instance is serialized. - Execution properties can be stored with the proxy instance. Custom property keys must not begin with "jakarta.enterprise.concurrent.".
- Execution properties are to be used for controlling how various contextual information is retrieved and applied to the thread. Although application components can store arbitrary property keys and values, it is not recommended. Jakarta EE product providers may impose limits to the size of the keys and values.
For example, to contextualize a single completion stage action such that it is able to access the namespace of the application component,
contextSvc = InitialContext.doLookup("java:comp/DefaultContextService"); stage2 = stage1.thenApply(contextSvc.contextualFunction(i -> { DataSource ds = InitialContext.doLookup("java:comp/env/dsRef"); try (Connection con = ds.getConnection()) { PreparedStatement stmt = con.prepareStatement(sql); stmt.setInt(1, i); ResultSet result = stmt.executeQuery(); return result.next() ? result.getInt(1) : 0; } }));
- Since:
- 1.0
-
Method Summary
Modifier and TypeMethodDescription<R> Callable<R>
contextualCallable
(Callable<R> callable) Wraps aCallable
with context that is captured from the thread that invokescontextualCallable
.<T,
U> BiConsumer<T, U> contextualConsumer
(BiConsumer<T, U> consumer) Wraps aBiConsumer
with context that is captured from the thread that invokescontextualConsumer
.<T> Consumer<T>
contextualConsumer
(Consumer<T> consumer) Wraps aConsumer
with context that is captured from the thread that invokescontextualConsumer
.<T,
U, R> BiFunction<T, U, R> contextualFunction
(BiFunction<T, U, R> function) Wraps aBiFunction
with context that is captured from the thread that invokescontextualFunction
.<T,
R> Function<T, R> contextualFunction
(Function<T, R> function) Wraps aBiFunction
with context that is captured from the thread that invokescontextualFunction
.<T,
R> Flow.Processor<T, R> contextualProcessor
(Flow.Processor<T, R> processor) Wraps aFlow.Processor
with context captured from the thread that invokescontextualProcessor
.contextualRunnable
(Runnable runnable) Wraps aRunnable
with context that is captured from the thread that invokescontextualRunnable
.<T> Flow.Subscriber<T>
contextualSubscriber
(Flow.Subscriber<T> subscriber) Wraps aFlow.Subscriber
with context captured from the thread that invokescontextualSubscriber
.<R> Supplier<R>
contextualSupplier
(Supplier<R> supplier) Wraps aSupplier
with context captured from the thread that invokescontextualSupplier
.createContextualProxy
(Object instance, Class<?>... interfaces) Creates a new contextual object proxy for the input object instance.createContextualProxy
(Object instance, Map<String, String> executionProperties, Class<?>... interfaces) Creates a new contextual object proxy for the input object instance.<T> T
createContextualProxy
(T instance, Class<T> intf) Creates a new contextual object proxy for the input object instance.<T> T
createContextualProxy
(T instance, Map<String, String> executionProperties, Class<T> intf) Creates a new contextual object proxy for the input object instance.Captures thread context as anExecutor
that runs tasks on the same thread from whichexecute
is invoked but with context that is captured from the thread that invokescurrentContextExecutor
.getExecutionProperties
(Object contextualProxy) Gets the current execution properties on the context proxy instance.<T> CompletableFuture<T>
withContextCapture
(CompletableFuture<T> stage) Returns a newCompletableFuture
that is completed by the completion of the specified stage.<T> CompletionStage<T>
withContextCapture
(CompletionStage<T> stage) Returns a newCompletionStage
that is completed by the completion of the specified stage.
-
Method Details
-
contextualCallable
Wraps a
Callable
with context that is captured from the thread that invokescontextualCallable
. Context is captured at the timecontextualCallable
is invoked.When
call
is invoked on the proxy instance, context is first established on the thread that will run thecall
method, then thecall
method of the providedCallable
is invoked. Finally, the previous context is restored on the thread, and the result of theCallable
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-contextualizedCallable
is supplied to this method.- Since:
- 3.0
-
contextualConsumer
Wraps a
BiConsumer
with context that is captured from the thread that invokescontextualConsumer
. Context is captured at the timecontextualConsumer
is invoked.When
accept
is invoked on the proxy instance, context is first established on the thread that will run theaccept
method, then theaccept
method of the providedBiConsumer
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-contextualizedBiConsumer
is supplied to this method.- Since:
- 3.0
-
contextualConsumer
Wraps a
Consumer
with context that is captured from the thread that invokescontextualConsumer
. Context is captured at the timecontextualConsumer
is invoked.When
accept
is invoked on the proxy instance, context is first established on the thread that will run theaccept
method, then theaccept
method of the providedConsumer
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-contextualizedConsumer
is supplied to this method.- Since:
- 3.0
-
contextualFunction
Wraps a
BiFunction
with context that is captured from the thread that invokescontextualFunction
. Context is captured at the timecontextualFunction
is invoked.When
apply
is invoked on the proxy instance, context is first established on the thread that will run theapply
method, then theapply
method of the providedBiFunction
is invoked. Finally, the previous context is restored on the thread, and the result of theBiFunction
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-contextualizedBiFunction
is supplied to this method.- Since:
- 3.0
-
contextualFunction
Wraps a
BiFunction
with context that is captured from the thread that invokescontextualFunction
. Context is captured at the timecontextualFunction
is invoked.When
apply
is invoked on the proxy instance, context is first established on the thread that will run theapply
method, then theapply
method of the providedFunction
is invoked. Finally, the previous context is restored on the thread, and the result of theFunction
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-contextualizedFunction
is supplied to this method.- Since:
- 3.0
-
contextualRunnable
Wraps a
Runnable
with context that is captured from the thread that invokescontextualRunnable
. Context is captured at the timecontextualRunnable
is invoked.When
run
is invoked on the proxy instance, context is first established on the thread that will run therun
method, then therun
method of the providedRunnable
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-contextualizedRunnable
is supplied to this method.- Since:
- 3.0
-
contextualSupplier
Wraps a
Supplier
with context captured from the thread that invokescontextualSupplier
. Context is captured at the timecontextualSupplier
is invoked.When
supply
is invoked on the proxy instance, context is first established on the thread that will run thesupply
method, then thesupply
method of the providedSupplier
is invoked. Finally, the previous context is restored on the thread, and the result of theSupplier
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-contextualizedSupplier
is supplied to this method.- Since:
- 3.0
-
contextualSubscriber
Wraps a
Flow.Subscriber
with context captured from the thread that invokescontextualSubscriber
. Context is captured at the timecontextualSubscriber
is invoked.Whenever one of the methods of the
Flow.Subscriber
interface (such asonSubscribe
,onNext
,onError
, oronComplete
) is invoked on the proxy instance, context is first established on the thread that will run the method, then the method of the providedFlow.Subscriber
is invoked. Finally, the previous context is restored on the thread, and the result of theFlow.Subscriber
method is returned to the invoker.- Type Parameters:
T
- the subscribed item type- Parameters:
subscriber
- instance to contextualize- Returns:
- contextualized proxy instance that wraps execution of all
Subscriber
methods. - Since:
- 3.1
-
contextualProcessor
Wraps a
Flow.Processor
with context captured from the thread that invokescontextualProcessor
. Context is captured at the timecontextualProcessor
is invoked.Whenever one of the methods of the
Flow.Subscriber
interface (such asonSubscribe
,onNext
,onError
, oronComplete
) from whichFlow.Processor
extends is invoked on the proxy instance, context is first established on the thread that will run the method, then the method of the providedFlow.Processor
is invoked. Finally, the previous context is restored on the thread, and the result of theFlow.Processor
method is returned to the invoker.- Type Parameters:
T
- the subscribed item typeR
- the published item type- Parameters:
processor
- instance to contextualize- Returns:
- contextualized proxy instance that wraps execution of all methods that are inherited from
Subscriber
. - Since:
- 3.1
-
createContextualProxy
Creates a new contextual object proxy for the input object instance.Each method invocation will have the context of the application component instance that created the contextual object proxy.
The contextual object is useful when developing or using Java™ SE threading mechanisms propagating events to other component instances.
If the application component that created the proxy is not started or deployed, all methods on reflected interfaces may throw an
IllegalStateException
.For example, to execute a Runnable which is contextualized with the creator's context using a Java™ SE ExecutorService:
public class MyRunnable implements Runnable { public void run() { System.out.println("MyRunnable.run with Jakarta EE Context available."); } } InitialContext ctx = new InitialContext(); ThreadFactory threadFactory = (ThreadFactory) ctx .lookup("java:comp/env/concurrent/ThreadFactory"); ContextService ctxService = (ContextService) ctx .lookup("java:comp/env/concurrent/ContextService"); MyRunnable myRunnableInstance = ...; Runnable rProxy = ctxService.createContextualProxy(myRunnableInstance, Runnable.class); ExecutorService exSvc = Executors.newThreadPool(10, threadFactory); Future f = exSvc.submit(rProxy);
- Type Parameters:
T
- the type of the instance to proxy- Parameters:
instance
- the instance of the object to proxy.intf
- the interface that the proxy should implement.- Returns:
- a proxy for the input object that implements the specified interface.
- Throws:
IllegalArgumentException
- - if theintf
argument is null or the instance does not implement the specified interface.UnsupportedOperationException
- - if theintf
interface isserializable
but a thread context type does not support serialization.
-
createContextualProxy
Creates a new contextual object proxy for the input object instance.This method is similar to
Example:<T> T createContextualProxy(T instance, Class<T> intf)
except that this method can be used if the proxy has to support multiple interfaces.public class MyRunnableWork implements Runnable, SomeWorkInterface { public void run() { System.out.println("MyRunnableWork.run with Jakarta EE Context available."); } public void someWorkInterfaceMethod() { ... } } ThreadFactory threadFactory = ...; ContextService ctxService = ...; MyRunnableWork myRunnableWorkInstance = ...; Object proxy = ctxService.createContextualProxy(myRunnableWorkInstance, Runnable.class, SomeWorkInterface.class); // call SomeWorkInterface method on the proxy ((SomeWorkInterface) proxy).someWorkInterfaceMethod(); ExecutorService exSvc = Executors.newThreadPool(10, threadFactory); // submit the proxy as a Runnable to the ExecutorService Future f = exSvc.submit( (Runnable)proxy);
- Parameters:
instance
- the instance of the object to proxy.interfaces
- the interfaces that the proxy should implement.- Returns:
- a proxy for the input object that implements all of the specified interfaces.
- Throws:
IllegalArgumentException
- - if theinterfaces
argument is null or the instance does not implement all the specified interfaces.UnsupportedOperationException
- - if any of theinterfaces
areserializable
but a thread context type does not support serialization.
-
createContextualProxy
Creates a new contextual object proxy for the input object instance.The contextual object is useful when developing or using Java™ SE threading mechanisms propagating events to other component instances.
If the application component that created the proxy is not started or deployed, all methods on reflected interfaces may throw an
IllegalStateException
.This method accepts a
Map
object which allows the contextual object creator to define what contexts or behaviors to capture when creating the contextual object. The specified properties will remain with the contextual object.For example, to call a Message Driven Bean (MDB) with the sender's context, but within the MDB's transaction:
public class MyServlet ... { public void doPost() throws NamingException, JMSException { InitialContext ctx = new InitialContext(); // Get the ContextService that only propagates // security context. ContextService ctxSvc = (ContextService) ctx.lookup("java:comp/env/SecurityContext"); // Set any custom context data through execution properties Map<String, String> execProps = new HashMap<>(); execProps.put("vendor_a.security.tokenexpiration", "15000"); // Specify that contextual object should run inside the current // transaction. If we have a failure, we don't want to consume // the message. execProps.put(ManagedTask.TRANSACTION, "USE_TRANSACTION_OF_EXECUTION_THREAD"); ProcessMessage msgProcessor = ctxSvc.createContextualProxy(new MessageProcessor(), execProps, ProcessMessage.class); ConnectionFactory cf = (ConnectionFactory) ctx.lookup("java:comp/env/MyTopicConnectionFactory"); Destination dest = (Destination) ctx.lookup("java:comp/env/MyTopic"); Connection con = cf.createConnection(); Session session = con.createSession(true, Session.AUTO_ACKNOWLEDGE); MessageProducer producer = session.createProducer(dest); Message msg = session.createObjectMessage((Serializable)msgProcessor); producer.send(dest, msg); ... } public class MyMDB ... { public void onMessage(Message msg) { // Get the ProcessMessage contextual object from the message. ObjectMessage omsg = (ObjectMessage)msg; ProcessMessage msgProcessor = (ProcessMessage)omsg.getObject(); // Process the message in the specified context. msgProcessor.processMessage(msg); } } public interface ProcessMessage { public void processMessage(Message msg); } public class MessageProcessor implements ProcessMessage, Serializable { public void processMessage(Message msg) { // Process the message with the application container // context that sent the message. } }
- Type Parameters:
T
- the type of the interface- Parameters:
instance
- the instance of the object to proxy.executionProperties
- the properties to use when creating and running the context object.intf
- the interface that the proxy should implement.- Returns:
- a proxy for the input object that implements the specified interface.
- Throws:
IllegalArgumentException
- - if theintf
argument null or the instance does not implement the specified interface.UnsupportedOperationException
- - if theintf
interface isserializable
but a thread context type does not support serialization.
-
createContextualProxy
Object createContextualProxy(Object instance, Map<String, String> executionProperties, Class<?>... interfaces) Creates a new contextual object proxy for the input object instance.This method is similar to
<T> T createContextualProxy(T instance, Map<String, String> executionProperties, Class<T> intf)
except that this method can be used if the proxy has to support multiple interfaces.- Parameters:
instance
- the instance of the object to proxy.executionProperties
- the properties to use when creating and running the context object.interfaces
- the interfaces that the proxy should implement.- Returns:
- a proxy for the input object that implements all of the specified interfaces.
- Throws:
IllegalArgumentException
- - if theinterfaces
argument is null or the instance does not implement all the specified interfaces.UnsupportedOperationException
- - if any of theinterfaces
areserializable
but a thread context type does not support serialization.
-
currentContextExecutor
Executor currentContextExecutor()Captures thread context as an
Executor
that runs tasks on the same thread from whichexecute
is invoked but with context that is captured from the thread that invokescurrentContextExecutor
.Example usage:
Executor contextSnapshot = contextSvc.currentContextExecutor(); ... // from another thread, or after thread context has changed, contextSnapshot.execute(() -> obj.doSomethingThatNeedsContext()); contextSnapshot.execute(() -> doSomethingElseThatNeedsContext(x, y));
The returned
Executor
must raiseIllegalArgumentException
if an already-contextualizedRunnable
is supplied to itsexecute
method.- Returns:
- an executor that wraps the
execute
method with context. - Since:
- 3.0
-
getExecutionProperties
Gets the current execution properties on the context proxy instance.- Parameters:
contextualProxy
- the contextual proxy instance to retrieve the execution properties.- Returns:
- A copy of the current contextual object execution properties, or null if the contextualProxy is created without specifying any execution properties.
- Throws:
IllegalArgumentException
- thrown if the input contextualProxy is not a valid contextual object proxy created with thecreateContextualProxy
method.
-
withContextCapture
Returns a new
CompletableFuture
that is completed by the completion of the specified stage.The new completable future gets its default asynchronous execution facility from this
ContextService
, using the sameManagedExecutorService
if thisContextService
was obtained byManagedExecutorService.getContextService()
.When dependent stages are created from the new completable future, and from the dependent stages of those stages, and so on, thread context is captured and/or cleared by the
ContextService
. 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 originally supplied completable future or any other dependent stages directly created from it (not using 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.
- Since:
- 3.0
-
withContextCapture
Returns a new
CompletionStage
that is completed by the completion of the specified stage.The new completion stage gets its default asynchronous execution facility from this
ContextService
, using the sameManagedExecutorService
if thisContextService
was obtained byManagedExecutorService.getContextService()
, otherwise using the DefaultManagedExecutorService.When dependent stages are created from the new completion stage, and from the dependent stages of those stages, and so on, thread context is captured and/or cleared by the
ContextService
. 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 originally supplied stage or any other dependent stages directly created from it (not using 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.
- Since:
- 3.0
-