Since updating to Spring Boot 3.4.0 / 3.4.1
Given this TestController:
@RestController
public class TestController {
@GetMapping("/test")
public ResponseEntity<String> testMe(Parameter params) {
return ResponseEntity.ok("Hello World");
}
}
with this Parameter Bean:
public class Parameter {
// This constructor will cause the request to result in an error 500....
public Parameter(List<String> params) {
this.params = params;
}
private List<String> params;
// ... getter & setter
}
A request to /test?params[]=123
will fail with this Exception:
Request processing failed: java.lang.StringIndexOutOfBoundsException: begin 7, end -1, length 8
jakarta.servlet.ServletException: Request processing failed: java.lang.StringIndexOutOfBoundsException: begin 7, end -1, length 8
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1022)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903)
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:564)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885)
at org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:72)
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658)
at org.springframework.mock.web.MockFilterChain$ServletFilterProxy.doFilter(MockFilterChain.java:165)
at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:132)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.springframework.test.web.servlet.setup.MockMvcFilterDecorator.doFilter(MockMvcFilterDecorator.java:162)
at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:132)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.springframework.test.web.servlet.setup.MockMvcFilterDecorator.doFilter(MockMvcFilterDecorator.java:162)
at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:132)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.springframework.test.web.servlet.setup.MockMvcFilterDecorator.doFilter(MockMvcFilterDecorator.java:162)
at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:132)
at org.springframework.test.web.servlet.MockMvc.perform(MockMvc.java:201)
at test.spring.databindererror500.TestControllerTest.shouldNotGetError500(TestControllerTest.java:23)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
Caused by: java.lang.StringIndexOutOfBoundsException: begin 7, end -1, length 8
at java.base/java.lang.String.checkBoundsBeginEnd(String.java:4601)
at java.base/java.lang.String.substring(String.java:2704)
at org.springframework.validation.DataBinder.getIndexes(DataBinder.java:1118)
at org.springframework.validation.DataBinder.createList(DataBinder.java:1057)
at org.springframework.validation.DataBinder.createObject(DataBinder.java:961)
at org.springframework.validation.DataBinder.construct(DataBinder.java:909)
at org.springframework.web.bind.ServletRequestDataBinder.construct(ServletRequestDataBinder.java:116)
at org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor.constructAttribute(ServletModelAttributeMethodProcessor.java:157)
at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:148)
at
org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:122)
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:226)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:180)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:986)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:891)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1088)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:978)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)
... 24 more
When requesting /test?params=123
everything works as expected.
When requesting /test?params[]=123
but without the constructor, everything also works as expected.
In Spring Boot <= 3.3.7 also everything works as expected.
You can find a simple demo application here: dataBinderError500.zip
My expectation would be that the parameter is parsed correctly despite the []. I could also live with a validation error or a BadRequest. But an Error 500 with StringOutOfBounds exception is unpleasant.
Edit: My first idea was that it was the @ConstructorProperties(“params”)
, but it is the constructor itself that causes the error.
Comment From: jerchende
ooh I am sorry, look like a duplicate to gh-34121, which is already fixed!
Comment From: snicoll
Indeed @jerchende. I would appreciate if you could give Spring Framework 6.2.2-SNAPSHOT a try. You can download the latest snapshot from https://repo.spring.io/snapshot.