Skip to content

Commit 2c7e866

Browse files
committed
Respect TaskDecorator configuration on DefaultManagedTaskExecutor
Closes gh-30442
1 parent c09055b commit 2c7e866

File tree

3 files changed

+51
-11
lines changed

3 files changed

+51
-11
lines changed

spring-context/src/main/java/org/springframework/scheduling/concurrent/ConcurrentTaskExecutor.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ public class ConcurrentTaskExecutor implements AsyncListenableTaskExecutor, Sche
8484

8585
private TaskExecutorAdapter adaptedExecutor;
8686

87+
@Nullable
88+
private TaskDecorator taskDecorator;
89+
8790

8891
/**
8992
* Create a new ConcurrentTaskExecutor, using a single thread executor as default.
@@ -139,6 +142,7 @@ public final Executor getConcurrentExecutor() {
139142
* @since 4.3
140143
*/
141144
public final void setTaskDecorator(TaskDecorator taskDecorator) {
145+
this.taskDecorator = taskDecorator;
142146
this.adaptedExecutor.setTaskDecorator(taskDecorator);
143147
}
144148

@@ -175,11 +179,15 @@ public <T> ListenableFuture<T> submitListenable(Callable<T> task) {
175179
}
176180

177181

178-
private static TaskExecutorAdapter getAdaptedExecutor(Executor concurrentExecutor) {
182+
private TaskExecutorAdapter getAdaptedExecutor(Executor concurrentExecutor) {
179183
if (managedExecutorServiceClass != null && managedExecutorServiceClass.isInstance(concurrentExecutor)) {
180184
return new ManagedTaskExecutorAdapter(concurrentExecutor);
181185
}
182-
return new TaskExecutorAdapter(concurrentExecutor);
186+
TaskExecutorAdapter adapter = new TaskExecutorAdapter(concurrentExecutor);
187+
if (this.taskDecorator != null) {
188+
adapter.setTaskDecorator(this.taskDecorator);
189+
}
190+
return adapter;
183191
}
184192

185193

spring-context/src/main/java/org/springframework/scheduling/concurrent/ConcurrentTaskScheduler.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ public class ConcurrentTaskScheduler extends ConcurrentTaskExecutor implements T
103103
*/
104104
public ConcurrentTaskScheduler() {
105105
super();
106-
this.scheduledExecutor = initScheduledExecutor(null);
106+
initScheduledExecutor(null);
107107
}
108108

109109
/**
@@ -118,7 +118,7 @@ public ConcurrentTaskScheduler() {
118118
*/
119119
public ConcurrentTaskScheduler(ScheduledExecutorService scheduledExecutor) {
120120
super(scheduledExecutor);
121-
this.scheduledExecutor = initScheduledExecutor(scheduledExecutor);
121+
initScheduledExecutor(scheduledExecutor);
122122
}
123123

124124
/**
@@ -134,11 +134,11 @@ public ConcurrentTaskScheduler(ScheduledExecutorService scheduledExecutor) {
134134
*/
135135
public ConcurrentTaskScheduler(Executor concurrentExecutor, ScheduledExecutorService scheduledExecutor) {
136136
super(concurrentExecutor);
137-
this.scheduledExecutor = initScheduledExecutor(scheduledExecutor);
137+
initScheduledExecutor(scheduledExecutor);
138138
}
139139

140140

141-
private ScheduledExecutorService initScheduledExecutor(@Nullable ScheduledExecutorService scheduledExecutor) {
141+
private void initScheduledExecutor(@Nullable ScheduledExecutorService scheduledExecutor) {
142142
if (scheduledExecutor != null) {
143143
this.scheduledExecutor = scheduledExecutor;
144144
this.enterpriseConcurrentScheduler = (managedScheduledExecutorServiceClass != null &&
@@ -148,7 +148,6 @@ private ScheduledExecutorService initScheduledExecutor(@Nullable ScheduledExecut
148148
this.scheduledExecutor = Executors.newSingleThreadScheduledExecutor();
149149
this.enterpriseConcurrentScheduler = false;
150150
}
151-
return this.scheduledExecutor;
152151
}
153152

154153
/**

spring-context/src/test/java/org/springframework/scheduling/concurrent/ConcurrentTaskExecutorTests.java

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2022 the original author or authors.
2+
* Copyright 2002-2023 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.scheduling.concurrent;
1818

19+
import java.util.concurrent.Executor;
1920
import java.util.concurrent.LinkedBlockingQueue;
2021
import java.util.concurrent.RunnableFuture;
2122
import java.util.concurrent.ThreadPoolExecutor;
@@ -25,6 +26,8 @@
2526
import org.junit.jupiter.api.Test;
2627

2728
import org.springframework.core.task.NoOpRunnable;
29+
import org.springframework.core.task.TaskDecorator;
30+
import org.springframework.util.Assert;
2831

2932
import static org.assertj.core.api.Assertions.assertThatCode;
3033

@@ -38,8 +41,8 @@ class ConcurrentTaskExecutorTests extends AbstractSchedulingTaskExecutorTests {
3841
new ThreadPoolExecutor(1, 1, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
3942

4043

41-
@Override
4244
@SuppressWarnings("deprecation")
45+
@Override
4346
protected org.springframework.core.task.AsyncListenableTaskExecutor buildExecutor() {
4447
concurrentExecutor.setThreadFactory(new CustomizableThreadFactory(this.threadNamePrefix));
4548
return new ConcurrentTaskExecutor(concurrentExecutor);
@@ -69,10 +72,40 @@ void passingNullExecutorToCtorResultsInDefaultTaskExecutorBeingUsed() {
6972
}
7073

7174
@Test
72-
void passingNullExecutorToSetterResultsInDefaultTaskExecutorBeingUsed() {
75+
void earlySetConcurrentExecutorCallRespectsConfiguredTaskDecorator() {
7376
ConcurrentTaskExecutor executor = new ConcurrentTaskExecutor();
74-
executor.setConcurrentExecutor(null);
77+
executor.setConcurrentExecutor(new DecoratedExecutor());
78+
executor.setTaskDecorator(new RunnableDecorator());
7579
assertThatCode(() -> executor.execute(new NoOpRunnable())).doesNotThrowAnyException();
7680
}
7781

82+
@Test
83+
void lateSetConcurrentExecutorCallRespectsConfiguredTaskDecorator() {
84+
ConcurrentTaskExecutor executor = new ConcurrentTaskExecutor();
85+
executor.setTaskDecorator(new RunnableDecorator());
86+
executor.setConcurrentExecutor(new DecoratedExecutor());
87+
assertThatCode(() -> executor.execute(new NoOpRunnable())).doesNotThrowAnyException();
88+
}
89+
90+
91+
private static class DecoratedRunnable implements Runnable {
92+
@Override
93+
public void run() {
94+
}
95+
}
96+
97+
private static class RunnableDecorator implements TaskDecorator {
98+
@Override
99+
public Runnable decorate(Runnable runnable) {
100+
return new DecoratedRunnable();
101+
}
102+
}
103+
104+
private static class DecoratedExecutor implements Executor {
105+
@Override
106+
public void execute(Runnable command) {
107+
Assert.state(command instanceof DecoratedRunnable, "TaskDecorator not applied");
108+
}
109+
}
110+
78111
}

0 commit comments

Comments
 (0)