diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/config/DiscoveryClientConfigServiceAutoConfiguration.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/config/DiscoveryClientConfigServiceAutoConfiguration.java index 75da08b6..402898ba 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/config/DiscoveryClientConfigServiceAutoConfiguration.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/config/DiscoveryClientConfigServiceAutoConfiguration.java @@ -49,11 +49,11 @@ public class DiscoveryClientConfigServiceAutoConfiguration { private ConfigurationPropertiesBindingPostProcessor binder; @Autowired - private EurekaDiscoveryClientConfiguration lifecycle; + private EurekaDiscoveryClientConfiguration clientConfiguration; @PostConstruct public void init() { - this.lifecycle.stop(); + this.clientConfiguration.stop(); rebind(this.clientConfig, "eurekaClientConfig"); rebind(this.instanceConfig, "eurekaInstanceConfig"); // Danger, here be dragons (once it shuts down it's hard to resurrect it) @@ -61,7 +61,7 @@ public class DiscoveryClientConfigServiceAutoConfiguration { // FIXME: reinit EurekaClient and ApplicationInfoManager // applicationInfoManager.initComponent(this.instanceConfig); // discoveryManager.initComponent(this.instanceConfig, this.clientConfig); - this.lifecycle.start(); + this.clientConfiguration.start(); } private void rebind(Object bean, String name) { diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/config/DiscoveryClientConfigServiceBootstrapConfiguration.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/config/DiscoveryClientConfigServiceBootstrapConfiguration.java index c30e890a..16767ab4 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/config/DiscoveryClientConfigServiceBootstrapConfiguration.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/config/DiscoveryClientConfigServiceBootstrapConfiguration.java @@ -19,17 +19,13 @@ package org.springframework.cloud.netflix.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.cloud.client.discovery.EnableDiscoveryClient; -import org.springframework.cloud.client.discovery.event.HeartbeatEvent; -import org.springframework.cloud.client.discovery.event.HeartbeatMonitor; import org.springframework.cloud.config.client.ConfigClientProperties; import org.springframework.cloud.config.client.ConfigServicePropertySourceLocator; import org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration; -import org.springframework.context.ApplicationEvent; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.context.event.ContextRefreshedEvent; -import org.springframework.context.event.SmartApplicationListener; +import org.springframework.context.event.EventListener; import com.netflix.appinfo.InstanceInfo; import com.netflix.discovery.EurekaClient; @@ -45,13 +41,9 @@ import lombok.extern.apachecommons.CommonsLog; @ConditionalOnClass({ EurekaClient.class, ConfigServicePropertySourceLocator.class }) @ConditionalOnProperty(value = "spring.cloud.config.discovery.enabled", matchIfMissing = false) @Configuration -@EnableDiscoveryClient @Import(EurekaClientAutoConfiguration.class) @CommonsLog -public class DiscoveryClientConfigServiceBootstrapConfiguration implements - SmartApplicationListener { - - private HeartbeatMonitor monitor = new HeartbeatMonitor(); +public class DiscoveryClientConfigServiceBootstrapConfiguration { @Autowired private ConfigClientProperties config; @@ -59,40 +51,18 @@ public class DiscoveryClientConfigServiceBootstrapConfiguration implements @Autowired private EurekaClient eurekaClient; - @Override - public void onApplicationEvent(ApplicationEvent event) { - if (event instanceof ContextRefreshedEvent) { - refresh(); - } - else if (event instanceof HeartbeatEvent) { - if (this.monitor.update(((HeartbeatEvent) event).getValue())) { - refresh(); - } - } + @EventListener(ContextRefreshedEvent.class) + public void onApplicationEvent(ContextRefreshedEvent event) { + refresh(); } - @Override - public int getOrder() { - return 0; - } - - @Override - public boolean supportsEventType(Class eventType) { - return ContextRefreshedEvent.class.isAssignableFrom(eventType) - || HeartbeatEvent.class.isAssignableFrom(eventType); - } - - @Override - public boolean supportsSourceType(Class sourceType) { - return true; - } + // TODO: re-instate heart beat (maybe? isn't it handled in the child context?) private void refresh() { try { log.debug("Locating configserver via discovery"); - InstanceInfo server = this.eurekaClient - .getNextServerFromEureka(this.config.getDiscovery().getServiceId(), - false); + InstanceInfo server = this.eurekaClient.getNextServerFromEureka( + this.config.getDiscovery().getServiceId(), false); String url = server.getHomePageUrl(); if (server.getMetadata().containsKey("password")) { String user = server.getMetadata().get("user"); diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaClientAutoConfiguration.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaClientAutoConfiguration.java index e84e39b4..4596e0e6 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaClientAutoConfiguration.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaClientAutoConfiguration.java @@ -16,9 +16,6 @@ package org.springframework.cloud.netflix.eureka; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - import javax.annotation.PostConstruct; import org.springframework.beans.factory.annotation.Autowired; @@ -27,16 +24,11 @@ import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.builder.ParentContextApplicationContextInitializer; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cloud.client.CommonsClientAutoConfiguration; import org.springframework.cloud.client.discovery.DiscoveryClient; -import org.springframework.cloud.client.discovery.event.HeartbeatEvent; -import org.springframework.cloud.client.discovery.event.ParentHeartbeatEvent; import org.springframework.cloud.client.discovery.noop.NoopDiscoveryClientAutoConfiguration; import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationListener; -import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -57,10 +49,9 @@ import lombok.SneakyThrows; @EnableConfigurationProperties @ConditionalOnClass(EurekaClientConfig.class) @ConditionalOnProperty(value = "eureka.client.enabled", matchIfMissing = true) -@AutoConfigureBefore({NoopDiscoveryClientAutoConfiguration.class, CommonsClientAutoConfiguration.class}) -public class EurekaClientAutoConfiguration implements ApplicationListener { - - private static final ConcurrentMap listenerAdded = new ConcurrentHashMap<>(); +@AutoConfigureBefore({ NoopDiscoveryClientAutoConfiguration.class, + CommonsClientAutoConfiguration.class }) +public class EurekaClientAutoConfiguration { @Autowired private ApplicationContext context; @@ -71,10 +62,10 @@ public class EurekaClientAutoConfiguration implements ApplicationListener() { - @Override - public void onApplicationEvent(HeartbeatEvent dhe) { - context.publishEvent(new ParentHeartbeatEvent(dhe - .getSource(), dhe.getValue())); - } - }); - } - } - } } diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaDiscoveryClientConfiguration.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaDiscoveryClientConfiguration.java index ef413e36..582a6854 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaDiscoveryClientConfiguration.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaDiscoveryClientConfiguration.java @@ -21,8 +21,6 @@ import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; -import lombok.extern.apachecommons.CommonsLog; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.actuate.endpoint.Endpoint; import org.springframework.boot.actuate.health.HealthAggregator; @@ -37,11 +35,13 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.embedded.EmbeddedServletContainerInitializedEvent; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cloud.client.discovery.event.InstanceRegisteredEvent; +import org.springframework.cloud.context.environment.EnvironmentChangeEvent; import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationListener; import org.springframework.context.SmartLifecycle; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.event.ContextClosedEvent; +import org.springframework.context.event.EventListener; import org.springframework.core.Ordered; import com.netflix.appinfo.ApplicationInfoManager; @@ -51,6 +51,8 @@ import com.netflix.appinfo.InstanceInfo.InstanceStatus; import com.netflix.discovery.EurekaClient; import com.netflix.discovery.EurekaClientConfig; +import lombok.extern.apachecommons.CommonsLog; + /** * @author Dave Syer * @author Spencer Gibb @@ -100,25 +102,24 @@ public class EurekaDiscoveryClientConfiguration implements SmartLifecycle, Order + " with eureka with status " + this.instanceConfig.getInitialStatus()); - applicationInfoManager.setInstanceStatus( - this.instanceConfig.getInitialStatus()); + this.applicationInfoManager + .setInstanceStatus(this.instanceConfig.getInitialStatus()); if (this.healthCheckHandler != null) { - eurekaClient.registerHealthCheck(this.healthCheckHandler); + this.eurekaClient.registerHealthCheck(this.healthCheckHandler); } - this.context.publishEvent(new InstanceRegisteredEvent<>(this, - this.instanceConfig)); + this.context.publishEvent( + new InstanceRegisteredEvent<>(this, this.instanceConfig)); this.running.set(true); } } @Override public void stop() { - log.info("Unregistering application " + this.instanceConfig.getAppname() - + " with eureka with status DOWN"); - if (applicationInfoManager.getInfo() != null) { - applicationInfoManager.setInstanceStatus( - InstanceStatus.DOWN); + if (this.applicationInfoManager.getInfo() != null) { + log.info("Unregistering application " + this.instanceConfig.getAppname() + + " with eureka with status DOWN"); + this.applicationInfoManager.setInstanceStatus(InstanceStatus.DOWN); } this.running.set(false); } @@ -149,18 +150,26 @@ public class EurekaDiscoveryClientConfiguration implements SmartLifecycle, Order return this.order; } - @Bean - protected ApplicationListener containerPortInitializer() { - return new ApplicationListener() { + @EventListener(EmbeddedServletContainerInitializedEvent.class) + public void onApplicationEvent(EmbeddedServletContainerInitializedEvent event) { + // TODO: take SSL into account when Spring Boot 1.2 is available + EurekaDiscoveryClientConfiguration.this.port.compareAndSet(0, + event.getEmbeddedServletContainer().getPort()); + EurekaDiscoveryClientConfiguration.this.start(); + } + + @EventListener(EnvironmentChangeEvent.class) + public void onApplicationEvent(EnvironmentChangeEvent event) { + // register in case meta data changed + stop(); + start(); + } - @Override - public void onApplicationEvent(EmbeddedServletContainerInitializedEvent event) { - // TODO: take SSL into account when Spring Boot 1.2 is available - EurekaDiscoveryClientConfiguration.this.port.compareAndSet(0, event - .getEmbeddedServletContainer().getPort()); - EurekaDiscoveryClientConfiguration.this.start(); - } - }; + @EventListener(ContextClosedEvent.class) + public void onApplicationEvent(ContextClosedEvent event) { + // register in case meta data changed + stop(); + this.eurekaClient.shutdown(); } @Configuration @@ -175,7 +184,8 @@ public class EurekaDiscoveryClientConfiguration implements SmartLifecycle, Order @ConditionalOnMissingBean public EurekaHealthIndicator eurekaHealthIndicator(EurekaClient eurekaClient, EurekaInstanceConfig config) { - CompositeMetricReader metrics = new CompositeMetricReader(this.metricReaders.toArray(new MetricReader[0])); + CompositeMetricReader metrics = new CompositeMetricReader( + this.metricReaders.toArray(new MetricReader[0])); return new EurekaHealthIndicator(eurekaClient, metrics, config); } } @@ -191,7 +201,7 @@ public class EurekaDiscoveryClientConfiguration implements SmartLifecycle, Order @Bean @ConditionalOnMissingBean(HealthCheckHandler.class) public EurekaHealthCheckHandler eurekaHealthCheckHandler() { - return new EurekaHealthCheckHandler(healthAggregator); + return new EurekaHealthCheckHandler(this.healthAggregator); } } } diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/config/DiscoveryClientConfigServiceAutoConfigurationTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/config/DiscoveryClientConfigServiceAutoConfigurationTests.java index a889a248..5895383c 100644 --- a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/config/DiscoveryClientConfigServiceAutoConfigurationTests.java +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/config/DiscoveryClientConfigServiceAutoConfigurationTests.java @@ -29,6 +29,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.test.EnvironmentTestUtils; import org.springframework.cloud.config.client.ConfigClientProperties; +import org.springframework.cloud.netflix.eureka.EurekaDiscoveryClientConfiguration; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Configuration; import org.springframework.core.env.ConfigurableEnvironment; @@ -61,19 +62,19 @@ public class DiscoveryClientConfigServiceAutoConfigurationTests { @Test public void onWhenRequested() throws Exception { - given(this.client.getNextServerFromEureka("CONFIGSERVER", false)).willReturn( - this.info); + given(this.client.getNextServerFromEureka("CONFIGSERVER", false)) + .willReturn(this.info); setup("spring.cloud.config.discovery.enabled=true"); - assertEquals( - 1, - this.context - .getBeanNamesForType(DiscoveryClientConfigServiceAutoConfiguration.class).length); - Mockito.verify(this.client, times(2)).getNextServerFromEureka("CONFIGSERVER", false); + assertEquals(1, this.context.getBeanNamesForType( + DiscoveryClientConfigServiceAutoConfiguration.class).length); + Mockito.verify(this.client, times(2)).getNextServerFromEureka("CONFIGSERVER", + false); Mockito.verify(this.client, times(0)).shutdown(); ConfigClientProperties locator = this.context .getBean(ConfigClientProperties.class); assertEquals("http://foo:7001/", locator.getRawUri()); - ApplicationInfoManager infoManager = this.context.getBean(ApplicationInfoManager.class); + ApplicationInfoManager infoManager = this.context + .getBean(ApplicationInfoManager.class); assertEquals("bar", infoManager.getInfo().getMetadata().get("foo")); } @@ -88,7 +89,8 @@ public class DiscoveryClientConfigServiceAutoConfigurationTests { parent.refresh(); this.context = new AnnotationConfigApplicationContext(); this.context.setParent(parent); - this.context.register(DiscoveryClientConfigServiceAutoConfiguration.class); + this.context.register(DiscoveryClientConfigServiceAutoConfiguration.class, + EurekaDiscoveryClientConfiguration.class); this.context.refresh(); }