@Override @Async public void asyncExceptionTest() { int i=1/0; }
How can I log this using Spring Async framework without having to put try catch around every async method? It doesn't seem to pass to the DefaultUncaughtExceptionHandler
like normal.
Simply put, annotating a method of a bean with @Async will make it execute in a separate thread. In other words, the caller will not wait for the completion of the called method. One interesting aspect in Spring is that the event support in the framework also has support for async processing if necessary.
public class SimpleAsyncUncaughtExceptionHandler extends Object implements AsyncUncaughtExceptionHandler. A default AsyncUncaughtExceptionHandler that simply logs the exception.
@Async
methods can be configured with a custom Executor
to log any thrown exceptions.
The following code implements this pattern. Any method tagged with @Async
will use the Executor
returned by the method public Executor getAsyncExecutor()
. This returns the HandlingExecutor
which takes care of all logging (in this case it just prints the word "CAUGHT!" but you can replace with logging.
@Configuration @EnableAsync public class ExampleConfig implements AsyncConfigurer { @Bean public Runnable testExec() { return new TestExec(); } @Override public Executor getAsyncExecutor() { final ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(7); executor.setMaxPoolSize(42); executor.setQueueCapacity(11); executor.setThreadNamePrefix("MyExecutor-"); executor.initialize(); return new HandlingExecutor(executor); } } public class HandlingExecutor implements AsyncTaskExecutor { private AsyncTaskExecutor executor; public HandlingExecutor(AsyncTaskExecutor executor) { this.executor = executor; } @Override public void execute(Runnable task) { executor.execute(task); } @Override public void execute(Runnable task, long startTimeout) { executor.execute(createWrappedRunnable(task), startTimeout); } @Override public Future<?> submit(Runnable task) { return executor.submit(createWrappedRunnable(task)); } @Override public <T> Future<T> submit(final Callable<T> task) { return executor.submit(createCallable(task)); } private <T> Callable<T> createCallable(final Callable<T> task) { return new Callable<T>() { @Override public T call() throws Exception { try { return task.call(); } catch (Exception e) { handle(e); throw e; } } }; } private Runnable createWrappedRunnable(final Runnable task) { return new Runnable() { @Override public void run() { try { task.run(); } catch (Exception e) { handle(e); } } }; } private void handle(Exception e) { System.out.println("CAUGHT!"); } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With