Skip to content

Commit fbfbec1

Browse files
committed
Use custom validator on supported classes only
Previously, a customer was set regardless of the fact that it is supported on the target bean. DataBinder has an actual assertion check that would fail in such a case. We now associate the custom validator only if it supports the target bean. Fixes gh-3581
1 parent a43cd18 commit fbfbec1

File tree

2 files changed

+84
-3
lines changed

2 files changed

+84
-3
lines changed

spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBindingPostProcessor.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2014 the original author or authors.
2+
* Copyright 2012-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -66,6 +66,7 @@
6666
* @author Dave Syer
6767
* @author Phillip Webb
6868
* @author Christian Dupuis
69+
* @author Stephane Nicoll
6970
*/
7071
public class ConfigurationPropertiesBindingPostProcessor implements BeanPostProcessor,
7172
BeanFactoryAware, ResourceLoaderAware, EnvironmentAware, ApplicationContextAware,
@@ -321,13 +322,15 @@ private String getAnnotationDetails(ConfigurationProperties annotation) {
321322
}
322323

323324
private Validator determineValidator(Object bean) {
325+
boolean globalValidatorSupportBean = (this.validator != null
326+
&& this.validator.supports(bean.getClass()));
324327
if (ClassUtils.isAssignable(Validator.class, bean.getClass())) {
325-
if (this.validator == null) {
328+
if (!globalValidatorSupportBean) {
326329
return (Validator) bean;
327330
}
328331
return new ChainingValidator(this.validator, (Validator) bean);
329332
}
330-
return this.validator;
333+
return globalValidatorSupportBean ? this.validator : null;
331334
}
332335

333336
private PropertySources loadPropertySources(String[] locations,

spring-boot/src/test/java/org/springframework/boot/context/properties/ConfigurationPropertiesBindingPostProcessorTests.java

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
*
5555
* @author Christian Dupuis
5656
* @author Phillip Webb
57+
* @author Stephane Nicoll
5758
*/
5859
public class ConfigurationPropertiesBindingPostProcessorTests {
5960

@@ -133,6 +134,39 @@ public void testInitializersSeeBoundProperties() {
133134
this.context.refresh();
134135
}
135136

137+
@Test
138+
public void testValidationWithCustomValidator() {
139+
this.context = new AnnotationConfigApplicationContext();
140+
this.context.register(TestConfigurationWithCustomValidator.class);
141+
try {
142+
this.context.refresh();
143+
fail("Expected exception");
144+
}
145+
catch (BeanCreationException ex) {
146+
BindException bex = (BindException) ex.getRootCause();
147+
assertEquals(1, bex.getErrorCount());
148+
}
149+
}
150+
151+
@Test
152+
public void testValidationWithCustomValidatorNotSupported() {
153+
MockEnvironment env = new MockEnvironment();
154+
env.setProperty("test.foo", "bar");
155+
this.context = new AnnotationConfigApplicationContext();
156+
this.context.setEnvironment(env);
157+
this.context.register(TestConfigurationWithCustomValidator.class,
158+
PropertyWithValidatingSetter.class);
159+
try {
160+
// PropertyWithValidatingSetter should not use validator
161+
this.context.refresh();
162+
fail("Expected exception");
163+
}
164+
catch (BeanCreationException ex) {
165+
BindException bex = (BindException) ex.getRootCause();
166+
assertEquals(1, bex.getErrorCount());
167+
}
168+
}
169+
136170
@Test
137171
public void testPropertyWithEnum() throws Exception {
138172
doEnumTest("test.theValue:foo");
@@ -373,6 +407,50 @@ public String getBar() {
373407

374408
}
375409

410+
@Configuration
411+
@EnableConfigurationProperties
412+
public static class TestConfigurationWithCustomValidator {
413+
414+
@Bean
415+
public PropertyWithCustomValidator propertyWithCustomValidator() {
416+
return new PropertyWithCustomValidator();
417+
}
418+
419+
@Bean
420+
public Validator configurationPropertiesValidator() {
421+
return new CustomPropertyValidator();
422+
}
423+
424+
}
425+
426+
@ConfigurationProperties(prefix = "custom")
427+
public static class PropertyWithCustomValidator {
428+
429+
private String foo;
430+
431+
public String getFoo() {
432+
return foo;
433+
}
434+
435+
public void setFoo(String foo) {
436+
this.foo = foo;
437+
}
438+
}
439+
440+
public static class CustomPropertyValidator implements Validator {
441+
442+
@Override
443+
public boolean supports(Class<?> aClass) {
444+
return aClass == PropertyWithCustomValidator.class;
445+
}
446+
447+
@Override
448+
public void validate(Object o, Errors errors) {
449+
ValidationUtils.rejectIfEmpty(errors, "foo", "TEST1");
450+
}
451+
452+
}
453+
376454
@Configuration
377455
@EnableConfigurationProperties
378456
@ConfigurationProperties(prefix = "test", ignoreUnknownFields = false)

0 commit comments

Comments
 (0)