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
executeis 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
executeis 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.