Skip to content

Commit a0870c1

Browse files
committed
Ignore binding failures for env vars and system properties
1.3.0.M4 tightened up the configuration property binding such that ignoreUnknownFields = false now works as intended. Unfortunately, this has led to some complaints as applications that worked with 1.2.x have stopped working. For example, a SERVER_HOME environment variable does not cause a failure in 1.2.x despite there being no home property on ServerProperties but will now fail in 1.3.0.M4. This commit updates RelaxedDataBinder to ignore binding failures for properties that come from a source outside of the application’s control, namely environment variables and system properties. Closes gh-3775
1 parent d74d657 commit a0870c1

File tree

2 files changed

+60
-4
lines changed

2 files changed

+60
-4
lines changed

spring-boot/src/main/java/org/springframework/boot/bind/RelaxedDataBinder.java

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import java.net.InetAddress;
2020
import java.util.ArrayList;
21+
import java.util.Arrays;
2122
import java.util.Collection;
2223
import java.util.Collections;
2324
import java.util.HashSet;
@@ -35,6 +36,7 @@
3536
import org.springframework.beans.NotWritablePropertyException;
3637
import org.springframework.beans.PropertyValue;
3738
import org.springframework.core.convert.TypeDescriptor;
39+
import org.springframework.core.env.StandardEnvironment;
3840
import org.springframework.util.LinkedMultiValueMap;
3941
import org.springframework.util.MultiValueMap;
4042
import org.springframework.util.StringUtils;
@@ -54,6 +56,11 @@
5456
*/
5557
public class RelaxedDataBinder extends DataBinder {
5658

59+
private static final Set<String> BENIGN_PROPERTY_SOURCE_NAMES = Collections
60+
.unmodifiableSet(new HashSet<String>(Arrays.asList(
61+
StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME,
62+
StandardEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME)));
63+
5764
private static final Object BLANK = new Object();
5865

5966
private String namePrefix;
@@ -254,11 +261,19 @@ public void setPropertyValue(PropertyValue pv) throws BeansException {
254261
}
255262
catch (NotWritablePropertyException ex) {
256263
PropertyOrigin origin = findPropertyOrigin(pv);
257-
if (origin != null) {
258-
throw new RelaxedBindingNotWritablePropertyException(ex,
259-
origin);
264+
if (isFatal(origin)) {
265+
if (origin != null) {
266+
throw new RelaxedBindingNotWritablePropertyException(
267+
ex, origin);
268+
}
269+
else {
270+
throw ex;
271+
}
272+
}
273+
else {
274+
logger.debug("Ignoring benign property binding failure",
275+
ex);
260276
}
261-
throw ex;
262277
}
263278
}
264279
};
@@ -271,6 +286,13 @@ public void setPropertyValue(PropertyValue pv) throws BeansException {
271286
};
272287
}
273288

289+
private boolean isFatal(PropertyOrigin origin) {
290+
if (origin == null) {
291+
return true;
292+
}
293+
return !BENIGN_PROPERTY_SOURCE_NAMES.contains(origin.getSource().getName());
294+
}
295+
274296
private PropertyOrigin findPropertyOrigin(PropertyValue propertyValue) {
275297
if (propertyValue instanceof OriginCapablePropertyValue) {
276298
return ((OriginCapablePropertyValue) propertyValue).getOrigin();

spring-boot/src/test/java/org/springframework/boot/bind/PropertiesConfigurationFactoryTests.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,11 @@
2424
import org.junit.Test;
2525
import org.springframework.beans.NotWritablePropertyException;
2626
import org.springframework.context.support.StaticMessageSource;
27+
import org.springframework.core.env.MutablePropertySources;
28+
import org.springframework.core.env.StandardEnvironment;
2729
import org.springframework.core.io.ByteArrayResource;
2830
import org.springframework.core.io.support.PropertiesLoaderUtils;
31+
import org.springframework.mock.env.MockPropertySource;
2932
import org.springframework.validation.BindException;
3033
import org.springframework.validation.Validator;
3134
import org.springframework.validation.beanvalidation.SpringValidatorAdapter;
@@ -82,6 +85,37 @@ public void testValidationErrorCanBeSuppressed() throws Exception {
8285
bindFoo("bar: blah");
8386
}
8487

88+
@Test
89+
public void systemEnvironmentBindingFailuresAreIgnored() throws Exception {
90+
setupFactory();
91+
MutablePropertySources propertySources = new MutablePropertySources();
92+
MockPropertySource propertySource = new MockPropertySource(
93+
StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME);
94+
propertySource.setProperty("doesNotExist", "foo");
95+
propertySource.setProperty("name", "bar");
96+
propertySources.addFirst(propertySource);
97+
this.factory.setPropertySources(propertySources);
98+
this.factory.setIgnoreUnknownFields(false);
99+
this.factory.afterPropertiesSet();
100+
this.factory.getObject();
101+
Foo foo = this.factory.getObject();
102+
assertEquals("bar", foo.name);
103+
}
104+
105+
@Test
106+
public void systemPropertyBindingFailuresAreIgnored() throws Exception {
107+
setupFactory();
108+
MutablePropertySources propertySources = new MutablePropertySources();
109+
MockPropertySource propertySource = new MockPropertySource(
110+
StandardEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME);
111+
propertySource.setProperty("doesNotExist", "foo");
112+
propertySource.setProperty("name", "bar");
113+
propertySources.addFirst(propertySource);
114+
this.factory.setPropertySources(propertySources);
115+
this.factory.setIgnoreUnknownFields(false);
116+
this.factory.afterPropertiesSet();
117+
}
118+
85119
private Foo createFoo(final String values) throws Exception {
86120
setupFactory();
87121
return bindFoo(values);

0 commit comments

Comments
 (0)