Commit c181163a by Taras Danylchuk Committed by Ryan Baxter

fixes https://github.com/spring-cloud/spring-cloud-netflix/issues/2972 (#3018)

root cause: cached bean trying to re-register resolution summary: get re-created bean from context to re-register
parent 8af3ae8a
......@@ -26,6 +26,7 @@ import java.lang.annotation.Target;
import java.net.MalformedURLException;
import java.util.Map;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.endpoint.Endpoint;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
......@@ -94,9 +95,6 @@ import com.netflix.discovery.EurekaClientConfig;
"org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration"})
public class EurekaClientAutoConfiguration {
@Autowired(required = false)
private HealthCheckHandler healthCheckHandler;
@Bean
public HasFeatures eurekaFeature() {
return HasFeatures.namedFeature("Eureka Client", EurekaClient.class);
......@@ -203,18 +201,8 @@ public class EurekaClientAutoConfiguration {
@Bean
@ConditionalOnBean(AutoServiceRegistrationProperties.class)
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
public EurekaRegistration eurekaRegistration(EurekaClient eurekaClient, CloudEurekaInstanceConfig instanceConfig, ApplicationInfoManager applicationInfoManager) {
return EurekaRegistration.builder(instanceConfig)
.with(applicationInfoManager)
.with(eurekaClient)
.with(healthCheckHandler)
.build();
}
@Bean
@ConditionalOnBean(AutoServiceRegistrationProperties.class)
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
public EurekaAutoServiceRegistration eurekaAutoServiceRegistration(ApplicationContext context, EurekaServiceRegistry registry, EurekaRegistration registration) {
public EurekaAutoServiceRegistration eurekaAutoServiceRegistration(ApplicationContext context, EurekaServiceRegistry registry,
EurekaRegistration registration) {
return new EurekaAutoServiceRegistration(context, registry, registration);
}
......@@ -242,6 +230,20 @@ public class EurekaClientAutoConfiguration {
InstanceInfo instanceInfo = new InstanceInfoFactory().create(config);
return new ApplicationInfoManager(config, instanceInfo);
}
@Bean
@ConditionalOnBean(AutoServiceRegistrationProperties.class)
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
public EurekaRegistration eurekaRegistration(EurekaClient eurekaClient,
CloudEurekaInstanceConfig instanceConfig,
ApplicationInfoManager applicationInfoManager,
@Autowired(required = false) HealthCheckHandler healthCheckHandler) {
return EurekaRegistration.builder(instanceConfig)
.with(applicationInfoManager)
.with(eurekaClient)
.with(healthCheckHandler)
.build();
}
}
@Configuration
......@@ -273,6 +275,21 @@ public class EurekaClientAutoConfiguration {
return new ApplicationInfoManager(config, instanceInfo);
}
@Bean
@org.springframework.cloud.context.config.annotation.RefreshScope
@ConditionalOnBean(AutoServiceRegistrationProperties.class)
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
public EurekaRegistration eurekaRegistration(EurekaClient eurekaClient,
CloudEurekaInstanceConfig instanceConfig,
ApplicationInfoManager applicationInfoManager,
@Autowired(required = false) HealthCheckHandler healthCheckHandler) {
return EurekaRegistration.builder(instanceConfig)
.with(applicationInfoManager)
.with(eurekaClient)
.with(healthCheckHandler)
.build();
}
}
@Target({ ElementType.TYPE, ElementType.METHOD })
......
......@@ -44,7 +44,7 @@ import com.netflix.discovery.EurekaClientConfig;
/**
* @author Spencer Gibb
*/
public class EurekaRegistration implements Registration, Closeable {
public class EurekaRegistration implements Registration {
private static final Log log = LogFactory.getLog(EurekaRegistration.class);
private final EurekaClient eurekaClient;
......@@ -201,8 +201,4 @@ public class EurekaRegistration implements Registration, Closeable {
return this.instanceConfig.getSecurePort();
}
@Override
public void close() throws IOException {
this.eurekaClient.shutdown();
}
}
......@@ -16,27 +16,32 @@
package org.springframework.cloud.netflix.eureka;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
import org.junit.After;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.aop.framework.Advised;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.SearchStrategy;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.autoconfigure.RefreshAutoConfiguration;
import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationProperties;
import org.springframework.cloud.commons.util.UtilAutoConfiguration;
import org.springframework.cloud.context.refresh.ContextRefresher;
import org.springframework.cloud.context.scope.GenericScope;
import org.springframework.cloud.netflix.eureka.serviceregistry.EurekaRegistration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.test.util.ReflectionTestUtils;
import com.netflix.appinfo.ApplicationInfoManager;
import com.netflix.appinfo.HealthCheckHandler;
import com.netflix.discovery.EurekaClient;
import com.netflix.discovery.EurekaClientConfig;
import com.netflix.discovery.shared.transport.jersey.EurekaJerseyClient;
......@@ -45,8 +50,6 @@ import com.sun.jersey.client.apache4.ApacheHttpClient4;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.springframework.boot.test.util.EnvironmentTestUtils.addEnvironment;
/**
......@@ -367,6 +370,43 @@ public class EurekaClientAutoConfigurationTests {
}
@Test
public void shouldReregisterHealthCheckHandlerAfterRefresh() throws Exception {
addEnvironment(this.context, "eureka.client.healthcheck.enabled=true");
setupContext(RefreshAutoConfiguration.class, AutoServiceRegistrationConfiguration.class);
EurekaClient oldEurekaClient = getLazyInitEurekaClient();
HealthCheckHandler healthCheckHandler = this.context.getBean("eurekaHealthCheckHandler", HealthCheckHandler.class);
assertThat(healthCheckHandler).isInstanceOf(EurekaHealthCheckHandler.class);
assertThat(oldEurekaClient.getHealthCheckHandler()).isSameAs(healthCheckHandler);
ContextRefresher refresher = this.context.getBean("contextRefresher", ContextRefresher.class);
refresher.refresh();
EurekaClient newEurekaClient = getLazyInitEurekaClient();
HealthCheckHandler newHealthCheckHandler = this.context.getBean("eurekaHealthCheckHandler", HealthCheckHandler.class);
assertThat(healthCheckHandler).isSameAs(newHealthCheckHandler);
assertThat(oldEurekaClient).isNotSameAs(newEurekaClient);
assertThat(newEurekaClient.getHealthCheckHandler()).isSameAs(healthCheckHandler);
}
@Test
public void shouldCloseDiscoveryClient() throws Exception {
addEnvironment(this.context, "eureka.client.healthcheck.enabled=true");
setupContext(RefreshAutoConfiguration.class, AutoServiceRegistrationConfiguration.class);
AtomicBoolean isShutdown = (AtomicBoolean) ReflectionTestUtils.getField(getLazyInitEurekaClient(), "isShutdown");
assertThat(isShutdown.get()).isFalse();
this.context.close();
assertThat(isShutdown.get()).isTrue();
}
@Test
public void basicAuth() {
addEnvironment(this.context, "server.port=8989",
"eureka.client.serviceUrl.defaultZone=http://user:foo@example.com:80/eureka");
......@@ -425,16 +465,6 @@ public class EurekaClientAutoConfigurationTests {
}
}
@Test
public void eurekaRegistrationClosed() throws IOException {
setupContext(TestEurekaRegistrationConfiguration.class);
if (this.context != null) {
EurekaRegistration registration = this.context.getBean(EurekaRegistration.class);
this.context.close();
verify(registration).close();
}
}
private void testNonSecurePort(String propName) {
addEnvironment(this.context, propName + ":8888");
setupContext();
......@@ -452,6 +482,10 @@ public class EurekaClientAutoConfigurationTests {
return this.context.getBean(EurekaInstanceConfigBean.class);
}
private EurekaClient getLazyInitEurekaClient() throws Exception {
return (EurekaClient)((Advised) this.context.getBean("eurekaClient", EurekaClient.class)).getTargetSource().getTarget();
}
@Configuration
@EnableConfigurationProperties
@Import({ UtilAutoConfiguration.class, EurekaClientAutoConfiguration.class })
......@@ -482,18 +516,6 @@ public class EurekaClientAutoConfigurationTests {
}
@Configuration
protected static class TestEurekaRegistrationConfiguration {
@Bean
public EurekaRegistration eurekaRegistration(EurekaClient eurekaClient, CloudEurekaInstanceConfig instanceConfig, ApplicationInfoManager applicationInfoManager) {
return spy(EurekaRegistration.builder(instanceConfig)
.with(applicationInfoManager)
.with(eurekaClient)
.build());
}
}
@Configuration
protected static class MockClientConfiguration {
@Bean
......@@ -515,4 +537,10 @@ public class EurekaClientAutoConfigurationTests {
return Mockito.mock(ApacheHttpClient4.class);
}
}
@Configuration
@EnableConfigurationProperties(AutoServiceRegistrationProperties.class)
public static class AutoServiceRegistrationConfiguration {
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment