From f4524f2602c91051758232568178ea10e5e015c6 Mon Sep 17 00:00:00 2001 From: Ryan Baxter Date: Tue, 23 Jan 2024 20:37:03 -0500 Subject: [PATCH] Revert changes in config server bootstrapper and use new PropertyResolver class (#328) Co-authored-by: Ryan Baxter <524254+ryanjbaxter@users.noreply.github.com> --- .../ZookeeperConfigServerBootstrapper.java | 123 +++++------------- 1 file changed, 30 insertions(+), 93 deletions(-) diff --git a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/configclient/ZookeeperConfigServerBootstrapper.java b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/configclient/ZookeeperConfigServerBootstrapper.java index 7f18ed2b..2093a2ba 100644 --- a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/configclient/ZookeeperConfigServerBootstrapper.java +++ b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/configclient/ZookeeperConfigServerBootstrapper.java @@ -17,13 +17,8 @@ package org.springframework.cloud.zookeeper.discovery.configclient; import java.util.Collections; -import java.util.List; -import java.util.stream.Stream; -import org.apache.commons.logging.Log; -import org.apache.curator.RetryPolicy; import org.apache.curator.framework.CuratorFramework; -import org.apache.curator.retry.ExponentialBackoffRetry; import org.apache.curator.x.discovery.ServiceDiscovery; import org.apache.curator.x.discovery.ServiceDiscoveryBuilder; import org.apache.curator.x.discovery.details.InstanceSerializer; @@ -33,15 +28,13 @@ import org.springframework.boot.BootstrapContext; import org.springframework.boot.BootstrapRegistry; import org.springframework.boot.BootstrapRegistryInitializer; import org.springframework.boot.context.properties.bind.BindHandler; -import org.springframework.boot.context.properties.bind.Bindable; import org.springframework.boot.context.properties.bind.Binder; -import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.commons.util.InetUtils; import org.springframework.cloud.commons.util.InetUtilsProperties; import org.springframework.cloud.config.client.ConfigClientProperties; +import org.springframework.cloud.config.client.ConfigServerConfigDataLocationResolver.PropertyResolver; import org.springframework.cloud.config.client.ConfigServerInstanceProvider; import org.springframework.cloud.zookeeper.CuratorFactory; -import org.springframework.cloud.zookeeper.ZookeeperProperties; import org.springframework.cloud.zookeeper.discovery.ConditionalOnZookeeperDiscoveryEnabled; import org.springframework.cloud.zookeeper.discovery.ZookeeperDiscoveryClient; import org.springframework.cloud.zookeeper.discovery.ZookeeperDiscoveryProperties; @@ -53,10 +46,16 @@ import org.springframework.util.ClassUtils; public class ZookeeperConfigServerBootstrapper implements BootstrapRegistryInitializer { - private static boolean isEnabled(Binder binder) { - return binder.bind(ConfigClientProperties.CONFIG_DISCOVERY_ENABLED, Boolean.class).orElse(false) && - binder.bind(ConditionalOnZookeeperDiscoveryEnabled.PROPERTY, Boolean.class).orElse(true) && - binder.bind("spring.cloud.discovery.enabled", Boolean.class).orElse(true); + private static PropertyResolver getPropertyResolver(BootstrapContext context) { + return context.getOrElseSupply(PropertyResolver.class, () -> new PropertyResolver( + context.get(Binder.class), context.getOrElse(BindHandler.class, null))); + } + + public static boolean isEnabled(BootstrapContext bootstrapContext) { + PropertyResolver propertyResolver = getPropertyResolver(bootstrapContext); + return propertyResolver.get(ConfigClientProperties.CONFIG_DISCOVERY_ENABLED, Boolean.class, false) && + propertyResolver.get(ConditionalOnZookeeperDiscoveryEnabled.PROPERTY, Boolean.class, true) && + propertyResolver.get("spring.cloud.discovery.enabled", Boolean.class, true); } @Override @@ -67,27 +66,28 @@ public class ZookeeperConfigServerBootstrapper implements BootstrapRegistryIniti ClassUtils.isPresent("org.springframework.cloud.bootstrap.marker.Marker", null)) { return; } + // create curator - CuratorFactory.registerCurator(registry, null, true, bootstrapContext -> isEnabled(bootstrapContext.get(Binder.class))); + CuratorFactory.registerCurator(registry, null, true, ZookeeperConfigServerBootstrapper::isEnabled); // create discovery registry.registerIfAbsent(ZookeeperDiscoveryProperties.class, context -> { - Binder binder = context.get(Binder.class); - if (!isEnabled(binder)) { + if (!isEnabled(context)) { return null; } - return binder.bind(ZookeeperDiscoveryProperties.PREFIX, Bindable - .of(ZookeeperDiscoveryProperties.class), getBindHandler(context)) - .orElseGet(() -> new ZookeeperDiscoveryProperties(new InetUtils(new InetUtilsProperties()))); + PropertyResolver propertyResolver = getPropertyResolver(context); + return propertyResolver.resolveConfigurationProperties(ZookeeperDiscoveryProperties.PREFIX, + ZookeeperDiscoveryProperties.class, + () -> new ZookeeperDiscoveryProperties(new InetUtils(new InetUtilsProperties()))); }); registry.registerIfAbsent(InstanceSerializer.class, context -> { - if (!isEnabled(context.get(Binder.class))) { + if (!isEnabled(context)) { return null; } return new JsonInstanceSerializer<>(ZookeeperInstance.class); }); registry.registerIfAbsent(ServiceDiscoveryCustomizer.class, context -> { - if (!isEnabled(context.get(Binder.class))) { + if (!isEnabled(context)) { return null; } CuratorFramework curator = context.get(CuratorFramework.class); @@ -96,30 +96,31 @@ public class ZookeeperConfigServerBootstrapper implements BootstrapRegistryIniti return new DefaultServiceDiscoveryCustomizer(curator, properties, serializer); }); registry.registerIfAbsent(ServiceDiscovery.class, context -> { - if (!isEnabled(context.get(Binder.class))) { + if (!isEnabled(context)) { return null; } ServiceDiscoveryCustomizer customizer = context.get(ServiceDiscoveryCustomizer.class); return customizer.customize(ServiceDiscoveryBuilder.builder(ZookeeperInstance.class)); }); registry.registerIfAbsent(ZookeeperDiscoveryClient.class, context -> { - Binder binder = context.get(Binder.class); - if (!isEnabled(binder)) { + if (!isEnabled(context)) { return null; } + PropertyResolver propertyResolver = getPropertyResolver(context); ServiceDiscovery serviceDiscovery = context.get(ServiceDiscovery.class); - ZookeeperDependencies dependencies = binder.bind(ZookeeperDependencies.PREFIX, Bindable - .of(ZookeeperDependencies.class), getBindHandler(context)) - .orElseGet(ZookeeperDependencies::new); + ZookeeperDependencies dependencies = propertyResolver.resolveConfigurationProperties(ZookeeperDependencies.PREFIX, ZookeeperDependencies.class, ZookeeperDependencies::new); ZookeeperDiscoveryProperties discoveryProperties = context.get(ZookeeperDiscoveryProperties.class); return new ZookeeperDiscoveryClient(serviceDiscovery, dependencies, discoveryProperties); }); // create instance provider - // We need to pass the lambda here so we do not create a new instance of ConfigServerInstanceProvider.Function - // which would result in a ClassNotFoundException when Spring Cloud Config is not on the classpath - registry.registerIfAbsent(ConfigServerInstanceProvider.Function.class, ZookeeperFunction::create); + registry.registerIfAbsent(ConfigServerInstanceProvider.Function.class, context -> { + if (!isEnabled(context)) { + return (id) -> Collections.emptyList(); + } + return context.get(ZookeeperDiscoveryClient.class)::getInstances; + }); // promote beans to context registry.addCloseListener(event -> { @@ -130,68 +131,4 @@ public class ZookeeperConfigServerBootstrapper implements BootstrapRegistryIniti } }); } - - private BindHandler getBindHandler(org.springframework.boot.BootstrapContext context) { - return context.getOrElse(BindHandler.class, null); - } - - /* - * This Function is executed when loading config data. Because of this we cannot rely on the - * BootstrapContext because Boot has not finished loading all the configuration data so if we - * ask the BootstrapContext for configuration data it will not have it. The apply method in this function - * is passed the Binder and BindHandler from the config data context which has the configuration properties that - * have been loaded so far in the config data process. - * - * We will create many of the same beans in this function as we do above in the initializer above. We do both - * to maintain compatibility since we are promoting those beans to the main application context. - */ - static final class ZookeeperFunction implements ConfigServerInstanceProvider.Function { - - private final BootstrapContext context; - - private ZookeeperFunction(BootstrapContext context) { - this.context = context; - } - - static ZookeeperFunction create(BootstrapContext context) { - return new ZookeeperFunction(context); - } - - @Override - public List apply(String serviceId) { - return apply(serviceId, null, null, null); - } - - @Override - public List apply(String serviceId, Binder binder, BindHandler bindHandler, Log log) { - if (binder == null || !isEnabled(binder)) { - return Collections.emptyList(); - } - - ZookeeperProperties properties = context.getOrElse(ZookeeperProperties.class, binder.bind(ZookeeperProperties.PREFIX, Bindable.of(ZookeeperProperties.class)) - .orElse(new ZookeeperProperties())); - RetryPolicy retryPolicy = context.getOrElse(RetryPolicy.class, new ExponentialBackoffRetry(properties.getBaseSleepTimeMs(), properties.getMaxRetries(), - properties.getMaxSleepMs())); - try { - CuratorFramework curatorFramework = context.getOrElse(CuratorFramework.class, CuratorFactory.curatorFramework(properties, retryPolicy, Stream::of, - () -> null, () -> null)); - InstanceSerializer serializer = context.getOrElse(InstanceSerializer.class, new JsonInstanceSerializer<>(ZookeeperInstance.class)); - ZookeeperDiscoveryProperties discoveryProperties = context.getOrElse(ZookeeperDiscoveryProperties.class, binder.bind(ZookeeperDiscoveryProperties.PREFIX, Bindable - .of(ZookeeperDiscoveryProperties.class), bindHandler) - .orElseGet(() -> new ZookeeperDiscoveryProperties(new InetUtils(new InetUtilsProperties())))); - ServiceDiscoveryCustomizer customizer = context.getOrElse(ServiceDiscoveryCustomizer.class, new DefaultServiceDiscoveryCustomizer(curatorFramework, discoveryProperties, serializer)); - ServiceDiscovery serviceDiscovery = customizer.customize(ServiceDiscoveryBuilder.builder(ZookeeperInstance.class)); - ZookeeperDependencies dependencies = context.getOrElse(ZookeeperDependencies.class, binder.bind(ZookeeperDependencies.PREFIX, Bindable - .of(ZookeeperDependencies.class), bindHandler) - .orElseGet(ZookeeperDependencies::new)); - return new ZookeeperDiscoveryClient(serviceDiscovery, dependencies, discoveryProperties).getInstances(serviceId); - } - catch (Exception e) { - log.warn("Error fetching config server instance from Zookeeper", e); - return Collections.emptyList(); - } - - } - } - }