Affects: spring-web 5.2.11
Given a controller like the following:
import javax.annotation.Nullable;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/path")
public class MyController {
private static class MyCriteria {
@Nullable
private String param1;
@Nullable
private MultiValueMap<String, String> otherParams;
// getters and setter omitted
}
@GetMapping
public void getByCriteria(MyCriteria criteria) {
// body
}
}
I would expect a GET request to /path?param1=a&otherParams[otherParam]=b
to cause an instance of MyCriteria
with param1 = "a"
and otherParams = {"otherParam": ["b"]}
to be passed in.
Instead, the following exception is thrown:
java.lang.ClassCastException: class java.lang.String cannot be cast to class java.util.List (java.lang.String and java.util.List are in module java.base of loader 'bootstrap')
at org.springframework.util.LinkedMultiValueMap.put(LinkedMultiValueMap.java:42)
at org.springframework.beans.AbstractNestablePropertyAccessor.processKeyedProperty(AbstractNestablePropertyAccessor.java:371)
at org.springframework.beans.AbstractNestablePropertyAccessor.setPropertyValue(AbstractNestablePropertyAccessor.java:275)
at org.springframework.beans.AbstractNestablePropertyAccessor.setPropertyValue(AbstractNestablePropertyAccessor.java:266)
at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:104)
at org.springframework.validation.DataBinder.applyPropertyValues(DataBinder.java:848)
at org.springframework.validation.DataBinder.doBind(DataBinder.java:744)
at org.springframework.web.bind.WebDataBinder.doBind(WebDataBinder.java:197)
at org.springframework.web.bind.ServletRequestDataBinder.bind(ServletRequestDataBinder.java:107)
This works as expected when MultiValueMap<String, String>
is replaced with Map<String, List<String>>
Comment From: jhoeller
MultiValueMap
value type detection does not seem to work in the core BeanWrapper
infrastructure underneath such a web data binding attempt, whereas it does work for a generically typed Map
with explicit collection values. We'll revisit this for 5.3.3, with an intent for a 5.2.13 backport.
Comment From: jhoeller
This turns out to be rather involved and simply not covered by our general Map support in the core BeanWrapper
infrastructure. We can certainly support MultiValueMap
specifically in separate code paths but this is only likely to materialize in 5.3.x at this point.
Comment From: jhoeller
Finally coming into 6.1 through a revised PropertyHandler
arrangement where we resolve map value types as a TypeDescriptor
now, introspecting the actual Map
generics and not the top-level generics on MultiValueMap
.