diff --git a/spring-web/src/main/java/org/springframework/web/bind/WebDataBinder.java b/spring-web/src/main/java/org/springframework/web/bind/WebDataBinder.java
index 7756239826..442b97185b 100644
--- a/spring-web/src/main/java/org/springframework/web/bind/WebDataBinder.java
+++ b/spring-web/src/main/java/org/springframework/web/bind/WebDataBinder.java
@@ -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");
* you may not use this file except in compliance with the License.
@@ -17,11 +17,13 @@
package org.springframework.web.bind;
import java.lang.reflect.Array;
+import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValue;
+import org.springframework.core.CollectionFactory;
import org.springframework.validation.DataBinder;
import org.springframework.web.multipart.MultipartFile;
@@ -40,6 +42,7 @@ import org.springframework.web.multipart.MultipartFile;
*
* @author Juergen Hoeller
* @author Scott Andrews
+ * @author Brian Clozel
* @since 1.2
* @see #registerCustomEditor
* @see #setAllowedFields
@@ -243,26 +246,41 @@ public class WebDataBinder extends DataBinder {
/**
* Determine an empty value for the specified field.
- *
Default implementation returns {@code Boolean.FALSE}
- * for boolean fields and an empty array of array types.
- * Else, {@code null} is used as default.
+ *
Default implementation returns:
+ *
+ * - {@code Boolean.FALSE} for boolean fields
+ *
- an empty array for array types
+ *
- Collection implementations for Collection types
+ *
- Map implementations for Map types
+ *
- else, {@code null} is used as default
+ *
* @param field the name of the field
* @param fieldType the type of the field
* @return the empty value (for most fields: null)
*/
protected Object getEmptyValue(String field, Class> fieldType) {
- if (fieldType != null && boolean.class == fieldType || Boolean.class == fieldType) {
- // Special handling of boolean property.
- return Boolean.FALSE;
- }
- else if (fieldType != null && fieldType.isArray()) {
- // Special handling of array property.
- return Array.newInstance(fieldType.getComponentType(), 0);
- }
- else {
- // Default value: try null.
- return null;
+ if (fieldType != null) {
+ try {
+ if (boolean.class == fieldType || Boolean.class == fieldType) {
+ // Special handling of boolean property.
+ return Boolean.FALSE;
+ }
+ else if (fieldType.isArray()) {
+ // Special handling of array property.
+ return Array.newInstance(fieldType.getComponentType(), 0);
+ }
+ else if (Collection.class.isAssignableFrom(fieldType)) {
+ return CollectionFactory.createCollection(fieldType, 0);
+ }
+ else if (Map.class.isAssignableFrom(fieldType)) {
+ return CollectionFactory.createMap(fieldType, 0);
+ }
+ } catch (IllegalArgumentException exc) {
+ return null;
+ }
}
+ // Default value: try null.
+ return null;
}
/**
diff --git a/spring-web/src/test/java/org/springframework/web/bind/support/WebRequestDataBinderTests.java b/spring-web/src/test/java/org/springframework/web/bind/support/WebRequestDataBinderTests.java
index 32b4c0e114..508be6d3ab 100644
--- a/spring-web/src/test/java/org/springframework/web/bind/support/WebRequestDataBinderTests.java
+++ b/spring-web/src/test/java/org/springframework/web/bind/support/WebRequestDataBinderTests.java
@@ -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");
* you may not use this file except in compliance with the License.
@@ -16,10 +16,15 @@
package org.springframework.web.bind.support;
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
import java.beans.PropertyEditorSupport;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
+import java.util.Set;
import org.junit.Test;
@@ -34,8 +39,6 @@ import org.springframework.web.bind.ServletRequestParameterPropertyValues;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.multipart.support.StringMultipartFileEditor;
-import static org.junit.Assert.*;
-
/**
* @author Juergen Hoeller
*/
@@ -126,6 +129,31 @@ public class WebRequestDataBinderTests {
assertFalse(target.isPostProcessed());
}
+ // SPR-13502
+ @Test
+ public void testCollectionFieldsDefault() throws Exception {
+ TestBean target = new TestBean();
+ target.setSomeSet(null);
+ target.setSomeList(null);
+ target.setSomeMap(null);
+ WebRequestDataBinder binder = new WebRequestDataBinder(target);
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.addParameter("_someSet", "visible");
+ request.addParameter("_someList", "visible");
+ request.addParameter("_someMap", "visible");
+
+ binder.bind(new ServletWebRequest(request));
+ assertThat(target.getSomeSet(), notNullValue());
+ assertThat(target.getSomeSet(), isA(Set.class));
+
+ assertThat(target.getSomeList(), notNullValue());
+ assertThat(target.getSomeList(), isA(List.class));
+
+ assertThat(target.getSomeMap(), notNullValue());
+ assertThat(target.getSomeMap(), isA(Map.class));
+ }
+
@Test
public void testFieldDefaultPreemptsFieldMarker() throws Exception {
TestBean target = new TestBean();