From 4da88ee142c15b0c42e3810660ab985abc971e09 Mon Sep 17 00:00:00 2001 From: Denys Ivano Date: Thu, 20 Sep 2018 13:07:09 +0300 Subject: [PATCH] Throw the target exception instead of InvocationTargetException (#1093) Fixes gh-1092 --- .../async/ExecutorBeanPostProcessor.java | 11 ++++++- .../async/ExecutorBeanPostProcessorTests.java | 31 +++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/ExecutorBeanPostProcessor.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/ExecutorBeanPostProcessor.java index 9ce03995e..904455a41 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/ExecutorBeanPostProcessor.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/ExecutorBeanPostProcessor.java @@ -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 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(); } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/ExecutorBeanPostProcessorTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/ExecutorBeanPostProcessorTests.java index 66d6fd06d..283c4ba73 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/ExecutorBeanPostProcessorTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/ExecutorBeanPostProcessorTests.java @@ -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"); + } + } + } \ No newline at end of file