From 464b676ec5924a5610338d3df7b5b9adb4c259c3 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Fri, 7 Jul 2023 23:59:10 +0200 Subject: [PATCH] Expose shutdown state in TaskRejectedException message See gh-27090 --- .../concurrent/ConcurrentTaskScheduler.java | 12 ++++----- .../concurrent/ThreadPoolTaskExecutor.java | 10 +++---- .../concurrent/ThreadPoolTaskScheduler.java | 22 ++++++++-------- .../core/task/TaskRejectedException.java | 26 ++++++++++++++++++- .../task/support/TaskExecutorAdapter.java | 15 ++++------- 5 files changed, 52 insertions(+), 33 deletions(-) diff --git a/spring-context/src/main/java/org/springframework/scheduling/concurrent/ConcurrentTaskScheduler.java b/spring-context/src/main/java/org/springframework/scheduling/concurrent/ConcurrentTaskScheduler.java index 9940597b8da6..88f36184efd9 100644 --- a/spring-context/src/main/java/org/springframework/scheduling/concurrent/ConcurrentTaskScheduler.java +++ b/spring-context/src/main/java/org/springframework/scheduling/concurrent/ConcurrentTaskScheduler.java @@ -206,7 +206,7 @@ public ScheduledFuture schedule(Runnable task, Trigger trigger) { } } catch (RejectedExecutionException ex) { - throw new TaskRejectedException("Executor [" + this.scheduledExecutor + "] did not accept task: " + task, ex); + throw new TaskRejectedException(this.scheduledExecutor, task, ex); } } @@ -217,7 +217,7 @@ public ScheduledFuture schedule(Runnable task, Instant startTime) { return this.scheduledExecutor.schedule(decorateTask(task, false), NANO.convert(delay), NANO); } catch (RejectedExecutionException ex) { - throw new TaskRejectedException("Executor [" + this.scheduledExecutor + "] did not accept task: " + task, ex); + throw new TaskRejectedException(this.scheduledExecutor, task, ex); } } @@ -229,7 +229,7 @@ public ScheduledFuture scheduleAtFixedRate(Runnable task, Instant startTime, NANO.convert(initialDelay), NANO.convert(period), NANO); } catch (RejectedExecutionException ex) { - throw new TaskRejectedException("Executor [" + this.scheduledExecutor + "] did not accept task: " + task, ex); + throw new TaskRejectedException(this.scheduledExecutor, task, ex); } } @@ -240,7 +240,7 @@ public ScheduledFuture scheduleAtFixedRate(Runnable task, Duration period) { 0, NANO.convert(period), NANO); } catch (RejectedExecutionException ex) { - throw new TaskRejectedException("Executor [" + this.scheduledExecutor + "] did not accept task: " + task, ex); + throw new TaskRejectedException(this.scheduledExecutor, task, ex); } } @@ -252,7 +252,7 @@ public ScheduledFuture scheduleWithFixedDelay(Runnable task, Instant startTim NANO.convert(initialDelay), NANO.convert(delay), NANO); } catch (RejectedExecutionException ex) { - throw new TaskRejectedException("Executor [" + this.scheduledExecutor + "] did not accept task: " + task, ex); + throw new TaskRejectedException(this.scheduledExecutor, task, ex); } } @@ -263,7 +263,7 @@ public ScheduledFuture scheduleWithFixedDelay(Runnable task, Duration delay) 0, NANO.convert(delay), NANO); } catch (RejectedExecutionException ex) { - throw new TaskRejectedException("Executor [" + this.scheduledExecutor + "] did not accept task: " + task, ex); + throw new TaskRejectedException(this.scheduledExecutor, task, ex); } } 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 c4c8638c949e..1a529f6cca94 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 @@ -362,7 +362,7 @@ public void execute(Runnable task) { executor.execute(task); } catch (RejectedExecutionException ex) { - throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex); + throw new TaskRejectedException(executor, task, ex); } } @@ -373,7 +373,7 @@ public Future submit(Runnable task) { return executor.submit(task); } catch (RejectedExecutionException ex) { - throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex); + throw new TaskRejectedException(executor, task, ex); } } @@ -384,7 +384,7 @@ public Future submit(Callable task) { return executor.submit(task); } catch (RejectedExecutionException ex) { - throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex); + throw new TaskRejectedException(executor, task, ex); } } @@ -397,7 +397,7 @@ public ListenableFuture submitListenable(Runnable task) { return future; } catch (RejectedExecutionException ex) { - throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex); + throw new TaskRejectedException(executor, task, ex); } } @@ -410,7 +410,7 @@ public ListenableFuture submitListenable(Callable task) { return future; } catch (RejectedExecutionException ex) { - throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex); + throw new TaskRejectedException(executor, task, ex); } } diff --git a/spring-context/src/main/java/org/springframework/scheduling/concurrent/ThreadPoolTaskScheduler.java b/spring-context/src/main/java/org/springframework/scheduling/concurrent/ThreadPoolTaskScheduler.java index 5a76840be979..fd1a8aba4c4c 100644 --- a/spring-context/src/main/java/org/springframework/scheduling/concurrent/ThreadPoolTaskScheduler.java +++ b/spring-context/src/main/java/org/springframework/scheduling/concurrent/ThreadPoolTaskScheduler.java @@ -290,7 +290,7 @@ public void execute(Runnable task) { executor.execute(errorHandlingTask(task, false)); } catch (RejectedExecutionException ex) { - throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex); + throw new TaskRejectedException(executor, task, ex); } } @@ -301,7 +301,7 @@ public Future submit(Runnable task) { return executor.submit(errorHandlingTask(task, false)); } catch (RejectedExecutionException ex) { - throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex); + throw new TaskRejectedException(executor, task, ex); } } @@ -317,7 +317,7 @@ public Future submit(Callable task) { return executor.submit(taskToUse); } catch (RejectedExecutionException ex) { - throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex); + throw new TaskRejectedException(executor, task, ex); } } @@ -330,7 +330,7 @@ public ListenableFuture submitListenable(Runnable task) { return listenableFuture; } catch (RejectedExecutionException ex) { - throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex); + throw new TaskRejectedException(executor, task, ex); } } @@ -343,7 +343,7 @@ public ListenableFuture submitListenable(Callable task) { return listenableFuture; } catch (RejectedExecutionException ex) { - throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex); + throw new TaskRejectedException(executor, task, ex); } } @@ -379,7 +379,7 @@ public ScheduledFuture schedule(Runnable task, Trigger trigger) { return new ReschedulingRunnable(task, trigger, this.clock, executor, errorHandler).schedule(); } catch (RejectedExecutionException ex) { - throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex); + throw new TaskRejectedException(executor, task, ex); } } @@ -391,7 +391,7 @@ public ScheduledFuture schedule(Runnable task, Instant startTime) { return executor.schedule(errorHandlingTask(task, false), NANO.convert(delay), NANO); } catch (RejectedExecutionException ex) { - throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex); + throw new TaskRejectedException(executor, task, ex); } } @@ -404,7 +404,7 @@ public ScheduledFuture scheduleAtFixedRate(Runnable task, Instant startTime, NANO.convert(initialDelay), NANO.convert(period), NANO); } catch (RejectedExecutionException ex) { - throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex); + throw new TaskRejectedException(executor, task, ex); } } @@ -416,7 +416,7 @@ public ScheduledFuture scheduleAtFixedRate(Runnable task, Duration period) { 0, NANO.convert(period), NANO); } catch (RejectedExecutionException ex) { - throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex); + throw new TaskRejectedException(executor, task, ex); } } @@ -429,7 +429,7 @@ public ScheduledFuture scheduleWithFixedDelay(Runnable task, Instant startTim NANO.convert(initialDelay), NANO.convert(delay), NANO); } catch (RejectedExecutionException ex) { - throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex); + throw new TaskRejectedException(executor, task, ex); } } @@ -441,7 +441,7 @@ public ScheduledFuture scheduleWithFixedDelay(Runnable task, Duration delay) 0, NANO.convert(delay), NANO); } catch (RejectedExecutionException ex) { - throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex); + throw new TaskRejectedException(executor, task, ex); } } diff --git a/spring-core/src/main/java/org/springframework/core/task/TaskRejectedException.java b/spring-core/src/main/java/org/springframework/core/task/TaskRejectedException.java index e77d4df1bc8c..6d70d26f4bef 100644 --- a/spring-core/src/main/java/org/springframework/core/task/TaskRejectedException.java +++ b/spring-core/src/main/java/org/springframework/core/task/TaskRejectedException.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 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. @@ -16,6 +16,8 @@ package org.springframework.core.task; +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; import java.util.concurrent.RejectedExecutionException; /** @@ -50,4 +52,26 @@ public TaskRejectedException(String msg, Throwable cause) { super(msg, cause); } + /** + * Create a new {@code TaskRejectedException} + * with a default message for the given executor and task. + * @param executor the {@code Executor} that rejected the task + * @param task the task object that got rejected + * @param cause the original {@link RejectedExecutionException} + * @since 6.1 + * @see ExecutorService#isShutdown() + * @see java.util.concurrent.RejectedExecutionException + */ + public TaskRejectedException(Executor executor, Object task, RejectedExecutionException cause) { + super(executorDescription(executor) + " did not accept task: " + task, cause); + } + + + private static String executorDescription(Executor executor) { + if (executor instanceof ExecutorService executorService) { + return "ExecutorService in " + (executorService.isShutdown() ? "shutdown" : "active") + " state"; + } + return executor.toString(); + } + } 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 ef2f6388a932..c7085ffa75ff 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 @@ -93,8 +93,7 @@ public void execute(Runnable task) { doExecute(this.concurrentExecutor, this.taskDecorator, task); } catch (RejectedExecutionException ex) { - throw new TaskRejectedException( - "Executor [" + this.concurrentExecutor + "] did not accept task: " + task, ex); + throw new TaskRejectedException(this.concurrentExecutor, task, ex); } } @@ -112,8 +111,7 @@ public Future submit(Runnable task) { } } catch (RejectedExecutionException ex) { - throw new TaskRejectedException( - "Executor [" + this.concurrentExecutor + "] did not accept task: " + task, ex); + throw new TaskRejectedException(this.concurrentExecutor, task, ex); } } @@ -131,8 +129,7 @@ public Future submit(Callable task) { } } catch (RejectedExecutionException ex) { - throw new TaskRejectedException( - "Executor [" + this.concurrentExecutor + "] did not accept task: " + task, ex); + throw new TaskRejectedException(this.concurrentExecutor, task, ex); } } @@ -144,8 +141,7 @@ public ListenableFuture submitListenable(Runnable task) { return future; } catch (RejectedExecutionException ex) { - throw new TaskRejectedException( - "Executor [" + this.concurrentExecutor + "] did not accept task: " + task, ex); + throw new TaskRejectedException(this.concurrentExecutor, task, ex); } } @@ -157,8 +153,7 @@ public ListenableFuture submitListenable(Callable task) { return future; } catch (RejectedExecutionException ex) { - throw new TaskRejectedException( - "Executor [" + this.concurrentExecutor + "] did not accept task: " + task, ex); + throw new TaskRejectedException(this.concurrentExecutor, task, ex); } }