From ae1ed9d458dbba1dbf151c8f0012c822e90f5784 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Wed, 10 Jun 2020 22:52:01 +0200 Subject: [PATCH] Document exception handling limitations in TaskDecorator implementations Closes gh-25231 --- .../scheduling/commonj/WorkManagerTaskExecutor.java | 13 +++++++++---- .../concurrent/ConcurrentTaskExecutor.java | 7 ++++++- .../concurrent/DefaultManagedTaskExecutor.java | 7 ++++--- .../concurrent/ThreadPoolTaskExecutor.java | 9 ++++++++- .../core/task/SimpleAsyncTaskExecutor.java | 7 ++++++- .../springframework/core/task/TaskDecorator.java | 11 +++++++++-- .../core/task/support/TaskExecutorAdapter.java | 7 ++++++- .../jca/work/WorkManagerTaskExecutor.java | 7 ++++++- 8 files changed, 54 insertions(+), 14 deletions(-) diff --git a/spring-context-support/src/main/java/org/springframework/scheduling/commonj/WorkManagerTaskExecutor.java b/spring-context-support/src/main/java/org/springframework/scheduling/commonj/WorkManagerTaskExecutor.java index f20fde56b175..a9adcc823d5a 100644 --- a/spring-context-support/src/main/java/org/springframework/scheduling/commonj/WorkManagerTaskExecutor.java +++ b/spring-context-support/src/main/java/org/springframework/scheduling/commonj/WorkManagerTaskExecutor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2020 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. @@ -58,13 +58,13 @@ *

The CommonJ WorkManager will usually be retrieved from the application * server's JNDI environment, as defined in the server's management console. * - *

Note: On the upcoming EE 7 compliant versions of WebLogic and WebSphere, a + *

Note: On EE 7/8 compliant versions of WebLogic and WebSphere, a * {@link org.springframework.scheduling.concurrent.DefaultManagedTaskExecutor} - * should be preferred, following JSR-236 support in Java EE 7. + * should be preferred, following JSR-236 support in Java EE 7/8. * * @author Juergen Hoeller * @since 2.0 - * @deprecated as of 5.1, in favor of EE 7's + * @deprecated as of 5.1, in favor of the EE 7/8 based * {@link org.springframework.scheduling.concurrent.DefaultManagedTaskExecutor} */ @Deprecated @@ -121,6 +121,11 @@ public void setWorkListener(WorkListener workListener) { * execution callback (which may be a wrapper around the user-supplied task). *

The primary use case is to set some execution context around the task's * invocation, or to provide some monitoring/statistics for task execution. + *

NOTE: Exception handling in {@code TaskDecorator} implementations + * is limited to plain {@code Runnable} execution via {@code execute} calls. + * In case of {@code #submit} calls, the exposed {@code Runnable} will be a + * {@code FutureTask} which does not propagate any exceptions; you might + * have to cast it and call {@code Future#get} to evaluate exceptions. * @since 4.3 */ public void setTaskDecorator(TaskDecorator taskDecorator) { diff --git a/spring-context/src/main/java/org/springframework/scheduling/concurrent/ConcurrentTaskExecutor.java b/spring-context/src/main/java/org/springframework/scheduling/concurrent/ConcurrentTaskExecutor.java index 876beb3d5885..0b976d3f00a3 100644 --- a/spring-context/src/main/java/org/springframework/scheduling/concurrent/ConcurrentTaskExecutor.java +++ b/spring-context/src/main/java/org/springframework/scheduling/concurrent/ConcurrentTaskExecutor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2020 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. @@ -130,6 +130,11 @@ public final Executor getConcurrentExecutor() { * execution callback (which may be a wrapper around the user-supplied task). *

The primary use case is to set some execution context around the task's * invocation, or to provide some monitoring/statistics for task execution. + *

NOTE: Exception handling in {@code TaskDecorator} implementations + * is limited to plain {@code Runnable} execution via {@code execute} calls. + * In case of {@code #submit} calls, the exposed {@code Runnable} will be a + * {@code FutureTask} which does not propagate any exceptions; you might + * have to cast it and call {@code Future#get} to evaluate exceptions. * @since 4.3 */ public final void setTaskDecorator(TaskDecorator taskDecorator) { diff --git a/spring-context/src/main/java/org/springframework/scheduling/concurrent/DefaultManagedTaskExecutor.java b/spring-context/src/main/java/org/springframework/scheduling/concurrent/DefaultManagedTaskExecutor.java index d4095bad58ea..62cb3dd9fb1f 100644 --- a/spring-context/src/main/java/org/springframework/scheduling/concurrent/DefaultManagedTaskExecutor.java +++ b/spring-context/src/main/java/org/springframework/scheduling/concurrent/DefaultManagedTaskExecutor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2020 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. @@ -28,7 +28,7 @@ /** * JNDI-based variant of {@link ConcurrentTaskExecutor}, performing a default lookup for - * JSR-236's "java:comp/DefaultManagedExecutorService" in a Java EE 7 environment. + * JSR-236's "java:comp/DefaultManagedExecutorService" in a Java EE 7/8 environment. * *

Note: This class is not strictly JSR-236 based; it can work with any regular * {@link java.util.concurrent.Executor} that can be found in JNDI. @@ -37,10 +37,11 @@ * * @author Juergen Hoeller * @since 4.0 + * @see javax.enterprise.concurrent.ManagedExecutorService */ public class DefaultManagedTaskExecutor extends ConcurrentTaskExecutor implements InitializingBean { - private JndiLocatorDelegate jndiLocator = new JndiLocatorDelegate(); + private final JndiLocatorDelegate jndiLocator = new JndiLocatorDelegate(); @Nullable private String jndiName = "java:comp/DefaultManagedExecutorService"; diff --git a/spring-context/src/main/java/org/springframework/scheduling/concurrent/ThreadPoolTaskExecutor.java b/spring-context/src/main/java/org/springframework/scheduling/concurrent/ThreadPoolTaskExecutor.java index a21d18eccd0b..f5e9edf58bfa 100644 --- a/spring-context/src/main/java/org/springframework/scheduling/concurrent/ThreadPoolTaskExecutor.java +++ b/spring-context/src/main/java/org/springframework/scheduling/concurrent/ThreadPoolTaskExecutor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2020 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. @@ -205,6 +205,13 @@ public void setAllowCoreThreadTimeOut(boolean allowCoreThreadTimeOut) { * execution callback (which may be a wrapper around the user-supplied task). *

The primary use case is to set some execution context around the task's * invocation, or to provide some monitoring/statistics for task execution. + *

NOTE: Exception handling in {@code TaskDecorator} implementations + * is limited to plain {@code Runnable} execution via {@code execute} calls. + * In case of {@code #submit} calls, the exposed {@code Runnable} will be a + * {@code FutureTask} which does not propagate any exceptions; you might + * have to cast it and call {@code Future#get} to evaluate exceptions. + * See the {@code ThreadPoolExecutor#afterExecute} javadoc for an example + * of how to access exceptions in such a {@code Future} case. * @since 4.3 */ public void setTaskDecorator(TaskDecorator taskDecorator) { diff --git a/spring-core/src/main/java/org/springframework/core/task/SimpleAsyncTaskExecutor.java b/spring-core/src/main/java/org/springframework/core/task/SimpleAsyncTaskExecutor.java index 0bc6aefee517..7d96032ad80b 100644 --- a/spring-core/src/main/java/org/springframework/core/task/SimpleAsyncTaskExecutor.java +++ b/spring-core/src/main/java/org/springframework/core/task/SimpleAsyncTaskExecutor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2020 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. @@ -126,6 +126,11 @@ public final ThreadFactory getThreadFactory() { * execution callback (which may be a wrapper around the user-supplied task). *

The primary use case is to set some execution context around the task's * invocation, or to provide some monitoring/statistics for task execution. + *

NOTE: Exception handling in {@code TaskDecorator} implementations + * is limited to plain {@code Runnable} execution via {@code execute} calls. + * In case of {@code #submit} calls, the exposed {@code Runnable} will be a + * {@code FutureTask} which does not propagate any exceptions; you might + * have to cast it and call {@code Future#get} to evaluate exceptions. * @since 4.3 */ public final void setTaskDecorator(TaskDecorator taskDecorator) { diff --git a/spring-core/src/main/java/org/springframework/core/task/TaskDecorator.java b/spring-core/src/main/java/org/springframework/core/task/TaskDecorator.java index 0d7734d3bd65..753bf2c5198f 100644 --- a/spring-core/src/main/java/org/springframework/core/task/TaskDecorator.java +++ b/spring-core/src/main/java/org/springframework/core/task/TaskDecorator.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-2020 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. @@ -27,17 +27,24 @@ *

The primary use case is to set some execution context around the task's * invocation, or to provide some monitoring/statistics for task execution. * + *

NOTE: Exception handling in {@code TaskDecorator} implementations + * may be limited. Specifically in case of a {@code Future}-based operation, + * the exposed {@code Runnable} will be a wrapper which does not propagate + * any exceptions from its {@code run} method. + * * @author Juergen Hoeller * @since 4.3 * @see TaskExecutor#execute(Runnable) * @see SimpleAsyncTaskExecutor#setTaskDecorator + * @see org.springframework.core.task.support.TaskExecutorAdapter#setTaskDecorator */ @FunctionalInterface public interface TaskDecorator { /** * Decorate the given {@code Runnable}, returning a potentially wrapped - * {@code Runnable} for actual execution. + * {@code Runnable} for actual execution, internally delegating to the + * original {@link Runnable#run()} implementation. * @param runnable the original {@code Runnable} * @return the decorated {@code Runnable} */ diff --git a/spring-core/src/main/java/org/springframework/core/task/support/TaskExecutorAdapter.java b/spring-core/src/main/java/org/springframework/core/task/support/TaskExecutorAdapter.java index 2162c7c42918..81da48db8e02 100644 --- a/spring-core/src/main/java/org/springframework/core/task/support/TaskExecutorAdapter.java +++ b/spring-core/src/main/java/org/springframework/core/task/support/TaskExecutorAdapter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-2020 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. @@ -70,6 +70,11 @@ public TaskExecutorAdapter(Executor concurrentExecutor) { * execution callback (which may be a wrapper around the user-supplied task). *

The primary use case is to set some execution context around the task's * invocation, or to provide some monitoring/statistics for task execution. + *

NOTE: Exception handling in {@code TaskDecorator} implementations + * is limited to plain {@code Runnable} execution via {@code execute} calls. + * In case of {@code #submit} calls, the exposed {@code Runnable} will be a + * {@code FutureTask} which does not propagate any exceptions; you might + * have to cast it and call {@code Future#get} to evaluate exceptions. * @since 4.3 */ public final void setTaskDecorator(TaskDecorator taskDecorator) { diff --git a/spring-tx/src/main/java/org/springframework/jca/work/WorkManagerTaskExecutor.java b/spring-tx/src/main/java/org/springframework/jca/work/WorkManagerTaskExecutor.java index 8a687f3c89d7..e4fe06bfeb35 100644 --- a/spring-tx/src/main/java/org/springframework/jca/work/WorkManagerTaskExecutor.java +++ b/spring-tx/src/main/java/org/springframework/jca/work/WorkManagerTaskExecutor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2020 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. @@ -175,6 +175,11 @@ public void setWorkListener(@Nullable WorkListener workListener) { * execution callback (which may be a wrapper around the user-supplied task). *

The primary use case is to set some execution context around the task's * invocation, or to provide some monitoring/statistics for task execution. + *

NOTE: Exception handling in {@code TaskDecorator} implementations + * is limited to plain {@code Runnable} execution via {@code execute} calls. + * In case of {@code #submit} calls, the exposed {@code Runnable} will be a + * {@code FutureTask} which does not propagate any exceptions; you might + * have to cast it and call {@code Future#get} to evaluate exceptions. * @since 4.3 */ public void setTaskDecorator(TaskDecorator taskDecorator) {