Commit a7f14809 authored by Madhura Bhave's avatar Madhura Bhave

Remove binding from ConfigFileApplicationListener

Closes gh-8101
parent bdf90389
...@@ -34,11 +34,14 @@ import org.apache.commons.logging.Log; ...@@ -34,11 +34,14 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.beans.CachedIntrospectionResults;
import org.springframework.beans.factory.groovy.GroovyBeanDefinitionReader; import org.springframework.beans.factory.groovy.GroovyBeanDefinitionReader;
import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanNameGenerator; import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.boot.Banner.Mode; import org.springframework.boot.Banner.Mode;
import org.springframework.boot.bind.PropertiesConfigurationFactory;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.boot.diagnostics.FailureAnalyzers; import org.springframework.boot.diagnostics.FailureAnalyzers;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ApplicationContextInitializer;
...@@ -52,6 +55,8 @@ import org.springframework.context.support.AbstractApplicationContext; ...@@ -52,6 +55,8 @@ import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericApplicationContext; import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.GenericTypeResolver; import org.springframework.core.GenericTypeResolver;
import org.springframework.core.annotation.AnnotationAwareOrderComparator; import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.core.env.CommandLinePropertySource; import org.springframework.core.env.CommandLinePropertySource;
import org.springframework.core.env.CompositePropertySource; import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.ConfigurableEnvironment;
...@@ -71,6 +76,7 @@ import org.springframework.util.ObjectUtils; ...@@ -71,6 +76,7 @@ import org.springframework.util.ObjectUtils;
import org.springframework.util.ReflectionUtils; import org.springframework.util.ReflectionUtils;
import org.springframework.util.StopWatch; import org.springframework.util.StopWatch;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.validation.BindException;
import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.StandardServletEnvironment; import org.springframework.web.context.support.StandardServletEnvironment;
...@@ -132,6 +138,12 @@ import org.springframework.web.context.support.StandardServletEnvironment; ...@@ -132,6 +138,12 @@ import org.springframework.web.context.support.StandardServletEnvironment;
* resolve to a {@link Resource} that exists it will be considered a {@link Package}.</li> * resolve to a {@link Resource} that exists it will be considered a {@link Package}.</li>
* </ul> * </ul>
* *
* Configuration properties are also bound to the {@link SpringApplication}. This makes it
* possible to set {@link SpringApplication} properties dynamically, like the sources
* ("spring.main.sources" - a CSV list) the flag to indicate a web environment
* ("spring.main.web_environment=true") or the flag to switch off the banner
* ("spring.main.show_banner=false").
*
* @author Phillip Webb * @author Phillip Webb
* @author Dave Syer * @author Dave Syer
* @author Andy Wilkinson * @author Andy Wilkinson
...@@ -140,6 +152,7 @@ import org.springframework.web.context.support.StandardServletEnvironment; ...@@ -140,6 +152,7 @@ import org.springframework.web.context.support.StandardServletEnvironment;
* @author Jeremy Rickard * @author Jeremy Rickard
* @author Craig Burke * @author Craig Burke
* @author Michael Simons * @author Michael Simons
* @author Madhura Bhave
* @see #run(Object, String[]) * @see #run(Object, String[])
* @see #run(Object[], String[]) * @see #run(Object[], String[])
* @see #SpringApplication(Object...) * @see #SpringApplication(Object...)
...@@ -306,6 +319,8 @@ public class SpringApplication { ...@@ -306,6 +319,8 @@ public class SpringApplication {
args); args);
ConfigurableEnvironment environment = prepareEnvironment(listeners, ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments); applicationArguments);
configureIgnoreBeanInfo(environment);
bindToSpringApplication(environment);
Banner printedBanner = printBanner(environment); Banner printedBanner = printBanner(environment);
context = createApplicationContext(); context = createApplicationContext();
analyzers = new FailureAnalyzers(context); analyzers = new FailureAnalyzers(context);
...@@ -535,6 +550,35 @@ public class SpringApplication { ...@@ -535,6 +550,35 @@ public class SpringApplication {
environment.setActiveProfiles(profiles.toArray(new String[profiles.size()])); environment.setActiveProfiles(profiles.toArray(new String[profiles.size()]));
} }
private void configureIgnoreBeanInfo(ConfigurableEnvironment environment) {
if (System.getProperty(
CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME) == null) {
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(environment,
"spring.beaninfo.");
Boolean ignore = resolver.getProperty("ignore", Boolean.class, Boolean.TRUE);
System.setProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME,
ignore.toString());
}
}
/**
* Bind the environment to the {@link SpringApplication}.
* @param environment the environment to bind
*/
protected void bindToSpringApplication(ConfigurableEnvironment environment) {
PropertiesConfigurationFactory<SpringApplication> binder = new PropertiesConfigurationFactory<>(this);
ConversionService conversionService = new DefaultConversionService();
binder.setTargetName("spring.main");
binder.setConversionService(conversionService);
binder.setPropertySources(environment.getPropertySources());
try {
binder.bindPropertiesToTarget();
}
catch (BindException ex) {
throw new IllegalStateException("Cannot bind to SpringApplication", ex);
}
}
private Banner printBanner(ConfigurableEnvironment environment) { private Banner printBanner(ConfigurableEnvironment environment) {
if (this.bannerMode == Banner.Mode.OFF) { if (this.bannerMode == Banner.Mode.OFF) {
return null; return null;
......
...@@ -31,14 +31,11 @@ import java.util.Set; ...@@ -31,14 +31,11 @@ import java.util.Set;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.springframework.beans.BeansException; import org.springframework.beans.BeansException;
import org.springframework.beans.CachedIntrospectionResults;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.bind.PropertiesConfigurationFactory;
import org.springframework.boot.bind.PropertySourcesPropertyValues; import org.springframework.boot.bind.PropertySourcesPropertyValues;
import org.springframework.boot.bind.RelaxedDataBinder; import org.springframework.boot.bind.RelaxedDataBinder;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.boot.context.event.ApplicationPreparedEvent; import org.springframework.boot.context.event.ApplicationPreparedEvent;
import org.springframework.boot.env.EnumerableCompositePropertySource; import org.springframework.boot.env.EnumerableCompositePropertySource;
...@@ -51,8 +48,6 @@ import org.springframework.context.ConfigurableApplicationContext; ...@@ -51,8 +48,6 @@ import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ConfigurationClassPostProcessor; import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.core.Ordered; import org.springframework.core.Ordered;
import org.springframework.core.annotation.AnnotationAwareOrderComparator; import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.EnumerablePropertySource; import org.springframework.core.env.EnumerablePropertySource;
import org.springframework.core.env.MutablePropertySources; import org.springframework.core.env.MutablePropertySources;
...@@ -65,7 +60,6 @@ import org.springframework.core.io.support.SpringFactoriesLoader; ...@@ -65,7 +60,6 @@ import org.springframework.core.io.support.SpringFactoriesLoader;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.ResourceUtils; import org.springframework.util.ResourceUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.validation.BindException;
/** /**
* {@link EnvironmentPostProcessor} that configures the context environment by loading * {@link EnvironmentPostProcessor} that configures the context environment by loading
...@@ -89,11 +83,6 @@ import org.springframework.validation.BindException; ...@@ -89,11 +83,6 @@ import org.springframework.validation.BindException;
* and the 'spring.config.location' property can be used to specify alternative search * and the 'spring.config.location' property can be used to specify alternative search
* locations or specific files. * locations or specific files.
* <p> * <p>
* Configuration properties are also bound to the {@link SpringApplication}. This makes it
* possible to set {@link SpringApplication} properties dynamically, like the sources
* ("spring.main.sources" - a CSV list) the flag to indicate a web environment
* ("spring.main.web_environment=true") or the flag to switch off the banner
* ("spring.main.show_banner=false").
* *
* @author Dave Syer * @author Dave Syer
* @author Phillip Webb * @author Phillip Webb
...@@ -149,8 +138,6 @@ public class ConfigFileApplicationListener implements EnvironmentPostProcessor, ...@@ -149,8 +138,6 @@ public class ConfigFileApplicationListener implements EnvironmentPostProcessor,
private int order = DEFAULT_ORDER; private int order = DEFAULT_ORDER;
private final ConversionService conversionService = new DefaultConversionService();
@Override @Override
public void onApplicationEvent(ApplicationEvent event) { public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ApplicationEnvironmentPreparedEvent) { if (event instanceof ApplicationEnvironmentPreparedEvent) {
...@@ -182,19 +169,6 @@ public class ConfigFileApplicationListener implements EnvironmentPostProcessor, ...@@ -182,19 +169,6 @@ public class ConfigFileApplicationListener implements EnvironmentPostProcessor,
public void postProcessEnvironment(ConfigurableEnvironment environment, public void postProcessEnvironment(ConfigurableEnvironment environment,
SpringApplication application) { SpringApplication application) {
addPropertySources(environment, application.getResourceLoader()); addPropertySources(environment, application.getResourceLoader());
configureIgnoreBeanInfo(environment);
bindToSpringApplication(environment, application);
}
private void configureIgnoreBeanInfo(ConfigurableEnvironment environment) {
if (System.getProperty(
CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME) == null) {
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(environment,
"spring.beaninfo.");
Boolean ignore = resolver.getProperty("ignore", Boolean.class, Boolean.TRUE);
System.setProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME,
ignore.toString());
}
} }
private void onApplicationPreparedEvent(ApplicationEvent event) { private void onApplicationPreparedEvent(ApplicationEvent event) {
...@@ -219,26 +193,6 @@ public class ConfigFileApplicationListener implements EnvironmentPostProcessor, ...@@ -219,26 +193,6 @@ public class ConfigFileApplicationListener implements EnvironmentPostProcessor,
} }
} }
/**
* Bind the environment to the {@link SpringApplication}.
* @param environment the environment to bind
* @param application the application to bind to
*/
protected void bindToSpringApplication(ConfigurableEnvironment environment,
SpringApplication application) {
PropertiesConfigurationFactory<SpringApplication> binder = new PropertiesConfigurationFactory<SpringApplication>(
application);
binder.setTargetName("spring.main");
binder.setConversionService(this.conversionService);
binder.setPropertySources(environment.getPropertySources());
try {
binder.bindPropertiesToTarget();
}
catch (BindException ex) {
throw new IllegalStateException("Cannot bind to SpringApplication", ex);
}
}
/** /**
* Add appropriate post-processors to post-configure the property-sources. * Add appropriate post-processors to post-configure the property-sources.
* @param context the context to configure * @param context the context to configure
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
package org.springframework.boot; package org.springframework.boot;
import java.lang.reflect.Field;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
...@@ -37,6 +38,7 @@ import org.junit.rules.ExpectedException; ...@@ -37,6 +38,7 @@ import org.junit.rules.ExpectedException;
import org.mockito.ArgumentCaptor; import org.mockito.ArgumentCaptor;
import org.springframework.beans.BeansException; import org.springframework.beans.BeansException;
import org.springframework.beans.CachedIntrospectionResults;
import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanNameGenerator; import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.beans.factory.support.DefaultBeanNameGenerator; import org.springframework.beans.factory.support.DefaultBeanNameGenerator;
...@@ -75,6 +77,7 @@ import org.springframework.core.io.DefaultResourceLoader; ...@@ -75,6 +77,7 @@ import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader; import org.springframework.core.io.ResourceLoader;
import org.springframework.test.context.support.TestPropertySourceUtils; import org.springframework.test.context.support.TestPropertySourceUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.web.context.support.StandardServletEnvironment; import org.springframework.web.context.support.StandardServletEnvironment;
...@@ -98,6 +101,7 @@ import static org.mockito.Mockito.verifyNoMoreInteractions; ...@@ -98,6 +101,7 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
* @author Stephane Nicoll * @author Stephane Nicoll
* @author Jeremy Rickard * @author Jeremy Rickard
* @author Craig Burke * @author Craig Burke
* @author Madhura Bhave
*/ */
public class SpringApplicationTests { public class SpringApplicationTests {
...@@ -126,6 +130,7 @@ public class SpringApplicationTests { ...@@ -126,6 +130,7 @@ public class SpringApplicationTests {
@After @After
public void reinstateHeadlessProperty() { public void reinstateHeadlessProperty() {
System.clearProperty("spring.main.banner-mode");
if (this.headlessProperty == null) { if (this.headlessProperty == null) {
System.clearProperty("java.awt.headless"); System.clearProperty("java.awt.headless");
} }
...@@ -231,6 +236,48 @@ public class SpringApplicationTests { ...@@ -231,6 +236,48 @@ public class SpringApplicationTests {
assertThat(this.output.toString()).contains("o.s.boot.SpringApplication"); assertThat(this.output.toString()).contains("o.s.boot.SpringApplication");
} }
@Test
public void setIgnoreBeanInfoPropertyByDefault() throws Exception {
SpringApplication application = new SpringApplication(ExampleConfig.class);
application.setWebEnvironment(false);
this.context = application.run();
String property = System
.getProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME);
assertThat(property).isEqualTo("true");
}
@Test
public void disableIgnoreBeanInfoProperty() throws Exception {
System.setProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME, "false");
SpringApplication application = new SpringApplication(ExampleConfig.class);
application.setWebEnvironment(false);
this.context = application.run();
String property = System
.getProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME);
assertThat(property).isEqualTo("false");
}
@Test
public void triggersConfigFileApplicationListenereBeforeBinding() throws Exception {
SpringApplication application = new SpringApplication(ExampleConfig.class);
application.setWebEnvironment(false);
this.context = application.run("--spring.config.name=bindtoapplication");
Field field = ReflectionUtils.findField(SpringApplication.class, "bannerMode");
field.setAccessible(true);
assertThat((Banner.Mode) field.get(application)).isEqualTo(Banner.Mode.OFF);
}
@Test
public void bindsSystemPropertyToSpringApplication() throws Exception {
System.setProperty("spring.main.banner-mode", "off");
SpringApplication application = new SpringApplication(ExampleConfig.class);
application.setWebEnvironment(false);
this.context = application.run();
Field field = ReflectionUtils.findField(SpringApplication.class, "bannerMode");
field.setAccessible(true);
assertThat((Banner.Mode) field.get(application)).isEqualTo(Banner.Mode.OFF);
}
@Test @Test
public void customId() throws Exception { public void customId() throws Exception {
SpringApplication application = new SpringApplication(ExampleConfig.class); SpringApplication application = new SpringApplication(ExampleConfig.class);
......
...@@ -19,7 +19,6 @@ package org.springframework.boot.context.config; ...@@ -19,7 +19,6 @@ package org.springframework.boot.context.config;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.lang.reflect.Field;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
...@@ -39,7 +38,6 @@ import org.junit.rules.ExpectedException; ...@@ -39,7 +38,6 @@ import org.junit.rules.ExpectedException;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.CachedIntrospectionResults; import org.springframework.beans.CachedIntrospectionResults;
import org.springframework.boot.Banner;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.context.config.ConfigFileApplicationListener.ConfigurationPropertySources; import org.springframework.boot.context.config.ConfigFileApplicationListener.ConfigurationPropertySources;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
...@@ -63,7 +61,6 @@ import org.springframework.core.io.ByteArrayResource; ...@@ -63,7 +61,6 @@ import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader; import org.springframework.core.io.ResourceLoader;
import org.springframework.test.context.support.TestPropertySourceUtils; import org.springframework.test.context.support.TestPropertySourceUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
...@@ -739,26 +736,6 @@ public class ConfigFileApplicationListenerTests { ...@@ -739,26 +736,6 @@ public class ConfigFileApplicationListenerTests {
assertThat(property).isEqualTo("baz"); assertThat(property).isEqualTo("baz");
} }
@Test
public void bindsToSpringApplication() throws Exception {
// gh-346
this.initializer.setSearchNames("bindtoapplication");
this.initializer.postProcessEnvironment(this.environment, this.application);
Field field = ReflectionUtils.findField(SpringApplication.class, "bannerMode");
field.setAccessible(true);
assertThat((Banner.Mode) field.get(this.application)).isEqualTo(Banner.Mode.OFF);
}
@Test
public void bindsSystemPropertyToSpringApplication() throws Exception {
// gh-951
System.setProperty("spring.main.banner-mode", "off");
this.initializer.postProcessEnvironment(this.environment, this.application);
Field field = ReflectionUtils.findField(SpringApplication.class, "bannerMode");
field.setAccessible(true);
assertThat((Banner.Mode) field.get(this.application)).isEqualTo(Banner.Mode.OFF);
}
@Test @Test
public void profileSubDocumentInDifferentProfileSpecificFile() throws Exception { public void profileSubDocumentInDifferentProfileSpecificFile() throws Exception {
// gh-4132 // gh-4132
...@@ -770,26 +747,6 @@ public class ConfigFileApplicationListenerTests { ...@@ -770,26 +747,6 @@ public class ConfigFileApplicationListenerTests {
assertThat(property).isEqualTo("baz"); assertThat(property).isEqualTo("baz");
} }
@Test
public void setIgnoreBeanInfoPropertyByDefault() throws Exception {
this.initializer.setSearchNames("testproperties");
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = System
.getProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME);
assertThat(property).isEqualTo("true");
}
@Test
public void disableIgnoreBeanInfoProperty() throws Exception {
this.initializer.setSearchNames("testproperties");
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment,
"spring.beaninfo.ignore=false");
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = System
.getProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME);
assertThat(property).isEqualTo("false");
}
@Test @Test
public void addBeforeDefaultProperties() throws Exception { public void addBeforeDefaultProperties() throws Exception {
MapPropertySource defaultSource = new MapPropertySource("defaultProperties", MapPropertySource defaultSource = new MapPropertySource("defaultProperties",
......
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