Provide seamless support for local.server.port
Previously, the actual HTTP port on which a web application is running on was only exposed in tests. This commit makes sure to provide that feature regardless of the environment so that applications can know on which port they are actually running on. If there are several containers, each is exposed via the namespace of their respective application context. Closes gh-3259
This commit is contained in:
@@ -50,8 +50,8 @@ import org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebAppl
|
||||
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainer;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainerInitializedEvent;
|
||||
import org.springframework.boot.context.web.ServerPortInfoApplicationContextInitializer;
|
||||
import org.springframework.boot.test.EnvironmentTestUtils;
|
||||
import org.springframework.boot.test.ServerPortInfoApplicationContextInitializer;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
@@ -400,6 +400,9 @@ code.
|
||||
=== Use a random unassigned HTTP port
|
||||
To scan for a free port (using OS natives to prevent clashes) use `server.port=0`.
|
||||
|
||||
TIP: You can know what port got allocated at runtime by looking at the `local.server.port`
|
||||
property in the `Environment`.
|
||||
|
||||
|
||||
|
||||
[[howto-discover-the-http-port-at-runtime]]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2014 the original author or authors.
|
||||
* Copyright 2012-2015 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.
|
||||
@@ -14,7 +14,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.test;
|
||||
package org.springframework.boot.context.web;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainer;
|
||||
@@ -24,7 +27,10 @@ import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextInitializer;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.env.MapPropertySource;
|
||||
import org.springframework.core.env.MutablePropertySources;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -75,8 +81,21 @@ public class ServerPortInfoApplicationContextInitializer implements
|
||||
|
||||
private void setPortProperty(ApplicationContext context, String propertyName, int port) {
|
||||
if (context instanceof ConfigurableApplicationContext) {
|
||||
EnvironmentTestUtils.addEnvironment((ConfigurableApplicationContext) context,
|
||||
propertyName + ":" + port);
|
||||
ConfigurableEnvironment environment = ((ConfigurableApplicationContext) context).getEnvironment();
|
||||
MutablePropertySources sources = environment.getPropertySources();
|
||||
Map<String, Object> map;
|
||||
if (!sources.contains("server.ports")) {
|
||||
map = new HashMap<String, Object>();
|
||||
MapPropertySource source = new MapPropertySource("server.ports", map);
|
||||
sources.addFirst(source);
|
||||
}
|
||||
else {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> value = (Map<String, Object>) sources.get("server.ports")
|
||||
.getSource();
|
||||
map = value;
|
||||
}
|
||||
map.put(propertyName, port);
|
||||
}
|
||||
if (context.getParent() != null) {
|
||||
setPortProperty(context.getParent(), propertyName, port);
|
||||
@@ -198,7 +198,6 @@ public class SpringApplicationContextLoader extends AbstractContextLoader {
|
||||
List<ApplicationContextInitializer<?>> initializers = new ArrayList<ApplicationContextInitializer<?>>();
|
||||
initializers.add(new PropertySourceLocationsInitializer(mergedConfig
|
||||
.getPropertySourceLocations()));
|
||||
initializers.add(new ServerPortInfoApplicationContextInitializer());
|
||||
initializers.addAll(application.getInitializers());
|
||||
for (Class<? extends ApplicationContextInitializer<?>> initializerClass : mergedConfig
|
||||
.getContextInitializerClasses()) {
|
||||
|
||||
@@ -11,7 +11,8 @@ org.springframework.boot.context.event.EventPublishingRunListener
|
||||
org.springframework.context.ApplicationContextInitializer=\
|
||||
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
|
||||
org.springframework.boot.context.ContextIdApplicationContextInitializer,\
|
||||
org.springframework.boot.context.config.DelegatingApplicationContextInitializer
|
||||
org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\
|
||||
org.springframework.boot.context.web.ServerPortInfoApplicationContextInitializer
|
||||
|
||||
# Application Listeners
|
||||
org.springframework.context.ApplicationListener=\
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2014 the original author or authors.
|
||||
* Copyright 2012-2015 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.
|
||||
@@ -239,7 +239,7 @@ public class SpringApplicationBuilderTests {
|
||||
SpringApplicationBuilder application = new SpringApplicationBuilder(
|
||||
ExampleConfig.class).web(false);
|
||||
this.context = application.run();
|
||||
assertEquals(3, application.application().getInitializers().size());
|
||||
assertEquals(4, application.application().getInitializers().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -247,7 +247,7 @@ public class SpringApplicationBuilderTests {
|
||||
SpringApplicationBuilder application = new SpringApplicationBuilder(
|
||||
ExampleConfig.class).child(ChildConfig.class).web(false);
|
||||
this.context = application.run();
|
||||
assertEquals(4, application.application().getInitializers().size());
|
||||
assertEquals(5, application.application().getInitializers().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -261,7 +261,7 @@ public class SpringApplicationBuilderTests {
|
||||
}
|
||||
});
|
||||
this.context = application.run();
|
||||
assertEquals(4, application.application().getInitializers().size());
|
||||
assertEquals(5, application.application().getInitializers().size());
|
||||
}
|
||||
|
||||
@Configuration
|
||||
|
||||
@@ -41,6 +41,7 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.config.ConstructorArgumentValues;
|
||||
import org.springframework.beans.factory.config.Scope;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.boot.context.web.ServerPortInfoApplicationContextInitializer;
|
||||
import org.springframework.context.ApplicationContextException;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.support.AbstractApplicationContext;
|
||||
@@ -73,6 +74,7 @@ import static org.mockito.Mockito.withSettings;
|
||||
* Tests for {@link EmbeddedWebApplicationContext}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public class EmbeddedWebApplicationContextTests {
|
||||
|
||||
@@ -144,6 +146,15 @@ public class EmbeddedWebApplicationContextTests {
|
||||
assertEquals(this.context, event.getApplicationContext());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void localPortIsAvailable() throws Exception {
|
||||
addEmbeddedServletContainerFactoryBean();
|
||||
new ServerPortInfoApplicationContextInitializer().initialize(this.context);
|
||||
this.context.refresh();
|
||||
assertTrue(this.context.getEnvironment().containsProperty("local.server.port"));
|
||||
assertEquals("8080", this.context.getEnvironment().getProperty("local.server.port"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stopOnClose() throws Exception {
|
||||
addEmbeddedServletContainerFactoryBean();
|
||||
|
||||
Reference in New Issue
Block a user