Skip to content

Commit b1faaa3

Browse files
committed
GH-9878: Fix ConcurrentModificationException in SpringIntegrationTestExecutionListener
Fixes: gh-9878 * return new list in MockIntegrationContext.getAutoStartupCandidates() Signed-off-by: Alexander Hain <[email protected]>
1 parent 7993e3c commit b1faaa3

File tree

1 file changed

+26
-26
lines changed

1 file changed

+26
-26
lines changed

spring-integration-test/src/main/java/org/springframework/integration/test/context/MockIntegrationContext.java

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2017-2024 the original author or authors.
2+
* Copyright 2017-2025 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.
@@ -19,6 +19,7 @@
1919
import java.util.ArrayList;
2020
import java.util.Arrays;
2121
import java.util.Collection;
22+
import java.util.Collections;
2223
import java.util.List;
2324

2425
import reactor.core.publisher.Mono;
@@ -59,6 +60,7 @@
5960
*
6061
* @author Artem Bilan
6162
* @author Yicheng Feng
63+
* @author Alexander Hain
6264
*
6365
* @since 5.0
6466
*
@@ -111,21 +113,21 @@ public void afterSingletonsInstantiated() {
111113
}
112114

113115
List<AbstractEndpoint> getAutoStartupCandidates() {
114-
return this.autoStartupCandidates;
116+
return Collections.unmodifiableList(this.autoStartupCandidates);
115117
}
116118

117119
/**
118120
* Reinstate the mocked beans after execution test to their real state.
119121
* Typically, this method is used from JUnit clean up methods.
122+
*
120123
* @param beanNames the bean names to reset.
121-
* If {@code null}, all the mocked beans are reset
124+
* If {@code null}, all the mocked beans are reset
122125
*/
123126
public void resetBeans(String... beanNames) {
124127
final Collection<String> names;
125128
if (!ObjectUtils.isEmpty(beanNames)) {
126129
names = Arrays.asList(beanNames);
127-
}
128-
else {
130+
} else {
129131
names = null;
130132
}
131133

@@ -142,8 +144,7 @@ public void resetBeans(String... beanNames) {
142144
for (String name : beanNames) {
143145
this.beans.remove(name);
144146
}
145-
}
146-
else {
147+
} else {
147148
this.beans.clear();
148149
}
149150
}
@@ -157,14 +158,11 @@ private void resetBean(Object endpoint, Object component) {
157158
}
158159
if (endpoint instanceof SourcePollingChannelAdapter && component instanceof MessageSource<?>) {
159160
directFieldAccessor.setPropertyValue("source", component);
160-
}
161-
else if (endpoint instanceof IntegrationConsumer && component instanceof MessageHandler) {
161+
} else if (endpoint instanceof IntegrationConsumer && component instanceof MessageHandler) {
162162
directFieldAccessor.setPropertyValue(HANDLER, component);
163-
}
164-
else if (endpoint instanceof ReactiveStreamsConsumer && component instanceof ReactiveMessageHandler) {
163+
} else if (endpoint instanceof ReactiveStreamsConsumer && component instanceof ReactiveMessageHandler) {
165164
directFieldAccessor.setPropertyValue(REACTIVE_MESSAGE_HANDLER, component);
166-
}
167-
else if (component instanceof Trigger) {
165+
} else if (component instanceof Trigger) {
168166
directFieldAccessor.setPropertyValue("trigger", component);
169167
}
170168
if (lifecycle != null && lifecycle.isAutoStartup()) {
@@ -176,7 +174,8 @@ else if (component instanceof Trigger) {
176174
* Replace the real {@link MessageSource} in the {@link SourcePollingChannelAdapter} bean
177175
* with provided {@link MessageSource} instance.
178176
* Can be a mock object.
179-
* @param pollingAdapterId the endpoint bean name
177+
*
178+
* @param pollingAdapterId the endpoint bean name
180179
* @param mockMessageSource the {@link MessageSource} to replace in the endpoint bean
181180
* @see org.springframework.integration.test.mock.MockIntegration#mockMessageSource
182181
*/
@@ -189,13 +188,14 @@ public void substituteMessageSourceFor(String pollingAdapterId, MessageSource<?>
189188
* with provided {@link MessageSource} instance.
190189
* Can be a mock object.
191190
* The endpoint is not started when {@code autoStartup == false}.
192-
* @param pollingAdapterId the endpoint bean name
191+
*
192+
* @param pollingAdapterId the endpoint bean name
193193
* @param mockMessageSource the {@link MessageSource} to replace in the endpoint bean
194-
* @param autoStartup start or not the endpoint after replacing its {@link MessageSource}
194+
* @param autoStartup start or not the endpoint after replacing its {@link MessageSource}
195195
* @see org.springframework.integration.test.mock.MockIntegration#mockMessageSource
196196
*/
197197
public void substituteMessageSourceFor(String pollingAdapterId, MessageSource<?> mockMessageSource,
198-
boolean autoStartup) {
198+
boolean autoStartup) {
199199

200200
substituteComponentFor(pollingAdapterId, mockMessageSource, SourcePollingChannelAdapter.class, "source",
201201
autoStartup);
@@ -206,7 +206,7 @@ public void substituteMessageHandlerFor(String consumerEndpointId, MessageHandle
206206
}
207207

208208
public void substituteMessageHandlerFor(String consumerEndpointId, // NOSONAR - complexity
209-
MessageHandler mockMessageHandler, boolean autoStartup) {
209+
MessageHandler mockMessageHandler, boolean autoStartup) {
210210

211211
Object endpoint = this.beanFactory.getBean(consumerEndpointId, IntegrationConsumer.class);
212212
if (autoStartup && endpoint instanceof Lifecycle lifecycle) {
@@ -227,15 +227,13 @@ public void substituteMessageHandlerFor(String consumerEndpointId, // NOSONAR -
227227
if (targetMessageHandler instanceof MessageProducer messageProducer) {
228228
MessageChannel outputChannel = messageProducer.getOutputChannel();
229229
mockMessageProducer.setOutputChannel(outputChannel);
230-
}
231-
else {
230+
} else {
232231
if (mockMessageHandler instanceof MockMessageHandler) {
233232
if (TestUtils.getPropertyValue(mockMessageHandler, "hasReplies", Boolean.class)) {
234233
throw new IllegalStateException("The [" + mockMessageHandler + "] " +
235234
"with replies can't replace simple MessageHandler [" + targetMessageHandler + "]");
236235
}
237-
}
238-
else {
236+
} else {
239237
throw new IllegalStateException("The MessageProducer handler [" + mockMessageHandler + "] " +
240238
"can't replace simple MessageHandler [" + targetMessageHandler + "]");
241239
}
@@ -257,8 +255,9 @@ public void substituteMessageHandlerFor(String consumerEndpointId, // NOSONAR -
257255

258256
/**
259257
* Replace the real {@link Trigger} in the {@link AbstractPollingEndpoint} bean with provided instance.
258+
*
260259
* @param pollingEndpointId the {@link AbstractPollingEndpoint} bean id to replace
261-
* @param trigger the {@link Trigger} to set into {@link AbstractPollingEndpoint}
260+
* @param trigger the {@link Trigger} to set into {@link AbstractPollingEndpoint}
262261
* @since 6.3
263262
*/
264263
public void substituteTriggerFor(String pollingEndpointId, Trigger trigger) {
@@ -268,17 +267,18 @@ public void substituteTriggerFor(String pollingEndpointId, Trigger trigger) {
268267
/**
269268
* Replace the real {@link Trigger} in the {@link AbstractPollingEndpoint} bean with provided instance.
270269
* The endpoint is not started when {@code autoStartup == false}.
270+
*
271271
* @param pollingEndpointId the {@link AbstractPollingEndpoint} bean id to replace
272-
* @param trigger the {@link Trigger} to set into {@link AbstractPollingEndpoint}
273-
* @param autoStartup start or not the endpoint after replacing its {@link MessageSource}
272+
* @param trigger the {@link Trigger} to set into {@link AbstractPollingEndpoint}
273+
* @param autoStartup start or not the endpoint after replacing its {@link MessageSource}
274274
* @since 6.3
275275
*/
276276
public void substituteTriggerFor(String pollingEndpointId, Trigger trigger, boolean autoStartup) {
277277
substituteComponentFor(pollingEndpointId, trigger, AbstractPollingEndpoint.class, "trigger", autoStartup);
278278
}
279279

280280
private void substituteComponentFor(String endpointId, Object messagingComponent, Class<?> endpointClass,
281-
String property, boolean autoStartup) {
281+
String property, boolean autoStartup) {
282282

283283
Object endpoint = this.beanFactory.getBean(endpointId, endpointClass);
284284
if (autoStartup && endpoint instanceof Lifecycle lifecycle) {

0 commit comments

Comments
 (0)