Spring boot Exception SimpleAsyncUncaughtExceptionHandler : Unexpected exception occurred invoking async method: is thrown if an exception is thrown from the @Async annotation method. This error is due to either to a coding problem or to a logical issue. If the error has been corrected, this exception SimpleAsyncUncaughtExceptionHandler : Unexpected exception occurred invoking async method: will be resolved.

If an error occurs in asynchronous methods, the SimpleAsyncUncaughtExceptionHandler class wrappers the exception and triggers in the spring boot application. The error in the asynchronous method should be corrected or the exception should be resolved in the method. The custom AsyncUncaughtExceptionHandler class will be configured to handle all exceptions in the @Async method in the application.

The spring boot framework executes the class methods in a sequential fashion. The @Async annotation allows to perform the method in parallel. This would improve the efficiency of the application. As the call method will not wait for the response of the @Async method, the exception to the @Async method cannot be handled. Here are illustrated the various ways to handle the @Async exceptions.



Exception

Spring boot exception SimpleAsyncUncaughtExceptionHandler: Unintended exception occurred invoking async method: will be shown as below stack trace. The actual error will be shown below the SimpleAsyncUncaughtExceptionHandler exception. If the root cause problem is addressed, the SimpleAsyncUncaughtExceptionHandler exception will be resolved immediately.

2020-12-04 15:03:12.926 ERROR 80850 --- [         task-1] .a.i.SimpleAsyncUncaughtExceptionHandler : Unexpected exception occurred invoking async method: public void com.yawintutor.TestService.print(int)

java.lang.ArithmeticException: / by zero
	at com.yawintutor.TestService.print(TestService.java:15) ~[classes/:na]
	at com.yawintutor.TestService$$FastClassBySpringCGLIB$$284b10a4.invoke(<generated>) ~[classes/:na]
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.1.jar:5.3.1]
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771) ~[spring-aop-5.3.1.jar:5.3.1]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.1.jar:5.3.1]
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749) ~[spring-aop-5.3.1.jar:5.3.1]
	at org.springframework.aop.interceptor.AsyncExecutionInterceptor.lambda$invoke$0(AsyncExecutionInterceptor.java:115) ~[spring-aop-5.3.1.jar:5.3.1]
	at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:1.8.0_101]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) ~[na:1.8.0_101]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) ~[na:1.8.0_101]
	at java.lang.Thread.run(Thread.java:745) ~[na:1.8.0_101]


How to reproduce this exception

If the spring boot @Async annotation method throws an exception, the exception will be caught within SimpleAsyncUncaughtExceptionHandler class and throws this exception in the console log. In the example below, a java.lang.ArithmeticException exception will be throw within the asynchronous method.

package com.yawintutor;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;

@SpringBootApplication
@EnableAsync
public class SpringBootAsyncApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringBootAsyncApplication.class, args);
	}
}
package com.yawintutor;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {

	@Autowired
	TestService testService;
	
	@RequestMapping(value = "/welcome", method = RequestMethod.GET)
	public String welcome() {
		testService.print(0);
		return "success";
	}
}
package com.yawintutor;

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

@Service
public class TestService {

	@Async
	public void print(int index) {
		int a = 1;
		int b = 0;
		int c = 0;
		
		c= a/b;
		System.out.println("C value is "+c);
	}
}

Output

If the program is invoked in a browser by calling the url http://localhost:8080/welcome, The exception below will be shown.

2020-12-04 15:03:12.926 ERROR 80850 --- [         task-1] .a.i.SimpleAsyncUncaughtExceptionHandler : Unexpected exception occurred invoking async method: public void com.yawintutor.TestService.print(int)

java.lang.ArithmeticException: / by zero
	at com.yawintutor.TestService.print(TestService.java:15) ~[classes/:na]
	at com.yawintutor.TestService$$FastClassBySpringCGLIB$$284b10a4.invoke(<generated>) ~[classes/:na]
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.1.jar:5.3.1]
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771) ~[spring-aop-5.3.1.jar:5.3.1]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.1.jar:5.3.1]
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749) ~[spring-aop-5.3.1.jar:5.3.1]
	at org.springframework.aop.interceptor.AsyncExecutionInterceptor.lambda$invoke$0(AsyncExecutionInterceptor.java:115) ~[spring-aop-5.3.1.jar:5.3.1]
	at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:1.8.0_101]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) ~[na:1.8.0_101]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) ~[na:1.8.0_101]
	at java.lang.Thread.run(Thread.java:745) ~[na:1.8.0_101]


Root Cause

The @Async method in the spring boot application throws an error in the code. The exception is due of the coding problem, the logical issue or the data issue. When the exception is addressed, the SimpleAsyncUncaughtExceptionHandler exception will be fixed automatically. Either the problem is resolved or the exception is dealt with in the code. The SimpleAsyncUncaughtExceptionHandler class is used to handle all exceptions to the @Async method in the spring boot application.



Solution 1

The code walk through should be done with in the @Async method to identify the root cause of the issue. The issue should be fixed with in the code. If the exception is addressed, the SimpleAsyncUncaughtExceptionHandler exception will be fixed automatically.

package com.yawintutor;

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

@Service
public class TestService {

	@Async
	public void print(int index) {
		int a = 1;
		int b = 0;
		int c = 0;
		
		if(b==0) {
			c= a;
		} else {
			c = a/b;
		}
		System.out.println("C value is "+c);
	}
}

Output

C value is 1


Solution 2

The spring boot @Async method will throw an unknown exception for some reason. The exception must be caught and handled by the asynchronous method. When an error exists, the exception may be logged in or ignored in the application. The try catch block will be added as shown in the example below. The exception SimpleAsyncUncaughtExceptionHandler : Unexpected exception occurred invoking async method: will be resolved automatically.

package com.yawintutor;

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

@Service
public class TestService {

	@Async
	public void print(int index) {
		int a = 1;
		int b = 0;
		int c = 0;
		
		try {
			c = a/b;
			System.out.println("C value is "+c);
		} catch (Exception e) {
			System.out.println("Error occurred");
		}
	}
}

Output

Error occurred


Solution 3

The customized AsyncUncaughtExceptionHandler is created to handle any unknown exception is thrown in the @Async methods with in the spring boot application. All the exception will be caught in a single ExceptionHandler class. The customized AsyncUncaughtExceptionHandler example will be shown as like below.

package com.yawintutor;

import java.lang.reflect.Method;
import java.util.concurrent.Executor;

import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

@Configuration
public class SpringAsyncConfiguration implements AsyncConfigurer {
	@Override
	public Executor getAsyncExecutor() {
		ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
		executor.setCorePoolSize(10);
		executor.setMaxPoolSize(10);
		executor.setQueueCapacity(10);
		executor.initialize();
		return executor;
	}

	@Override
	public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
		return new AsyncUncaughtExceptionHandler() {

			@Override
			public void handleUncaughtException(Throwable ex, Method method, Object... params) {
				System.out.println("Throwable Exception message : " + ex.getMessage());
				System.out.println("Method name                 : " + method.getName());
				for (Object param : params) {
					System.out.println("Parameter value             : " + param);
				}
				System.out.println("stack Trace ");
				ex.printStackTrace();
			}

		};
	}
}

Output

Throwable Exception message : / by zero
Method name                 : print
Parameter value             : 0
stack Trace 
java.lang.ArithmeticException: / by zero
	at com.yawintutor.TestService.print(TestService.java:15)
	at com.yawintutor.TestService$$FastClassBySpringCGLIB$$284b10a4.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
	at org.springframework.aop.interceptor.AsyncExecutionInterceptor.lambda$invoke$0(AsyncExecutionInterceptor.java:115)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)



Leave a Reply