public 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:
createContextualProxy
methods.
hashCode
,
equals
, toString
and all other methods declared in
Object
.
Serializable
if the proxied object instance is serializable.
Serializable
if the proxy instance is serialized.
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; } }));
Modifier and Type | Method and Description |
---|---|
<R> java.util.concurrent.Callable<R> |
contextualCallable(java.util.concurrent.Callable<R> callable)
Wraps a
Callable with context
that is captured from the thread that invokes
contextualCallable . |
<T,U> java.util.function.BiConsumer<T,U> |
contextualConsumer(java.util.function.BiConsumer<T,U> consumer)
Wraps a
BiConsumer with context
that is captured from the thread that invokes
contextualConsumer . |
<T> java.util.function.Consumer<T> |
contextualConsumer(java.util.function.Consumer<T> consumer)
Wraps a
Consumer with context
that is captured from the thread that invokes
contextualConsumer . |
<T,U,R> java.util.function.BiFunction<T,U,R> |
contextualFunction(java.util.function.BiFunction<T,U,R> function)
Wraps a
BiFunction with context
that is captured from the thread that invokes
contextualFunction . |
<T,R> java.util.function.Function<T,R> |
contextualFunction(java.util.function.Function<T,R> function)
Wraps a
BiFunction with context
that is captured from the thread that invokes
contextualFunction . |
java.lang.Runnable |
contextualRunnable(java.lang.Runnable runnable)
Wraps a
Runnable with context
that is captured from the thread that invokes
contextualRunnable . |
<R> java.util.function.Supplier<R> |
contextualSupplier(java.util.function.Supplier<R> supplier)
Wraps a
Supplier with context captured from the thread that invokes
contextualSupplier . |
java.lang.Object |
createContextualProxy(java.lang.Object instance,
java.lang.Class<?>... interfaces)
Creates a new contextual object proxy for the input object instance.
|
java.lang.Object |
createContextualProxy(java.lang.Object instance,
java.util.Map<java.lang.String,java.lang.String> executionProperties,
java.lang.Class<?>... interfaces)
Creates a new contextual object proxy for the input object instance.
|
<T> T |
createContextualProxy(T instance,
java.lang.Class<T> intf)
Creates a new contextual object proxy for the input object instance.
|
<T> T |
createContextualProxy(T instance,
java.util.Map<java.lang.String,java.lang.String> executionProperties,
java.lang.Class<T> intf)
Creates a new contextual object proxy for the input object instance.
|
java.util.concurrent.Executor |
currentContextExecutor()
Captures thread context as an
Executor
that runs tasks on the same thread from which
execute is invoked but with context that is captured from the thread
that invokes currentContextExecutor . |
java.util.Map<java.lang.String,java.lang.String> |
getExecutionProperties(java.lang.Object contextualProxy)
Gets the current execution properties on the context proxy instance.
|
<T> java.util.concurrent.CompletableFuture<T> |
withContextCapture(java.util.concurrent.CompletableFuture<T> stage)
Returns a new
CompletableFuture that is completed by the completion of the
specified stage. |
<T> java.util.concurrent.CompletionStage<T> |
withContextCapture(java.util.concurrent.CompletionStage<T> stage)
Returns a new
CompletionStage that is completed by the completion of the
specified stage. |
<R> java.util.concurrent.Callable<R> contextualCallable(java.util.concurrent.Callable<R> callable)
Wraps a Callable
with context
that is captured from the thread that invokes
contextualCallable
. Context is captured at the time contextualCallable
is invoked.
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.
R
- callable result type.callable
- instance to contextualize.call
method with context.java.lang.IllegalArgumentException
- if an already-contextualized Callable
is supplied to this method.<T,U> java.util.function.BiConsumer<T,U> contextualConsumer(java.util.function.BiConsumer<T,U> consumer)
Wraps a BiConsumer
with context
that is captured from the thread that invokes
contextualConsumer
. Context is captured at the time contextualConsumer
is invoked.
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.
T
- type of first parameter to consumer.U
- type of second parameter to consumer.consumer
- instance to contextualize.accept
method with context.java.lang.IllegalArgumentException
- if an already-contextualized BiConsumer
is supplied to this method.<T> java.util.function.Consumer<T> contextualConsumer(java.util.function.Consumer<T> consumer)
Wraps a Consumer
with context
that is captured from the thread that invokes
contextualConsumer
. Context is captured at the time contextualConsumer
is invoked.
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.
T
- type of parameter to consumer.consumer
- instance to contextualize.accept
method with context.java.lang.IllegalArgumentException
- if an already-contextualized Consumer
is supplied to this method.<T,U,R> java.util.function.BiFunction<T,U,R> contextualFunction(java.util.function.BiFunction<T,U,R> function)
Wraps a BiFunction
with context
that is captured from the thread that invokes
contextualFunction
. Context is captured at the time contextualFunction
is invoked.
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.
T
- type of first parameter to function.U
- type of second parameter to function.R
- function result type.function
- instance to contextualize.apply
method with context.java.lang.IllegalArgumentException
- if an already-contextualized BiFunction
is supplied to this method.<T,R> java.util.function.Function<T,R> contextualFunction(java.util.function.Function<T,R> function)
Wraps a BiFunction
with context
that is captured from the thread that invokes
contextualFunction
. Context is captured at the time contextualFunction
is invoked.
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.
T
- type of parameter to function.R
- function result type.function
- instance to contextualize.apply
method with context.java.lang.IllegalArgumentException
- if an already-contextualized Function
is supplied to this method.java.lang.Runnable contextualRunnable(java.lang.Runnable runnable)
Wraps a Runnable
with context
that is captured from the thread that invokes
contextualRunnable
. Context is captured at the time contextualRunnable
is invoked.
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.
runnable
- instance to contextualize.run
method with context.java.lang.IllegalArgumentException
- if an already-contextualized Runnable
is supplied to this method.<R> java.util.function.Supplier<R> contextualSupplier(java.util.function.Supplier<R> supplier)
Wraps a Supplier
with context captured from the thread that invokes
contextualSupplier
. Context is captured at the time contextualSupplier
is invoked.
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.
R
- supplier result type.supplier
- instance to contextualize.supply
method with context.java.lang.IllegalArgumentException
- if an already-contextualized Supplier
is supplied to this method.<T> T createContextualProxy(T instance, java.lang.Class<T> intf)
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);
T
- the type of the instance to proxyinstance
- the instance of the object to proxy.intf
- the interface that the proxy should implement.java.lang.IllegalArgumentException
- - if the intf
argument
is null or the instance does not implement the specified
interface.java.lang.UnsupportedOperationException
- - if the intf
interface is serializable
but a thread context type does not support serialization.java.lang.Object createContextualProxy(java.lang.Object instance, java.lang.Class<?>... interfaces)
This method is similar to <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);
instance
- the instance of the object to proxy.interfaces
- the interfaces that the proxy should implement.java.lang.IllegalArgumentException
- - if the interfaces
argument is null or the instance does not implement
all the specified interfaces.java.lang.UnsupportedOperationException
- - if any of the interfaces
are serializable
but a thread context type
does not support serialization.<T> T createContextualProxy(T instance, java.util.Map<java.lang.String,java.lang.String> executionProperties, java.lang.Class<T> intf)
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. } }
T
- the type of the interfaceinstance
- 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.java.lang.IllegalArgumentException
- - if the intf
argument
null or the instance does not implement the specified interface.java.lang.UnsupportedOperationException
- - if the intf
interface is serializable
but a thread context type does not support serialization.java.lang.Object createContextualProxy(java.lang.Object instance, java.util.Map<java.lang.String,java.lang.String> executionProperties, java.lang.Class<?>... interfaces)
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.
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.java.lang.IllegalArgumentException
- - if the interfaces
argument is null or the instance does not implement all the specified
interfaces.java.lang.UnsupportedOperationException
- - if any of the interfaces
are serializable
but a thread context type
does not support serialization.java.util.concurrent.Executor currentContextExecutor()
Captures thread context as an Executor
that runs tasks on the same thread from which
execute
is invoked but with context that is captured from the thread
that invokes currentContextExecutor
.
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 raise IllegalArgumentException
if an already-contextualized Runnable
is supplied to its
execute
method.
execute
method with context.java.util.Map<java.lang.String,java.lang.String> getExecutionProperties(java.lang.Object contextualProxy)
contextualProxy
- the contextual proxy instance to retrieve the execution properties.java.lang.IllegalArgumentException
- thrown if the input contextualProxy is not a valid
contextual object proxy created with the
createContextualProxy
method.<T> java.util.concurrent.CompletableFuture<T> withContextCapture(java.util.concurrent.CompletableFuture<T> stage)
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 same ManagedExecutorService
if this ContextService
was obtained by ManagedExecutorService.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).
T
- completable future result type.stage
- a completable future whose completion triggers completion of the new completable
future that is created by this method.<T> java.util.concurrent.CompletionStage<T> withContextCapture(java.util.concurrent.CompletionStage<T> stage)
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 same ManagedExecutorService
if this ContextService
was obtained by ManagedExecutorService.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).
T
- completion stage result type.stage
- a completion stage whose completion triggers completion of the new stage
that is created by this method.