Configure managed thread factories

We can configure ManagedThreadFactory instances to create new threads that run with a thread context of the thread from which the managed thread factory is looked up or injected. It is a best practice for Java EE applications to avoid directly managing their own threads; therefore, the ManagedThreadFactory extends the JSE ThreadFactory to provide a way to create managed threads within an application server environment. We might also configure the ManagedThreadFactory to capture a thread context that is relevant to Java EE applications and propagate it to the new thread. The managed thread factory is available under the <concurrent-1.0> feature and enabled in the server.xml file as follows:

Thread context capture and propagation 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 ManagedThreadFactory does not specify a context service. For more information about context service instances, refer to the Configure thread context service instances topic.

A default instance of ManagedThreadFactory (DefaultManagedThreadFactory) is available as java:comp/DefaultManagedThreadFactory and uses the default context service instance for thread context capture and propagation.

Example configuration in the server.xml file:

  • Managed thread factory that is registered in JNDI with the name concurrent/threadFactory, and that uses the default context service instance:

  • Managed thread factory with context service configured to capture and propagate securityContext only:

      <managedThreadFactory jndiName="concurrent/threadFactory1">
      	<contextService>
      		<securityContext/>
      	</contextService>
      </managedThreadFactory>

  • Managed thread factory with classloaderContext and jeeMetadataContext:

      <managedThreadFactory jndiName="concurrent/threadFactory2"> 
      	<contextService>
      		<classloaderContext/>
      		<jeeMetadataContext/>
      	</contextService>
      </managedThreadFactory>
      

  • Thread context service that is shared by multiple managed thread factories:


Example

Managed thread factories 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, it can be used interchangeably as javax.enterprise.concurrent.ManagedThreadFactory or java.util.concurrent.ThreadFactory.

  • Example that looks up the default managed thread factory:

      ManagedThreadFactory threadFactory =
          (ManagedThreadFactory) new InitialContext().lookup(
              "java:comp/DefaultManagedThreadFactory");
      // Create an executor that always runs tasks with the thread context of the managed thread factory
      ExecutorService executor = new ThreadPoolExecutor(
          coreThreads, maxThreads, keepAliveTime, TimeUnit.MINUTES,
          new ArrayBlockingQueue<Runnable>(workRequestQueueSize),
          threadFactory, new ThreadPoolExecutor.AbortPolicy());

  • Example that uses @Resource to inject as java.util.concurrent.ThreadFactory: :

      @Resource(lookup="concurrent/threadFactory2")
      ThreadFactory threadFactory
      ...
      
      // create a new thread
      Thread dailySalesAnalysisTask = threadFactory.newThread(new Runnable() {   public void run() {       // java:comp lookup is possible because <jeeMetadataContext> is configured
          DataSource ds = (DataSource) new InitialContext().lookup("java:comp/env/jdbc/ds1");
          ... analyze the data
        }
      });
      dailySalesAnalysisTask.start();

  • Example that uses @Resource to inject as javax.enterprise.concurrent.ManagedThreadFactory:

      @Resource(lookup="concurrent/threadFactory2")
      ManagedThreadFactory threadFactory;
      
      ... usage is same as previous example

  • Example <resource-env-ref> for java.util.concurrent.ThreadFactory in the web.xml file:

      <resource-env-ref>
      	<resource-env-ref-name>concurrent/threadFactory1</resource-env-ref-name>
      	<resource-env-ref-type>java.util.concurrent.ThreadFactory</resource-env-ref-type>
      </resource-env-ref>

  • Example <resource-env-ref> for javax.enterprise.concurrent.ManagedThreadFactory in the web.xml file:

      <resource-env-ref>
      	<resource-env-ref-name>concurrent/threadFactory2</resource-env-ref-name>
      	<resource-env-ref-type>javax.enterprise.concurrent.ManagedThreadFactory</resource-
      env-ref-type>
      </resource-env-ref>

  • Example lookup that uses a resource environment reference:

      ManagedThreadFactory threadFactory =
        (ManagedThreadFactory) new InitialContext().lookup("java:comp/env/concurrent/threadFactory");
      // Create a scheduled executor that always runs tasks with the thread context of the managed thread factory
      ScheduledExecutorService executor = Executors.newScheduledThreadPool(5, threadFactory);
      ... use executor to schedule tasks from any thread