Configure ManagedExecutorService instances
You can configure ManagedExecutorService instances to run asynchronous tasks with the specified thread context. It is a best practice for Java EE applications to avoid directly managing their own threads; therefore, the ManagedExecutorService extends the JSE ExecutorService to provide a way to launch asynchronous tasks within an application server environment. You might also configure the ManagedExecutorService to propagate various thread contexts that are relevant to Java EE applications to the thread of the asynchronous task.
The ManagedExecutorService is available under the <concurrent-1.0> feature and enabled in server.xml as follows:
<featureManager> <feature>concurrent-1.0</feature> </featureManager>Propagation of context to the thread of a task that is executed by the ManagedExecutorService is managed by the context service. A default instance of the context service (DefaultContextService) is created by the server and configured to propagate at least classloaderContext, jeeMetadataContext and securityContext. This default context service instance is used if a ManagedExecutorService is created without referring to a specific context service instance or configuring a context service instance directly within. Refer to the Configuring thread context service instances topic for more information.
A default managed executor instance (DefaultManagedExecutorService) is available as java:comp/DefaultManagedExecutorService and uses the default context service instance for thread context capture and propagation.
Attention: A current limitation in the Alpha is that submitted tasks might not run until Future.get is invoked.
Example configuration in server.xml:
- Managed executor service instance that is registered in JNDI with the name concurrent/execSvc, and that uses the default context service instance:
<managedExecutorService jndiName="concurrent/execSvc"/>
- Managed executor service instance with context service configured to propagate jeeMetadataContext only:
<managedExecutorService jndiName="concurrent/execSvc1"> <contextService> <jeeMetadataContext/> </contextService> </managedExecutorService>
- Managed executor service instance with classloaderContext and securityContext:
<managedExecutorService jndiName="concurrent/execSvc2"> <contextService> <classloaderContext/> <securityContext/> </contextService> </managedExecutorService>
- Thread context service that is shared by multiple managed executor service instances:
<contextService id="contextSvc1"> <jeeMetadataContext/> </contextService> <managedExecutorService jndiName="concurrent/execSvc3" contextServiceRef="contextSvc1"/> <managedExecutorService jndiName="concurrent/execSvc4" contextServiceRef="contextSvc1"/>
- Thread context service that inherits from the previous example and is used by a managed executor service instance:
<contextService id="contextSvc2" baseContextRef="contextSvc1"> <classloaderContext/> </contextService> <managedExecutorService jndiName="concurrent/execSvc5" contextServiceRef="contextSvc2"/>
- Managed executor service instance with zosWLMContext plus thread context propagation inherited from the default context service instance:
<managedExecutorService jndiName="concurrent/execSvc6"> <contextService baseContextRef="DefaultContextService"> <zosWLMContext defaultTransactionClass="TRAN1"/> </contextService> </managedExecutorService>
Example
Managed executor serviced instances can be injected into application components (using @Resource) or looked up with resource environment references (resource-env-ref). Regardless of how the instance is obtained, we can use it interchangeably as javax.enterprise.concurrent.ManagedExecutorService or its java.util.concurrent.ExecutorSerivce superclass.
- Example that uses @Resource to inject as java.util.concurrent.ExecutorService:
@Resource(lookup="concurrent/execSvc1") ExecutorService execSvc1; ... // submit task to run Future<Integer> future1 = execSvc1.submit(new Callable<Integer>() { public Integer call() throws Exception { // java:comp lookup is possible because <jeeMetadataContext> is configured DataSource ds = (DataSource) new InitialContext().lookup("java:comp/env/jdbc/ds1"); ... make updates to the database return updateCount; } }); Future<Integer> future2 = execSvc1.submit(anotherTaskThatUpdatesADatabase); numUpdatesCompleted = future1.get() + future2.get();
- Example that uses @Resource to inject as javax.enterprise.concurrent.ManagedExecutorService:
@Resource(lookup="concurrent/execSvc1") ManagedExecutorService execSvc1; ... // submit task to run Future<Integer> future1 = execSvc1.submit(new Callable<Integer>() { public Integer call() throws Exception { // java:comp lookup is possible because <jeeMetadataContext> is configured DataSource ds = (DataSource) new InitialContext().lookup("java:comp/env/jdbc/ds1"); ... make updates to the database return updateCount; } }); Future<Integer> future2 = execSvc1.submit(anotherTaskThatUpdatesADatabase); numUpdatesCompleted = future1.get() + future2.get();
- Example <resource-env-ref> for java.util.concurrent.ExecutorService in the web.xml file:
<resource-env-ref> <resource-env-ref-name>concurrent/execSvc2</resource-env-ref-name> <resource-env-ref-type>java.util.concurrent.ExecutorService</resource-env-ref-type> </resource-env-ref>
- Example <resource-env-ref> for javax.enterprise.concurrent.ManagedExecutorService in the web.xml file:
<resource-env-ref> <resource-env-ref-name>concurrent/execSvc2</resource-env-ref-name> <resource-env-ref-type>javax.enterprise.concurrent.ManagedExecutorService</resource-env-ref-type> </resource-env-ref>
- Example lookup that uses a resource environment reference:
ExecutorService execSvc2 = (ExecutorService) new InitialContext().lookup("java:comp/env/concurrent/execSvc2"); futures = execSvc2.invokeAll(Arrays.asList(task1, task2, task3));
- Example lookup that uses a resource environment reference and casts to ManagedExecutorService:
ManagedExecutorService execSvc2 = (ManagedExecutorService) new InitialContext().lookup("java:comp/env/concurrent/execSvc2"); futures = execSvc2.invokeAll(Arrays.asList(task1, task2, task3));
Parent topic: Administer the Liberty profile manually