October 10, 2013

Simple Managed Thread Factory Example in Wildfly

In this example we are going to use the ManagedThreadFactory (part of Java EE7 Concurrency Utils) to create and run a background task. The advantage of this, rather than using java.lang.Thread, is that your new thread will have access to the other Java EE services. Using the ManagedThreadFactory ensures your threads are created, and managed, by the container.

Example

Like previous examples, we need a Runnable task which will define what work is to be done in the background.

public class ReportTask implements Runnable {

    Logger logger = Logger.getLogger(getClass().getSimpleName());

    public void run() {
        logger.log(Level.INFO, "New thread running...");
        try {
            //do your background task
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            logger.log(Level.SEVERE, "Thread interrupted", e);
        }
    }
}

To get a container managed thread, we simply ask the ManagedThreadFactory for a new thread, and pass it our Runnable instance.  To start the thread we call start().

@Stateless
public class ReportBean {
 
    @Resource(lookup="java:jboss/ee/concurrency/factory/MyManagedThreadFactory")
    private ManagedThreadFactory threadFactory;

    public void runReports() {
        ReportTask reportTask = new ReportTask();
        Thread thread = threadFactory.newThread(reportTask);
        thread.start();
    }
}

We now need to configure our ManagedThreadFactory within Wildfly. This snippet is taken from the ee subsystem configuration in standalone.xml. The 'lookup' attribute of the @Resource annotation maps to 'jndi-name' attribute within the <managed-thread-factory> tag.

<subsystem xmlns="urn:jboss:domain:ee:2.0">
    ...
    <managed-thread-factories>
        <managed-thread-factory name="default" jndi-name="java:jboss/ee/concurrency/factory/default" context-service="default"/>
        <managed-thread-factory name="myManagedThreadFactory" jndi-name="java:jboss/ee/concurrency/factory/MyManagedThreadFactory" context-service="default" priority="1"/>
    </managed-thread-factories>
    ...
</subsystem>

Below is the full list of attributes you can use to configure your managed-thread-factory in Wildfly.
  • name - This is the name of the resource. This attribute is manditory.
  • jndi-name - The JNDI name for this resource. This attribute is manditory
  • context-service - The context service to use, if not supplied, the default context service is used.
  • priority - The priority that the thread should have, from 1 to 10 inclusive. Default is 5. 

Using the Command Line Interface (CLI)

To create your ManagedThreadFactory using CLI, go to your terminal and connect to your server by running the following command, swapping out wildfly for your WildFly root directory:
$ wildfly/bin/jboss-cli.sh --connect
Now create the ManagedThreadFactory and set its properties by using the add command, passing through the required property-value pairs.
[standalone@localhost:9990 /] /subsystem=ee/managed-thread-factory=myManagedThreadFactory:add(priority=1,context-service=default,jndi-name=java:jboss/ee/concurrency/factory/MyManagedThreadFactory)
If you want to modify any of these properties use the write-attribute command, passing though the name of the attribute and the new value:
[standalone@localhost:9990 /] /subsystem=ee/managed-thread-factory=myManagedThreadFactory:write-attribute(name=priority,value=3)
Finally reload the server to make your changes avaliable:
[standalone@localhost:9990 /] /:reload

The Admin Console

To view your thread factory in the Wildfly Admin console, navigate to Runtime > JNDI View > java:jboss > ee > concurrent.  Here, you can see all the concurrent resources including your newly configured resource.


Note: Using the JNDI prefix of java:jboss/ee/concurrency/factory ensures that the resource shows under concurrency/factory list in the Wildfly admin console.


9 comments :

  1. Thanks! would be nice to show also jboss-cli way of configuring the factory

    ReplyDelete
    Replies
    1. Good idea! I have updated the post to include using CLI to create and configure the ManagedThreadFactory.

      Delete
  2. Hi is it possible to start a Managed Thread from a singleton EJB? I tried doing this from the @PostConstruct method of an EJB but I get an 'java.lang.IllegalStateException' thrown. The reason I need to do this is because I want to monitor a directory on the Glassfish server so I need a long running thread.

    ReplyDelete
  3. Hi Matt, yes this is possible from a singleton EJB.

    ReplyDelete
  4. Is it proper to use InitialContext to lookup a managed thread factory from the context of a websocket endpoint? I setup a test case and it works. Is this the correct way to go? I want to send messages periodically from the server. Thanks!

    ReplyDelete
  5. It sounds reasonable to me to have a ManagedThreadFactory inside your websocket endpoint, although I am no expect on websocket best practices. Maybe you could post a question on stackoverflow? You may get a better answer that the one I have given.

    ReplyDelete
  6. How can I be sure that this task is being performed ?

    ReplyDelete