@ -1,5 +1,5 @@
@@ -1,5 +1,5 @@
/ *
* Copyright 2002 - 2014 the original author or authors .
* Copyright 2002 - 2015 the original author or authors .
*
* Licensed under the Apache License , Version 2 . 0 ( the "License" ) ;
* you may not use this file except in compliance with the License .
@ -25,15 +25,20 @@ import java.util.concurrent.TimeUnit;
@@ -25,15 +25,20 @@ import java.util.concurrent.TimeUnit;
import org.junit.Test ;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler ;
import org.springframework.aop.support.AopUtils ;
import org.springframework.beans.factory.config.BeanDefinition ;
import org.springframework.beans.factory.support.RootBeanDefinition ;
import org.springframework.context.ConfigurableApplicationContext ;
import org.springframework.context.annotation.AnnotationConfigApplicationContext ;
import org.springframework.context.annotation.Bean ;
import org.springframework.context.annotation.Configuration ;
import org.springframework.context.support.GenericXmlApplicationContext ;
import org.springframework.context.support.StaticApplicationContext ;
import org.springframework.core.io.ClassPathResource ;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor ;
import org.springframework.util.ReflectionUtils ;
import org.springframework.util.concurrent.ListenableFuture ;
import static org.junit.Assert.* ;
@ -106,10 +111,32 @@ public class AsyncAnnotationBeanPostProcessorTests {
@@ -106,10 +111,32 @@ public class AsyncAnnotationBeanPostProcessorTests {
@Test
public void handleExceptionWithFuture ( ) {
ConfigurableApplicationContext context = initContext (
new RootBeanDefinition ( AsyncAnnotationBeanPostProcesso r. class ) ) ;
ConfigurableApplicationContext context =
new AnnotationConfigApplicationContext ( ConfigWithExceptionHandle r. class ) ;
ITestBean testBean = context . getBean ( "target" , ITestBean . class ) ;
final Future < Object > result = testBean . failWithFuture ( ) ;
TestableAsyncUncaughtExceptionHandler exceptionHandler =
context . getBean ( "exceptionHandler" , TestableAsyncUncaughtExceptionHandler . class ) ;
assertFalse ( "handler should not have been called yet" , exceptionHandler . isCalled ( ) ) ;
Future < Object > result = testBean . failWithFuture ( ) ;
assertFutureWithException ( result , exceptionHandler ) ;
}
@Test
public void handleExceptionWithListenableFuture ( ) {
ConfigurableApplicationContext context =
new AnnotationConfigApplicationContext ( ConfigWithExceptionHandler . class ) ;
ITestBean testBean = context . getBean ( "target" , ITestBean . class ) ;
TestableAsyncUncaughtExceptionHandler exceptionHandler =
context . getBean ( "exceptionHandler" , TestableAsyncUncaughtExceptionHandler . class ) ;
assertFalse ( "handler should not have been called yet" , exceptionHandler . isCalled ( ) ) ;
Future < Object > result = testBean . failWithListenableFuture ( ) ;
assertFutureWithException ( result , exceptionHandler ) ;
}
private void assertFutureWithException ( Future < Object > result ,
TestableAsyncUncaughtExceptionHandler exceptionHandler ) {
try {
result . get ( ) ;
@ -121,6 +148,7 @@ public class AsyncAnnotationBeanPostProcessorTests {
@@ -121,6 +148,7 @@ public class AsyncAnnotationBeanPostProcessorTests {
// expected
assertEquals ( "Wrong exception cause" , UnsupportedOperationException . class , ex . getCause ( ) . getClass ( ) ) ;
}
assertFalse ( "handler should never be called with Future return type" , exceptionHandler . isCalled ( ) ) ;
}
@Test
@ -173,7 +201,7 @@ public class AsyncAnnotationBeanPostProcessorTests {
@@ -173,7 +201,7 @@ public class AsyncAnnotationBeanPostProcessorTests {
}
private static interface ITestBean {
private interface ITestBean {
Thread getThread ( ) ;
@ -181,6 +209,8 @@ public class AsyncAnnotationBeanPostProcessorTests {
@@ -181,6 +209,8 @@ public class AsyncAnnotationBeanPostProcessorTests {
Future < Object > failWithFuture ( ) ;
ListenableFuture < Object > failWithListenableFuture ( ) ;
void failWithVoid ( ) ;
void await ( long timeout ) ;
@ -206,11 +236,19 @@ public class AsyncAnnotationBeanPostProcessorTests {
@@ -206,11 +236,19 @@ public class AsyncAnnotationBeanPostProcessorTests {
}
@Async
@Override
public Future < Object > failWithFuture ( ) {
throw new UnsupportedOperationException ( "failWithFuture" ) ;
}
@Async
@Override
public ListenableFuture < Object > failWithListenableFuture ( ) {
throw new UnsupportedOperationException ( "failWithListenableFuture" ) ;
}
@Async
@Override
public void failWithVoid ( ) {
throw new UnsupportedOperationException ( "failWithVoid" ) ;
}
@ -234,4 +272,25 @@ public class AsyncAnnotationBeanPostProcessorTests {
@@ -234,4 +272,25 @@ public class AsyncAnnotationBeanPostProcessorTests {
}
}
@Configuration
@EnableAsync
static class ConfigWithExceptionHandler extends AsyncConfigurerSupport {
@Bean
public ITestBean target ( ) {
return new TestBean ( ) ;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler ( ) {
return exceptionHandler ( ) ;
}
@Bean
public TestableAsyncUncaughtExceptionHandler exceptionHandler ( ) {
return new TestableAsyncUncaughtExceptionHandler ( ) ;
}
}
}