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
This commit is contained in:
parent
d74d657372
commit
a0870c1c4a
|
|
@ -18,6 +18,7 @@ package org.springframework.boot.bind;
|
|||
|
||||
import java.net.InetAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
|
|
@ -35,6 +36,7 @@ import org.springframework.beans.MutablePropertyValues;
|
|||
import org.springframework.beans.NotWritablePropertyException;
|
||||
import org.springframework.beans.PropertyValue;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
|
@ -54,6 +56,11 @@ import org.springframework.validation.DataBinder;
|
|||
*/
|
||||
public class RelaxedDataBinder extends DataBinder {
|
||||
|
||||
private static final Set<String> BENIGN_PROPERTY_SOURCE_NAMES = Collections
|
||||
.unmodifiableSet(new HashSet<String>(Arrays.asList(
|
||||
StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME,
|
||||
StandardEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME)));
|
||||
|
||||
private static final Object BLANK = new Object();
|
||||
|
||||
private String namePrefix;
|
||||
|
|
@ -254,11 +261,19 @@ public class RelaxedDataBinder extends DataBinder {
|
|||
}
|
||||
catch (NotWritablePropertyException ex) {
|
||||
PropertyOrigin origin = findPropertyOrigin(pv);
|
||||
if (origin != null) {
|
||||
throw new RelaxedBindingNotWritablePropertyException(ex,
|
||||
origin);
|
||||
if (isFatal(origin)) {
|
||||
if (origin != null) {
|
||||
throw new RelaxedBindingNotWritablePropertyException(
|
||||
ex, origin);
|
||||
}
|
||||
else {
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
else {
|
||||
logger.debug("Ignoring benign property binding failure",
|
||||
ex);
|
||||
}
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -271,6 +286,13 @@ public class RelaxedDataBinder extends DataBinder {
|
|||
};
|
||||
}
|
||||
|
||||
private boolean isFatal(PropertyOrigin origin) {
|
||||
if (origin == null) {
|
||||
return true;
|
||||
}
|
||||
return !BENIGN_PROPERTY_SOURCE_NAMES.contains(origin.getSource().getName());
|
||||
}
|
||||
|
||||
private PropertyOrigin findPropertyOrigin(PropertyValue propertyValue) {
|
||||
if (propertyValue instanceof OriginCapablePropertyValue) {
|
||||
return ((OriginCapablePropertyValue) propertyValue).getOrigin();
|
||||
|
|
|
|||
|
|
@ -24,8 +24,11 @@ import javax.validation.constraints.NotNull;
|
|||
import org.junit.Test;
|
||||
import org.springframework.beans.NotWritablePropertyException;
|
||||
import org.springframework.context.support.StaticMessageSource;
|
||||
import org.springframework.core.env.MutablePropertySources;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
import org.springframework.core.io.ByteArrayResource;
|
||||
import org.springframework.core.io.support.PropertiesLoaderUtils;
|
||||
import org.springframework.mock.env.MockPropertySource;
|
||||
import org.springframework.validation.BindException;
|
||||
import org.springframework.validation.Validator;
|
||||
import org.springframework.validation.beanvalidation.SpringValidatorAdapter;
|
||||
|
|
@ -82,6 +85,37 @@ public class PropertiesConfigurationFactoryTests {
|
|||
bindFoo("bar: blah");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void systemEnvironmentBindingFailuresAreIgnored() throws Exception {
|
||||
setupFactory();
|
||||
MutablePropertySources propertySources = new MutablePropertySources();
|
||||
MockPropertySource propertySource = new MockPropertySource(
|
||||
StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME);
|
||||
propertySource.setProperty("doesNotExist", "foo");
|
||||
propertySource.setProperty("name", "bar");
|
||||
propertySources.addFirst(propertySource);
|
||||
this.factory.setPropertySources(propertySources);
|
||||
this.factory.setIgnoreUnknownFields(false);
|
||||
this.factory.afterPropertiesSet();
|
||||
this.factory.getObject();
|
||||
Foo foo = this.factory.getObject();
|
||||
assertEquals("bar", foo.name);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void systemPropertyBindingFailuresAreIgnored() throws Exception {
|
||||
setupFactory();
|
||||
MutablePropertySources propertySources = new MutablePropertySources();
|
||||
MockPropertySource propertySource = new MockPropertySource(
|
||||
StandardEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME);
|
||||
propertySource.setProperty("doesNotExist", "foo");
|
||||
propertySource.setProperty("name", "bar");
|
||||
propertySources.addFirst(propertySource);
|
||||
this.factory.setPropertySources(propertySources);
|
||||
this.factory.setIgnoreUnknownFields(false);
|
||||
this.factory.afterPropertiesSet();
|
||||
}
|
||||
|
||||
private Foo createFoo(final String values) throws Exception {
|
||||
setupFactory();
|
||||
return bindFoo(values);
|
||||
|
|
|
|||
Loading…
Reference in New Issue