• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

TAKETODAY / today-infrastructure / 18154768944

01 Oct 2025 07:26AM UTC coverage: 81.882% (-0.005%) from 81.887%
18154768944

push

github

web-flow
Merge pull request #290 from TAKETODAY/dev/jspecify

jspecify

59788 of 78013 branches covered (76.64%)

Branch coverage included in aggregate %.

141239 of 167496 relevant lines covered (84.32%)

3.6 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.38
today-context/src/main/java/infra/scheduling/support/SimpleAsyncTaskExecutorBuilder.java
1
/*
2
 * Copyright 2017 - 2025 the original author or authors.
3
 *
4
 * This program is free software: you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License as published by
6
 * the Free Software Foundation, either version 3 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program. If not, see [https://www.gnu.org/licenses/]
16
 */
17

18
package infra.scheduling.support;
19

20
import org.jspecify.annotations.Nullable;
21

22
import java.time.Duration;
23
import java.util.Arrays;
24
import java.util.Collections;
25
import java.util.LinkedHashSet;
26
import java.util.Set;
27

28
import infra.beans.BeanUtils;
29
import infra.core.task.SimpleAsyncTaskExecutor;
30
import infra.core.task.TaskDecorator;
31
import infra.lang.Assert;
32
import infra.util.CollectionUtils;
33

34
/**
35
 * Builder that can be used to configure and create a {@link SimpleAsyncTaskExecutor}.
36
 * Provides convenience methods to set common {@link SimpleAsyncTaskExecutor} settings and
37
 * register {@link #taskDecorator(TaskDecorator)}). For advanced configuration, consider
38
 * using {@link SimpleAsyncTaskExecutorCustomizer}.
39
 * <p>
40
 * In a typical auto-configured Infra application this builder is available as a
41
 * bean and can be injected whenever a {@link SimpleAsyncTaskExecutor} is needed.
42
 *
43
 * @author Stephane Nicoll
44
 * @author Filip Hrisafov
45
 * @author Moritz Halbritter
46
 * @author <a href="https://github.com/TAKETODAY">Harry Yang</a>
47
 * @since 4.0
48
 */
49
public class SimpleAsyncTaskExecutorBuilder {
50

51
  @Nullable
52
  private final Boolean virtualThreads;
53

54
  @Nullable
55
  private final String threadNamePrefix;
56

57
  @Nullable
58
  private final Integer concurrencyLimit;
59

60
  @Nullable
61
  private final TaskDecorator taskDecorator;
62

63
  @Nullable
64
  private final Set<SimpleAsyncTaskExecutorCustomizer> customizers;
65

66
  @Nullable
67
  private final Duration taskTerminationTimeout;
68

69
  public SimpleAsyncTaskExecutorBuilder() {
70
    this(null, null, null, null, null, null);
8✔
71
  }
1✔
72

73
  private SimpleAsyncTaskExecutorBuilder(@Nullable Boolean virtualThreads, @Nullable String threadNamePrefix, @Nullable Integer concurrencyLimit,
74
          @Nullable TaskDecorator taskDecorator, @Nullable Set<SimpleAsyncTaskExecutorCustomizer> customizers, @Nullable Duration taskTerminationTimeout) {
2✔
75
    this.virtualThreads = virtualThreads;
3✔
76
    this.threadNamePrefix = threadNamePrefix;
3✔
77
    this.concurrencyLimit = concurrencyLimit;
3✔
78
    this.taskDecorator = taskDecorator;
3✔
79
    this.customizers = customizers;
3✔
80
    this.taskTerminationTimeout = taskTerminationTimeout;
3✔
81
  }
1✔
82

83
  /**
84
   * Set the prefix to use for the names of newly created threads.
85
   *
86
   * @param threadNamePrefix the thread name prefix to set
87
   * @return a new builder instance
88
   */
89
  public SimpleAsyncTaskExecutorBuilder threadNamePrefix(String threadNamePrefix) {
90
    return new SimpleAsyncTaskExecutorBuilder(this.virtualThreads, threadNamePrefix, this.concurrencyLimit,
15✔
91
            this.taskDecorator, this.customizers, this.taskTerminationTimeout);
92
  }
93

94
  /**
95
   * Set whether to use virtual threads.
96
   *
97
   * @param virtualThreads whether to use virtual threads
98
   * @return a new builder instance
99
   */
100
  public SimpleAsyncTaskExecutorBuilder virtualThreads(Boolean virtualThreads) {
101
    return new SimpleAsyncTaskExecutorBuilder(virtualThreads, this.threadNamePrefix, this.concurrencyLimit,
15✔
102
            this.taskDecorator, this.customizers, this.taskTerminationTimeout);
103
  }
104

105
  /**
106
   * Set the concurrency limit.
107
   *
108
   * @param concurrencyLimit the concurrency limit
109
   * @return a new builder instance
110
   */
111
  public SimpleAsyncTaskExecutorBuilder concurrencyLimit(@Nullable Integer concurrencyLimit) {
112
    return new SimpleAsyncTaskExecutorBuilder(this.virtualThreads, this.threadNamePrefix, concurrencyLimit,
15✔
113
            this.taskDecorator, this.customizers, this.taskTerminationTimeout);
114
  }
115

116
  /**
117
   * Set the {@link TaskDecorator} to use or {@code null} to not use any.
118
   *
119
   * @param taskDecorator the task decorator to use
120
   * @return a new builder instance
121
   */
122
  public SimpleAsyncTaskExecutorBuilder taskDecorator(@Nullable TaskDecorator taskDecorator) {
123
    return new SimpleAsyncTaskExecutorBuilder(this.virtualThreads, this.threadNamePrefix, this.concurrencyLimit,
15✔
124
            taskDecorator, this.customizers, this.taskTerminationTimeout);
125
  }
126

127
  /**
128
   * Set the task termination timeout.
129
   *
130
   * @param taskTerminationTimeout the task termination timeout
131
   * @return a new builder instance
132
   */
133
  public SimpleAsyncTaskExecutorBuilder taskTerminationTimeout(@Nullable Duration taskTerminationTimeout) {
134
    return new SimpleAsyncTaskExecutorBuilder(this.virtualThreads, this.threadNamePrefix, this.concurrencyLimit,
15✔
135
            this.taskDecorator, this.customizers, taskTerminationTimeout);
136
  }
137

138
  /**
139
   * Set the {@link SimpleAsyncTaskExecutorCustomizer customizers} that should be
140
   * applied to the {@link SimpleAsyncTaskExecutor}. Customizers are applied in the
141
   * order that they were added after builder configuration has been applied. Setting
142
   * this value will replace any previously configured customizers.
143
   *
144
   * @param customizers the customizers to set
145
   * @return a new builder instance
146
   * @see #additionalCustomizers(SimpleAsyncTaskExecutorCustomizer...)
147
   */
148
  public SimpleAsyncTaskExecutorBuilder customizers(SimpleAsyncTaskExecutorCustomizer... customizers) {
149
    Assert.notNull(customizers, "Customizers is required");
3✔
150
    return customizers(Arrays.asList(customizers));
5✔
151
  }
152

153
  /**
154
   * Set the {@link SimpleAsyncTaskExecutorCustomizer customizers} that should be
155
   * applied to the {@link SimpleAsyncTaskExecutor}. Customizers are applied in the
156
   * order that they were added after builder configuration has been applied. Setting
157
   * this value will replace any previously configured customizers.
158
   *
159
   * @param customizers the customizers to set
160
   * @return a new builder instance
161
   * @see #additionalCustomizers(Iterable)
162
   */
163
  public SimpleAsyncTaskExecutorBuilder customizers(Iterable<? extends SimpleAsyncTaskExecutorCustomizer> customizers) {
164
    Assert.notNull(customizers, "Customizers is required");
3✔
165
    return new SimpleAsyncTaskExecutorBuilder(this.virtualThreads, this.threadNamePrefix, this.concurrencyLimit,
14✔
166
            this.taskDecorator, append(null, customizers), this.taskTerminationTimeout);
4✔
167
  }
168

169
  /**
170
   * Add {@link SimpleAsyncTaskExecutorCustomizer customizers} that should be applied to
171
   * the {@link SimpleAsyncTaskExecutor}. Customizers are applied in the order that they
172
   * were added after builder configuration has been applied.
173
   *
174
   * @param customizers the customizers to add
175
   * @return a new builder instance
176
   * @see #customizers(SimpleAsyncTaskExecutorCustomizer...)
177
   */
178
  public SimpleAsyncTaskExecutorBuilder additionalCustomizers(SimpleAsyncTaskExecutorCustomizer... customizers) {
179
    Assert.notNull(customizers, "Customizers is required");
3✔
180
    return additionalCustomizers(Arrays.asList(customizers));
5✔
181
  }
182

183
  /**
184
   * Add {@link SimpleAsyncTaskExecutorCustomizer customizers} that should be applied to
185
   * the {@link SimpleAsyncTaskExecutor}. Customizers are applied in the order that they
186
   * were added after builder configuration has been applied.
187
   *
188
   * @param customizers the customizers to add
189
   * @return a new builder instance
190
   * @see #customizers(Iterable)
191
   */
192
  public SimpleAsyncTaskExecutorBuilder additionalCustomizers(Iterable<? extends SimpleAsyncTaskExecutorCustomizer> customizers) {
193
    Assert.notNull(customizers, "Customizers is required");
3✔
194
    return new SimpleAsyncTaskExecutorBuilder(this.virtualThreads, this.threadNamePrefix, this.concurrencyLimit,
15✔
195
            this.taskDecorator, append(this.customizers, customizers), this.taskTerminationTimeout);
4✔
196
  }
197

198
  /**
199
   * Build a new {@link SimpleAsyncTaskExecutor} instance and configure it using this
200
   * builder.
201
   *
202
   * @return a configured {@link SimpleAsyncTaskExecutor} instance.
203
   * @see #build(Class)
204
   * @see #configure(SimpleAsyncTaskExecutor)
205
   */
206
  public SimpleAsyncTaskExecutor build() {
207
    return configure(new SimpleAsyncTaskExecutor());
6✔
208
  }
209

210
  /**
211
   * Build a new {@link SimpleAsyncTaskExecutor} instance of the specified type and
212
   * configure it using this builder.
213
   *
214
   * @param <T> the type of task executor
215
   * @param taskExecutorClass the template type to create
216
   * @return a configured {@link SimpleAsyncTaskExecutor} instance.
217
   * @see #build()
218
   * @see #configure(SimpleAsyncTaskExecutor)
219
   */
220
  public <T extends SimpleAsyncTaskExecutor> T build(Class<T> taskExecutorClass) {
221
    return configure(BeanUtils.newInstance(taskExecutorClass));
×
222
  }
223

224
  /**
225
   * Configure the provided {@link SimpleAsyncTaskExecutor} instance using this builder.
226
   *
227
   * @param <T> the type of task executor
228
   * @param taskExecutor the {@link SimpleAsyncTaskExecutor} to configure
229
   * @return the task executor instance
230
   * @see #build()
231
   * @see #build(Class)
232
   */
233
  public <T extends SimpleAsyncTaskExecutor> T configure(T taskExecutor) {
234
    if (threadNamePrefix != null) {
3✔
235
      taskExecutor.setThreadNamePrefix(threadNamePrefix);
4✔
236
    }
237
    if (concurrencyLimit != null) {
3✔
238
      taskExecutor.setConcurrencyLimit(concurrencyLimit);
5✔
239
    }
240
    if (virtualThreads != null) {
3!
241
      taskExecutor.setVirtualThreads(virtualThreads);
×
242
    }
243
    if (taskDecorator != null) {
3✔
244
      taskExecutor.setTaskDecorator(taskDecorator);
4✔
245
    }
246
    if (taskTerminationTimeout != null) {
3✔
247
      taskExecutor.setTaskTerminationTimeout(taskTerminationTimeout.toMillis());
5✔
248
    }
249

250
    if (CollectionUtils.isNotEmpty(customizers)) {
4✔
251
      for (SimpleAsyncTaskExecutorCustomizer customizer : customizers) {
11✔
252
        customizer.customize(taskExecutor);
3✔
253
      }
1✔
254
    }
255
    return taskExecutor;
2✔
256
  }
257

258
  private <T> Set<T> append(@Nullable Set<T> set, Iterable<? extends T> additions) {
259
    LinkedHashSet<T> result = new LinkedHashSet<>((set != null) ? set : Collections.emptySet());
9✔
260
    for (T addition : additions) {
9✔
261
      result.add(addition);
4✔
262
    }
1✔
263
    return Collections.unmodifiableSet(result);
3✔
264
  }
265

266
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc