From c2457b960fb681bb4a48e1922d0fbd6322a03016 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 | 11 ++++++++--- .../scheduling/concurrent/ConcurrentTaskExecutor.java | 7 ++++++- .../concurrent/DefaultManagedTaskExecutor.java | 7 ++++--- .../scheduling/concurrent/ThreadPoolTaskExecutor.java | 9 ++++++++- .../core/task/SimpleAsyncTaskExecutor.java | 7 ++++++- .../org/springframework/core/task/TaskDecorator.java | 11 +++++++++-- .../core/task/support/TaskExecutorAdapter.java | 7 ++++++- .../jca/work/WorkManagerTaskExecutor.java | 7 ++++++- 8 files changed, 53 insertions(+), 13 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 f300b40b3d1b..c2cb5f741046 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-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. @@ -57,9 +57,9 @@ *

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 @@ -117,6 +117,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 2bdb6e0b7e3c..23cf9a332976 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. @@ -129,6 +129,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 f728b7acdc2b..9251bafd44b7 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. @@ -27,7 +27,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. @@ -36,10 +36,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 1d3f02e449d5..40cd58558efc 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 75093b9d260d..3ec83d6e5876 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-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. @@ -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 ba78048fdf57..0166690435fc 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-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. @@ -174,6 +174,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) {