Skip to content

Commit 1dbe0ee

Browse files
committed
Respect TaskDecorator configuration on DefaultManagedTaskExecutor
Closes gh-30442
1 parent 0211016 commit 1dbe0ee

File tree

3 files changed

+52
-12
lines changed

3 files changed

+52
-12
lines changed

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

+11-3
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.
@@ -83,6 +83,9 @@ public class ConcurrentTaskExecutor implements AsyncListenableTaskExecutor, Sche
8383

8484
private TaskExecutorAdapter adaptedExecutor;
8585

86+
@Nullable
87+
private TaskDecorator taskDecorator;
88+
8689

8790
/**
8891
* Create a new ConcurrentTaskExecutor, using a single thread executor as default.
@@ -138,6 +141,7 @@ public final Executor getConcurrentExecutor() {
138141
* @since 4.3
139142
*/
140143
public final void setTaskDecorator(TaskDecorator taskDecorator) {
144+
this.taskDecorator = taskDecorator;
141145
this.adaptedExecutor.setTaskDecorator(taskDecorator);
142146
}
143147

@@ -174,11 +178,15 @@ public <T> ListenableFuture<T> submitListenable(Callable<T> task) {
174178
}
175179

176180

177-
private static TaskExecutorAdapter getAdaptedExecutor(Executor concurrentExecutor) {
181+
private TaskExecutorAdapter getAdaptedExecutor(Executor concurrentExecutor) {
178182
if (managedExecutorServiceClass != null && managedExecutorServiceClass.isInstance(concurrentExecutor)) {
179183
return new ManagedTaskExecutorAdapter(concurrentExecutor);
180184
}
181-
return new TaskExecutorAdapter(concurrentExecutor);
185+
TaskExecutorAdapter adapter = new TaskExecutorAdapter(concurrentExecutor);
186+
if (this.taskDecorator != null) {
187+
adapter.setTaskDecorator(this.taskDecorator);
188+
}
189+
return adapter;
182190
}
183191

184192

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

+5-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2020 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.
@@ -100,7 +100,7 @@ public class ConcurrentTaskScheduler extends ConcurrentTaskExecutor implements T
100100
*/
101101
public ConcurrentTaskScheduler() {
102102
super();
103-
this.scheduledExecutor = initScheduledExecutor(null);
103+
initScheduledExecutor(null);
104104
}
105105

106106
/**
@@ -115,7 +115,7 @@ public ConcurrentTaskScheduler() {
115115
*/
116116
public ConcurrentTaskScheduler(ScheduledExecutorService scheduledExecutor) {
117117
super(scheduledExecutor);
118-
this.scheduledExecutor = initScheduledExecutor(scheduledExecutor);
118+
initScheduledExecutor(scheduledExecutor);
119119
}
120120

121121
/**
@@ -131,11 +131,11 @@ public ConcurrentTaskScheduler(ScheduledExecutorService scheduledExecutor) {
131131
*/
132132
public ConcurrentTaskScheduler(Executor concurrentExecutor, ScheduledExecutorService scheduledExecutor) {
133133
super(concurrentExecutor);
134-
this.scheduledExecutor = initScheduledExecutor(scheduledExecutor);
134+
initScheduledExecutor(scheduledExecutor);
135135
}
136136

137137

138-
private ScheduledExecutorService initScheduledExecutor(@Nullable ScheduledExecutorService scheduledExecutor) {
138+
private void initScheduledExecutor(@Nullable ScheduledExecutorService scheduledExecutor) {
139139
if (scheduledExecutor != null) {
140140
this.scheduledExecutor = scheduledExecutor;
141141
this.enterpriseConcurrentScheduler = (managedScheduledExecutorServiceClass != null &&
@@ -145,7 +145,6 @@ private ScheduledExecutorService initScheduledExecutor(@Nullable ScheduledExecut
145145
this.scheduledExecutor = Executors.newSingleThreadScheduledExecutor();
146146
this.enterpriseConcurrentScheduler = false;
147147
}
148-
return this.scheduledExecutor;
149148
}
150149

151150
/**

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

+36-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2020 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;
@@ -26,6 +27,8 @@
2627

2728
import org.springframework.core.task.AsyncListenableTaskExecutor;
2829
import org.springframework.core.task.NoOpRunnable;
30+
import org.springframework.core.task.TaskDecorator;
31+
import org.springframework.util.Assert;
2932

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

@@ -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)