diff --git a/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigServerConfigDataLocationResolver.java b/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigServerConfigDataLocationResolver.java index 9ff987b8..92b1761d 100644 --- a/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigServerConfigDataLocationResolver.java +++ b/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigServerConfigDataLocationResolver.java @@ -210,7 +210,8 @@ public class ConfigServerConfigDataLocationResolver if (ConfigClientRetryBootstrapper.RETRY_IS_PRESENT && retryEnabled) { log.debug(LogMessage.format("discovery plus retry enabled")); RetryTemplate retryTemplate = RetryTemplateFactory.create(propertyHolder.retryProperties, log); - instanceProvider = new ConfigServerInstanceProvider(function) { + instanceProvider = new ConfigServerInstanceProvider(function, resolverContext.getBinder(), + getBindHandler(resolverContext)) { @Override public List getConfigServerInstances(String serviceId) { return retryTemplate.execute(retryContext -> super.getConfigServerInstances(serviceId)); @@ -218,7 +219,8 @@ public class ConfigServerConfigDataLocationResolver }; } else { - instanceProvider = new ConfigServerInstanceProvider(function); + instanceProvider = new ConfigServerInstanceProvider(function, resolverContext.getBinder(), + getBindHandler(resolverContext)); } instanceProvider.setLog(log); diff --git a/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigServerInstanceProvider.java b/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigServerInstanceProvider.java index 4f444a4f..8140c1d6 100644 --- a/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigServerInstanceProvider.java +++ b/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigServerInstanceProvider.java @@ -21,6 +21,8 @@ import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.boot.context.properties.bind.BindHandler; +import org.springframework.boot.context.properties.bind.Binder; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.retry.annotation.Retryable; @@ -36,6 +38,10 @@ public class ConfigServerInstanceProvider { private final Function function; + private BindHandler bindHandler; + + private Binder binder; + @Deprecated public ConfigServerInstanceProvider(DiscoveryClient client) { this.function = client::getInstances; @@ -45,6 +51,12 @@ public class ConfigServerInstanceProvider { this.function = function; } + public ConfigServerInstanceProvider(Function function, Binder binder, BindHandler bindHandler) { + this.function = function; + this.binder = binder; + this.bindHandler = bindHandler; + } + void setLog(Log log) { this.log = log; } @@ -54,7 +66,13 @@ public class ConfigServerInstanceProvider { if (log.isDebugEnabled()) { log.debug("Locating configserver (" + serviceId + ") via discovery"); } - List instances = this.function.apply(serviceId); + List instances; + if (binder == null || bindHandler == null) { + instances = this.function.apply(serviceId); + } + else { + instances = this.function.apply(serviceId, binder, bindHandler, log); + } if (instances.isEmpty()) { throw new IllegalStateException("No instances found of configserver (" + serviceId + ")"); } @@ -70,6 +88,10 @@ public class ConfigServerInstanceProvider { List apply(String serviceId); + default List apply(String serviceId, Binder binder, BindHandler bindHandler, Log log) { + return apply(serviceId); + }; + } } diff --git a/spring-cloud-config-client/src/test/java/org/springframework/cloud/config/client/DiscoveryClientConfigDataConfigurationNoRetryTests.java b/spring-cloud-config-client/src/test/java/org/springframework/cloud/config/client/DiscoveryClientConfigDataConfigurationNoRetryTests.java index bbb35bf5..c1231a27 100644 --- a/spring-cloud-config-client/src/test/java/org/springframework/cloud/config/client/DiscoveryClientConfigDataConfigurationNoRetryTests.java +++ b/spring-cloud-config-client/src/test/java/org/springframework/cloud/config/client/DiscoveryClientConfigDataConfigurationNoRetryTests.java @@ -21,16 +21,18 @@ import java.util.Collections; import java.util.LinkedHashSet; import java.util.Set; +import org.apache.commons.logging.Log; import org.junit.After; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.Mockito; import org.springframework.boot.BootstrapRegistry; import org.springframework.boot.BootstrapRegistryInitializer; import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.context.properties.bind.BindHandler; +import org.springframework.boot.context.properties.bind.Binder; import org.springframework.cloud.client.DefaultServiceInstance; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; @@ -41,8 +43,14 @@ import org.springframework.context.ConfigurableApplicationContext; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import static org.springframework.cloud.config.client.ConfigClientProperties.Discovery.DEFAULT_CONFIG_SERVER; /** @@ -54,7 +62,7 @@ public class DiscoveryClientConfigDataConfigurationNoRetryTests { protected ConfigurableApplicationContext context; - protected DiscoveryClient client = Mockito.mock(DiscoveryClient.class); + protected DiscoveryClient client = mock(DiscoveryClient.class); protected ServiceInstance info = new DefaultServiceInstance("app:8877", "app", "foo", 8877, false); @@ -68,43 +76,54 @@ public class DiscoveryClientConfigDataConfigurationNoRetryTests { @Test public void shouldFailWithExceptionGetConfigServerInstanceFromDiscoveryClient() throws Exception { givenDiscoveryClientReturnsNoInfo(); - - assertThatThrownBy(() -> context = setup("spring.cloud.config.discovery.enabled=true", + ConfigServerInstanceProvider.Function function = mock(ConfigServerInstanceProvider.Function.class); + when(function.apply(anyString(), any(Binder.class), any(BindHandler.class), any(Log.class))) + .thenAnswer(invocation -> client.getInstances(invocation.getArgument(0))); + assertThatThrownBy(() -> context = setup(true, function, "spring.cloud.config.discovery.enabled=true", "spring.cloud.config.fail-fast=true").run()).isInstanceOf(IllegalStateException.class) .hasMessageContaining("No instances found of configserver"); + verify(function).apply(eq(DEFAULT_CONFIG_SERVER), any(Binder.class), any(BindHandler.class), any(Log.class)); + verify(function, never()).apply(eq(DEFAULT_CONFIG_SERVER)); } @Test public void shouldFailWithMessageGetConfigServerInstanceFromDiscoveryClient() throws Exception { givenDiscoveryClientReturnsNoInfo(); - - context = setup("spring.cloud.config.discovery.enabled=true", "spring.cloud.config.fail-fast=false").run(); + ConfigServerInstanceProvider.Function function = mock(ConfigServerInstanceProvider.Function.class); + when(function.apply(anyString(), any(Binder.class), any(BindHandler.class), any(Log.class))) + .thenAnswer(invocation -> client.getInstances(invocation.getArgument(0))); + context = setup(true, function, "spring.cloud.config.discovery.enabled=true", + "spring.cloud.config.fail-fast=false").run(); // expectDiscoveryClientConfigServiceBootstrapConfigurationIsSetup(); expectConfigClientPropertiesHasDefaultConfiguration(); verifyDiscoveryClientCalledOnce(); + verify(function).apply(eq(DEFAULT_CONFIG_SERVER), any(Binder.class), any(BindHandler.class), any(Log.class)); + verify(function, never()).apply(eq(DEFAULT_CONFIG_SERVER)); } @Test public void shouldSucceedGetConfigServerInstanceFromDiscoveryClient() throws Exception { givenDiscoveryClientReturnsInfo(); - - context = setup("spring.cloud.config.discovery.enabled=true", "spring.cloud.config.fail-fast=true").run(); + ConfigServerInstanceProvider.Function function = mock(ConfigServerInstanceProvider.Function.class); + when(function.apply(eq(DEFAULT_CONFIG_SERVER), any(Binder.class), any(BindHandler.class), any(Log.class))) + .thenAnswer(invocation -> client.getInstances(invocation.getArgument(0))); + context = setup(true, function, "spring.cloud.config.discovery.enabled=true", + "spring.cloud.config.fail-fast=true").run(); // expectDiscoveryClientConfigServiceBootstrapConfigurationIsSetup(); // expectConfigClientPropertiesHasConfigurationFromEureka(); verifyDiscoveryClientCalledOnce(); + verify(function).apply(eq(DEFAULT_CONFIG_SERVER), any(Binder.class), any(BindHandler.class), any(Log.class)); + verify(function, never()).apply(eq(DEFAULT_CONFIG_SERVER)); } - SpringApplicationBuilder setup(String... env) { - return setup(true, env); - } - - SpringApplicationBuilder setup(boolean addInstanceProvider, String... env) { + SpringApplicationBuilder setup(boolean addInstanceProvider, ConfigServerInstanceProvider.Function function, + String... env) { SpringApplicationBuilder builder = new SpringApplicationBuilder(TestConfig.class) .properties(addDefaultEnv(env)); if (addInstanceProvider) { - builder.addBootstrapRegistryInitializer(instanceProviderBootstrapper()); + builder.addBootstrapRegistryInitializer(instanceProviderBootstrapper(function)); // ignore actual calls to config server since we're just testing discovery // client. builder.addBootstrapRegistryInitializer(registry -> registry @@ -116,9 +135,10 @@ public class DiscoveryClientConfigDataConfigurationNoRetryTests { })); } - protected BootstrapRegistryInitializer instanceProviderBootstrapper() { + protected BootstrapRegistryInitializer instanceProviderBootstrapper( + ConfigServerInstanceProvider.Function function) { return registry -> registry.register(ConfigServerInstanceProvider.Function.class, - BootstrapRegistry.InstanceSupplier.from(() -> this.client::getInstances)); + BootstrapRegistry.InstanceSupplier.from(() -> function)); } private String[] addDefaultEnv(String[] env) {