Skip to content

Commit 9f22928

Browse files
committed
Support lazy initialization of BindingResult when customize a MessageCodesResolver
Issue: SPR-15009
1 parent 5169c51 commit 9f22928

File tree

2 files changed

+85
-1
lines changed

2 files changed

+85
-1
lines changed

spring-context/src/main/java/org/springframework/validation/DataBinder.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,8 @@ public class DataBinder implements PropertyEditorRegistry, TypeConverter {
150150

151151
private ConversionService conversionService;
152152

153+
private MessageCodesResolver messageCodesResolver;
154+
153155

154156
/**
155157
* Create a new DataBinder instance, with default object name.
@@ -253,6 +255,9 @@ protected AbstractPropertyBindingResult createBeanPropertyBindingResult() {
253255
if (this.conversionService != null) {
254256
result.initConversion(this.conversionService);
255257
}
258+
if (this.messageCodesResolver != null) {
259+
result.setMessageCodesResolver(this.messageCodesResolver);
260+
}
256261
return result;
257262
}
258263

@@ -279,6 +284,9 @@ protected AbstractPropertyBindingResult createDirectFieldBindingResult() {
279284
if (this.conversionService != null) {
280285
result.initConversion(this.conversionService);
281286
}
287+
if (this.messageCodesResolver != null) {
288+
result.setMessageCodesResolver(this.messageCodesResolver);
289+
}
282290
return result;
283291
}
284292

@@ -486,7 +494,11 @@ public void setExtractOldValueForEditor(boolean extractOldValueForEditor) {
486494
* @see DefaultMessageCodesResolver
487495
*/
488496
public void setMessageCodesResolver(MessageCodesResolver messageCodesResolver) {
489-
getInternalBindingResult().setMessageCodesResolver(messageCodesResolver);
497+
Assert.state(this.messageCodesResolver == null, "DataBinder is already initialized with MessageCodesResolver");
498+
this.messageCodesResolver = messageCodesResolver;
499+
if (this.bindingResult != null && messageCodesResolver != null) {
500+
this.bindingResult.setMessageCodesResolver(messageCodesResolver);
501+
}
490502
}
491503

492504
/**

spring-context/src/test/java/org/springframework/validation/DataBinderTests.java

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import org.junit.Test;
4141
import org.junit.rules.ExpectedException;
4242

43+
import org.springframework.beans.BeanWrapper;
4344
import org.springframework.beans.InvalidPropertyException;
4445
import org.springframework.beans.MutablePropertyValues;
4546
import org.springframework.beans.NotWritablePropertyException;
@@ -2013,6 +2014,77 @@ public void testSetAutoGrowCollectionLimitAfterInitialization() {
20132014
binder.setAutoGrowCollectionLimit(257);
20142015
}
20152016

2017+
@Test // SPR-15009
2018+
public void testSetCustomMessageCodesResolverBeforeInitializeBindingResultForBeanPropertyAccess() {
2019+
TestBean testBean = new TestBean();
2020+
DataBinder binder = new DataBinder(testBean, "testBean");
2021+
DefaultMessageCodesResolver messageCodesResolver = new DefaultMessageCodesResolver();
2022+
messageCodesResolver.setPrefix("errors.");
2023+
binder.setMessageCodesResolver(messageCodesResolver);
2024+
binder.setAutoGrowCollectionLimit(512); // allow configuration after set a MessageCodesResolver
2025+
binder.initBeanPropertyAccess();
2026+
2027+
MutablePropertyValues mpv = new MutablePropertyValues();
2028+
mpv.add("age", "invalid");
2029+
binder.bind(mpv);
2030+
assertEquals("errors.typeMismatch", binder.getBindingResult().getFieldError("age").getCode());
2031+
assertEquals(512, BeanWrapper.class.cast(binder.getInternalBindingResult().getPropertyAccessor()).getAutoGrowCollectionLimit());
2032+
}
2033+
2034+
@Test // SPR-15009
2035+
public void testSetCustomMessageCodesResolverBeforeInitializeBindingResultForDirectFieldAccess() {
2036+
TestBean testBean = new TestBean();
2037+
DataBinder binder = new DataBinder(testBean, "testBean");
2038+
DefaultMessageCodesResolver messageCodesResolver = new DefaultMessageCodesResolver();
2039+
messageCodesResolver.setPrefix("errors.");
2040+
binder.setMessageCodesResolver(messageCodesResolver);
2041+
binder.initDirectFieldAccess();
2042+
2043+
MutablePropertyValues mpv = new MutablePropertyValues();
2044+
mpv.add("age", "invalid");
2045+
binder.bind(mpv);
2046+
assertEquals("errors.typeMismatch", binder.getBindingResult().getFieldError("age").getCode());
2047+
}
2048+
2049+
@Test // SPR-15009
2050+
public void testSetCustomMessageCodesResolverAfterInitializeBindingResult() {
2051+
TestBean testBean = new TestBean();
2052+
DataBinder binder = new DataBinder(testBean, "testBean");
2053+
binder.initBeanPropertyAccess();
2054+
DefaultMessageCodesResolver messageCodesResolver = new DefaultMessageCodesResolver();
2055+
messageCodesResolver.setPrefix("errors.");
2056+
binder.setMessageCodesResolver(messageCodesResolver);
2057+
2058+
MutablePropertyValues mpv = new MutablePropertyValues();
2059+
mpv.add("age", "invalid");
2060+
binder.bind(mpv);
2061+
assertEquals("errors.typeMismatch", binder.getBindingResult().getFieldError("age").getCode());
2062+
}
2063+
2064+
@Test // SPR-15009
2065+
public void testSetMessageCodesResolverIsNullAfterInitializeBindingResult() {
2066+
TestBean testBean = new TestBean();
2067+
DataBinder binder = new DataBinder(testBean, "testBean");
2068+
binder.initBeanPropertyAccess();
2069+
binder.setMessageCodesResolver(null);
2070+
2071+
MutablePropertyValues mpv = new MutablePropertyValues();
2072+
mpv.add("age", "invalid");
2073+
binder.bind(mpv);
2074+
assertEquals("typeMismatch", binder.getBindingResult().getFieldError("age").getCode()); // Keep a default MessageCodesResolver
2075+
}
2076+
2077+
@Test // SPR-15009
2078+
public void testCallSetMessageCodesResolverTwice() {
2079+
expectedException.expect(IllegalStateException.class);
2080+
expectedException.expectMessage("DataBinder is already initialized with MessageCodesResolver");
2081+
2082+
TestBean testBean = new TestBean();
2083+
DataBinder binder = new DataBinder(testBean, "testBean");
2084+
binder.setMessageCodesResolver(new DefaultMessageCodesResolver());
2085+
binder.setMessageCodesResolver(new DefaultMessageCodesResolver());
2086+
2087+
}
20162088

20172089
@SuppressWarnings("unused")
20182090
private static class BeanWithIntegerList {

0 commit comments

Comments
 (0)