Skip to content

Commit 499739f

Browse files
authored
Uses BindHandler if registered in bootstrap. (#1773)
* Uses BindHandler if registered in bootstrap. This allows spring-cloud-context to register a TextEncryptorBindHandler and handle `{cipher}` prefixed properties prior to sending for remote data. * Adds test that a BindHandler in bootstrap context is used. * Makes KeyProperties a bean that is conditional on missing.
1 parent f5e5753 commit 499739f

File tree

5 files changed

+53
-13
lines changed

5 files changed

+53
-13
lines changed

spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigServerConfigDataLocationResolver.java

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import org.springframework.boot.context.config.ConfigDataLocationResolverContext;
3333
import org.springframework.boot.context.config.ConfigDataResourceNotFoundException;
3434
import org.springframework.boot.context.config.Profiles;
35+
import org.springframework.boot.context.properties.bind.BindHandler;
3536
import org.springframework.boot.context.properties.bind.Bindable;
3637
import org.springframework.boot.context.properties.bind.Binder;
3738
import org.springframework.core.Ordered;
@@ -61,15 +62,22 @@ public int getOrder() {
6162
return -1;
6263
}
6364

64-
protected ConfigClientProperties loadProperties(Binder binder) {
65+
protected ConfigClientProperties loadProperties(ConfigDataLocationResolverContext context) {
66+
Binder binder = context.getBinder();
67+
BindHandler bindHandler = getBindHandler(context);
6568
ConfigClientProperties configClientProperties = binder
66-
.bind(ConfigClientProperties.PREFIX, Bindable.of(ConfigClientProperties.class))
67-
.orElse(new ConfigClientProperties());
68-
String applicationName = binder.bind("spring.application.name", String.class).orElse("application");
69+
.bind(ConfigClientProperties.PREFIX, Bindable.of(ConfigClientProperties.class), bindHandler)
70+
.orElseGet(ConfigClientProperties::new);
71+
String applicationName = binder.bind("spring.application.name", Bindable.of(String.class), bindHandler)
72+
.orElse("application");
6973
configClientProperties.setName(applicationName);
7074
return configClientProperties;
7175
}
7276

77+
private BindHandler getBindHandler(ConfigDataLocationResolverContext context) {
78+
return context.getBootstrapContext().getOrElse(BindHandler.class, null);
79+
}
80+
7381
protected RestTemplate createRestTemplate(ConfigClientProperties properties) {
7482
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
7583
if (properties.getRequestReadTimeout() < 0) {
@@ -120,8 +128,7 @@ public List<ConfigServerConfigDataResource> resolve(ConfigDataLocationResolverCo
120128
public List<ConfigServerConfigDataResource> resolveProfileSpecific(
121129
ConfigDataLocationResolverContext resolverContext, ConfigDataLocation location, Profiles profiles)
122130
throws ConfigDataLocationNotFoundException {
123-
ConfigClientProperties properties = loadProperties(resolverContext.getBinder());
124-
131+
ConfigClientProperties properties = loadProperties(resolverContext);
125132
String uris = location.getNonPrefixedValue(getPrefix());
126133

127134
if (StringUtils.hasText(uris)) {
@@ -139,7 +146,8 @@ public List<ConfigServerConfigDataResource> resolveProfileSpecific(
139146
return createRestTemplate(props);
140147
});
141148

142-
boolean discoveryEnabled = resolverContext.getBinder().bind(CONFIG_DISCOVERY_ENABLED, Boolean.class)
149+
boolean discoveryEnabled = resolverContext.getBinder()
150+
.bind(CONFIG_DISCOVERY_ENABLED, Bindable.of(Boolean.class), getBindHandler(resolverContext))
143151
.orElse(false);
144152

145153
if (discoveryEnabled) {

spring-cloud-config-client/src/test/java/org/springframework/cloud/config/client/ConfigServerConfigDataCustomizationIntegrationTests.java

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,17 @@
2020

2121
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
2222
import org.springframework.boot.BootstrapContext;
23+
import org.springframework.boot.BootstrapRegistry;
24+
import org.springframework.boot.Bootstrapper;
2325
import org.springframework.boot.SpringBootConfiguration;
2426
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
2527
import org.springframework.boot.builder.SpringApplicationBuilder;
2628
import org.springframework.boot.context.config.ConfigData;
29+
import org.springframework.boot.context.properties.bind.BindContext;
30+
import org.springframework.boot.context.properties.bind.BindHandler;
31+
import org.springframework.boot.context.properties.bind.Bindable;
2732
import org.springframework.boot.context.properties.bind.Binder;
33+
import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
2834
import org.springframework.cloud.config.client.ConfigServerBootstrapper.LoaderInterceptor;
2935
import org.springframework.context.ConfigurableApplicationContext;
3036
import org.springframework.web.client.RestTemplate;
@@ -37,7 +43,8 @@ public class ConfigServerConfigDataCustomizationIntegrationTests {
3743
void customizableRestTemplate() {
3844
ConfigurableApplicationContext context = null;
3945
try {
40-
context = new SpringApplicationBuilder(TestConfig.class)
46+
BindHandlerBootstrapper bindHandlerBootstrapper = new BindHandlerBootstrapper();
47+
context = new SpringApplicationBuilder(TestConfig.class).addBootstrapper(bindHandlerBootstrapper)
4148
.addBootstrapper(ConfigServerBootstrapper.create().withLoaderInterceptor(new Interceptor())
4249
.withRestTemplateFactory(this::restTemplate))
4350
.addBootstrapper(registry -> registry.addCloseListener(event -> {
@@ -47,7 +54,8 @@ void customizableRestTemplate() {
4754
RestTemplate restTemplate = bootstrapContext.get(RestTemplate.class);
4855
beanFactory.registerSingleton("holder", new RestTemplateHolder(restTemplate));
4956
beanFactory.registerSingleton("interceptor", bootstrapContext.get(LoaderInterceptor.class));
50-
})).run("--spring.config.import=optional:configserver:", "--custom.prop=customval");
57+
})).run("--spring.config.import=optional:configserver:", "--custom.prop=customval",
58+
"--spring.cloud.config.label=mylabel");
5159

5260
RestTemplateHolder holder = context.getBean(RestTemplateHolder.class);
5361
assertThat(holder).isNotNull();
@@ -60,6 +68,8 @@ void customizableRestTemplate() {
6068
Interceptor interceptor = (Interceptor) loaderInterceptor;
6169
assertThat(interceptor.applied).isTrue();
6270
assertThat(interceptor.hasBinder).isTrue();
71+
72+
assertThat(bindHandlerBootstrapper.onSuccessCount).isGreaterThan(1);
6373
}
6474
finally {
6575
if (context != null) {
@@ -115,4 +125,22 @@ static class CustomRestTemplate extends RestTemplate {
115125

116126
}
117127

128+
static class BindHandlerBootstrapper implements Bootstrapper {
129+
130+
private int onSuccessCount = 0;
131+
132+
@Override
133+
public void intitialize(BootstrapRegistry registry) {
134+
registry.register(BindHandler.class, context -> new BindHandler() {
135+
@Override
136+
public Object onSuccess(ConfigurationPropertyName name, Bindable<?> target, BindContext context,
137+
Object result) {
138+
onSuccessCount++;
139+
return result;
140+
}
141+
});
142+
}
143+
144+
}
145+
118146
}

spring-cloud-config-sample/src/test/java/sample/ApplicationFailFastTests.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525

2626
public class ApplicationFailFastTests {
2727

28-
// FIXME: configdata failfast works.
2928
@Test
3029
public void contextFails() {
3130
try {

spring-cloud-config-sample/src/test/java/sample/ApplicationTests.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,7 @@
4040
@RunWith(SpringRunner.class)
4141
@SpringBootTest(classes = Application.class,
4242
// Normally spring.cloud.config.enabled:true is the default but since we have the
43-
// config
44-
// server on the classpath we need to set it explicitly
43+
// config server on the classpath we need to set it explicitly
4544
properties = { "spring.cloud.config.enabled:true",
4645
// FIXME: configdata why is this needed here?
4746
"spring.config.use-legacy-processing=true", "management.security.enabled=false",

spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/config/EncryptionAutoConfiguration.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,16 @@
5353
*
5454
*/
5555
@Configuration(proxyBeanMethods = false)
56-
@EnableConfigurationProperties(KeyProperties.class)
56+
@EnableConfigurationProperties
5757
@Import({ SingleTextEncryptorConfiguration.class, DefaultTextEncryptorConfiguration.class })
5858
public class EncryptionAutoConfiguration {
5959

60+
@Bean
61+
@ConditionalOnMissingBean
62+
public KeyProperties keyProperties() {
63+
return new KeyProperties();
64+
}
65+
6066
@Configuration(proxyBeanMethods = false)
6167
@ConditionalOnProperty(value = "spring.cloud.config.server.encrypt.enabled", matchIfMissing = true)
6268
protected static class EncryptorConfiguration {

0 commit comments

Comments
 (0)