Spring 4 @Async Exception Handling with AsyncUncaughtExceptionHandler

By Arvind Rai, November 21, 2015
This page will walk through Spring 4 @Async exception handling with AsyncUncaughtExceptionHandler. We need to override handleUncaughtException() method of AsyncUncaughtExceptionHandler in our class. When a method annotated with @Async throws an uncaught exception, then thread terminates. The exception thrown will be caught in handleUncaughtException() method. To get the instance of AsyncUncaughtExceptionHandler, we need to override getAsyncUncaughtExceptionHandler() method of AsyncConfigurer in JavaConfig. Find the example.

Software Used

Find the software used in demo.
1. Java 8
2. Spring 4.1.8.RELEASE
3. Gradle
4. Eclipse

build.gradle

apply plugin: 'java'
apply plugin: 'eclipse'
archivesBaseName = 'SpringDemo'
version = '1' 
repositories {
    mavenCentral()
}
dependencies {
    compile 'org.springframework.boot:spring-boot-starter:1.2.7.RELEASE'
}  

AsyncUncaughtExceptionHandler: Override handleUncaughtException() Method

org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler handles uncaught exception thrown by method annotated with @Async . If the thread terminates because of un caught exception, we can catch the exception in handleUncaughtException() method of AsyncUncaughtExceptionHandler. To achieve it, we have to create a class implementing AsyncUncaughtExceptionHandler and override handleUncaughtException() method in which we can log the exception and can access the java.lang.reflect.Method instance. Find our sample class.
MyAsyncUncaughtExceptionHandler.java
package com.concretepage;
import java.lang.reflect.Method;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
public class MyAsyncUncaughtExceptionHandler implements AsyncUncaughtExceptionHandler {
    @Override
    public void handleUncaughtException(Throwable ex, Method method, Object... params) {
        System.out.println("Method Name::"+method.getName());
        System.out.println("Exception occurred::"+ ex);
    }
} 

JavaConfig: Override getAsyncUncaughtExceptionHandler() Method

To get the instance of AsyncUncaughtExceptionHandler, we need to override getAsyncUncaughtExceptionHandler method in JavaConfig. Our configuration class will implement AsyncConfigurer.
AppConfig.java
package com.concretepage;
import java.util.concurrent.Executor;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
@Configuration
@EnableAsync
@ComponentScan(basePackages="com.concretepage")
public class AppConfig implements AsyncConfigurer {
    @Override
    public Executor getAsyncExecutor() {
	    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
            executor.setCorePoolSize(5);
            executor.setMaxPoolSize(10);
            executor.setQueueCapacity(10);
            executor.initialize();
            return executor;
    }
    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new MyAsyncUncaughtExceptionHandler();
    }
} 

Scenario that throws Uncaught Exception using @Async

Now we will create a scenario that will throw uncaught exception using @Async.
AsyncTask.java
package com.concretepage;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
@Service
public class AsyncTask {
	@Async
	public void doAsyncTask(){
		String str= "hello";
		int cnt = 0;
		while(true) {
			cnt++;
			System.out.println(str.trim());
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
			}
			if(cnt==2) {
				//Scenario for NullPointerException
				str = null;
			}
		}
	}
} 

Run Application

What we are doing here is that after loop count two, the method annotated with @Async, will throw NullPointerException. The exception will be caught in handleUncaughtException() method of AsyncUncaughtExceptionHandler.
AppTest.java
package com.concretepage;
import java.sql.SQLException;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class AppTest {
	public static void main(String[] args) throws SQLException {
		AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
		ctx.register(AppConfig.class);
		ctx.refresh();
		AsyncTask task= ctx.getBean(AsyncTask.class);
		task.doAsyncTask();
	}
} 

Output

Find the output.
hello
hello
Method Name::doAsyncTask
Exception occurred::java.lang.NullPointerException 

Download Source Code

POSTED BY
ARVIND RAI
ARVIND RAI







©2024 concretepage.com | Privacy Policy | Contact Us