Throw the target exception instead of InvocationTargetException (#1093)

Fixes gh-1092
This commit is contained in:
Denys Ivano
2018-09-20 13:07:09 +03:00
committed by Marcin Grzejszczak
parent 6eca124999
commit 4da88ee142
2 changed files with 41 additions and 1 deletions

View File

@@ -16,6 +16,7 @@
package org.springframework.cloud.sleuth.instrument.async;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.concurrent.Executor;
@@ -38,6 +39,8 @@ import org.springframework.util.ReflectionUtils;
* method or is final.
*
* @author Marcin Grzejszczak
* @author Jesus Alonso
* @author Denys Ivano
* @since 1.1.4
*/
class ExecutorBeanPostProcessor implements BeanPostProcessor {
@@ -124,7 +127,13 @@ class ExecutorMethodInterceptor<T extends Executor> implements MethodInterceptor
Executor executor = executor(this.beanFactory, this.delegate);
Method methodOnTracedBean = getMethod(invocation, executor);
if (methodOnTracedBean != null) {
return methodOnTracedBean.invoke(executor, invocation.getArguments());
try {
return methodOnTracedBean.invoke(executor, invocation.getArguments());
} catch (InvocationTargetException ex) {
// gh-1092: throw the target exception (if present)
Throwable cause = ex.getCause();
throw (cause != null) ? cause : ex;
}
}
return invocation.proceed();
}

View File

@@ -18,14 +18,20 @@ package org.springframework.cloud.sleuth.instrument.async;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ScheduledExecutorService;
import brave.Tracing;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.aop.framework.AopConfigException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.cloud.sleuth.DefaultSpanNamer;
import org.springframework.cloud.sleuth.SpanNamer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.util.ClassUtils;
@@ -34,6 +40,7 @@ import static org.assertj.core.api.BDDAssertions.thenThrownBy;
/**
* @author Marcin Grzejszczak
* @author Denys Ivano
*/
@RunWith(MockitoJUnitRunner.class)
public class ExecutorBeanPostProcessorTests {
@@ -110,4 +117,28 @@ public class ExecutorBeanPostProcessorTests {
.hasMessage("foo");
}
@Test
public void should_throw_real_exception_when_using_proxy() throws Exception {
// for LazyTraceExecutor
Mockito.when(this.beanFactory.getBean(Tracing.class))
.thenReturn(Tracing.newBuilder().build());
Mockito.when(this.beanFactory.getBean(SpanNamer.class))
.thenReturn(new DefaultSpanNamer());
Object o = new ExecutorBeanPostProcessor(this.beanFactory)
.postProcessAfterInitialization(new RejectedExecutionExecutor(), "fooExecutor");
then(o).isInstanceOf(RejectedExecutionExecutor.class);
then(ClassUtils.isCglibProxy(o)).isTrue();
thenThrownBy(() -> ((RejectedExecutionExecutor) o).execute(() -> {}))
.isInstanceOf(RejectedExecutionException.class)
.hasMessage("rejected");
}
class RejectedExecutionExecutor implements Executor {
@Override public void execute(Runnable task) {
throw new RejectedExecutionException("rejected");
}
}
}