Start discovery lifecycle in traditional war deployments.

fixes https://github.com/spring-cloud/spring-cloud-consul/issues/173
This commit is contained in:
Spencer Gibb
2016-04-25 16:33:28 -06:00
parent f85f5b0ecf
commit f76687e949
3 changed files with 114 additions and 7 deletions

View File

@@ -16,25 +16,32 @@
package org.springframework.cloud.client.discovery;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import javax.annotation.PreDestroy;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.embedded.EmbeddedServletContainerInitializedEvent;
import org.springframework.boot.context.embedded.EmbeddedWebApplicationContext;
import org.springframework.cloud.client.discovery.event.InstanceRegisteredEvent;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.core.env.Environment;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Lifecycle methods that may be useful and common to various DiscoveryClient implementations.
* @author Spencer Gibb
*/
public abstract class AbstractDiscoveryLifecycle implements DiscoveryLifecycle,
ApplicationContextAware, ApplicationListener<EmbeddedServletContainerInitializedEvent> {
ApplicationContextAware {
private final Log logger = LogFactory.getLog(getClass());
private boolean autoStartup = true;
@@ -48,6 +55,9 @@ public abstract class AbstractDiscoveryLifecycle implements DiscoveryLifecycle,
private AtomicInteger port = new AtomicInteger(0);
@Value("${server.port:${SERVER_PORT:${PORT:-1}}}")
private Integer serverPort;
protected ApplicationContext getContext() {
return context;
}
@@ -203,8 +213,8 @@ public abstract class AbstractDiscoveryLifecycle implements DiscoveryLifecycle,
return 0;
}
@Override
public void onApplicationEvent(EmbeddedServletContainerInitializedEvent event) {
@EventListener
public void handleContainerInit(EmbeddedServletContainerInitializedEvent event) {
// TODO: take SSL into account
// Don't register the management port as THE port
if (!"management".equals(event.getApplicationContext().getNamespace())) {
@@ -212,4 +222,26 @@ public abstract class AbstractDiscoveryLifecycle implements DiscoveryLifecycle,
this.start();
}
}
/**
* Handles the start() method for a traditional war deployment.
* @param event
*/
@EventListener
public void handleContextRefreshed(ContextRefreshedEvent event) {
if (!isEmbeddedContext(event)) {
if (this.serverPort == null || this.serverPort <= 0) {
throw new IllegalStateException("Running as a traditional war and server.port is not set");
} else {
this.logger.info("Starting AbstractDiscoveryLifecycle during traditional war deployment using server.port: " + this.serverPort);
this.port.compareAndSet(0, this.serverPort);
this.start();
}
}
}
protected boolean isEmbeddedContext(ContextRefreshedEvent event) {
return event.getApplicationContext() instanceof EmbeddedWebApplicationContext
&& ((EmbeddedWebApplicationContext) event.getApplicationContext()).getEmbeddedServletContainer() != null;
}
}

View File

@@ -7,10 +7,12 @@ import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.context.embedded.EmbeddedServletContainerInitializedEvent;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.boot.test.WebIntegrationTest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
@@ -38,6 +40,8 @@ public class AbstractDiscoveryLifecycleTests {
assertTrue("Lifecycle not running", lifecycle.isRunning());
assertTrue("Lifecycle not registered", lifecycle.isRegistered());
assertEquals("Lifecycle appName is wrong", "application", lifecycle.getAppName());
assertTrue("Lifecycle didn't handle containerInit", lifecycle.isContainerInitHandled());
assertFalse("Lifecycle handled contextRefreshed", lifecycle.isContextRefreshedHandled());
}
@EnableAutoConfiguration
@@ -53,6 +57,8 @@ public class AbstractDiscoveryLifecycleTests {
private int port = 0;
private boolean registered = false;
private boolean deregistered = false;
private boolean containerInitHandled = false;
private boolean contextRefreshedHandled = false;
@Override
protected int getConfiguredPort() {
@@ -84,6 +90,20 @@ public class AbstractDiscoveryLifecycleTests {
return true;
}
@Override
public void handleContainerInit(EmbeddedServletContainerInitializedEvent event) {
this.containerInitHandled = true;
super.handleContainerInit(event);
}
@Override
public void handleContextRefreshed(ContextRefreshedEvent event) {
if (!super.isEmbeddedContext(event)) {
this.contextRefreshedHandled = true;
}
super.handleContextRefreshed(event);
}
public boolean isRegistered() {
return registered;
}
@@ -91,5 +111,13 @@ public class AbstractDiscoveryLifecycleTests {
public boolean isDeregistered() {
return deregistered;
}
public boolean isContainerInitHandled() {
return containerInitHandled;
}
public boolean isContextRefreshedHandled() {
return contextRefreshedHandled;
}
}
}

View File

@@ -0,0 +1,47 @@
package org.springframework.cloud.client.discovery;
import org.junit.Test;
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.autoconfigure.test.ImportAutoConfiguration;
import org.springframework.boot.test.EnvironmentTestUtils;
import org.springframework.cloud.client.discovery.AbstractDiscoveryLifecycleTests.TestDiscoveryLifecycle;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
* @author Spencer Gibb
*/
public class AbstractDiscoveryLifecycleWarTests {
@Test
public void portsWork() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(Config.class);
EnvironmentTestUtils.addEnvironment(context.getEnvironment(), "server.port=7777");
context.refresh();
TestDiscoveryLifecycle lifecycle = context.getBean(TestDiscoveryLifecycle.class);
assertEquals("Lifecycle port is wrong", 7777, lifecycle.getPort().get());
assertFalse("Lifecycle handled containerInit", lifecycle.isContainerInitHandled());
assertTrue("Lifecycle didn't handle contextRefreshed", lifecycle.isContextRefreshedHandled());
}
@Test(expected = IllegalStateException.class)
public void portsFailIfNotSet() {
new AnnotationConfigApplicationContext(Config.class);
}
@ImportAutoConfiguration({PropertyPlaceholderAutoConfiguration.class})
@Configuration
public static class Config {
@Bean
public TestDiscoveryLifecycle testDiscoveryLifecycle() {
return new TestDiscoveryLifecycle();
}
}
}