Skip to content

Latest commit

 

History

History
285 lines (243 loc) · 13 KB

exercise5-concurrency.adoc

File metadata and controls

285 lines (243 loc) · 13 KB

Exercise 5 - Java EE Concurrency Utilities

What you will learn

Doing this exercise, participants will learn:

  • what are the "Concurrency Utilities for Java EE 1.0"

  • how to use the the Java Concurrency API

  • how to configure the concurrency services on JBoss EAP 7

Background information

Concurrency is the ability of a system to execute several tasks in parallel, during overlapping time periods, instead of sequentially. The "Concurrency Utilities for Java EE 1.0" (JSR342) specification was developed to fulfill the following goals:

  • provide a simple/flexible/usable API for implementing simple and advanced concurrency patterns

  • facilitate the migration from Java SE and EE

It has been built on top of the "Concurrency Utilities API" for Java SE (JSR166). The Java SE specification has been made Java EE aware by getting capabilities like container context propagation, transaction management and task events notification. Thanks to this API, Java EE 7 platforms are aware of the resources used by threads and capable of managing their pools and life-cycles properly.

The API provides thread pools and executor with 4 managed object types in the javax.enterprise.concurrent package:

  • Context (javax.enterprise.concurrent.ContextService)

    The Context Service is a concurrency utility which creates contextual proxies from existent objects. JBoss EAP 7 Context Services are also used to propagate the context from a Java EE application invocation thread, to the threads internally used by the other EE Concurrency Utilities. Context Service instances may be created using the subsystem XML configuration:

    <context-services>
      <context-service
      name="default"
      jndi-name="java:jboss/ee/concurrency/context/default"
      use-transaction-setup-provider="true" />
    </context-services>
  • Thread Factory (javax.enterprise.concurrent.ManagedThreadFactory)

    The Managed Thread Factory allows Java EE applications to create new threads. The Managed Thread Factory instances may also, optionally, use a Context Service instance to propagate the Java EE application thread’s context to the new threads. Instance creation is done through the EE subsystem, by editing the subsystem XML configuration:

    <managed-thread-factories>
      <managed-thread-factory
      name="default"
      jndi-name="java:jboss/ee/concurrency/factory/default"
      context-service="default"
      priority="1" />
    </managed-thread-factories>
  • Executor (javax.enterprise.concurrent.ManagedExecutorService)

    The Managed Executor Service is the Java EE adaptation of Java SE Executor Service, providing to Java EE applications the functionality of asynchronous task execution. JBoss EAP 7 is responsible to manage the lifecycle of Managed Executor Service instances, which are specified through the EE subsystem XML configuration:

    <managed-executor-services>
      <managed-executor-service
      name="default"
      jndi-name="java:jboss/ee/concurrency/executor/default"
      context-service="default"
      thread-factory="default"
      hung-task-threshold="60000"
      core-threads="5"
      max-threads="25"
      keepalive-time="5000"
      queue-length="1000000"
      reject-policy="RETRY_ABORT" />
    </managed-executor-services>
  • Scheduled Executor (javax.enterprise.concurrent.ManagedScheduledExecutorService)

    The Managed Scheduled Executor Service is the Java EE adaptation of Java SE Scheduled Executor Service, providing to Java EE applications the functionality of scheduling task execution. JBoss EAP 7 is responsible to manage the lifecycle of Managed Scheduled Executor Service instances, which are specified through the EE subsystem XML configuration:

    <managed-scheduled-executor-services>
      <managed-scheduled-executor-service
      name="default"
      jndi-name="java:jboss/ee/concurrency/scheduler/default"
      context-service="default"
      thread-factory="default"
      hung-task-threshold="60000"
      core-threads="5"
      keepalive-time="5000"
      reject-policy="RETRY_ABORT" />
    </managed-scheduled-executor-services>

In addition to these main interfaces, the specification provides many other interfaces, for example to monitor the stat of a task’s Future object (ManagedTaskListener).

Lab

This lab builds on the "managed-executor-service" quickstart of JBoss EAP 7. It demonstrates how Java EE applications can submit tasks for asynchronous execution.

Step 1 - Build the "managed-executor-service" quickstart project

First build the managed-executor-service project as follows:

$ cd ~/exercises/projects/05_concurrency/managed-executor-service # (1)
$ mvn clean eclipse:clean eclipse:eclipse install # (2)
$ pwd (3)
  1. Move to the directory of the quickstart

  2. Clean and build the quickstart and generate the eclipse project

  3. Displays the current path (useful for import in JBDS)

Step 2 - Import the project in JBoss Developer Studio (JBDS)

Open JBoss Developer Studio (desktop shortcut).

Import the maven project you just built. (File → Import → Existing Projects into Workspace → Next → Paste "root directory") → Finish)

JBDS import (1/2)
JBDS import (2/2)
Step 3 - Have a look at the Java code

The imported application contains a JAX-RS resource (ProductResourceRESTService class) providing access to several operations that are executed asynchronously: PersitTask, LongRunningTask and DeleteTask.

Take some time to understand how these classes inter-relate and how the ManagedExecutorService is used.

A test class (ProductsRestClientTest) has been defined to invoke the exposed REST methods and execute the defined tasks. In the next step, we are going to execute this test class.

Step 4 - Start JBoss EAP 7 and deploy the application

Start your JBoss EAP 7 server as described in the first lab.

You have two options for deploying the "jboss-managed-executor-service.war" binary:

  • Option 1: maven

    Type this command to build and deploy the application:

    $ mvn clean install wildfly:deploy
  • Option 2: JBDS

    Right click on "/managed-executor-service/target/jboss-managed-executor-service.war" and select "Mark as Deployable"

Step 5 - Run the tests

This quickstart provides tests that shows how the asynchronous tasks are executed. By default, these tests are configured to be skipped as the tests requires that the application to be deployed first.

You have two choices for executing the test:

  • Option 1: use maven

    $ mvn clean test -Prest-test
  • Option 2: use JBDS

    Right click on the project or individual classes and select Run As → JUnit Test in the context menu.

Step 6 - Investigate the results

Review the JBoss EAR 7 console log output and relate it to the code. You should see log messages like the following:

13:34:07,940 INFO  [ProductResourceRESTService] (default task-51) Will create a new Product on other Thread
13:34:07,940 INFO  [ProductResourceRESTService] (default task-51) Returning response
13:34:07,941 INFO  [PersitTask] (EE-ManagedExecutorService-default-Thread-5) Begin transaction
13:34:07,941 INFO  [PersitTask] (EE-ManagedExecutorService-default-Thread-5) Persisting a new product
13:34:07,946 INFO  [PersitTask] (EE-ManagedExecutorService-default-Thread-5) Commit transaction
13:34:08,002 INFO  [ProductResourceRESTService] (default task-52) Submitting a new long running task to be executed
13:34:08,003 INFO  [ProductResourceRESTService] (default task-52) Waiting for the result to be available...
13:34:08,009 INFO  [LongRunningTask] (EE-ManagedExecutorService-default-Thread-5) Starting a long running task
13:34:08,010 INFO  [LongRunningTask] (EE-ManagedExecutorService-default-Thread-5) Analysing A Product
13:34:08,306 INFO  [ProductResourceRESTService] (default task-52) Waiting for the result to be available...
13:34:08,608 INFO  [ProductResourceRESTService] (default task-52) Waiting for the result to be available...
13:34:08,912 INFO  [ProductResourceRESTService] (default task-52) Waiting for the result to be available...
13:34:09,215 INFO  [ProductResourceRESTService] (default task-52) Waiting for the result to be available...
13:34:09,519 INFO  [ProductResourceRESTService] (default task-52) Waiting for the result to be available...
13:34:09,823 INFO  [ProductResourceRESTService] (default task-52) Waiting for the result to be available...
13:34:10,128 INFO  [ProductResourceRESTService] (default task-52) Waiting for the result to be available...
13:34:10,431 INFO  [ProductResourceRESTService] (default task-52) Waiting for the result to be available...
13:34:10,735 INFO  [ProductResourceRESTService] (default task-52) Waiting for the result to be available...
13:34:11,040 INFO  [ProductResourceRESTService] (default task-52) Result is available. Returning result...56
13:34:11,082 INFO  [ProductResourceRESTService] (default task-53) Will delete all Products on other Thread
13:34:11,082 INFO  [ProductResourceRESTService] (default task-53) Returning response
13:34:11,082 INFO  [DeleteTask] (EE-ManagedExecutorService-default-Thread-5) Begin transaction
13:34:11,083 INFO  [DeleteTask] (EE-ManagedExecutorService-default-Thread-5) Deleting all products
13:34:11,092 INFO  [DeleteTask] (EE-ManagedExecutorService-default-Thread-5) Commit transaction. Products deleted: 1
Step 7 - Monitor the thread pools

In order to have a look at how the thread pools are managed, we will use the jconsole utility. To do so, open a Terminal and type:

$ cd $JBOSS_HOME/bin
$ ./jconsole.sh

A modal window will open, offering you to select various processes. Select the local process having a name starting with "jboss-modules.jar" and click on "connect".

jconsole open

A pop-up asking you if an insecure connection should be used is then displayed. Click on "Insecure connection".

jconsole open

Then you will see the threads used and consumed by the JBoss EAP 7:

jconsole threads
Step 8 - Increase the load

Now it is time to increase the load and send a lot of requests showing how the ManagedExecutorService behaves.

Find your preferred way to run many times the defined long-running task in parallel. Use then jconsole, as presented in step 7, to have a look on how the thread pool is behaving.

For example, you could add a test method like the following one and re-run the test:

@Test
public void parallelTest() throws InterruptedException {
    Callable<String> c = () -> ClientBuilder.newClient().target(REST_TARGET_URL + "/longrunningtask").request().get(String.class);
    List<Callable<String>> callables = new ArrayList<Callable<String>>();
    for (int i = 0; i < 100; i++) {
      callables.add(c);
    }

    Executors.newWorkStealingPool().invokeAll(callables).stream().map(future -> {
      try {
        return future.get();
      } catch (Exception e) {
        throw new IllegalStateException(e);
      }
    }).forEach(System.out::println);
}
Step 9 - Review the EE concurrency configuration

The "Thread" subsystem of JBoss EAP 6 has been removed. All JBoss EAP 7 subsystems needing threads define their own thread pool. The Java EE concurrency utilities is configured within the "EE" subsystem of JBoss EAP 7.

The configuration can be viewed and modified in the JBoss EAP 7 management console over Configuration → Subsystems → EE, clicking on "View".

EAP configuration

After selecting the "Services" tab, you are able to view and modify the configuration of the four previously listed concurrency services.

EAP configuration

Another option to view and modify the configuration is to edit the standalone.xml file (while the server is stopped) or execute CLI commands.

Summary

In this lab, you learned what are the EE concurrency utilities and how they can be configured within JBoss EAP 7. You deployed and reviewed an application using the Java Concurrency API and monitored the behavior of the application platform using jconsole.