You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Spring Cloud Sleuth provides functionality for wrapping instances of Executor and bind a copy of current trace context to another thread to make it accessible from running task. But it looks like there is a bug that changes the behaviour when trying to submit task to filled Executor, because instead of TaskRejectedException (RejectedExecutionException), we receive UndeclaredThrowableException.
When spring-cloud-starter-sleuth dependency is removed or spring.sleuth.async.enabled=false property is added, a TaskRejectedException message will be returned on HTTP request:
2018-09-19 19:02:37.784 WARN 31461 --- [nio-8080-exec-1] c.e.s.c.sleuth.exception.Application : Task rejected
org.springframework.core.task.TaskRejectedException: Executor [java.util.concurrent.ThreadPoolExecutor@3f18fde0[Running, pool size = 1, active threads = 1, queued tasks = 0, completed tasks = 0]] did not accept task: com.example.spring.cloud.sleuth.exception.Application$$Lambda$320/90355657@2487f435
at org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor.execute(ThreadPoolTaskExecutor.java:317) ~[spring-context-5.0.8.RELEASE.jar:5.0.8.RELEASE]
at com.example.spring.cloud.sleuth.exception.Application.test(Application.java:34) ~[classes/:na]
...
Caused by: java.util.concurrent.RejectedExecutionException: Task com.example.spring.cloud.sleuth.exception.Application$$Lambda$320/90355657@2487f435 rejected from java.util.concurrent.ThreadPoolExecutor@3f18fde0[Running, pool size = 1, active threads = 1, queued tasks = 0, completed tasks = 0]
at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2047) ~[na:1.8.0_121]
at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:823) [na:1.8.0_121]
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1369) [na:1.8.0_121]
at org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor.execute(ThreadPoolTaskExecutor.java:314) ~[spring-context-5.0.8.RELEASE.jar:5.0.8.RELEASE]
... 55 common frames omitted
But with ExecutorBeanPostProcessor being used, an UndeclaredThrowableException message will be returned:
2018-09-19 19:00:47.156 WARN [-,bb87832a01adccf6,bb87832a01adccf6,false] 31296 --- [nio-8080-exec-5] c.e.s.c.sleuth.exception.Application : UndeclaredThrowableException received
java.lang.reflect.UndeclaredThrowableException: null
at org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor$$EnhancerBySpringCGLIB$$32afee45.execute(<generated>) ~[spring-context-5.0.8.RELEASE.jar:5.0.8.RELEASE]
at com.example.spring.cloud.sleuth.exception.Application.test(Application.java:32) ~[classes/:na]
...
Caused by: java.lang.reflect.InvocationTargetException: null
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_121]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_121]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_121]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_121]
at org.springframework.cloud.sleuth.instrument.async.ExecutorMethodInterceptor.invoke(ExecutorBeanPostProcessor.java:127) ~[spring-cloud-sleuth-core-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.8.RELEASE.jar:5.0.8.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688) ~[spring-aop-5.0.8.RELEASE.jar:5.0.8.RELEASE]
... 62 common frames omitted
Caused by: org.springframework.core.task.TaskRejectedException: Executor [java.util.concurrent.ThreadPoolExecutor@7101c622[Running, pool size = 1, active threads = 1, queued tasks = 0, completed tasks = 2]] did not accept task: org.springframework.cloud.sleuth.instrument.async.TraceRunnable@741cd618
at org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor.execute(ThreadPoolTaskExecutor.java:317) ~[spring-context-5.0.8.RELEASE.jar:5.0.8.RELEASE]
at org.springframework.cloud.sleuth.instrument.async.LazyTraceThreadPoolTaskExecutor.execute(LazyTraceThreadPoolTaskExecutor.java:60) ~[spring-cloud-sleuth-core-2.0.1.RELEASE.jar:2.0.1.RELEASE]
... 69 common frames omitted
Caused by: java.util.concurrent.RejectedExecutionException: Task org.springframework.cloud.sleuth.instrument.async.TraceRunnable@741cd618 rejected from java.util.concurrent.ThreadPoolExecutor@7101c622[Running, pool size = 1, active threads = 1, queued tasks = 0, completed tasks = 2]
at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2047) ~[na:1.8.0_121]
at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:823) [na:1.8.0_121]
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1369) [na:1.8.0_121]
at org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor.execute(ThreadPoolTaskExecutor.java:314) ~[spring-context-5.0.8.RELEASE.jar:5.0.8.RELEASE]
... 70 common frames omitted
This happens because an instance of checked exception (InvocationTargetException) is being thrown while proxying calls to Executor methods. Because Executor's and TaskExecutor's methods don't declare any checked exceptions, an InvocationTargetException is being wrapped into UndeclaredThrowableException.
Take a look at how ExecutorMethodInterceptor invokes the target method:
Spring Cloud Sleuth provides functionality for wrapping instances of
Executor
and bind a copy of current trace context to another thread to make it accessible from running task. But it looks like there is a bug that changes the behaviour when trying to submit task to filledExecutor
, because instead ofTaskRejectedException
(RejectedExecutionException
), we receiveUndeclaredThrowableException
.Consider sample application:
Application.java
pom.xml
When
spring-cloud-starter-sleuth
dependency is removed orspring.sleuth.async.enabled=false
property is added, aTaskRejectedException
message will be returned on HTTP request:But with
ExecutorBeanPostProcessor
being used, anUndeclaredThrowableException
message will be returned:This happens because an instance of checked exception (
InvocationTargetException
) is being thrown while proxying calls toExecutor
methods. BecauseExecutor
's andTaskExecutor
's methods don't declare any checked exceptions, anInvocationTargetException
is being wrapped intoUndeclaredThrowableException
.Take a look at how
ExecutorMethodInterceptor
invokes the target method:Call to
methodOnTracedBean.invoke(executor, invocation.getArguments())
throws anInvocationTargetException
.Would it be better to catch checked
InvocationTargetException
and re-throw it's cause (if present)?The text was updated successfully, but these errors were encountered: