Java – recover the asynch threadpooltaskexecutor after a server crash / shutdown
I have a spring rest controller that uses spring's @ async method to call asynchronous methods and immediately returns an HTTP 202 code (accepted) to the client (asynchronous jobs are heavy and may cause timeouts)
Everything is fine, but I ask myself, what should I do if my server / JVM crashes or it shuts down? My customer will receive a 202 code and will never receive a status email
Is there any way to synchronize the (real-time) threadpooltaskexecutor in the database or even in the file, so that the server can recover at startup without managing complex rules and evolutionary states by itself?
This is my executor configuration
@Configuration @EnableAsync public class AsyncConfig implements AsyncConfigurer { @Override public Executor getAsyncExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(4); executor.setMaxPoolSize(8); executor.setQueueCapacity(100); executor.setThreadNamePrefix("asyncTaskExecutor-"); executor.setAwaitTerminationSeconds(120); executor.setKeepAliveSeconds(30); executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); executor.initialize(); return executor; } @Override public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { return new SimpleAsyncUncaughtExceptionHandler(); } }
The controller that starts the asynchronous task
@RequestMapping(value = "/testAsync",method = RequestMethod.GET) public void testAsync() throws InterruptedException{ businessService.doHeavyThings(); }
Asynchronous method call:
@Async public void doHeavyThings() throws InterruptedException { LOGGER.error("Start doHeavyThings with configured executor - " + Thread.currentThread().getName() + " at " + new Date()); Thread.sleep(5000L); LOGGER.error("Stop doHeavyThings with configured executor - " + Thread.currentThread().getName() + " at " + new Date()); }
}
thank you
Solution
For web server shutdown, the application life cycle in Java Web applications is usually servletcontextlistener If you provide an implementation of servletcontextlistener, you can put the "processed content" logic in the contextdestroyed method
When you start the web server or application again, you can use the listener to resume reprocessing the unprocessed items of the job using the contextinitialized method
Another option is to use spring construction callbacks and put the logic here
HTH