Java and Spring development

Spring asynchronous support

with 4 comments

Spring 3 supports declarative concurrency support. At its simplest, you only need to specify in the Spring configuration file and add an @Async annotation above the method that you want to execute in an asynchronous process.

@Async
public void findBalanceAsync(final Account account) {
	accountRepository.findBalance(account);
}

See also this blog for step by step guide on how to execute a void method asynchronously.

In many cases you also want the response message from a method executed asynchronously. To achieve this, Spring returns a java.util.concurrent.Future object. All that’s required from the implementation is to create and return a new AsyncResult object like this:

@Async
public Future<Balance> findBalanceAsync(final Account account) {
	Balance balance = accountRepository.findBalance(account);
	return new AsyncResult<Balance>(balance);
}

Further, to retrieve the balance from this future object:

Balance balance = future.get();

If the method that’s executed asynchronously throws an exception, it will be wrapped inside an ExecutionException and throwed when the Future’s get method gets called.

Java EE 6 specification support

If you prefer to use the Java EE 6 specification, then you can replace Spring’s Async and AsyncResult classes with the corresponding classes in the javax.ejb package in the commons annotations 1.1 specification.

@javax.ejb.Asynchronous
public Future<Balance> findBalanceAsync(final Account account) {
	Balance balance = accountRepository.findBalance(account);
	return new javax.ejb.AsyncResult<Balance>(balance);
}

Configuring the task elements

The Spring container understand the javax.ejb classes without any configuration changes. You only need to add the commons annotation API on the classpath.

Spring’s task support can be configured with values like the thread pool and wich implementation you prefer to use. The easiest approach is to use the task namespace’s executor element. This element instantiates a ThreadPoolTaskExecutor object. This class implements the java.util.concurrent.Executor interface. Another option is declare your own bean like the ExecutorService bean below and let the annotation-driven task element reference to it. See example below:

<bean id="executorService" class="java.util.concurrent.Executors"
	factory-method="newFixedThreadPool">
	<constructor-arg value="10" />
</bean>

<task:executor id="threadPoolTaskExecutor" pool-size="10" />

<task:annotation-driven executor="executorService" />

Work with the underlying ExecutorService implementation

If you want to configure the ExecutorService object used by the Spring container after it’s initialized, then you can to do it programmatically as long as it’s a singleton bean. The first step is to retrieve the object with dependency injection like this:

@Inject
ExecutorService executorService;

Then cast it to a TreadPoolExecutor object and adjust the settings like the pool size showed below:

ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) executorService;
threadPoolExecutor.setMaximumPoolSize(poolSize);
threadPoolExecutor.setCorePoolSize(poolSize);

An another example it can be useful to handle the underlying implementation is if you want to abort all work in the ExecutorService or ThreadPoolTaskExecutor’s queue. Then you can execute the shutdown method like this:

executorService.shutdown();

Conclusion

Spring’s asynchronous support abstracts away most of the complex threading logic for you and still provides full access to the implementation behind. It also supports the new async API in Java EE 6 without any configuration changes.

The code used in this article was developed in my work time at Redpill Linpro.


Redpill Linpro is the leading provider of Professional Open Source services and products in the Nordic region.

Advertisements

Written by Espen

March 8, 2010 at 00:44

Posted in Concurrency

Tagged with , , ,

4 Responses

Subscribe to comments with RSS.

  1. Hi!

    I have a rudimentary question due to the fact that I am completely new to Spring’s asynchronous support.

    How do I actually use a method with a response?

    Could you perhaps explain the following example further? I don’t understand how the Future and AsyncResult work toogether. And do not understand how I can use Balance balance = future.get(); To get the response from my method.

    “In many cases you also want the response message from a method executed asynchronously. To achieve this, Spring returns a java.util.concurrent.Future object. All that’s required from the implementation is to create and return a new AsyncResult object like this:

    @Async
    public Future findBalanceAsync(final Account account) {
    Balance balance = accountRepository.findBalance(account);
    return new AsyncResult(balance);
    }

    Further, to retrieve the balance from this future object:

    Balance balance = future.get();”

    Best, Daniel

    Daniel

    March 22, 2012 at 11:55

  2. Hello,

    The method returns a future object. Use it like any other method with a return value. The main difference is that you may wait for the result since the method is executed in another thread.

    Future<Balance> balanceFuture = findBalanceAsync(account);
    Balance balance = BalanceFuture.get();

    If you’re new to thread handling and the classes in the java.util.concurrent package, it can be smart to try out these classes to understand what the Spring container does behind the scenes.

    I hope it helps!

    Espen

    March 22, 2012 at 13:13

  3. great article. But it might be usefull to know – in what way spring create proxies for this class. If you write a little bit about this – it will be great.

    Vasyl Khrystiuk

    July 2, 2013 at 23:45

  4. What’s up to every one, the contents present at this site are really amazing for people knowledge, well, keep up
    the nice work fellows.

    Bettye

    May 27, 2016 at 20:49


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: