From 365a1540c7cc0eed4365d48310ce60dc1a6fa795 Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Fri, 14 Dec 2018 15:18:00 -0500 Subject: [PATCH] Moves handling of WebServerInitializedEvent to outside class. This lets the ConsulAutoServiceRegistration.start() method be called externally to spring-retry aop is utilized and retry functions again. fixes gh-419 --- .../ConsulAutoServiceRegistration.java | 12 ++- ...oServiceRegistrationAutoConfiguration.java | 5 ++ ...ConsulAutoServiceRegistrationListener.java | 47 ++++++++++++ ...nsulAutoServiceRegistrationRetryTests.java | 73 +++++++++++++++++++ 4 files changed, 135 insertions(+), 2 deletions(-) create mode 100644 spring-cloud-consul-discovery/src/main/java/org/springframework/cloud/consul/serviceregistry/ConsulAutoServiceRegistrationListener.java create mode 100644 spring-cloud-consul-discovery/src/test/java/org/springframework/cloud/consul/serviceregistry/ConsulAutoServiceRegistrationRetryTests.java diff --git a/spring-cloud-consul-discovery/src/main/java/org/springframework/cloud/consul/serviceregistry/ConsulAutoServiceRegistration.java b/spring-cloud-consul-discovery/src/main/java/org/springframework/cloud/consul/serviceregistry/ConsulAutoServiceRegistration.java index 68179723..ac59a041 100644 --- a/spring-cloud-consul-discovery/src/main/java/org/springframework/cloud/consul/serviceregistry/ConsulAutoServiceRegistration.java +++ b/spring-cloud-consul-discovery/src/main/java/org/springframework/cloud/consul/serviceregistry/ConsulAutoServiceRegistration.java @@ -18,6 +18,7 @@ package org.springframework.cloud.consul.serviceregistry; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.boot.web.context.WebServerInitializedEvent; import org.springframework.cloud.client.serviceregistry.AbstractAutoServiceRegistration; import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationProperties; import org.springframework.cloud.consul.discovery.ConsulDiscoveryProperties; @@ -48,6 +49,10 @@ public class ConsulAutoServiceRegistration extends AbstractAutoServiceRegistrati getPort().set(port); } + void setPortIfNeeded(int port) { + getPort().compareAndSet(0, port); + } + @Override protected ConsulAutoRegistration getRegistration() { if (this.registration.getService().getPort() == null && this.getPort().get() > 0) { @@ -120,6 +125,9 @@ public class ConsulAutoServiceRegistration extends AbstractAutoServiceRegistrati return StringUtils.isEmpty(appName) ? super.getAppName() : appName; } - - + @Override + public void bind(WebServerInitializedEvent event) { + // do nothing so we can listen for this event in a different class + // this ensures start() can be retried if spring-retry is available + } } diff --git a/spring-cloud-consul-discovery/src/main/java/org/springframework/cloud/consul/serviceregistry/ConsulAutoServiceRegistrationAutoConfiguration.java b/spring-cloud-consul-discovery/src/main/java/org/springframework/cloud/consul/serviceregistry/ConsulAutoServiceRegistrationAutoConfiguration.java index 21dbc1f1..87b8ac5c 100644 --- a/spring-cloud-consul-discovery/src/main/java/org/springframework/cloud/consul/serviceregistry/ConsulAutoServiceRegistrationAutoConfiguration.java +++ b/spring-cloud-consul-discovery/src/main/java/org/springframework/cloud/consul/serviceregistry/ConsulAutoServiceRegistrationAutoConfiguration.java @@ -61,6 +61,11 @@ public class ConsulAutoServiceRegistrationAutoConfiguration { autoServiceRegistrationProperties, properties, consulRegistration); } + @Bean + public ConsulAutoServiceRegistrationListener consulAutoServiceRegistrationListener(ConsulAutoServiceRegistration registration) { + return new ConsulAutoServiceRegistrationListener(registration); + } + @Bean @ConditionalOnMissingBean public ConsulAutoRegistration consulRegistration(AutoServiceRegistrationProperties autoServiceRegistrationProperties, diff --git a/spring-cloud-consul-discovery/src/main/java/org/springframework/cloud/consul/serviceregistry/ConsulAutoServiceRegistrationListener.java b/spring-cloud-consul-discovery/src/main/java/org/springframework/cloud/consul/serviceregistry/ConsulAutoServiceRegistrationListener.java new file mode 100644 index 00000000..765916d7 --- /dev/null +++ b/spring-cloud-consul-discovery/src/main/java/org/springframework/cloud/consul/serviceregistry/ConsulAutoServiceRegistrationListener.java @@ -0,0 +1,47 @@ +package org.springframework.cloud.consul.serviceregistry; + +import org.springframework.boot.web.context.ConfigurableWebServerApplicationContext; +import org.springframework.boot.web.context.WebServerInitializedEvent; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationEvent; +import org.springframework.context.event.SmartApplicationListener; + +public class ConsulAutoServiceRegistrationListener implements SmartApplicationListener { + private final ConsulAutoServiceRegistration autoServiceRegistration; + + public ConsulAutoServiceRegistrationListener(ConsulAutoServiceRegistration autoServiceRegistration) { + this.autoServiceRegistration = autoServiceRegistration; + } + + @Override + public boolean supportsEventType(Class eventType) { + return WebServerInitializedEvent.class.isAssignableFrom(eventType); + } + + @Override + public boolean supportsSourceType(Class sourceType) { + return true; + } + + @Override + public void onApplicationEvent(ApplicationEvent applicationEvent) { + if (applicationEvent instanceof WebServerInitializedEvent) { + WebServerInitializedEvent event = (WebServerInitializedEvent) applicationEvent; + + ApplicationContext context = event.getApplicationContext(); + if (context instanceof ConfigurableWebServerApplicationContext) { + if ("management".equals( + ((ConfigurableWebServerApplicationContext) context).getServerNamespace())) { + return; + } + } + this.autoServiceRegistration.setPortIfNeeded(event.getWebServer().getPort()); + this.autoServiceRegistration.start(); + } + } + + @Override + public int getOrder() { + return 0; + } +} diff --git a/spring-cloud-consul-discovery/src/test/java/org/springframework/cloud/consul/serviceregistry/ConsulAutoServiceRegistrationRetryTests.java b/spring-cloud-consul-discovery/src/test/java/org/springframework/cloud/consul/serviceregistry/ConsulAutoServiceRegistrationRetryTests.java new file mode 100644 index 00000000..bfd9bb6d --- /dev/null +++ b/spring-cloud-consul-discovery/src/test/java/org/springframework/cloud/consul/serviceregistry/ConsulAutoServiceRegistrationRetryTests.java @@ -0,0 +1,73 @@ +/* + * Copyright 2013-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.consul.serviceregistry; + +import com.ecwid.consul.ConsulException; +import com.ecwid.consul.v1.ConsulClient; +import org.hamcrest.Matchers; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import org.springframework.boot.SpringBootConfiguration; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.ImportAutoConfiguration; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.test.rule.OutputCapture; +import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration; +import org.springframework.cloud.consul.ConsulAutoConfiguration; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.test.annotation.DirtiesContext; + +/** + * @author Spencer Gibb + * @author Venil Noronha + */ +@DirtiesContext +public class ConsulAutoServiceRegistrationRetryTests { + + @Rule + public ExpectedException exception = ExpectedException.none(); + + @Rule + public OutputCapture output = new OutputCapture(); + + @Test + public void testRetry() { + this.exception.expect(ConsulException.class); + try (ConfigurableApplicationContext context = new SpringApplicationBuilder(TestConfig.class).properties("spring.application.name=testregistrationretry", + "spring.jmx.default-domain=testautoregretry", + "spring.cloud.consul.retry.max-attempts=2", + "logging.level.org.springframework.retry=DEBUG", + "server.port=0").run()) { + output.expect(Matchers.containsString("Retry: count=")); + } + } + + @SpringBootConfiguration + @EnableAutoConfiguration + @ImportAutoConfiguration({ AutoServiceRegistrationConfiguration.class, ConsulAutoConfiguration.class, ConsulAutoServiceRegistrationAutoConfiguration.class }) + protected static class TestConfig { + + @Bean + public ConsulClient consulClient() { + return new ConsulClient("localhost", 4321); + } + } +} +