Spring MVC how to get progress of running async task
Solution 1
Have you looked at the @Async
annotation in the Spring reference doc?
First, create a bean for your asynchronous task:
@Service
public class AsyncServiceBean implements ServiceBean {
private AtomicInteger cn;
@Async
public void doSomething() {
// triggers the async task, which updates the cn status accordingly
}
public Integer getCn() {
return cn.get();
}
}
Next, call it from the controller:
@Controller
public class YourController {
private final ServiceBean bean;
@Autowired
YourController(ServiceBean bean) {
this.bean = bean;
}
@RequestMapping(value = "/trigger")
void triggerAsyncJob() {
bean.doSomething();
}
@RequestMapping(value = "/status")
@ResponseBody
Map<String, Integer> fetchStatus() {
return Collections.singletonMap("cn", bean.getCn());
}
}
Remember to configure an executor accordingly, e.g.
<task:annotation-driven executor="myExecutor"/>
<task:executor id="myExecutor" pool-size="5"/>
Solution 2
One solution could be: in your async thread, write to a DB, and have your checking code check the DB table for progress. You get the additional benefit of persisting performance data for later evaluation.
Also, just use the @Async
annotation to kick off the asynchronous thread - makes life easier and is a Spring Way To Do It.
Solution 3
Check this github source, it gives pretty simple way of catching status of the background job using @Async of Spring mvc.
https://github.com/frenos/spring-mvc-async-progress/tree/master/src/main/java/de/codepotion/examples/asyncExample
Josef Prochazka
Updated on June 06, 2022Comments
-
Josef Prochazka about 2 years
I would like to start an asynchronous task from within controller like in following code sniplet from Spring docs.
import org.springframework.core.task.TaskExecutor; public class TaskExecutorExample { private class MessagePrinterTask implements Runnable { private int cn; public MessagePrinterTask() { } public void run() { //dummy code for (int i = 0; i < 10; i++) { cn = i; } } } private TaskExecutor taskExecutor; public TaskExecutorExample(TaskExecutor taskExecutor) { this.taskExecutor = taskExecutor; } public void printMessages() { taskExecutor.execute(new MessagePrinterTask()); } }
afterwards in annother request (in the case that task is running) I need to check the progress of the task. Basicaly get the value of cn.
What would be the best aproach in Spring MVC a how to avoid syncronisation issues.
Thanks
Pepa Procházka
-
Josef Prochazka about 12 yearsthaks, that was my first idea, but I need to only show the progres and I dont want to persist any information. Now I am logging the progress to tomcat log and I want to have faster way how to check it.
-
Javi Pedrera over 11 yearshello, how do you get the taskExecutor? I have seen that is taken from the context using the .xml. Could you explain more your solution?
-
matsev over 11 yearsCertainly, you can use
@Autowired
,@Inject
, or any other Spring DI method that you would normally use. -
matsev over 11 yearsFrom the Spring Reference Docs: By default when specifying @Async on a method, the executor that will be used is the one supplied to the 'annotation-driven' element
-
Javi Pedrera over 11 yearsThanks, I have implemented the example and I use a Loop in the function triggerAsyncJob but only one thread is fired. I need to execute at least 5 at the same time. I have to config anything else?
-
Fernando Fradegrada over 6 yearsIt's a nice implementation, but it seems to me that this would only work for only one instance of the task going on. Is there any way to have multiple times the same task, for example "processFile" called by more than one user, and having the progress for each user?