Merge 3.1.0 development branch into trunk
Branch in question is 'env' branch from git://git.springsource.org/sandbox/cbeams.git; merged into
git-svn repository with:
git merge -s recursive -Xtheirs --no-commit env
No merge conflicts, but did need to
git rm spring-build
prior to committing.
With this change, Spring 3.1.0 development is now happening on SVN
trunk. Further commits to the 3.0.x line will happen in an as-yet
uncreated SVN branch. 3.1.0 snapshots will be available
per the usual nightly CI build from trunk.
This commit is contained in:
@@ -1,44 +1,281 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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.beans.factory.config;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.nullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.rootBeanDefinition;
|
||||
import static org.springframework.beans.factory.support.BeanDefinitionReaderUtils.registerWithGeneratedName;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.core.io.ByteArrayResource;
|
||||
|
||||
import test.beans.TestBean;
|
||||
|
||||
|
||||
/**
|
||||
* Tests cornering SPR-7547.
|
||||
* Unit tests for {@link EnvironmentAwarePropertyPlaceholderConfigurer}.
|
||||
*
|
||||
* @see PropertyResourceConfigurerTests
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class PropertyPlaceholderConfigurerTests {
|
||||
private static final String P1 = "p1";
|
||||
private static final String P1_LOCAL_PROPS_VAL = "p1LocalPropsVal";
|
||||
private static final String P1_SYSTEM_PROPS_VAL = "p1SystemPropsVal";
|
||||
private static final String P1_SYSTEM_ENV_VAL = "p1SystemEnvVal";
|
||||
|
||||
private DefaultListableBeanFactory bf;
|
||||
private AbstractPropertyPlaceholderConfigurer ppc;
|
||||
private Properties ppcProperties;
|
||||
|
||||
private AbstractBeanDefinition p1BeanDef;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
p1BeanDef = rootBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "${"+P1+"}")
|
||||
.getBeanDefinition();
|
||||
|
||||
bf = new DefaultListableBeanFactory();
|
||||
|
||||
ppcProperties = new Properties();
|
||||
ppcProperties.setProperty(P1, P1_LOCAL_PROPS_VAL);
|
||||
System.setProperty(P1, P1_SYSTEM_PROPS_VAL);
|
||||
getModifiableSystemEnvironment().put(P1, P1_SYSTEM_ENV_VAL);
|
||||
ppc = new PropertyPlaceholderConfigurer();
|
||||
ppc.setProperties(ppcProperties);
|
||||
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
System.clearProperty(P1);
|
||||
getModifiableSystemEnvironment().remove(P1);
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Tests to ensure backward-compatibility for Environment refactoring
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
public void resolveFromSystemProperties() {
|
||||
getModifiableSystemEnvironment().put("otherKey", "systemValue");
|
||||
p1BeanDef = rootBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "${"+P1+"}")
|
||||
.addPropertyValue("sex", "${otherKey}")
|
||||
.getBeanDefinition();
|
||||
registerWithGeneratedName(p1BeanDef, bf);
|
||||
ppc.postProcessBeanFactory(bf);
|
||||
TestBean bean = bf.getBean(TestBean.class);
|
||||
assertThat(bean.getName(), equalTo(P1_LOCAL_PROPS_VAL));
|
||||
assertThat(bean.getSex(), equalTo("systemValue"));
|
||||
getModifiableSystemEnvironment().remove("otherKey");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveFromLocalProperties() {
|
||||
tearDown(); // eliminate entries from system props/environment
|
||||
registerWithGeneratedName(p1BeanDef, bf);
|
||||
ppc.postProcessBeanFactory(bf);
|
||||
TestBean bean = bf.getBean(TestBean.class);
|
||||
assertThat(bean.getName(), equalTo(P1_LOCAL_PROPS_VAL));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setSystemPropertiesMode_defaultIsFallback() {
|
||||
registerWithGeneratedName(p1BeanDef, bf);
|
||||
ppc.postProcessBeanFactory(bf);
|
||||
TestBean bean = bf.getBean(TestBean.class);
|
||||
assertThat(bean.getName(), equalTo(P1_LOCAL_PROPS_VAL));
|
||||
}
|
||||
|
||||
/*
|
||||
@Test
|
||||
public void setSystemSystemPropertiesMode_toOverride_andResolveFromSystemProperties() {
|
||||
registerWithGeneratedName(p1BeanDef, bf);
|
||||
ppc.setSystemPropertiesMode(PropertyPlaceholderConfigurer.SYSTEM_PROPERTIES_MODE_OVERRIDE);
|
||||
ppc.postProcessBeanFactory(bf);
|
||||
TestBean bean = bf.getBean(TestBean.class);
|
||||
assertThat(bean.getName(), equalTo(P1_SYSTEM_PROPS_VAL));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setSystemSystemPropertiesMode_toOverride_andResolveFromSystemEnvironment() {
|
||||
registerWithGeneratedName(p1BeanDef, bf);
|
||||
System.clearProperty(P1); // will now fall all the way back to system environment
|
||||
ppc.setSystemPropertiesMode(PropertyPlaceholderConfigurer.SYSTEM_PROPERTIES_MODE_OVERRIDE);
|
||||
ppc.postProcessBeanFactory(bf);
|
||||
TestBean bean = bf.getBean(TestBean.class);
|
||||
assertThat(bean.getName(), equalTo(P1_SYSTEM_ENV_VAL));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setSystemSystemPropertiesMode_toOverride_andSetSearchSystemEnvironment_toFalse() {
|
||||
registerWithGeneratedName(p1BeanDef, bf);
|
||||
System.clearProperty(P1); // will now fall all the way back to system environment
|
||||
ppc.setSearchSystemEnvironment(false);
|
||||
ppc.setSystemPropertiesMode(PropertyPlaceholderConfigurer.SYSTEM_PROPERTIES_MODE_OVERRIDE);
|
||||
ppc.postProcessBeanFactory(bf);
|
||||
TestBean bean = bf.getBean(TestBean.class);
|
||||
assertThat(bean.getName(), equalTo(P1_LOCAL_PROPS_VAL)); // has to resort to local props
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Prior to the fix for SPR-7547, the following would throw
|
||||
* IllegalStateException because the PropertiesLoaderSupport base class
|
||||
* assumed ByteArrayResource implements Resource.getFilename(). It does
|
||||
* not, and AbstractResource.getFilename() is called instead, raising the
|
||||
* exception. The following now works, as getFilename() is called in a
|
||||
* try/catch to check whether the resource is actually file-based or not.
|
||||
*
|
||||
* See SPR-7552, which suggests paths to address the root issue rather than
|
||||
* just patching the problem.
|
||||
* Creates a scenario in which two PPCs are configured, each with different
|
||||
* settings regarding resolving properties from the environment.
|
||||
*/
|
||||
@Test
|
||||
public void repro() {
|
||||
public void twoPlacholderConfigurers_withConflictingSettings() {
|
||||
String P2 = "p2";
|
||||
String P2_LOCAL_PROPS_VAL = "p2LocalPropsVal";
|
||||
String P2_SYSTEM_PROPS_VAL = "p2SystemPropsVal";
|
||||
String P2_SYSTEM_ENV_VAL = "p2SystemEnvVal";
|
||||
|
||||
AbstractBeanDefinition p2BeanDef = rootBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "${"+P1+"}")
|
||||
.addPropertyValue("country", "${"+P2+"}")
|
||||
.getBeanDefinition();
|
||||
|
||||
bf.registerBeanDefinition("p1Bean", p1BeanDef);
|
||||
bf.registerBeanDefinition("p2Bean", p2BeanDef);
|
||||
|
||||
ppc.setIgnoreUnresolvablePlaceholders(true);
|
||||
ppc.postProcessBeanFactory(bf);
|
||||
|
||||
System.setProperty(P2, P2_SYSTEM_PROPS_VAL);
|
||||
getModifiableSystemEnvironment().put(P2, P2_SYSTEM_ENV_VAL);
|
||||
Properties ppc2Properties = new Properties();
|
||||
ppc2Properties.put(P2, P2_LOCAL_PROPS_VAL);
|
||||
|
||||
PropertyPlaceholderConfigurer ppc2 = new PropertyPlaceholderConfigurer();
|
||||
ppc2.setSystemPropertiesMode(PropertyPlaceholderConfigurer.SYSTEM_PROPERTIES_MODE_OVERRIDE);
|
||||
ppc2.setProperties(ppc2Properties);
|
||||
|
||||
ppc2Properties = new Properties();
|
||||
ppc2Properties.setProperty(P2, P2_LOCAL_PROPS_VAL);
|
||||
ppc2.postProcessBeanFactory(bf);
|
||||
|
||||
TestBean p1Bean = bf.getBean("p1Bean", TestBean.class);
|
||||
assertThat(p1Bean.getName(), equalTo(P1_LOCAL_PROPS_VAL));
|
||||
|
||||
TestBean p2Bean = bf.getBean("p2Bean", TestBean.class);
|
||||
assertThat(p2Bean.getName(), equalTo(P1_LOCAL_PROPS_VAL));
|
||||
assertThat(p2Bean.getCountry(), equalTo(P2_SYSTEM_PROPS_VAL));
|
||||
|
||||
System.clearProperty(P2);
|
||||
getModifiableSystemEnvironment().remove(P2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customPlaceholderPrefixAndSuffix() {
|
||||
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
|
||||
ppc.setPlaceholderPrefix("@<");
|
||||
ppc.setPlaceholderSuffix(">");
|
||||
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.registerBeanDefinition("testBean",
|
||||
rootBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "${my.name}").getBeanDefinition());
|
||||
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
|
||||
ppc.setLocation(new ByteArrayResource("my.name=Inigo Montoya".getBytes()));
|
||||
ppc.postProcessBeanFactory(bf);
|
||||
.addPropertyValue("name", "@<key1>")
|
||||
.addPropertyValue("sex", "${key2}")
|
||||
.getBeanDefinition());
|
||||
|
||||
TestBean testBean = bf.getBean(TestBean.class);
|
||||
assertThat(testBean.getName(), equalTo("Inigo Montoya"));
|
||||
System.setProperty("key1", "systemKey1Value");
|
||||
System.setProperty("key2", "systemKey2Value");
|
||||
ppc.postProcessBeanFactory(bf);
|
||||
System.clearProperty("key1");
|
||||
System.clearProperty("key2");
|
||||
|
||||
assertThat(bf.getBean(TestBean.class).getName(), is("systemKey1Value"));
|
||||
assertThat(bf.getBean(TestBean.class).getSex(), is("${key2}"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nullValueIsPreserved() {
|
||||
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
|
||||
ppc.setNullValue("customNull");
|
||||
getModifiableSystemEnvironment().put("my.name", "customNull");
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.registerBeanDefinition("testBean", rootBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "${my.name}")
|
||||
.getBeanDefinition());
|
||||
ppc.postProcessBeanFactory(bf);
|
||||
assertThat(bf.getBean(TestBean.class).getName(), nullValue());
|
||||
getModifiableSystemEnvironment().remove("my.name");
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Tests for functionality not possible prior to Environment refactoring
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Tests that properties against a BeanFactory's Environment are used by
|
||||
* PropertyPlaceholderConfigurer during placeholder resolution.
|
||||
@Test @SuppressWarnings({ "unchecked", "rawtypes", "serial" })
|
||||
public void replacePlaceholdersFromBeanFactoryEnvironmentPropertySources() {
|
||||
System.setProperty("key1", "systemValue");
|
||||
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.getEnvironment().addPropertySource("psCustom", new HashMap() {{ put("key1", "customValue"); }});
|
||||
bf.registerBeanDefinition("testBean",
|
||||
rootBeanDefinition(TestBean.class).addPropertyValue("name", "${key1}").getBeanDefinition());
|
||||
|
||||
new PropertyPlaceholderConfigurer().postProcessBeanFactory(bf);
|
||||
assertThat(bf.getBean(TestBean.class).getName(), is("customValue"));
|
||||
|
||||
System.clearProperty("key1");
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Utilities
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// TODO SPR-7508: duplicated from EnvironmentPropertyResolutionSearchTests
|
||||
@SuppressWarnings("unchecked")
|
||||
private static Map<String, String> getModifiableSystemEnvironment() {
|
||||
Class<?>[] classes = Collections.class.getDeclaredClasses();
|
||||
Map<String, String> env = System.getenv();
|
||||
for (Class<?> cl : classes) {
|
||||
if ("java.util.Collections$UnmodifiableMap".equals(cl.getName())) {
|
||||
try {
|
||||
Field field = cl.getDeclaredField("m");
|
||||
field.setAccessible(true);
|
||||
Object obj = field.get(env);
|
||||
return (Map<String, String>) obj;
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,14 @@
|
||||
|
||||
package org.springframework.beans.factory.config;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.genericBeanDefinition;
|
||||
import static test.util.TestResourceUtils.qualifiedResource;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -23,18 +31,12 @@ import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.prefs.Preferences;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import test.beans.IndexedTestBean;
|
||||
import test.beans.TestBean;
|
||||
import static test.util.TestResourceUtils.*;
|
||||
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.BeanInitializationException;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.*;
|
||||
import org.springframework.beans.factory.support.ChildBeanDefinition;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.ManagedList;
|
||||
@@ -43,11 +45,15 @@ import org.springframework.beans.factory.support.ManagedSet;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
import test.beans.IndexedTestBean;
|
||||
import test.beans.TestBean;
|
||||
|
||||
/**
|
||||
* Unit tests for various {@link PropertyResourceConfigurer} implementations including:
|
||||
* {@link PropertyPlaceholderConfigurer}, {@link PropertyOverrideConfigurer} and
|
||||
* {@link PreferencesPlaceholderConfigurer}.
|
||||
*
|
||||
* @see PropertyPlaceholderConfigurerTests
|
||||
* @since 02.10.2003
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
@@ -794,6 +800,39 @@ public final class PropertyResourceConfigurerTests {
|
||||
Preferences.systemRoot().node("mySystemPath/mypath").remove("myName");
|
||||
}
|
||||
|
||||
/* TODO SPR-7508: uncomment after EnvironmentAwarePropertyPlaceholderConfigurer implementation
|
||||
@Test
|
||||
public void testPreferencesPlaceholderConfigurerWithCustomPropertiesInEnvironment() {
|
||||
factory.registerBeanDefinition("tb",
|
||||
genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "${mypath/myName}")
|
||||
.addPropertyValue("age", "${myAge}")
|
||||
.addPropertyValue("touchy", "${myotherpath/myTouchy}")
|
||||
.getBeanDefinition());
|
||||
|
||||
Properties props = new Properties();
|
||||
props.put("myAge", "99");
|
||||
factory.getEnvironment().getPropertySources().add(new PropertiesPropertySource("localProps", props));
|
||||
|
||||
PreferencesPlaceholderConfigurer ppc = new PreferencesPlaceholderConfigurer();
|
||||
ppc.setSystemTreePath("mySystemPath");
|
||||
ppc.setUserTreePath("myUserPath");
|
||||
Preferences.systemRoot().node("mySystemPath").node("mypath").put("myName", "myNameValue");
|
||||
Preferences.systemRoot().node("mySystemPath/myotherpath").put("myTouchy", "myTouchyValue");
|
||||
Preferences.userRoot().node("myUserPath/myotherpath").put("myTouchy", "myOtherTouchyValue");
|
||||
ppc.afterPropertiesSet();
|
||||
ppc.postProcessBeanFactory(factory);
|
||||
|
||||
TestBean tb = (TestBean) factory.getBean("tb");
|
||||
assertEquals("myNameValue", tb.getName());
|
||||
assertEquals(99, tb.getAge());
|
||||
assertEquals("myOtherTouchyValue", tb.getTouchy());
|
||||
Preferences.userRoot().node("myUserPath/myotherpath").remove("myTouchy");
|
||||
Preferences.systemRoot().node("mySystemPath/myotherpath").remove("myTouchy");
|
||||
Preferences.systemRoot().node("mySystemPath/mypath").remove("myName");
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
private static class ConvertingOverrideConfigurer extends PropertyOverrideConfigurer {
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
|
||||
|
||||
<bean id="testBean" class="test.beans.TestBean">
|
||||
<property name="name" value="topLevel"/>
|
||||
</bean>
|
||||
|
||||
<beans>
|
||||
<bean id="testBean" class="test.beans.TestBean">
|
||||
<property name="name" value="nested"/>
|
||||
</bean>
|
||||
</beans>
|
||||
</beans>
|
||||
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
|
||||
|
||||
<bean id="testBean" class="test.beans.TestBean">
|
||||
<property name="name" value="original"/>
|
||||
</bean>
|
||||
|
||||
<!-- STS should raise an error for this duplicate id -->
|
||||
<bean id="testBean" class="test.beans.TestBean">
|
||||
<property name="name" value="duplicate"/>
|
||||
</bean>
|
||||
</beans>
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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.beans.factory.xml;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
|
||||
import test.beans.TestBean;
|
||||
|
||||
|
||||
/**
|
||||
* With Spring 3.1, bean id attributes (and all other id attributes across the
|
||||
* core schemas) are no longer typed as xsd:id, but as xsd:string. This allows
|
||||
* for using the same bean id within nested <beans> elements.
|
||||
*
|
||||
* Duplicate ids *within the same level of nesting* will still be treated as an
|
||||
* error through the ProblemReporter, as this could never be an intended/valid
|
||||
* situation.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @since 3.1
|
||||
* @see org.springframework.beans.factory.xml.XmlBeanFactoryTests#testWithDuplicateName
|
||||
* @see org.springframework.beans.factory.xml.XmlBeanFactoryTests#testWithDuplicateNameInAlias
|
||||
*/
|
||||
public class DuplicateBeanIdTests {
|
||||
|
||||
@Test
|
||||
public void duplicateBeanIdsWithinSameNestingLevelRaisesError() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(bf);
|
||||
try {
|
||||
reader.loadBeanDefinitions(new ClassPathResource("DuplicateBeanIdTests-sameLevel-context.xml", this.getClass()));
|
||||
fail("expected parsing exception due to duplicate ids in same nesting level");
|
||||
} catch (Exception ex) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void duplicateBeanIdsAcrossNestingLevels() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(bf);
|
||||
reader.loadBeanDefinitions(new ClassPathResource("DuplicateBeanIdTests-multiLevel-context.xml", this.getClass()));
|
||||
TestBean testBean = bf.getBean(TestBean.class); // there should be only one
|
||||
assertThat(testBean.getName(), equalTo("nested"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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.beans.factory.xml;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.not;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.Matcher;
|
||||
import org.junit.Test;
|
||||
import org.junit.internal.matchers.TypeSafeMatcher;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.core.env.DefaultEnvironment;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
|
||||
/**
|
||||
* TODO SPR-7508: document
|
||||
*
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class EnvironmentBeansTests {
|
||||
|
||||
private static final String PROD_ELIGIBLE_XML = "environmentBeans-prodProfile.xml";
|
||||
private static final String DEV_ELIGIBLE_XML = "environmentBeans-devProfile.xml";
|
||||
private static final String ALL_ELIGIBLE_XML = "environmentBeans-noProfile.xml";
|
||||
private static final String MULTI_ELIGIBLE_XML = "environmentBeans-multiProfile.xml";
|
||||
private static final String UNKOWN_ELIGIBLE_XML = "environmentBeans-unknownProfile.xml";
|
||||
|
||||
private static final String PROD_ACTIVE = "prod";
|
||||
private static final String DEV_ACTIVE = "dev";
|
||||
private static final String NULL_ACTIVE = null;
|
||||
private static final String UNKNOWN_ACTIVE = "unknown";
|
||||
private static final String[] NONE_ACTIVE = new String[0];
|
||||
private static final String[] MULTI_ACTIVE = new String[] { PROD_ACTIVE, DEV_ACTIVE };
|
||||
|
||||
private static final String TARGET_BEAN = "foo";
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
assertThat(beanFactoryFor(PROD_ELIGIBLE_XML, NONE_ACTIVE), not(containsTargetBean()));
|
||||
assertThat(beanFactoryFor(PROD_ELIGIBLE_XML, NULL_ACTIVE), not(containsTargetBean()));
|
||||
assertThat(beanFactoryFor(PROD_ELIGIBLE_XML, DEV_ACTIVE), not(containsTargetBean()));
|
||||
assertThat(beanFactoryFor(PROD_ELIGIBLE_XML, PROD_ACTIVE), containsTargetBean());
|
||||
assertThat(beanFactoryFor(PROD_ELIGIBLE_XML, MULTI_ACTIVE), containsTargetBean());
|
||||
|
||||
assertThat(beanFactoryFor(DEV_ELIGIBLE_XML, NONE_ACTIVE), not(containsTargetBean()));
|
||||
assertThat(beanFactoryFor(DEV_ELIGIBLE_XML, NULL_ACTIVE), not(containsTargetBean()));
|
||||
assertThat(beanFactoryFor(DEV_ELIGIBLE_XML, PROD_ACTIVE), not(containsTargetBean()));
|
||||
assertThat(beanFactoryFor(DEV_ELIGIBLE_XML, DEV_ACTIVE), containsTargetBean());
|
||||
assertThat(beanFactoryFor(DEV_ELIGIBLE_XML, MULTI_ACTIVE), containsTargetBean());
|
||||
|
||||
assertThat(beanFactoryFor(ALL_ELIGIBLE_XML, NONE_ACTIVE), containsTargetBean());
|
||||
assertThat(beanFactoryFor(ALL_ELIGIBLE_XML, NULL_ACTIVE), containsTargetBean());
|
||||
assertThat(beanFactoryFor(ALL_ELIGIBLE_XML, DEV_ACTIVE), containsTargetBean());
|
||||
assertThat(beanFactoryFor(ALL_ELIGIBLE_XML, PROD_ACTIVE), containsTargetBean());
|
||||
assertThat(beanFactoryFor(ALL_ELIGIBLE_XML, MULTI_ACTIVE), containsTargetBean());
|
||||
|
||||
assertThat(beanFactoryFor(MULTI_ELIGIBLE_XML, NONE_ACTIVE), not(containsTargetBean()));
|
||||
assertThat(beanFactoryFor(MULTI_ELIGIBLE_XML, NULL_ACTIVE), not(containsTargetBean()));
|
||||
assertThat(beanFactoryFor(MULTI_ELIGIBLE_XML, UNKNOWN_ACTIVE), not(containsTargetBean()));
|
||||
assertThat(beanFactoryFor(MULTI_ELIGIBLE_XML, DEV_ACTIVE), containsTargetBean());
|
||||
assertThat(beanFactoryFor(MULTI_ELIGIBLE_XML, PROD_ACTIVE), containsTargetBean());
|
||||
assertThat(beanFactoryFor(MULTI_ELIGIBLE_XML, MULTI_ACTIVE), containsTargetBean());
|
||||
|
||||
assertThat(beanFactoryFor(UNKOWN_ELIGIBLE_XML, MULTI_ACTIVE), not(containsTargetBean()));
|
||||
}
|
||||
|
||||
private BeanDefinitionRegistry beanFactoryFor(String xmlName, String... activeProfileNames) {
|
||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
|
||||
DefaultEnvironment env = new DefaultEnvironment();
|
||||
env.setActiveProfiles(activeProfileNames);
|
||||
reader.setEnvironment(env);
|
||||
reader.loadBeanDefinitions(new ClassPathResource(xmlName, getClass()));
|
||||
return beanFactory;
|
||||
}
|
||||
|
||||
|
||||
private static Matcher<BeanDefinitionRegistry> containsBeanDefinition(final String beanName) {
|
||||
return new TypeSafeMatcher<BeanDefinitionRegistry>() {
|
||||
|
||||
public void describeTo(Description desc) {
|
||||
desc.appendText("a BeanDefinitionRegistry containing bean named ")
|
||||
.appendValue(beanName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matchesSafely(BeanDefinitionRegistry beanFactory) {
|
||||
return beanFactory.containsBeanDefinition(beanName);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
private static Matcher<BeanDefinitionRegistry> containsTargetBean() {
|
||||
return containsBeanDefinition(TARGET_BEAN);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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.beans.factory.xml;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.not;
|
||||
import static org.hamcrest.Matchers.hasItems;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
|
||||
import test.beans.TestBean;
|
||||
|
||||
/**
|
||||
* Tests for propagating enclosing beans element defaults to nested beans elements.
|
||||
*
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class NestedBeansElementAttributeRecursionTests {
|
||||
|
||||
@Test
|
||||
public void defaultLazyInit() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(
|
||||
new ClassPathResource("NestedBeansElementAttributeRecursionTests-lazy-context.xml", this.getClass()));
|
||||
|
||||
BeanDefinition foo = bf.getBeanDefinition("foo");
|
||||
BeanDefinition bar = bf.getBeanDefinition("bar");
|
||||
BeanDefinition baz = bf.getBeanDefinition("baz");
|
||||
BeanDefinition biz = bf.getBeanDefinition("biz");
|
||||
BeanDefinition buz = bf.getBeanDefinition("buz");
|
||||
|
||||
assertThat(foo.isLazyInit(), is(false));
|
||||
assertThat(bar.isLazyInit(), is(true));
|
||||
assertThat(baz.isLazyInit(), is(false));
|
||||
assertThat(biz.isLazyInit(), is(true));
|
||||
assertThat(buz.isLazyInit(), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void defaultMerge() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(
|
||||
new ClassPathResource("NestedBeansElementAttributeRecursionTests-merge-context.xml", this.getClass()));
|
||||
|
||||
TestBean topLevel = bf.getBean("topLevelConcreteTestBean", TestBean.class);
|
||||
// has the concrete child bean values
|
||||
assertThat(topLevel.getSomeList(), hasItems("charlie", "delta"));
|
||||
// but does not merge the parent values
|
||||
assertThat(topLevel.getSomeList(), not(hasItems("alpha", "bravo")));
|
||||
|
||||
TestBean firstLevel = bf.getBean("firstLevelNestedTestBean", TestBean.class);
|
||||
// merges all values
|
||||
assertThat(firstLevel.getSomeList(),
|
||||
hasItems("charlie", "delta", "echo", "foxtrot"));
|
||||
|
||||
TestBean secondLevel = bf.getBean("secondLevelNestedTestBean", TestBean.class);
|
||||
// merges all values
|
||||
assertThat(secondLevel.getSomeList(),
|
||||
hasItems("charlie", "delta", "echo", "foxtrot", "golf", "hotel"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultAutowireCandidates() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(
|
||||
new ClassPathResource("NestedBeansElementAttributeRecursionTests-autowire-candidates-context.xml", this.getClass()));
|
||||
|
||||
assertThat(bf.getBeanDefinition("fooService").isAutowireCandidate(), is(true));
|
||||
assertThat(bf.getBeanDefinition("fooRepository").isAutowireCandidate(), is(true));
|
||||
assertThat(bf.getBeanDefinition("other").isAutowireCandidate(), is(false));
|
||||
|
||||
assertThat(bf.getBeanDefinition("barService").isAutowireCandidate(), is(true));
|
||||
assertThat(bf.getBeanDefinition("fooController").isAutowireCandidate(), is(false));
|
||||
|
||||
assertThat(bf.getBeanDefinition("bizRepository").isAutowireCandidate(), is(true));
|
||||
assertThat(bf.getBeanDefinition("bizService").isAutowireCandidate(), is(false));
|
||||
|
||||
assertThat(bf.getBeanDefinition("bazService").isAutowireCandidate(), is(true));
|
||||
assertThat(bf.getBeanDefinition("random").isAutowireCandidate(), is(false));
|
||||
assertThat(bf.getBeanDefinition("fooComponent").isAutowireCandidate(), is(false));
|
||||
assertThat(bf.getBeanDefinition("fRepository").isAutowireCandidate(), is(false));
|
||||
|
||||
assertThat(bf.getBeanDefinition("aComponent").isAutowireCandidate(), is(true));
|
||||
assertThat(bf.getBeanDefinition("someService").isAutowireCandidate(), is(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void initMethod() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(
|
||||
new ClassPathResource("NestedBeansElementAttributeRecursionTests-init-destroy-context.xml", this.getClass()));
|
||||
|
||||
InitDestroyBean beanA = bf.getBean("beanA", InitDestroyBean.class);
|
||||
InitDestroyBean beanB = bf.getBean("beanB", InitDestroyBean.class);
|
||||
InitDestroyBean beanC = bf.getBean("beanC", InitDestroyBean.class);
|
||||
InitDestroyBean beanD = bf.getBean("beanD", InitDestroyBean.class);
|
||||
|
||||
assertThat(beanA.initMethod1Called, is(true));
|
||||
assertThat(beanB.initMethod2Called, is(true));
|
||||
assertThat(beanC.initMethod3Called, is(true));
|
||||
assertThat(beanD.initMethod2Called, is(true));
|
||||
|
||||
bf.destroySingletons();
|
||||
|
||||
assertThat(beanA.destroyMethod1Called, is(true));
|
||||
assertThat(beanB.destroyMethod2Called, is(true));
|
||||
assertThat(beanC.destroyMethod3Called, is(true));
|
||||
assertThat(beanD.destroyMethod2Called, is(true));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class InitDestroyBean {
|
||||
boolean initMethod1Called;
|
||||
boolean initMethod2Called;
|
||||
boolean initMethod3Called;
|
||||
|
||||
boolean destroyMethod1Called;
|
||||
boolean destroyMethod2Called;
|
||||
boolean destroyMethod3Called;
|
||||
|
||||
void initMethod1() { this.initMethod1Called = true; }
|
||||
void initMethod2() { this.initMethod2Called = true; }
|
||||
void initMethod3() { this.initMethod3Called = true; }
|
||||
|
||||
void destroyMethod1() { this.destroyMethod1Called = true; }
|
||||
void destroyMethod2() { this.destroyMethod2Called = true; }
|
||||
void destroyMethod3() { this.destroyMethod3Called = true; }
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package org.springframework.beans.factory.xml;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.DefaultEnvironment;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
/**
|
||||
* Tests for new nested beans element support in Spring XML
|
||||
*
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class NestedBeansElementTests {
|
||||
private final Resource XML =
|
||||
new ClassPathResource("NestedBeansElementTests-context.xml", this.getClass());
|
||||
|
||||
@Test
|
||||
public void getBean_withoutActiveProfile() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(XML);
|
||||
|
||||
Object foo = bf.getBean("foo");
|
||||
assertThat(foo, instanceOf(String.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getBean_withActiveProfile() {
|
||||
ConfigurableEnvironment env = new DefaultEnvironment();
|
||||
env.setActiveProfiles("dev");
|
||||
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(bf);
|
||||
reader.setEnvironment(env);
|
||||
reader.loadBeanDefinitions(XML);
|
||||
|
||||
bf.getBean("devOnlyBean"); // should not throw NSBDE
|
||||
|
||||
Object foo = bf.getBean("foo");
|
||||
assertThat(foo, instanceOf(Integer.class));
|
||||
|
||||
bf.getBean("devOnlyBean");
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user