Skip to content

Commit e950a35

Browse files
committed
* Add an IntegrationEnvironmentPostProcessor to load a META-INF/spring.integration.properties
file and register it as an origin resource for mapped `IntegrationProperties` from it and as the last one letting the properties from a general Spring Boot environment to win
1 parent 777dcbb commit e950a35

File tree

4 files changed

+138
-46
lines changed

4 files changed

+138
-46
lines changed

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/integration/IntegrationAutoConfiguration.java

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@ public class IntegrationAutoConfiguration {
8484

8585
@Bean(name = IntegrationContextUtils.INTEGRATION_GLOBAL_PROPERTIES_BEAN_NAME)
8686
@ConditionalOnMissingBean(name = IntegrationContextUtils.INTEGRATION_GLOBAL_PROPERTIES_BEAN_NAME)
87-
@Conditional(NoSpringIntegrationPropertiesFile.class)
8887
public static org.springframework.integration.context.IntegrationProperties integrationGlobalProperties(
8988
IntegrationProperties properties) {
9089
org.springframework.integration.context.IntegrationProperties integrationProperties = new org.springframework.integration.context.IntegrationProperties();
@@ -100,19 +99,6 @@ public static org.springframework.integration.context.IntegrationProperties inte
10099
return integrationProperties;
101100
}
102101

103-
static class NoSpringIntegrationPropertiesFile extends NoneNestedConditions {
104-
105-
NoSpringIntegrationPropertiesFile() {
106-
super(ConfigurationPhase.REGISTER_BEAN);
107-
}
108-
109-
@ConditionalOnResource(resources = "META-INF/spring.integration.properties")
110-
static class SpringIntegrationPropertiesFile {
111-
112-
}
113-
114-
}
115-
116102
/**
117103
* Basic Spring Integration configuration.
118104
*/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/*
2+
* Copyright 2012-2021 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.autoconfigure.integration;
18+
19+
import java.io.FileNotFoundException;
20+
import java.io.IOException;
21+
import java.util.HashMap;
22+
import java.util.Map;
23+
24+
import org.springframework.boot.SpringApplication;
25+
import org.springframework.boot.env.EnvironmentPostProcessor;
26+
import org.springframework.boot.env.OriginTrackedMapPropertySource;
27+
import org.springframework.boot.env.PropertiesPropertySourceLoader;
28+
import org.springframework.boot.origin.Origin;
29+
import org.springframework.boot.origin.OriginLookup;
30+
import org.springframework.core.Ordered;
31+
import org.springframework.core.env.ConfigurableEnvironment;
32+
import org.springframework.core.env.PropertySource;
33+
import org.springframework.core.io.ClassPathResource;
34+
import org.springframework.core.io.Resource;
35+
import org.springframework.integration.context.IntegrationProperties;
36+
37+
/**
38+
* The {@link EnvironmentPostProcessor} for Spring Integration.
39+
*
40+
* @author Artem Bilan
41+
* @since 2.5
42+
*/
43+
public class IntegrationEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {
44+
45+
@Override
46+
public int getOrder() {
47+
return Ordered.LOWEST_PRECEDENCE;
48+
}
49+
50+
@Override
51+
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
52+
registerIntegrationPropertiesFileSource(environment);
53+
}
54+
55+
private static void registerIntegrationPropertiesFileSource(ConfigurableEnvironment environment) {
56+
Resource integrationPropertiesResource = new ClassPathResource("META-INF/spring.integration.properties");
57+
PropertiesPropertySourceLoader loader = new PropertiesPropertySourceLoader();
58+
try {
59+
OriginTrackedMapPropertySource propertyFileSource = (OriginTrackedMapPropertySource) loader
60+
.load("integration-properties-file", integrationPropertiesResource).get(0);
61+
62+
environment.getPropertySources().addLast(new IntegrationPropertySource(propertyFileSource));
63+
}
64+
catch (FileNotFoundException ex) {
65+
// Ignore when no META-INF/spring.integration.properties file in classpath
66+
}
67+
catch (IOException ex) {
68+
throw new IllegalStateException(
69+
"Failed to load integration properties from " + integrationPropertiesResource, ex);
70+
}
71+
}
72+
73+
private static final class IntegrationPropertySource extends PropertySource<Map<String, Object>>
74+
implements OriginLookup<String> {
75+
76+
private static final String PREFIX = "spring.integration.";
77+
78+
private static final Map<String, String> KEYS_MAPPING = new HashMap<>();
79+
80+
static {
81+
KEYS_MAPPING.put(PREFIX + "channels.auto-create", IntegrationProperties.CHANNELS_AUTOCREATE);
82+
KEYS_MAPPING.put(PREFIX + "channels.max-unicast-subscribers",
83+
IntegrationProperties.CHANNELS_MAX_UNICAST_SUBSCRIBERS);
84+
KEYS_MAPPING.put(PREFIX + "channels.max-broadcast-subscribers",
85+
IntegrationProperties.CHANNELS_MAX_BROADCAST_SUBSCRIBERS);
86+
KEYS_MAPPING.put(PREFIX + "channels.error-require-subscribers",
87+
IntegrationProperties.ERROR_CHANNEL_REQUIRE_SUBSCRIBERS);
88+
KEYS_MAPPING.put(PREFIX + "channels.error-ignore-failures",
89+
IntegrationProperties.ERROR_CHANNEL_IGNORE_FAILURES);
90+
KEYS_MAPPING.put(PREFIX + "endpoints.throw-exception-on-late-reply",
91+
IntegrationProperties.THROW_EXCEPTION_ON_LATE_REPLY);
92+
KEYS_MAPPING.put(PREFIX + "endpoints.read-only-headers", IntegrationProperties.READ_ONLY_HEADERS);
93+
KEYS_MAPPING.put(PREFIX + "endpoints.no-auto-startup", IntegrationProperties.ENDPOINTS_NO_AUTO_STARTUP);
94+
}
95+
96+
private final OriginTrackedMapPropertySource origin;
97+
98+
IntegrationPropertySource(OriginTrackedMapPropertySource origin) {
99+
super("original-integration-properties", origin.getSource());
100+
this.origin = origin;
101+
}
102+
103+
@Override
104+
public Object getProperty(String name) {
105+
return this.origin.getProperty(KEYS_MAPPING.get(name));
106+
}
107+
108+
@Override
109+
public Origin getOrigin(String key) {
110+
return this.origin.getOrigin(KEYS_MAPPING.get(name));
111+
}
112+
113+
}
114+
115+
}

spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingL
77
org.springframework.context.ApplicationListener=\
88
org.springframework.boot.autoconfigure.BackgroundPreinitializer
99

10+
# Environment Post Processors
11+
org.springframework.boot.env.EnvironmentPostProcessor=\
12+
org.springframework.boot.autoconfigure.integration.IntegrationEnvironmentPostProcessor
13+
1014
# Auto Configuration Import Listeners
1115
org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\
1216
org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/integration/IntegrationAutoConfigurationTests.java

Lines changed: 19 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,18 @@
1616

1717
package org.springframework.boot.autoconfigure.integration;
1818

19+
import static org.assertj.core.api.Assertions.assertThat;
20+
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
21+
import static org.mockito.Mockito.mock;
22+
1923
import java.io.File;
2024
import java.util.Arrays;
2125
import java.util.List;
2226

2327
import javax.management.MBeanServer;
2428

25-
import io.rsocket.transport.ClientTransport;
26-
import io.rsocket.transport.netty.client.TcpClientTransport;
2729
import org.assertj.core.api.InstanceOfAssertFactories;
2830
import org.junit.jupiter.api.Test;
29-
import reactor.core.publisher.Mono;
3031

3132
import org.springframework.beans.DirectFieldAccessor;
3233
import org.springframework.boot.autoconfigure.AutoConfigurations;
@@ -74,9 +75,9 @@
7475
import org.springframework.messaging.rsocket.annotation.support.RSocketMessageHandler;
7576
import org.springframework.scheduling.TaskScheduler;
7677

77-
import static org.assertj.core.api.Assertions.assertThat;
78-
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
79-
import static org.mockito.Mockito.mock;
78+
import io.rsocket.transport.ClientTransport;
79+
import io.rsocket.transport.netty.client.TcpClientTransport;
80+
import reactor.core.publisher.Mono;
8081

8182
/**
8283
* Tests for {@link IntegrationAutoConfiguration}.
@@ -280,7 +281,10 @@ void integrationGlobalPropertiesAutoConfigured() {
280281
"spring.integration.endpoints.throw-exception-on-late-reply=true",
281282
"spring.integration.endpoints.read-only-headers=ignoredHeader",
282283
"spring.integration.endpoints.no-auto-startup=notStartedEndpoint,_org.springframework.integration.errorLogger")
283-
.withBean("testDirectChannel", DirectChannel.class).run((context) -> {
284+
.withBean("testDirectChannel", DirectChannel.class)
285+
.withInitializer((applicationContext) -> new IntegrationEnvironmentPostProcessor()
286+
.postProcessEnvironment(applicationContext.getEnvironment(), null))
287+
.run((context) -> {
284288
assertThat(context)
285289
.getBean(IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME, PublishSubscribeChannel.class)
286290
.hasFieldOrPropertyWithValue("requireSubscribers", false)
@@ -321,6 +325,8 @@ void integrationGlobalPropertiesUserBeanOverridesAutoConfiguration() {
321325
properties.setChannelsMaxUnicastSubscribers(5);
322326
return properties;
323327
})
328+
.withInitializer((applicationContext) -> new IntegrationEnvironmentPostProcessor()
329+
.postProcessEnvironment(applicationContext.getEnvironment(), null))
324330
.run((context) -> assertThat(context).getBean(LoggingHandler.class)
325331
.extracting("integrationProperties", InstanceOfAssertFactories.MAP)
326332
.containsEntry(
@@ -353,38 +359,19 @@ void integrationGlobalPropertiesFromSpringIntegrationPropertiesFile() {
353359
// See META-INF/spring.integration.properties
354360
this.contextRunner
355361
.withPropertyValues("spring.integration.channels.auto-create=false",
356-
"spring.integration.channels.max-unicast-subscribers=2",
357-
"spring.integration.channels.max-broadcast-subscribers=3",
358-
"spring.integration.channels.error-require-subscribers=false",
359-
"spring.integration.channels.error-ignore-failures=false",
360-
"spring.integration.endpoints.throw-exception-on-late-reply=true",
361-
"spring.integration.endpoints.read-only-headers=ignoredHeader",
362-
"spring.integration.endpoints.no-auto-startup=notStartedEndpoint")
362+
"spring.integration.endpoints.read-only-headers=ignoredHeader")
363+
.withInitializer((applicationContext) -> new IntegrationEnvironmentPostProcessor()
364+
.postProcessEnvironment(applicationContext.getEnvironment(), null))
363365
.run((context) -> assertThat(context).getBean(LoggingHandler.class)
364366
.extracting("integrationProperties", InstanceOfAssertFactories.MAP)
365367
.containsEntry(
366368
org.springframework.integration.context.IntegrationProperties.CHANNELS_AUTOCREATE,
367-
"true")
368-
.containsEntry(
369-
org.springframework.integration.context.IntegrationProperties.ERROR_CHANNEL_REQUIRE_SUBSCRIBERS,
370-
"true")
371-
.containsEntry(
372-
org.springframework.integration.context.IntegrationProperties.ERROR_CHANNEL_IGNORE_FAILURES,
373-
"true")
374-
.containsEntry(
375-
org.springframework.integration.context.IntegrationProperties.THROW_EXCEPTION_ON_LATE_REPLY,
376369
"false")
377-
.containsEntry(
378-
org.springframework.integration.context.IntegrationProperties.CHANNELS_MAX_UNICAST_SUBSCRIBERS,
379-
"2147483647")
380-
.containsEntry(
381-
org.springframework.integration.context.IntegrationProperties.CHANNELS_MAX_BROADCAST_SUBSCRIBERS,
382-
"2147483647")
370+
.containsEntry(org.springframework.integration.context.IntegrationProperties.READ_ONLY_HEADERS,
371+
"ignoredHeader")
383372
.containsEntry(
384373
org.springframework.integration.context.IntegrationProperties.ENDPOINTS_NO_AUTO_STARTUP,
385-
"testService*")
386-
.containsEntry(org.springframework.integration.context.IntegrationProperties.READ_ONLY_HEADERS,
387-
""));
374+
"testService*"));
388375
}
389376

390377
@Configuration(proxyBeanMethods = false)

0 commit comments

Comments
 (0)