Monday Feb 11, 2013

Create ManagedExecutorService, ManagedScheduledExecutorService, ManagedThreadFactory, ContextService in GlassFish 4 build 74 (TOTD #203)


Latest GlassFish 4 promoted build (74 at this time) has the first cut of Concurrency Utilities for Java EE (JSR 236) implementation integrated. An earlier blog provided an overview of the specification, lets see what can be actually done with this build.

This build introduce new commands to create ManagedExecutorService, ManagedScheduledExecutorService, ManagedThreadFactory, and ContextService.

A simple command execution as:

asadmin create-managed-executor-service concurrent/myExecutor
Managed executor service concurrent/myExecutor created successfully.
Command create-managed-executor-service executed successfully.

creates the configuration for a default ManagedExecutorService. Adding --help shows more details about the command:

create-managed-executor-service
    [--enabled=true]
    [--contextinfo=contextinfo]
    [--threadpriority=5]
    [--longrunningtasks=false]
    [--hungafterseconds=hungafterseconds]
    [--corepoolsize=0]
    [--maximumpoolsize=2147483647]
    [--keepaliveseconds=60]
    [--threadlifetimeseconds=0]
    [--taskqueuecapacity=2147483647]
    [--description=description]
    [--property=property]
    [--target=target]
    jndi_name

The created executor can then be injected into a Java EE component (say Servlet) as:

@Resource(name = "concurrent/myExecutor")
ManagedExecutorService executor;

or looked up using JNDI as:

InitialContext ctx = new InitialContext();
ManagedExecutorService executor = (ManagedExecutorService) ctx.lookup("concurrent/myExecutor");

A task can be defined as:

public class MyRunnableTask implements Runnable {

private int id;

public MyRunnableTask(int id) {
this.id = id;
}

@Override
public void run() {
try {
System.out.format("%d (runnable): starting", id);
System.out.format("%d (runnable): sleeping 2 seconds", id);
Thread.sleep(2000);
System.out.format("%d (runnable): complete", id);
} catch (InterruptedException ex) {
Logger.getLogger(TestResourceServlet.class.getName()).log(Level.SEVERE, null, ex);
}
}
}

Task can be submitted as:

Future<?> f = executor.submit(new MyRunnableTask(1));

OR

executor.execute(new MyRunnableTask(2));

A task may also be defined as:

public class MyCallableTask implements Callable<Product> {

private int id;

public MyCallableTask(int id) {
this.id = id;
}

@Override
public Product call() {
try {
System.out.format("%d (callable): starting", id);
System.out.format("%d (callable): sleeping 2 seconds", id);
Thread.sleep(2000);
System.out.format("%d (callable): complete", id);
} catch (InterruptedException ex) {
Logger.getLogger(TestResourceServlet.class.getName()).log(Level.SEVERE, null, ex);
}
return new Product(id);
}
}

where Product is a domain-specific class. In this case, the task is submited for execution as:

Future<Product> f2 = executor.submit(new MyCallableTask(3));
A ManagedScheduledExecutorService can be created as:

asadmin create-managed-scheduled-executor-service concurrent/myScheduledExecutor
Managed scheduled executor service concurrent/myScheduledExecutor created successfully.
Command create-managed-scheduled-executor-service executed successfully.

A ManagedThreadFactory can be created as:

asadmin create-managed-thread-factory concurrent/myThreadFactory
Managed thread factory concurrent/myThreadFactory created successfully.
Command create-managed-thread-factory executed successfully.

A ContextService can be created as:

asadmin create-context-service concurrent/myContextService
Context service concurrent/myContextService created successfully.
Command create-context-service executed successfully.

Note, this is the first integration and some of the options may not work. But you can definitely start playing around with basic stuff now.

The complete source code used in this Tip Of The Day (TOTD) is available here and will run on GlassFish 4 b74.

Wednesday Dec 05, 2012

Concurrency Utilities for Java EE Early Draft (JSR 236)


Concurrency Utilities for Java EE is being worked as JSR 236 and has released an Early Draft. It provides concurrency capabilities to Java EE application components without compromising container integrity. Simple (common) and advanced concurrency patterns are easily supported without sacrificing usability.

Using Java SE concurrency utilities such as java.util.concurrent API, java.lang.Thread and java.util.Timer in a Java EE application component such as EJB or Servlet are problematic since the container and server have no knowledge of these resources. The JSR 236 enables concurrency largely by extending the Concurrency Utilities API developed under JSR-166. This also allows a consistency between Java SE and Java EE concurrency programming model. The threads so spawned are provided and managed by the container.

There are four main programming interfaces available:
  • ManagedExecutorService
  • ManagedScheduledExecutorService
  • ContextService
  • ManagedThreadFactory

ManagedExecutorService is a managed version of java.util.concurrent.ExecutorService. The implementations of this interface are provided by the container and accessible using JNDI reference:

<resource-env-ref>
  <resource-env-ref-name>
    concurrent/BatchExecutor
  </resource-env-ref-name>
  <resource-env-ref-type>
    javax.enterprise.concurrent.ManagedExecutorService
  </resource-env-ref-type>
<resource-env-ref>

and available as:

@Resource(name="concurrent/BatchExecutor")
ManagedExecutorService executor;

Its recommended to bind the JNDI references in the java:comp/env/concurrent subcontext.

The asynchronous tasks that need to be executed need to implement java.lang.Runnable or java.util.concurrent.Callable interface as:

public class MyTask implements Runnable {
public void run() {
// business logic goes here
}
}

OR

public class MyTask2 implements Callable<Date> {
  public Date call() {
// business logic goes here
  }
}

The task is then submitted to the executor using one of the submit method that return a Future instance. The Future represents the result of the task and can also be used to check if the task is complete or wait for its completion.

Future<String> future = executor.submit(new MyTask(), String.class);
. . .
String result = future.get();

The task would run on a separate thread provided and managed by the container.

Another example to submit tasks is:

class MyTask implements Callable<Long> { . . . }
class MyTask2 implements Callable<Date> { . . . }

ArrayList<Callable> tasks = new ArrayList<();
tasks.add(new MyTask());
tasks.add(new MyTask2());
List<Future<Object>> result = executor.invokeAll(tasks);

The ManagedExecutorService may be configured for different properties such as:

  • Hung Task Threshold: Time in milliseconds that a task can execute before it is considered hung
  • Pool Info
    • Core Size: Number of threads to keep alive
    • Maximum Size: Maximum number of threads allowed in the pool
    • Keep Alive: Time to allow threads to remain idle when # of threads > Core Size
    • Work Queue Capacity: # of tasks that can be stored in inbound buffer
  • Thread Use: Application intend to run short vs long-running tasks, accordingly pooled or daemon threads are picked

The specification does not mandate any configuration attributes. The above mentioned properties are only examples and may not be supported by all application servers.

ManagedScheduledExecutorService adds delay and periodic task running capabilities to ManagedExecutorService. The implementations of this interface are provided by the container and accessible using JNDI reference:

<resource-env-ref>
  <resource-env-ref-name>
    concurrent/BatchExecutor
  </resource-env-ref-name>
  <resource-env-ref-type>
    javax.enterprise.concurrent.ManagedExecutorService
  </resource-env-ref-type>
<resource-env-ref>

and available as:

@Resource(name="concurrent/timedExecutor")
ManagedExecutorService executor;

And then the tasks are submitted using submit, invokeXXX or scheduleXXX methods.

ScheduledFuture<?> future = executor.schedule(new MyTask(), 5, TimeUnit.SECONDS);

This will create and execute a one-shot action that becomes enabled after 5 seconds of delay.

More control is possible using one of the newly added methods:

MyTaskListener implements ManagedTaskListener {
  public void taskStarting(...) { . . . }
  public void taskSubmitted(...) { . . . }
  public void taskDone(...) { . . . }
  public void taskAborted(...) { . . . } }
ScheduledFuture<?> future =
executor.schedule(new MyTask(),
5,
TimeUnit.SECONDS,
new MyTaskListener());

Here, ManagedTaskListener is used to monitor the state of a task's future.

ManagedThreadFactory provides a method for creating threads for execution in a managed environment. A simple usage is:

@Resource(name="concurrent/myThreadFactory")
ManagedThreadFactory factory;
. . .
Thread thread = factory.newThread(new Runnable() { . . . });

concurrent/myThreadFactory is a JNDI resource.

There is lot of interesting content in the Early Draft, download it, and read yourself. The implementation will be made available soon and also be integrated in GlassFish 4 as well.

Some references for further exploration ...

About

profile image
Arun Gupta is a technology enthusiast, a passionate runner, author, and a community guy who works for Oracle Corp.


Java EE 7 Samples

Stay Connected

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today