M1 cut of environment, profiles and property work (SPR-7508)
Decomposed Environment interface into PropertySources, PropertyResolver
objects
Environment interface and implementations are still present, but
simpler.
PropertySources container aggregates PropertySource objects;
PropertyResolver provides search, conversion, placeholder
replacement. Single implementation for now is
PropertySourcesPlaceholderResolver
Renamed EnvironmentAwarePropertyPlaceholderConfigurer to
PropertySourcesPlaceholderConfigurer
<context:property-placeholder/> now registers PSPC by default, else
PPC if systemPropertiesMode* settings are involved
Refined configuration and behavior of default profiles
See Environment interface Javadoc for details
Added Portlet implementations of relevant interfaces:
* DefaultPortletEnvironment
* PortletConfigPropertySource, PortletContextPropertySource
* Integrated each appropriately throughout Portlet app contexts
Added protected 'createEnvironment()' method to AbstractApplicationContext
Subclasses can override at will to supply a custom Environment
implementation. In practice throughout the framework, this is how
Web- and Portlet-related ApplicationContexts override use of the
DefaultEnvironment and swap in DefaultWebEnvironment or
DefaultPortletEnvironment as appropriate.
Introduced "stub-and-replace" behavior for Servlet- and Portlet-based
PropertySource implementations
Allows for early registration and ordering of the stub, then
replacement with actual backing object at refresh() time.
Added AbstractApplicationContext.initPropertySources() method to
support stub-and-replace behavior. Called from within existing
prepareRefresh() method so as to avoid impact with
ApplicationContext implementations that copy and modify AAC's
refresh() method (e.g.: Spring DM).
Added methods to WebApplicationContextUtils and
PortletApplicationContextUtils to support stub-and-replace behavior
Added comprehensive Javadoc for all new or modified types and members
Added XSD documentation for all new or modified elements and attributes
Including nested <beans>, <beans profile="..."/>, and changes for
certain attributes type from xsd:IDREF to xsd:string
Improved fix for detecting non-file based Resources in
PropertiesLoaderSupport (SPR-7547, SPR-7552)
Technically unrelated to environment work, but grouped in with
this changeset for convenience.
Deprecated (removed) context:property-placeholder
'system-properties-mode' attribute from spring-context-3.1.xsd
Functionality is preserved for those using schemas up to and including
spring-context-3.0. For 3.1, system-properties-mode is no longer
supported as it conflicts with the idea of managing a set of property
sources within the context's Environment object. See Javadoc in
PropertyPlaceholderConfigurer, AbstractPropertyPlaceholderConfigurer
and PropertySourcesPlaceholderConfigurer for details.
Introduced CollectionUtils.toArray(Enumeration<E>, A[])
Work items remaining for 3.1 M2:
Consider repackaging PropertySource* types; eliminate internal use
of SystemPropertyUtils and deprecate
Further work on composition of Environment interface; consider
repurposing existing PlaceholderResolver interface to obviate need
for resolve[Required]Placeholder() methods currently in Environment.
Ensure configurability of placeholder prefix, suffix, and value
separator when working against an AbstractPropertyResolver
Add JNDI-based Environment / PropertySource implementatinos
Consider support for @Profile at the @Bean level
Provide consistent logging for the entire property resolution
lifecycle; consider issuing all such messages against a dedicated
logger with a single category.
Add reference documentation to cover the featureset.
This commit is contained in:
@@ -18,9 +18,7 @@ package org.springframework.core.env;
|
||||
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.isIn;
|
||||
import static org.hamcrest.Matchers.lessThan;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.rootBeanDefinition;
|
||||
@@ -37,8 +35,6 @@ import static org.springframework.core.env.EnvironmentIntegrationTests.Constants
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -64,16 +60,19 @@ import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.jca.context.ResourceAdapterApplicationContext;
|
||||
import org.springframework.jca.support.SimpleBootstrapContext;
|
||||
import org.springframework.jca.work.SimpleTaskWorkManager;
|
||||
import org.springframework.mock.env.MockPropertySource;
|
||||
import org.springframework.mock.web.MockServletConfig;
|
||||
import org.springframework.mock.web.MockServletContext;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.context.support.AbstractRefreshableWebApplicationContext;
|
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||
import org.springframework.web.context.support.DefaultWebEnvironment;
|
||||
import org.springframework.web.context.support.GenericWebApplicationContext;
|
||||
import org.springframework.web.context.support.StaticWebApplicationContext;
|
||||
import org.springframework.web.context.support.XmlWebApplicationContext;
|
||||
import org.springframework.web.portlet.context.AbstractRefreshablePortletApplicationContext;
|
||||
import org.springframework.web.portlet.context.DefaultPortletEnvironment;
|
||||
import org.springframework.web.portlet.context.StaticPortletApplicationContext;
|
||||
import org.springframework.web.portlet.context.XmlPortletApplicationContext;
|
||||
|
||||
@@ -433,34 +432,33 @@ public class EnvironmentIntegrationTests {
|
||||
|
||||
ConfigurableEnvironment environment = ctx.getEnvironment();
|
||||
assertThat(environment, instanceOf(DefaultWebEnvironment.class));
|
||||
LinkedList<PropertySource<?>> propertySources = environment.getPropertySources();
|
||||
assertThat(PropertySource.named(DefaultWebEnvironment.SERVLET_CONTEXT_PARAMS_PROPERTY_SOURCE_NAME), isIn(propertySources));
|
||||
assertThat(PropertySource.named(DefaultWebEnvironment.SERVLET_CONFIG_PARAMS_PROPERTY_SOURCE_NAME), isIn(propertySources));
|
||||
MutablePropertySources propertySources = environment.getPropertySources();
|
||||
PropertyResolver propertyResolver = environment.getPropertyResolver();
|
||||
assertThat(propertySources.contains(DefaultWebEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME), is(true));
|
||||
assertThat(propertySources.contains(DefaultWebEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME), is(true));
|
||||
|
||||
// ServletConfig gets precedence
|
||||
assertThat(environment.getProperty("pCommon"), is("pCommonConfigValue"));
|
||||
assertThat(propertySources.indexOf(PropertySource.named(DefaultWebEnvironment.SERVLET_CONFIG_PARAMS_PROPERTY_SOURCE_NAME)),
|
||||
lessThan(propertySources.indexOf(PropertySource.named(DefaultWebEnvironment.SERVLET_CONTEXT_PARAMS_PROPERTY_SOURCE_NAME))));
|
||||
assertThat(propertyResolver.getProperty("pCommon"), is("pCommonConfigValue"));
|
||||
assertThat(propertySources.asList().indexOf(PropertySource.named(DefaultWebEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME)),
|
||||
lessThan(propertySources.asList().indexOf(PropertySource.named(DefaultWebEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME))));
|
||||
|
||||
// but all params are available
|
||||
assertThat(environment.getProperty("pContext1"), is("pContext1Value"));
|
||||
assertThat(environment.getProperty("pConfig1"), is("pConfig1Value"));
|
||||
assertThat(propertyResolver.getProperty("pContext1"), is("pContext1Value"));
|
||||
assertThat(propertyResolver.getProperty("pConfig1"), is("pConfig1Value"));
|
||||
|
||||
// Servlet* PropertySources have precedence over System* PropertySources
|
||||
assertThat(propertySources.indexOf(PropertySource.named(DefaultWebEnvironment.SERVLET_CONFIG_PARAMS_PROPERTY_SOURCE_NAME)),
|
||||
lessThan(propertySources.indexOf(PropertySource.named(DefaultEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME))));
|
||||
assertThat(propertySources.asList().indexOf(PropertySource.named(DefaultWebEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME)),
|
||||
lessThan(propertySources.asList().indexOf(PropertySource.named(DefaultEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME))));
|
||||
|
||||
// Replace system properties with a mock property source for convenience
|
||||
MockPropertySource mockSystemProperties = new MockPropertySource(DefaultEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME);
|
||||
mockSystemProperties.setProperty("pCommon", "pCommonSysPropsValue");
|
||||
mockSystemProperties.setProperty("pSysProps1", "pSysProps1Value");
|
||||
propertySources.set(
|
||||
propertySources.indexOf(PropertySource.named(DefaultEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME)),
|
||||
mockSystemProperties);
|
||||
propertySources.replace(DefaultEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, mockSystemProperties);
|
||||
|
||||
// assert that servletconfig init params resolve with higher precedence than sysprops
|
||||
assertThat(environment.getProperty("pCommon"), is("pCommonConfigValue"));
|
||||
assertThat(environment.getProperty("pSysProps1"), is("pSysProps1Value"));
|
||||
// assert that servletconfig params resolve with higher precedence than sysprops
|
||||
assertThat(propertyResolver.getProperty("pCommon"), is("pCommonConfigValue"));
|
||||
assertThat(propertyResolver.getProperty("pSysProps1"), is("pSysProps1Value"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -475,29 +473,27 @@ public class EnvironmentIntegrationTests {
|
||||
|
||||
ConfigurableEnvironment environment = ctx.getEnvironment();
|
||||
assertThat(environment, instanceOf(DefaultWebEnvironment.class));
|
||||
LinkedList<PropertySource<?>> propertySources = environment.getPropertySources();
|
||||
assertThat(PropertySource.named(DefaultWebEnvironment.SERVLET_CONTEXT_PARAMS_PROPERTY_SOURCE_NAME), isIn(propertySources));
|
||||
assertThat(PropertySource.named(DefaultWebEnvironment.SERVLET_CONFIG_PARAMS_PROPERTY_SOURCE_NAME), not(isIn(propertySources)));
|
||||
MutablePropertySources propertySources = environment.getPropertySources();
|
||||
PropertyResolver propertyResolver = environment.getPropertyResolver();
|
||||
assertThat(propertySources.contains(DefaultWebEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME), is(true));
|
||||
|
||||
// ServletContext params are available
|
||||
assertThat(environment.getProperty("pCommon"), is("pCommonContextValue"));
|
||||
assertThat(environment.getProperty("pContext1"), is("pContext1Value"));
|
||||
assertThat(propertyResolver.getProperty("pCommon"), is("pCommonContextValue"));
|
||||
assertThat(propertyResolver.getProperty("pContext1"), is("pContext1Value"));
|
||||
|
||||
// Servlet* PropertySources have precedence over System* PropertySources
|
||||
assertThat(propertySources.indexOf(PropertySource.named(DefaultWebEnvironment.SERVLET_CONTEXT_PARAMS_PROPERTY_SOURCE_NAME)),
|
||||
lessThan(propertySources.indexOf(PropertySource.named(DefaultEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME))));
|
||||
assertThat(propertySources.asList().indexOf(PropertySource.named(DefaultWebEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME)),
|
||||
lessThan(propertySources.asList().indexOf(PropertySource.named(DefaultEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME))));
|
||||
|
||||
// Replace system properties with a mock property source for convenience
|
||||
MockPropertySource mockSystemProperties = new MockPropertySource(DefaultEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME);
|
||||
mockSystemProperties.setProperty("pCommon", "pCommonSysPropsValue");
|
||||
mockSystemProperties.setProperty("pSysProps1", "pSysProps1Value");
|
||||
propertySources.set(
|
||||
propertySources.indexOf(PropertySource.named(DefaultEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME)),
|
||||
mockSystemProperties);
|
||||
propertySources.replace(DefaultEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, mockSystemProperties);
|
||||
|
||||
// assert that servletcontext init params resolve with higher precedence than sysprops
|
||||
assertThat(environment.getProperty("pCommon"), is("pCommonContextValue"));
|
||||
assertThat(environment.getProperty("pSysProps1"), is("pSysProps1Value"));
|
||||
assertThat(propertyResolver.getProperty("pCommon"), is("pCommonContextValue"));
|
||||
assertThat(propertyResolver.getProperty("pSysProps1"), is("pSysProps1Value"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -515,48 +511,33 @@ public class EnvironmentIntegrationTests {
|
||||
ctx.refresh();
|
||||
|
||||
ConfigurableEnvironment environment = ctx.getEnvironment();
|
||||
LinkedList<PropertySource<?>> propertySources = environment.getPropertySources();
|
||||
assertThat(PropertySource.named(DefaultWebEnvironment.SERVLET_CONTEXT_PARAMS_PROPERTY_SOURCE_NAME), isIn(propertySources));
|
||||
assertThat(PropertySource.named(DefaultWebEnvironment.SERVLET_CONFIG_PARAMS_PROPERTY_SOURCE_NAME), isIn(propertySources));
|
||||
MutablePropertySources propertySources = environment.getPropertySources();
|
||||
PropertyResolver propertyResolver = environment.getPropertyResolver();
|
||||
assertThat(propertySources.contains(DefaultWebEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME), is(true));
|
||||
assertThat(propertySources.contains(DefaultWebEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME), is(true));
|
||||
|
||||
// ServletConfig gets precedence
|
||||
assertThat(environment.getProperty("pCommon"), is("pCommonConfigValue"));
|
||||
assertThat(propertySources.indexOf(PropertySource.named(DefaultWebEnvironment.SERVLET_CONFIG_PARAMS_PROPERTY_SOURCE_NAME)),
|
||||
lessThan(propertySources.indexOf(PropertySource.named(DefaultWebEnvironment.SERVLET_CONTEXT_PARAMS_PROPERTY_SOURCE_NAME))));
|
||||
assertThat(propertyResolver.getProperty("pCommon"), is("pCommonConfigValue"));
|
||||
assertThat(propertySources.asList().indexOf(PropertySource.named(DefaultWebEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME)),
|
||||
lessThan(propertySources.asList().indexOf(PropertySource.named(DefaultWebEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME))));
|
||||
|
||||
// but all params are available
|
||||
assertThat(environment.getProperty("pContext1"), is("pContext1Value"));
|
||||
assertThat(environment.getProperty("pConfig1"), is("pConfig1Value"));
|
||||
assertThat(propertyResolver.getProperty("pContext1"), is("pContext1Value"));
|
||||
assertThat(propertyResolver.getProperty("pConfig1"), is("pConfig1Value"));
|
||||
|
||||
// Servlet* PropertySources have precedence over System* PropertySources
|
||||
assertThat(propertySources.indexOf(PropertySource.named(DefaultWebEnvironment.SERVLET_CONFIG_PARAMS_PROPERTY_SOURCE_NAME)),
|
||||
lessThan(propertySources.indexOf(PropertySource.named(DefaultEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME))));
|
||||
assertThat(propertySources.asList().indexOf(PropertySource.named(DefaultWebEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME)),
|
||||
lessThan(propertySources.asList().indexOf(PropertySource.named(DefaultEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME))));
|
||||
|
||||
// Replace system properties with a mock property source for convenience
|
||||
MockPropertySource mockSystemProperties = new MockPropertySource(DefaultEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME);
|
||||
mockSystemProperties.setProperty("pCommon", "pCommonSysPropsValue");
|
||||
mockSystemProperties.setProperty("pSysProps1", "pSysProps1Value");
|
||||
propertySources.set(
|
||||
propertySources.indexOf(PropertySource.named(DefaultEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME)),
|
||||
mockSystemProperties);
|
||||
propertySources.replace(DefaultEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, mockSystemProperties);
|
||||
|
||||
// assert that servletconfig init params resolve with higher precedence than sysprops
|
||||
assertThat(environment.getProperty("pCommon"), is("pCommonConfigValue"));
|
||||
assertThat(environment.getProperty("pSysProps1"), is("pSysProps1Value"));
|
||||
}
|
||||
|
||||
static class MockPropertySource extends PropertiesPropertySource {
|
||||
public MockPropertySource() {
|
||||
this("MockPropertySource");
|
||||
}
|
||||
|
||||
public MockPropertySource(String name) {
|
||||
super(name, new Properties());
|
||||
}
|
||||
|
||||
public void setProperty(String key, String value) {
|
||||
this.source.setProperty(key, value);
|
||||
}
|
||||
// assert that servletconfig params resolve with higher precedence than sysprops
|
||||
assertThat(propertyResolver.getProperty("pCommon"), is("pCommonConfigValue"));
|
||||
assertThat(propertyResolver.getProperty("pSysProps1"), is("pSysProps1Value"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -580,8 +561,7 @@ public class EnvironmentIntegrationTests {
|
||||
public void staticPortletApplicationContext() {
|
||||
StaticPortletApplicationContext ctx = new StaticPortletApplicationContext();
|
||||
|
||||
// TODO SPR-7508: should be a Portlet-specific environment?
|
||||
assertHasDefaultWebEnvironment(ctx);
|
||||
assertHasDefaultPortletEnvironment(ctx);
|
||||
|
||||
registerEnvironmentBeanDefinition(ctx);
|
||||
|
||||
@@ -638,6 +618,12 @@ public class EnvironmentIntegrationTests {
|
||||
assertThat(defaultEnv, instanceOf(DefaultWebEnvironment.class));
|
||||
}
|
||||
|
||||
private void assertHasDefaultPortletEnvironment(WebApplicationContext ctx) {
|
||||
Environment defaultEnv = ctx.getEnvironment();
|
||||
assertThat(defaultEnv, notNullValue());
|
||||
assertThat(defaultEnv, instanceOf(DefaultPortletEnvironment.class));
|
||||
}
|
||||
|
||||
private void assertHasEnvironment(ApplicationContext ctx, Environment expectedEnv) {
|
||||
// ensure the custom environment took
|
||||
Environment actualEnv = ctx.getEnvironment();
|
||||
|
||||
Reference in New Issue
Block a user