Migrating applications that use concurrency and asynchronous programming models to Liberty

You can migrate applications that use Concurrency Utilities for Java™ EE, Asynchronous beans, and CommonJ Timer and Work Manager from WebSphere® Application Server traditional to WebSphere Application Server Liberty.

Asynchronous beans and CommonJ Timer and Work Manager are not available in Liberty. When migrating to Liberty, applications must switch to the Concurrency Utilities for Java EE programming model. For more information, see Example API tasks that implement Concurrency Utilities for Java EE.

Differences in configuration and threading

WebSphere Application Server traditional provides a number of configuration options for Concurrency Utilities for Java EE, related to thread pooling, which are not available in Liberty. Liberty has a single common thread pool across all managed executors and managed scheduled executors that are also shared by Liberty components. This allows Liberty to optimize thread management. In WebSphere Application Server traditional, each work manager can be configured with two thread pools. One thread pool is for tasks that are submitted to run as soon as possible (submit/execute/invoke methods of managed executor) and has a configurable work request queue and action to take when the queue capacity is exceeded. The other thread pool is for scheduled tasks (schedule methods of managed scheduled executor).

If you plan to use Concurrency Utilities for Java EE with separate thread pools in Liberty, various approaches can be taken to achieve behavior similar to the configuration options that are available in WebSphere Application Server traditional.

Constructing a Java SE executor around a managed thread factory

The java.util.concurrent package of Java SE provides several ways to construct thread pools as executors and scheduled executors around a specific thread factory. A managed thread factory can be supplied in place of an unmanaged thread factory, producing a thread pool that runs tasks on managed threads. Unlike the managed executor and managed scheduled executors, the managed threads that are pooled by these executors run with the thread context from when the managed thread factory was looked up, rather than from when the task was submitted or scheduled. Thread context also remains on the managed thread for the life of thread, which reduces thread context switching overhead.

Example replacement for maximum work threads and work queue configuration

int minThreads = 1;
int maxThreads = 2;
int workRequestQueueSize = 3;
RejectedExecutionHandler workRequestQueueFullAction =
    new ThreadPoolExecutor.AbortPolicy(); 
ManagedThreadFactory threadFactory =
    (ManagedThreadFactory) new InitialContext().lookup(
        "java:comp/DefaultManagedThreadFactory");
ExecutorService executor = new ThreadPoolExecutor(
    minThreads, // similar, but not exact match for coreSize
    maxThreads, keepAliveTime, keepAliveTimeUnit,
    new ArrayBlockingQueue<Runnable>(workRequestQueueSize),
    threadFactory,
    workRequestQueueFullAction);
Callable<Integer> task = new MyTask();
Future<Integer> future = executor.submit(task);
int result = future.get();

Example replacement for maximum alarm threads

int maxAlarms = 2;
ManagedThreadFactory threadFactory =
    (ManagedThreadFactory) new InitialContext().lookup(
        "java:comp/DefaultManagedThreadFactory");
ScheduledExecutorService executor =
    Executors.newScheduledThreadPool(maxAlarms, threadFactory);
Callable<Integer> task = new MyTask();
ScheduledFuture<Integer> future = executor.schedule(
    task, 50, TimeUnit.SECONDS);
int result = future.get();

Applying a work timeout

WebSphere Application Server traditional allows you to configure a work timeout that applies to tasks that are submitted to run as soon as possible (submit/execute/invoke methods). If a task is running for longer than the allotted work timeout, an attempt is made to cancel the task by interrupting it. However, Liberty does not have work timeout as a configuration option but a similar behavior can be implemented by submitting the task with a managed task listener, which, in response to the taskStarting notification, schedules a task to cancel the task's Future. Alternately, when using a thread pool executor as in the previous example, where managed task listener is not available, it is possible to override the thread pool executor's beforeExecute method to schedule a task to interrupt the thread of execution.

Example replacement for work timeout

ManagedExecutorService executor =
    (ManagedExecutorService) new InitialContext().lookup(
        "java:comp/DefaultManagedExecutorService");
Callable<Long> slowTask = new SlowTask();
slowTask = ManagedExecutors.managedTask(
           slowTask, new WorkTimeout(5, TimeUnit.SECONDS));
Future<Long> future = executor.submit(slowTask);
try {
    long result = future.get(1, TimeUnit.MINUTES);
    // task successful...
} catch (CancellationException x) {
    // task was canceled, possibly due to timeout
}

public class WorkTimeout implements ManagedTaskListener {
    private final long timeout;
    private final TimeUnit unit;

    public WorkTimeout(long timeout, TimeUnit unit) {
        this.timeout = timeout;
        this.unit = unit;
    }

    public void taskSubmitted(Future<?> future,
        ManagedExecutorService executor, Object task) {}

    public void taskStarting(final Future<?> future,
        ManagedExecutorService executor, Object task) {
        try {
            ScheduledExecutorService scheduledExecutor =
                (ScheduledExecutorService) new InitialContext().lookup(
                    "java:comp/DefaultManagedScheduledExecutorService");
            scheduledExecutor.schedule(new Runnable() {
                @Override
                public void run() {
                    if (!future.isDone())
                        future.cancel(true);
                }
            }, timeout, unit);
        } catch (NamingException x) {
            x.printStackTrace(System.out);
        }
    }

    public void taskAborted(Future<?> future, ManagedExecutorService executor, Object task, Throwable x) {}

    public void taskDone(Future<?> future, ManagedExecutorService executor, Object task, Throwable x) {}
}

Icon that indicates the type of topic Reference topic

File name: rwlp_mig_workmgr.html