Spring 3: How to call @Async annotated methods from the TaskExecutor
Here's an example of @Async
use:
@Asyncvoid doSomething() { // this will be executed asynchronously}
Now call that method from another class and it will run asynchronously. If you want a return value use a Future
@AsyncFuture<String> returnSomething(int i) { // this will be executed asynchronously}
The relationship between @Async
and TaskExecutor
is that @Async
uses a TaskExecutor
behind the scenes. From the docs:
By default when specifying @Async on a method, the executor that will be used is the one supplied to the 'annotation-driven' element as described above. However, the value attribute of the @Async annotation can be used when needing to indicate that an executor other than the default should be used when executing a given method.
So to set up a default executor, add this to your spring config
<task:annotation-driven executor="myExecutor" />
Or to use a particular executor for a single use try
@Async("otherExecutor")
Complete Example
Config Spring
@Configuration @EnableAsync @ComponentScan("com.async")public class AppConfig { @Bean public AsyncManager asyncManger() { return new AsyncManager(); } @Bean public AsyncExecutor asyncExecutor() { return new AsyncExecutor(); }}
Executor Class Created, Executor i have created so that spring takes care of thread management.
public class AsyncExecutor extends AsyncConfigurerSupport { @Override public Executor getAsyncExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(2); executor.setMaxPoolSize(2); executor.setQueueCapacity(500); executor.setThreadNamePrefix("Violation-"); executor.initialize(); return executor; }}
Create a manager.
public class AsyncManager { @Autowired private AsyncService asyncService; public void doAsyncTask(){ try { Map<Long, ViolationDetails> violation = asyncService.getViolation(); if(!org.springframework.util.CollectionUtils.isEmpty(violation)){ violation.entrySet().forEach( violationEntry -> {System.out.println(violationEntry.getKey() +"" +violationEntry.getValue());}); } System.out.println("do some async task"); } catch (Exception e) { } }}
Configure your service class.
@Servicepublic class AsyncService { @Autowired private AsyncExecutor asyncExecutor; @Async public Map<Long,ViolationDetails> getViolation() { // TODO Auto-generated method stub List<Long> list = Arrays.asList(100l,200l,300l,400l,500l,600l,700l); Executor executor = asyncExecutor.getAsyncExecutor(); Map<Long,ViolationDetails> returnMap = new HashMap<>(); for(Long estCode : list){ ViolationDetails violationDetails = new ViolationDetails(estCode); returnMap.put(estCode, violationDetails); executor.execute((Runnable)new ViolationWorker(violationDetails)); } return returnMap; }}class ViolationWorker implements Runnable{ private ViolationDetails violationDetails; public ViolationWorker(ViolationDetails violationDetails){ this.violationDetails = violationDetails; } @Override public void run() { violationDetails.setViolation(System.currentTimeMillis()); System.out.println(violationDetails.getEstablishmentID() + " " + violationDetails.getViolation()); }}
Model.
public class ViolationDetails { private long establishmentID; private long violation; public ViolationDetails(long establishmentID){ this.establishmentID = establishmentID; } public long getEstablishmentID() { return establishmentID; } public void setEstablishmentID(long establishmentID) { this.establishmentID = establishmentID; } public long getViolation() { return violation; } public void setViolation(long violation) { this.violation = violation; }}
Test to Run
public class AppTest { public static void main(String[] args) throws SQLException { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); ctx.register(AppConfig.class); ctx.refresh(); AsyncManager task= ctx.getBean(AsyncManager.class); task.doAsyncTask(); }}
In the config file, one should mention an annotation driven task with the thread pool name and method with @Async(pool name) will be executed as part of that pool. This creates a proxy class for the one which has @Async annotation and executes it for every thread.