Placeholder configurers allow for trimming of property values

Issue: SPR-5839
This commit is contained in:
Juergen Hoeller 2016-02-19 19:19:39 +01:00
parent 890819f886
commit a7ad49adcf
10 changed files with 213 additions and 93 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2015 the original author or authors. * Copyright 2002-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -107,6 +107,8 @@ public abstract class PlaceholderConfigurerSupport extends PropertyResourceConfi
/** Defaults to {@value #DEFAULT_VALUE_SEPARATOR} */ /** Defaults to {@value #DEFAULT_VALUE_SEPARATOR} */
protected String valueSeparator = DEFAULT_VALUE_SEPARATOR; protected String valueSeparator = DEFAULT_VALUE_SEPARATOR;
protected boolean trimValues = false;
protected String nullValue; protected String nullValue;
protected boolean ignoreUnresolvablePlaceholders = false; protected boolean ignoreUnresolvablePlaceholders = false;
@ -142,6 +144,16 @@ public abstract class PlaceholderConfigurerSupport extends PropertyResourceConfi
this.valueSeparator = valueSeparator; this.valueSeparator = valueSeparator;
} }
/**
* Specify whether to trim resolved values before applying them,
* removing superfluous whitespace from the beginning and end.
* <p>Default is {@code false}.
* @since 4.3
*/
public void setTrimValues(boolean trimValues) {
this.trimValues = trimValues;
}
/** /**
* Set a value that should be treated as {@code null} when resolved * Set a value that should be treated as {@code null} when resolved
* as a placeholder value: e.g. "" (empty String) or "null". * as a placeholder value: e.g. "" (empty String) or "null".

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2015 the original author or authors. * Copyright 2002-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -255,8 +255,11 @@ public class PropertyPlaceholderConfigurer extends PlaceholderConfigurerSupport
@Override @Override
public String resolveStringValue(String strVal) throws BeansException { public String resolveStringValue(String strVal) throws BeansException {
String value = this.helper.replacePlaceholders(strVal, this.resolver); String resolved = this.helper.replacePlaceholders(strVal, this.resolver);
return (value.equals(nullValue) ? null : value); if (trimValues) {
resolved = resolved.trim();
}
return (resolved.equals(nullValue) ? null : resolved);
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2013 the original author or authors. * Copyright 2002-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -39,11 +39,10 @@ import static org.springframework.beans.factory.support.BeanDefinitionReaderUtil
/** /**
* Unit tests for {@link PropertyPlaceholderConfigurer}. * Unit tests for {@link PropertyPlaceholderConfigurer}.
* *
* @see PropertySourcesPlaceholderConfigurerTests
* @see PropertyResourceConfigurerTests
* @author Chris Beams * @author Chris Beams
*/ */
public class PropertyPlaceholderConfigurerTests { public class PropertyPlaceholderConfigurerTests {
private static final String P1 = "p1"; private static final String P1 = "p1";
private static final String P1_LOCAL_PROPS_VAL = "p1LocalPropsVal"; private static final String P1_LOCAL_PROPS_VAL = "p1LocalPropsVal";
private static final String P1_SYSTEM_PROPS_VAL = "p1SystemPropsVal"; private static final String P1_SYSTEM_PROPS_VAL = "p1SystemPropsVal";
@ -55,6 +54,7 @@ public class PropertyPlaceholderConfigurerTests {
private AbstractBeanDefinition p1BeanDef; private AbstractBeanDefinition p1BeanDef;
@Before @Before
public void setUp() { public void setUp() {
p1BeanDef = rootBeanDefinition(TestBean.class) p1BeanDef = rootBeanDefinition(TestBean.class)
@ -238,6 +238,33 @@ public class PropertyPlaceholderConfigurerTests {
getModifiableSystemEnvironment().remove("my.name"); getModifiableSystemEnvironment().remove("my.name");
} }
@Test
public void trimValuesIsOffByDefault() {
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
getModifiableSystemEnvironment().put("my.name", " myValue ");
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
bf.registerBeanDefinition("testBean", rootBeanDefinition(TestBean.class)
.addPropertyValue("name", "${my.name}")
.getBeanDefinition());
ppc.postProcessBeanFactory(bf);
assertThat(bf.getBean(TestBean.class).getName(), equalTo(" myValue "));
getModifiableSystemEnvironment().remove("my.name");
}
@Test
public void trimValuesIsApplied() {
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
ppc.setTrimValues(true);
getModifiableSystemEnvironment().put("my.name", " myValue ");
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
bf.registerBeanDefinition("testBean", rootBeanDefinition(TestBean.class)
.addPropertyValue("name", "${my.name}")
.getBeanDefinition());
ppc.postProcessBeanFactory(bf);
assertThat(bf.getBean(TestBean.class).getName(), equalTo("myValue"));
getModifiableSystemEnvironment().remove("my.name");
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private static Map<String, String> getModifiableSystemEnvironment() { private static Map<String, String> getModifiableSystemEnvironment() {
@ -253,7 +280,8 @@ public class PropertyPlaceholderConfigurerTests {
if (obj != null && obj.getClass().getName().equals("java.lang.ProcessEnvironment$StringEnvironment")) { if (obj != null && obj.getClass().getName().equals("java.lang.ProcessEnvironment$StringEnvironment")) {
return (Map<String, String>) obj; return (Map<String, String>) obj;
} }
} catch (Exception ex) { }
catch (Exception ex) {
throw new RuntimeException(ex); throw new RuntimeException(ex);
} }
} }
@ -263,8 +291,9 @@ public class PropertyPlaceholderConfigurerTests {
Class<?> processEnvironmentClass; Class<?> processEnvironmentClass;
try { try {
processEnvironmentClass = Class.forName("java.lang.ProcessEnvironment"); processEnvironmentClass = Class.forName("java.lang.ProcessEnvironment");
} catch (Exception e) { }
throw new RuntimeException(e); catch (Exception ex) {
throw new RuntimeException(ex);
} }
try { try {
@ -272,10 +301,12 @@ public class PropertyPlaceholderConfigurerTests {
theCaseInsensitiveEnvironmentField.setAccessible(true); theCaseInsensitiveEnvironmentField.setAccessible(true);
Object obj = theCaseInsensitiveEnvironmentField.get(null); Object obj = theCaseInsensitiveEnvironmentField.get(null);
return (Map<String, String>) obj; return (Map<String, String>) obj;
} catch (NoSuchFieldException e) { }
catch (NoSuchFieldException ex) {
// do nothing // do nothing
} catch (Exception e) { }
throw new RuntimeException(e); catch (Exception ex) {
throw new RuntimeException(ex);
} }
try { try {
@ -283,10 +314,12 @@ public class PropertyPlaceholderConfigurerTests {
theEnvironmentField.setAccessible(true); theEnvironmentField.setAccessible(true);
Object obj = theEnvironmentField.get(null); Object obj = theEnvironmentField.get(null);
return (Map<String, String>) obj; return (Map<String, String>) obj;
} catch (NoSuchFieldException e) { }
catch (NoSuchFieldException ex) {
// do nothing // do nothing
} catch (Exception e) { }
throw new RuntimeException(e); catch (Exception ex) {
throw new RuntimeException(ex);
} }
throw new IllegalStateException(); throw new IllegalStateException();

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2015 the original author or authors. * Copyright 2002-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -69,7 +69,9 @@ class PropertyPlaceholderBeanDefinitionParser extends AbstractPropertyLoadingBea
if (element.hasAttribute("value-separator")) { if (element.hasAttribute("value-separator")) {
builder.addPropertyValue("valueSeparator", element.getAttribute("value-separator")); builder.addPropertyValue("valueSeparator", element.getAttribute("value-separator"));
} }
if (element.hasAttribute("trim-values")) {
builder.addPropertyValue("trimValues", element.getAttribute("trim-values"));
}
if (element.hasAttribute("null-value")) { if (element.hasAttribute("null-value")) {
builder.addPropertyValue("nullValue", element.getAttribute("null-value")); builder.addPropertyValue("nullValue", element.getAttribute("null-value"));
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2015 the original author or authors. * Copyright 2002-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -167,9 +167,12 @@ public class PropertySourcesPlaceholderConfigurer extends PlaceholderConfigurerS
StringValueResolver valueResolver = new StringValueResolver() { StringValueResolver valueResolver = new StringValueResolver() {
@Override @Override
public String resolveStringValue(String strVal) { public String resolveStringValue(String strVal) {
String resolved = ignoreUnresolvablePlaceholders ? String resolved = (ignoreUnresolvablePlaceholders ?
propertyResolver.resolvePlaceholders(strVal) : propertyResolver.resolvePlaceholders(strVal) :
propertyResolver.resolveRequiredPlaceholders(strVal); propertyResolver.resolveRequiredPlaceholders(strVal));
if (trimValues) {
resolved = resolved.trim();
}
return (resolved.equals(nullValue) ? null : resolved); return (resolved.equals(nullValue) ? null : resolved);
} }
}; };

View File

@ -149,6 +149,14 @@
<xsd:documentation><![CDATA[ <xsd:documentation><![CDATA[
The separating character between the placeholder variable and the associated The separating character between the placeholder variable and the associated
default value: by default, a ':' symbol. default value: by default, a ':' symbol.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="trim-values">
<xsd:annotation>
<xsd:documentation><![CDATA[
Whether to trim resolved values before applying them, removing superfluous
whitespace (in particular tab characters) from the beginning and end.
]]></xsd:documentation> ]]></xsd:documentation>
</xsd:annotation> </xsd:annotation>
</xsd:attribute> </xsd:attribute>

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2015 the original author or authors. * Copyright 2002-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -18,14 +18,10 @@ package org.springframework.context.config;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.Map;
import org.junit.After; import org.junit.After;
import org.junit.Test; import org.junit.Test;
import org.springframework.beans.factory.config.PlaceholderConfigurerSupport;
import org.springframework.beans.factory.config.PropertyOverrideConfigurer;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext; import org.springframework.context.support.GenericXmlApplicationContext;
@ -53,9 +49,6 @@ public class ContextNamespaceHandlerTests {
public void propertyPlaceholder() throws Exception { public void propertyPlaceholder() throws Exception {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext( ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
"contextNamespaceHandlerTests-replace.xml", getClass()); "contextNamespaceHandlerTests-replace.xml", getClass());
Map<String, PlaceholderConfigurerSupport> beans = applicationContext
.getBeansOfType(PlaceholderConfigurerSupport.class);
assertFalse("No PropertyPlaceholderConfigurer found", beans.isEmpty());
assertEquals("bar", applicationContext.getBean("string")); assertEquals("bar", applicationContext.getBean("string"));
assertEquals("null", applicationContext.getBean("nullString")); assertEquals("null", applicationContext.getBean("nullString"));
} }
@ -66,9 +59,6 @@ public class ContextNamespaceHandlerTests {
try { try {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext( ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
"contextNamespaceHandlerTests-system.xml", getClass()); "contextNamespaceHandlerTests-system.xml", getClass());
Map<String, PropertyPlaceholderConfigurer> beans = applicationContext
.getBeansOfType(PropertyPlaceholderConfigurer.class);
assertFalse("No PropertyPlaceholderConfigurer found", beans.isEmpty());
assertEquals("spam", applicationContext.getBean("string")); assertEquals("spam", applicationContext.getBean("string"));
assertEquals("none", applicationContext.getBean("fallback")); assertEquals("none", applicationContext.getBean("fallback"));
} }
@ -86,9 +76,6 @@ public class ContextNamespaceHandlerTests {
applicationContext.setEnvironment(env); applicationContext.setEnvironment(env);
applicationContext.load(new ClassPathResource("contextNamespaceHandlerTests-simple.xml", getClass())); applicationContext.load(new ClassPathResource("contextNamespaceHandlerTests-simple.xml", getClass()));
applicationContext.refresh(); applicationContext.refresh();
Map<String, PlaceholderConfigurerSupport> beans = applicationContext
.getBeansOfType(PlaceholderConfigurerSupport.class);
assertFalse("No PropertyPlaceholderConfigurer found", beans.isEmpty());
assertEquals("spam", applicationContext.getBean("string")); assertEquals("spam", applicationContext.getBean("string"));
assertEquals("none", applicationContext.getBean("fallback")); assertEquals("none", applicationContext.getBean("fallback"));
} }
@ -97,9 +84,6 @@ public class ContextNamespaceHandlerTests {
public void propertyPlaceholderLocation() throws Exception { public void propertyPlaceholderLocation() throws Exception {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext( ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
"contextNamespaceHandlerTests-location.xml", getClass()); "contextNamespaceHandlerTests-location.xml", getClass());
Map<String, PropertyPlaceholderConfigurer> beans = applicationContext
.getBeansOfType(PropertyPlaceholderConfigurer.class);
assertFalse("No PropertyPlaceholderConfigurer found", beans.isEmpty());
assertEquals("bar", applicationContext.getBean("foo")); assertEquals("bar", applicationContext.getBean("foo"));
assertEquals("foo", applicationContext.getBean("bar")); assertEquals("foo", applicationContext.getBean("bar"));
assertEquals("maps", applicationContext.getBean("spam")); assertEquals("maps", applicationContext.getBean("spam"));
@ -109,9 +93,6 @@ public class ContextNamespaceHandlerTests {
public void propertyPlaceholderIgnored() throws Exception { public void propertyPlaceholderIgnored() throws Exception {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext( ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
"contextNamespaceHandlerTests-replace-ignore.xml", getClass()); "contextNamespaceHandlerTests-replace-ignore.xml", getClass());
Map<String, PlaceholderConfigurerSupport> beans = applicationContext
.getBeansOfType(PlaceholderConfigurerSupport.class);
assertFalse("No PropertyPlaceholderConfigurer found", beans.isEmpty());
assertEquals("${bar}", applicationContext.getBean("string")); assertEquals("${bar}", applicationContext.getBean("string"));
assertEquals("null", applicationContext.getBean("nullString")); assertEquals("null", applicationContext.getBean("nullString"));
} }
@ -120,9 +101,6 @@ public class ContextNamespaceHandlerTests {
public void propertyOverride() throws Exception { public void propertyOverride() throws Exception {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext( ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
"contextNamespaceHandlerTests-override.xml", getClass()); "contextNamespaceHandlerTests-override.xml", getClass());
Map<String, PropertyOverrideConfigurer> beans = applicationContext
.getBeansOfType(PropertyOverrideConfigurer.class);
assertFalse("No PropertyOverrideConfigurer found", beans.isEmpty());
Date date = (Date) applicationContext.getBean("date"); Date date = (Date) applicationContext.getBean("date");
Calendar calendar = Calendar.getInstance(); Calendar calendar = Calendar.getInstance();
calendar.setTime(date); calendar.setTime(date);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2013 the original author or authors. * Copyright 2002-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,6 +16,7 @@
package org.springframework.context.support; package org.springframework.context.support;
import java.util.Optional;
import java.util.Properties; import java.util.Properties;
import org.junit.Rule; import org.junit.Rule;
@ -24,6 +25,7 @@ import org.junit.rules.ExpectedException;
import org.springframework.beans.factory.BeanDefinitionStoreException; import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.core.env.MutablePropertySources; import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource; import org.springframework.core.env.PropertySource;
import org.springframework.core.env.StandardEnvironment; import org.springframework.core.env.StandardEnvironment;
@ -39,6 +41,7 @@ import static org.springframework.beans.factory.support.BeanDefinitionBuilder.*;
/** /**
* @author Chris Beams * @author Chris Beams
* @author Juergen Hoeller
* @since 3.1 * @since 3.1
*/ */
public class PropertySourcesPlaceholderConfigurerTests { public class PropertySourcesPlaceholderConfigurerTests {
@ -46,6 +49,7 @@ public class PropertySourcesPlaceholderConfigurerTests {
@Rule @Rule
public ExpectedException thrown = ExpectedException.none(); public ExpectedException thrown = ExpectedException.none();
@Test @Test
public void replacementFromEnvironmentProperties() { public void replacementFromEnvironmentProperties() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
@ -57,8 +61,7 @@ public class PropertySourcesPlaceholderConfigurerTests {
MockEnvironment env = new MockEnvironment(); MockEnvironment env = new MockEnvironment();
env.setProperty("my.name", "myValue"); env.setProperty("my.name", "myValue");
PropertySourcesPlaceholderConfigurer ppc = PropertySourcesPlaceholderConfigurer ppc = new PropertySourcesPlaceholderConfigurer();
new PropertySourcesPlaceholderConfigurer();
ppc.setEnvironment(env); ppc.setEnvironment(env);
ppc.postProcessBeanFactory(bf); ppc.postProcessBeanFactory(bf);
assertThat(bf.getBean(TestBean.class).getName(), equalTo("myValue")); assertThat(bf.getBean(TestBean.class).getName(), equalTo("myValue"));
@ -73,10 +76,10 @@ public class PropertySourcesPlaceholderConfigurerTests {
.addPropertyValue("name", "${my.name}") .addPropertyValue("name", "${my.name}")
.getBeanDefinition()); .getBeanDefinition());
PropertySourcesPlaceholderConfigurer pc = new PropertySourcesPlaceholderConfigurer(); PropertySourcesPlaceholderConfigurer ppc = new PropertySourcesPlaceholderConfigurer();
Resource resource = new ClassPathResource("PropertySourcesPlaceholderConfigurerTests.properties", this.getClass()); Resource resource = new ClassPathResource("PropertySourcesPlaceholderConfigurerTests.properties", this.getClass());
pc.setLocation(resource); ppc.setLocation(resource);
pc.postProcessBeanFactory(bf); ppc.postProcessBeanFactory(bf);
assertThat(bf.getBean(TestBean.class).getName(), equalTo("foo")); assertThat(bf.getBean(TestBean.class).getName(), equalTo("foo"));
} }
@ -101,11 +104,11 @@ public class PropertySourcesPlaceholderConfigurerTests {
MutablePropertySources propertySources = new MutablePropertySources(); MutablePropertySources propertySources = new MutablePropertySources();
propertySources.addLast(new MockPropertySource().withProperty("my.name", "foo")); propertySources.addLast(new MockPropertySource().withProperty("my.name", "foo"));
PropertySourcesPlaceholderConfigurer pc = new PropertySourcesPlaceholderConfigurer(); PropertySourcesPlaceholderConfigurer ppc = new PropertySourcesPlaceholderConfigurer();
pc.setPropertySources(propertySources); ppc.setPropertySources(propertySources);
pc.postProcessBeanFactory(bf); ppc.postProcessBeanFactory(bf);
assertThat(bf.getBean(TestBean.class).getName(), equalTo("foo")); assertThat(bf.getBean(TestBean.class).getName(), equalTo("foo"));
assertEquals(pc.getAppliedPropertySources().iterator().next(), propertySources.iterator().next()); assertEquals(ppc.getAppliedPropertySources().iterator().next(), propertySources.iterator().next());
} }
@Test @Test
@ -119,13 +122,13 @@ public class PropertySourcesPlaceholderConfigurerTests {
MutablePropertySources propertySources = new MutablePropertySources(); MutablePropertySources propertySources = new MutablePropertySources();
propertySources.addLast(new MockPropertySource()); propertySources.addLast(new MockPropertySource());
PropertySourcesPlaceholderConfigurer pc = new PropertySourcesPlaceholderConfigurer(); PropertySourcesPlaceholderConfigurer ppc = new PropertySourcesPlaceholderConfigurer();
pc.setPropertySources(propertySources); ppc.setPropertySources(propertySources);
pc.setEnvironment(new MockEnvironment().withProperty("my.name", "env")); ppc.setEnvironment(new MockEnvironment().withProperty("my.name", "env"));
pc.setIgnoreUnresolvablePlaceholders(true); ppc.setIgnoreUnresolvablePlaceholders(true);
pc.postProcessBeanFactory(bf); ppc.postProcessBeanFactory(bf);
assertThat(bf.getBean(TestBean.class).getName(), equalTo("${my.name}")); assertThat(bf.getBean(TestBean.class).getName(), equalTo("${my.name}"));
assertEquals(pc.getAppliedPropertySources().iterator().next(), propertySources.iterator().next()); assertEquals(ppc.getAppliedPropertySources().iterator().next(), propertySources.iterator().next());
} }
@Test @Test
@ -140,13 +143,13 @@ public class PropertySourcesPlaceholderConfigurerTests {
MutablePropertySources propertySources = new MutablePropertySources(); MutablePropertySources propertySources = new MutablePropertySources();
propertySources.addLast(new MockPropertySource()); propertySources.addLast(new MockPropertySource());
PropertySourcesPlaceholderConfigurer pc = new PropertySourcesPlaceholderConfigurer(); PropertySourcesPlaceholderConfigurer ppc = new PropertySourcesPlaceholderConfigurer();
pc.setPropertySources(propertySources); ppc.setPropertySources(propertySources);
pc.setProperties(new Properties() {{ ppc.setProperties(new Properties() {{
put("my.name", "local"); put("my.name", "local");
}}); }});
pc.setIgnoreUnresolvablePlaceholders(true); ppc.setIgnoreUnresolvablePlaceholders(true);
pc.postProcessBeanFactory(bf); ppc.postProcessBeanFactory(bf);
assertThat(bf.getBean(TestBean.class).getName(), equalTo("${my.name}")); assertThat(bf.getBean(TestBean.class).getName(), equalTo("${my.name}"));
} }
@ -158,9 +161,9 @@ public class PropertySourcesPlaceholderConfigurerTests {
.addPropertyValue("name", "${my.name}") .addPropertyValue("name", "${my.name}")
.getBeanDefinition()); .getBeanDefinition());
PropertySourcesPlaceholderConfigurer pc = new PropertySourcesPlaceholderConfigurer(); PropertySourcesPlaceholderConfigurer ppc = new PropertySourcesPlaceholderConfigurer();
//pc.setIgnoreUnresolvablePlaceholders(false); // the default //pc.setIgnoreUnresolvablePlaceholders(false); // the default
pc.postProcessBeanFactory(bf); // should throw ppc.postProcessBeanFactory(bf); // should throw
} }
@Test @Test
@ -171,9 +174,9 @@ public class PropertySourcesPlaceholderConfigurerTests {
.addPropertyValue("name", "${my.name}") .addPropertyValue("name", "${my.name}")
.getBeanDefinition()); .getBeanDefinition());
PropertySourcesPlaceholderConfigurer pc = new PropertySourcesPlaceholderConfigurer(); PropertySourcesPlaceholderConfigurer ppc = new PropertySourcesPlaceholderConfigurer();
pc.setIgnoreUnresolvablePlaceholders(true); ppc.setIgnoreUnresolvablePlaceholders(true);
pc.postProcessBeanFactory(bf); ppc.postProcessBeanFactory(bf);
assertThat(bf.getBean(TestBean.class).getName(), equalTo("${my.name}")); assertThat(bf.getBean(TestBean.class).getName(), equalTo("${my.name}"));
} }
@ -186,11 +189,11 @@ public class PropertySourcesPlaceholderConfigurerTests {
.addPropertyValue("name", "${my.name}") .addPropertyValue("name", "${my.name}")
.getBeanDefinition()); .getBeanDefinition());
PropertySourcesPlaceholderConfigurer pc = new PropertySourcesPlaceholderConfigurer(); PropertySourcesPlaceholderConfigurer ppc = new PropertySourcesPlaceholderConfigurer();
pc.setProperties(new Properties() {{ ppc.setProperties(new Properties() {{
put("my.name", "${bogus}"); put("my.name", "${bogus}");
}}); }});
pc.postProcessBeanFactory(bf); // should throw ppc.postProcessBeanFactory(bf); // should throw
} }
@Test @Test
@ -202,12 +205,12 @@ public class PropertySourcesPlaceholderConfigurerTests {
.addPropertyValue("name", "${my.name}") .addPropertyValue("name", "${my.name}")
.getBeanDefinition()); .getBeanDefinition());
PropertySourcesPlaceholderConfigurer pc = new PropertySourcesPlaceholderConfigurer(); PropertySourcesPlaceholderConfigurer ppc = new PropertySourcesPlaceholderConfigurer();
pc.setProperties(new Properties() {{ ppc.setProperties(new Properties() {{
put("my.name", "${bogus}"); put("my.name", "${bogus}");
}}); }});
pc.setIgnoreUnresolvablePlaceholders(true); ppc.setIgnoreUnresolvablePlaceholders(true);
pc.postProcessBeanFactory(bf); ppc.postProcessBeanFactory(bf);
assertThat(bf.getBean(TestBean.class).getName(), equalTo("${bogus}")); assertThat(bf.getBean(TestBean.class).getName(), equalTo("${bogus}"));
} }
@ -295,6 +298,31 @@ public class PropertySourcesPlaceholderConfigurerTests {
assertThat(bf.getBean(TestBean.class).getName(), nullValue()); assertThat(bf.getBean(TestBean.class).getName(), nullValue());
} }
@Test
public void trimValuesIsOffByDefault() {
PropertySourcesPlaceholderConfigurer ppc = new PropertySourcesPlaceholderConfigurer();
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
bf.registerBeanDefinition("testBean", rootBeanDefinition(TestBean.class)
.addPropertyValue("name", "${my.name}")
.getBeanDefinition());
ppc.setEnvironment(new MockEnvironment().withProperty("my.name", " myValue "));
ppc.postProcessBeanFactory(bf);
assertThat(bf.getBean(TestBean.class).getName(), equalTo(" myValue "));
}
@Test
public void trimValuesIsApplied() {
PropertySourcesPlaceholderConfigurer ppc = new PropertySourcesPlaceholderConfigurer();
ppc.setTrimValues(true);
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
bf.registerBeanDefinition("testBean", rootBeanDefinition(TestBean.class)
.addPropertyValue("name", "${my.name}")
.getBeanDefinition());
ppc.setEnvironment(new MockEnvironment().withProperty("my.name", " myValue "));
ppc.postProcessBeanFactory(bf);
assertThat(bf.getBean(TestBean.class).getName(), equalTo("myValue"));
}
@Test @Test
public void getAppliedPropertySourcesTooEarly() throws Exception { public void getAppliedPropertySourcesTooEarly() throws Exception {
PropertySourcesPlaceholderConfigurer ppc = new PropertySourcesPlaceholderConfigurer(); PropertySourcesPlaceholderConfigurer ppc = new PropertySourcesPlaceholderConfigurer();
@ -308,7 +336,7 @@ public class PropertySourcesPlaceholderConfigurerTests {
PropertySourcesPlaceholderConfigurer ppc = new PropertySourcesPlaceholderConfigurer(); PropertySourcesPlaceholderConfigurer ppc = new PropertySourcesPlaceholderConfigurer();
ClassPathResource doesNotHave = new ClassPathResource("test.properties", getClass()); ClassPathResource doesNotHave = new ClassPathResource("test.properties", getClass());
ClassPathResource setToTrue = new ClassPathResource("placeholder.properties", getClass()); ClassPathResource setToTrue = new ClassPathResource("placeholder.properties", getClass());
ppc.setLocations(new Resource[] { doesNotHave, setToTrue }); ppc.setLocations(doesNotHave, setToTrue);
ppc.setIgnoreResourceNotFound(true); ppc.setIgnoreResourceNotFound(true);
ppc.setIgnoreUnresolvablePlaceholders(true); ppc.setIgnoreUnresolvablePlaceholders(true);
DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
@ -320,4 +348,57 @@ public class PropertySourcesPlaceholderConfigurerTests {
assertThat(bf.getBean(TestBean.class).isJedi(), equalTo(true)); assertThat(bf.getBean(TestBean.class).isJedi(), equalTo(true));
} }
@Test
public void optionalPropertyWithValue() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
bf.setConversionService(new DefaultConversionService());
bf.registerBeanDefinition("testBean",
genericBeanDefinition(OptionalTestBean.class)
.addPropertyValue("name", "${my.name}")
.getBeanDefinition());
MockEnvironment env = new MockEnvironment();
env.setProperty("my.name", "myValue");
PropertySourcesPlaceholderConfigurer ppc = new PropertySourcesPlaceholderConfigurer();
ppc.setEnvironment(env);
ppc.setIgnoreUnresolvablePlaceholders(true);
ppc.postProcessBeanFactory(bf);
assertThat(bf.getBean(OptionalTestBean.class).getName(), equalTo(Optional.of("myValue")));
}
@Test
public void optionalPropertyWithoutValue() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
bf.setConversionService(new DefaultConversionService());
bf.registerBeanDefinition("testBean",
genericBeanDefinition(OptionalTestBean.class)
.addPropertyValue("name", "${my.name}")
.getBeanDefinition());
MockEnvironment env = new MockEnvironment();
env.setProperty("my.name", "");
PropertySourcesPlaceholderConfigurer ppc = new PropertySourcesPlaceholderConfigurer();
ppc.setEnvironment(env);
ppc.setIgnoreUnresolvablePlaceholders(true);
ppc.setNullValue("");
ppc.postProcessBeanFactory(bf);
assertThat(bf.getBean(OptionalTestBean.class).getName(), equalTo(Optional.empty()));
}
private static class OptionalTestBean {
private Optional<String> name;
public Optional<String> getName() {
return name;
}
public void setName(Optional<String> name) {
this.name = name;
}
}
} }

View File

@ -2,12 +2,12 @@
<beans xmlns="http://www.springframework.org/schema/beans" <beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<context:property-placeholder <context:property-placeholder
location="classpath*:/org/springframework/context/config/test-*.properties,classpath*:/org/springframework/context/config/empty-*.properties,classpath*:/org/springframework/context/config/missing-*.properties" location="classpath*:/org/springframework/context/config/test-*.properties,classpath*:/org/springframework/context/config/empty-*.properties,classpath*:/org/springframework/context/config/missing-*.properties"
file-encoding="ISO-8859-1"/> file-encoding="ISO-8859-1" trim-values="true"/>
<bean id="foo" class="java.lang.String"> <bean id="foo" class="java.lang.String">
<constructor-arg value="${foo}"/> <constructor-arg value="${foo}"/>

View File

@ -1,2 +1,2 @@
bar=foo bar= foo\t
spam=maps spam=\tmaps