@Configuration @EnableAsync public class SpringAsyncConfig { ... }
<task:executor id="myexecutor" pool-size="5" /> <task:annotation-driven executor="myexecutor"/>
@Async public void asyncMethodWithVoidReturnType() { System.out.println("Execute method asynchronously. " + Thread.currentThread().getName()); }2. Methods With Return Type
@Service public class GitHubLookupService { RestTemplate restTemplate = new RestTemplate(); @Async public Future<User> findUser(String user) throws InterruptedException { System.out.println("Looking up " + user); User results = restTemplate.getForObject("https://api.github.com/users/" + user, User.class); // Artificial delay of 1s for demonstration purposes Thread.sleep(1000L); return new AsyncResult<User>(results); } }Spring also provides a AsyncResult class which implements Future. This can be used to track the result of asynchronous method execution.
public void testAsyncAnnotationForMethodsWithReturnType() throws InterruptedException, ExecutionException { System.out.println("Invoking an asynchronous method. " + Thread.currentThread().getName()); Future<User> future = GitHubLookupService.findUser(user); while (true) { if (future.isDone()) { System.out.println("Result from asynchronous process - " + future.get()); break; } System.out.println("Continue doing something else. "); Thread.sleep(1000); } }
@Configuration @EnableAsync public class SpringAsyncConfig { @Bean(name = "threadPoolTaskExecutor") public Executor threadPoolTaskExecutor() { return new ThreadPoolTaskExecutor(); } }Then the executor name should be provided as an attribute in @Async:
@Async("threadPoolTaskExecutor") public void asyncMethodWithConfiguredExecutor() { System.out.println("Execute method with configured executor - " + Thread.currentThread().getName()); }2. Override the Executor at the Application Level
@Configuration @EnableAsync public class SpringAsyncConfig implements AsyncConfigurer { @Override public Executor getAsyncExecutor() { return new ThreadPoolTaskExecutor(); } }The configuration class should implement the AsyncConfigurer interface – which will mean that it has the implement the getAsyncExecutor() method. It’s here that we will return the executor for the entire application – this now becomes the default executor to run methods annotated with @Async.
public class CustomAsyncExceptionHandler implements AsyncUncaughtExceptionHandler { @Override public void handleUncaughtException(Throwable throwable, Method method, Object... obj) { System.out.println("Exception message - " + throwable.getMessage()); System.out.println("Method name - " + method.getName()); for (Object param : obj) { System.out.println("Parameter value - " + param); } } }When a method return type is a Future, exception handling is easy – Future.get() method will throw the exception.
@Override public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { return new CustomAsyncExceptionHandler(); }
Labels: Spring3.0