Showing posts with label Concurrency. Show all posts
Showing posts with label Concurrency. Show all posts

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.


September 26, 2013

How to Configure Scheduled Tasks in Wildfly

This example shows you how to create a scheduled concurrent task that runs every hour, using the Concurrency Utils API, and how to configure the properties of a ManagedScheduledExecutorService within Wildfly.

Example


Firstly, lets create the Runnable task which will define what work is to be done in the background thread.

public class ReportTask implements Runnable {
 
    public void run() {
        try {
            //do your background task
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            //handle execption
        }
    }
}

Now we schedule the executor to run its first execution immediately, and every hour thereafter. This executor will continue to run until you either terminate it, or until an exception it thrown by the task. We call the scheduledAtFixedRate() method, passing through our runnable task, along with the properties defining our schedule, i.e. the delay, the frequency and time unit.

@Stateless
public class ReportBean {
 
    @Resource(lookup="java:jboss/ee/concurrency/scheduler/MyScheduledExectutorService")
    private ManagedScheduledExecutorService executorService;

    public void runReports() {
        ReportTask reportTask = new ReportTask();
        executorService.scheduleAtFixedRate(reportTask, 0L, 1L, TimeUnit.HOURS);
    }
}

Lastly we need to configure our ManagedScheduledExecutorService in Wildfly.  The 'lookup' attribute of the @Resource annotation maps to 'jndi-name' attribute within the <managed-scheduled-executor-service> tag.

<subsystem xmlns="urn:jboss:domain:ee:2.0">
            <spec-descriptor-property-replacement>false</spec-descriptor-property-replacement>
            <jboss-descriptor-property-replacement>true</jboss-descriptor-property-replacement>
            <concurrent>
                <context-services>
                    <context-service name="default" jndi-name="java:jboss/ee/concurrency/context/default" use-transaction-setup-provider="true"/>
                </context-services>
                <managed-thread-factories>
                    <managed-thread-factory name="default" jndi-name="java:jboss/ee/concurrency/factory/default" context-service="default"/>
                </managed-thread-factories>
                <managed-executor-services>
                    <managed-executor-service name="default" jndi-name="java:jboss/ee/concurrency/executor/default" context-service="default" hung-task-threshold="60000" core-threads="5" max-threads="25" keepalive-time="5000"/>
                </managed-executor-services>
                <managed-scheduled-executor-services>
                    <managed-scheduled-executor-service name="default" jndi-name="java:jboss/ee/concurrency/scheduler/default" context-service="default" hung-task-threshold="60000" core-threads="2" keepalive-time="3000"/>
                    <managed-scheduled-executor-service name="myScheduledExecutorService" jndi-name="java:jboss/ee/concurrency/scheduler/MyScheduledExectutorService" hung-task-threshold="50000" core-threads="4" keepalive-time="5000" reject-policy="RETRY_ABORT"/>
                </managed-scheduled-executor-services>
            </concurrent>
            <default-bindings context-service="java:jboss/ee/concurrency/context/default" datasource="java:jboss/datasources/ExampleDS" jms-connection-factory="java:jboss/DefaultJMSConnectionFactory" managed-executor-service="java:jboss/ee/concurrency/executor/default" managed-scheduled-executor-service="java:jboss/ee/concurrency/scheduler/default" managed-thread-factory="java:jboss/ee/concurrency/factory/default"/>
</subsystem>

Note: If we were not to specify a any lookup or name attribute in the @Resource annotation, Wildfly would inject the default execution service.


Below is the full list of attributes you can use to configure your managed-scheduled-executor-service 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.
  • thread-factory - The name of the thread factory, if not supplied, the default thread factory is used.
  • hung-task-threshold - how long, in milliseconds, to allow threads to run for before they are considered unresponsive. (default=0, 0=no limit, min=0)
  • long-running-tasks - Whether this is a short or long running thread. (default=false)
  • core-threads - The number of threads within the executors thread pool, including idle threads.  This attribute is mandatory. (min=0)
  • keepalive-time - How long threads can remain idle when the number of threads is greater than the core-thread size. This attribute is manditory. (min=0, default=60000)
  • reject-policy - How to handle a failed task. 'ABORT' will cause an exception to be thrown; 'RETRY_ABORT' which will cause a retry, and then an abort if the retry fails. (default=ABORT) 
To view your executor in the Wildfly Admin console, login, and navigate to Runtime > JNDI View > java:jboss > ee > concurrent.  Here, you can see all the concurrent resources including your newly configured scheduledexecutor.


Note: You will notice that I have used the JNDI name of java:jboss/ee/concurrency/scheduler/MyScheduledExectutorService, which at first glance looks excessively long. Using this path ensures that the resource shows under concurrency/scheduler list in the Wildfly admin console.



September 18, 2013

Simple Concurrency Example with Wildfly

Concurrency is the ability to run several threads in parallel, within a single process.

Since its origin Java has had java.lang.Thread for dealing with concurrency. With Java SE 5 improved support was added with the java.util.concurrency package.

Enterprise containers manage their own thread pools and ensure that the other Java EE services are available to these threads. Creating threads using the concurrency API, provided by Java SE, is not recommended in an enterprise environment as there is no guarantee that your thread would have access to these services.

By using the new Concurrency Utils you can run asynchronous operations with java.util.concurrent.ExecutorService which will result in your thread being managed by the container.

The main concurrency components are:

ManagedExecutorService - used to execute tasks in a second thread. These threads are started and managed by the container

ManagedScheduledExecutorService - Same as the ManagedExecutorService except that you can schedule the thread to start as specific times

ContextService - used for creating dynamic proxy objects

ManagedThreadFactory - used by applications to create threads that are managed by the container

Example

This example demonstrates the use of the ManagedExecutorService.

First we need to create a task object that implements Callable. Within the call() method we will define the work that we want carried out in a separate thread.

public class ReportTask implements Callable<Report> {

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

    public Report call() {
        try {
            Thread.sleep(3000);
        catch (InterruptedException e) {
            logger.log(Level.SEVERE, "Thread interrupted", e);
        }
    return new Report();
    }
}

Then we need to invoke the task by passing it though to the submit() method of the ManagedExecutorService.

@Stateless
public class ReportBean {

    @Resource
    private ManagedExecutorService executorService;

    public void runReports() {
        ReportTask reportTask = new ReportTask();
        Future<Report> future = executorService.submit(reportTask);
    }
}

By not specifying the lookup attribute of the @Resource annotation, Wildfly will inject a managed executor service with default configuration as configured within the ee subsystem in standalone.xml.

<subsystem xmlns="urn:jboss:domain:ee:2.0">
    <spec-descriptor-property-replacement>false</spec-descriptor-property-replacement>
    <jboss-descriptor-property-replacement>true</jboss-descriptor-property-replacement>
    <concurrent>
        <default-context-service/>
        <default-managed-thread-factory/>
        <default-managed-executor-service hung-task-threshold="60000" core-threads="5" max-threads="25" keepalive-time="5000"/>
        <default-managed-scheduled-executor-service hung-task-threshold="60000" core-threads="2" keepalive-time="3000"/>
    </concurrent>
</subsystem>