|
|
|
|
@ -2252,6 +2252,112 @@ class ServletAnnotationControllerHandlerMethodTests extends AbstractServletHandl
@@ -2252,6 +2252,112 @@ class ServletAnnotationControllerHandlerMethodTests extends AbstractServletHandl
|
|
|
|
|
assertThat(response.getContentAsString()).isEqualTo("value1-true-3"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@PathPatternsParameterizedTest |
|
|
|
|
void nestedDataClassBinding(boolean usePathPatterns) throws Exception { |
|
|
|
|
initDispatcherServlet(NestedDataClassController.class, usePathPatterns); |
|
|
|
|
|
|
|
|
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/bind"); |
|
|
|
|
request.addParameter("param1", "value1"); |
|
|
|
|
request.addParameter("nestedParam2.param1", "nestedValue1"); |
|
|
|
|
request.addParameter("nestedParam2.param2", "true"); |
|
|
|
|
MockHttpServletResponse response = new MockHttpServletResponse(); |
|
|
|
|
getServlet().service(request, response); |
|
|
|
|
assertThat(response.getContentAsString()).isEqualTo("value1-nestedValue1-true-0"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@PathPatternsParameterizedTest |
|
|
|
|
void nestedDataClassBindingWithAdditionalSetter(boolean usePathPatterns) throws Exception { |
|
|
|
|
initDispatcherServlet(NestedDataClassController.class, usePathPatterns); |
|
|
|
|
|
|
|
|
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/bind"); |
|
|
|
|
request.addParameter("param1", "value1"); |
|
|
|
|
request.addParameter("nestedParam2.param1", "nestedValue1"); |
|
|
|
|
request.addParameter("nestedParam2.param2", "true"); |
|
|
|
|
request.addParameter("nestedParam2.param3", "3"); |
|
|
|
|
MockHttpServletResponse response = new MockHttpServletResponse(); |
|
|
|
|
getServlet().service(request, response); |
|
|
|
|
assertThat(response.getContentAsString()).isEqualTo("value1-nestedValue1-true-3"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@PathPatternsParameterizedTest |
|
|
|
|
void nestedDataClassBindingWithOptionalParameter(boolean usePathPatterns) throws Exception { |
|
|
|
|
initDispatcherServlet(NestedValidatedDataClassController.class, usePathPatterns); |
|
|
|
|
|
|
|
|
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/bind"); |
|
|
|
|
request.addParameter("param1", "value1"); |
|
|
|
|
request.addParameter("nestedParam2.param1", "nestedValue1"); |
|
|
|
|
request.addParameter("nestedParam2.param2", "true"); |
|
|
|
|
request.addParameter("nestedParam2.optionalParam", "8"); |
|
|
|
|
MockHttpServletResponse response = new MockHttpServletResponse(); |
|
|
|
|
getServlet().service(request, response); |
|
|
|
|
assertThat(response.getContentAsString()).isEqualTo("value1-nestedValue1-true-8"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@PathPatternsParameterizedTest |
|
|
|
|
void nestedDataClassBindingWithMissingParameter(boolean usePathPatterns) throws Exception { |
|
|
|
|
initDispatcherServlet(NestedValidatedDataClassController.class, usePathPatterns); |
|
|
|
|
|
|
|
|
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/bind"); |
|
|
|
|
request.addParameter("param1", "value1"); |
|
|
|
|
request.addParameter("nestedParam2.param1", "nestedValue1"); |
|
|
|
|
MockHttpServletResponse response = new MockHttpServletResponse(); |
|
|
|
|
getServlet().service(request, response); |
|
|
|
|
assertThat(response.getContentAsString()).isEqualTo("1:value1-nestedValue1-null-null"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@PathPatternsParameterizedTest |
|
|
|
|
void nestedDataClassBindingWithConversionError(boolean usePathPatterns) throws Exception { |
|
|
|
|
initDispatcherServlet(NestedValidatedDataClassController.class, usePathPatterns); |
|
|
|
|
|
|
|
|
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/bind"); |
|
|
|
|
request.addParameter("param1", "value1"); |
|
|
|
|
request.addParameter("nestedParam2.param1", "nestedValue1"); |
|
|
|
|
request.addParameter("nestedParam2.param2", "x"); |
|
|
|
|
MockHttpServletResponse response = new MockHttpServletResponse(); |
|
|
|
|
getServlet().service(request, response); |
|
|
|
|
assertThat(response.getContentAsString()).isEqualTo("1:value1-nestedValue1-x-null"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@PathPatternsParameterizedTest |
|
|
|
|
void nestedDataClassBindingWithValidationError(boolean usePathPatterns) throws Exception { |
|
|
|
|
initDispatcherServlet(NestedValidatedDataClassController.class, usePathPatterns); |
|
|
|
|
|
|
|
|
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/bind"); |
|
|
|
|
request.addParameter("param1", "value1"); |
|
|
|
|
request.addParameter("nestedParam2.param2", "true"); |
|
|
|
|
request.addParameter("nestedParam2.param3", "0"); |
|
|
|
|
MockHttpServletResponse response = new MockHttpServletResponse(); |
|
|
|
|
getServlet().service(request, response); |
|
|
|
|
assertThat(response.getContentAsString()).isEqualTo("1:value1--true-0"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@PathPatternsParameterizedTest |
|
|
|
|
void nestedDataClassBindingWithValidationErrorAndConversionError(boolean usePathPatterns) throws Exception { |
|
|
|
|
initDispatcherServlet(NestedValidatedDataClassController.class, usePathPatterns); |
|
|
|
|
|
|
|
|
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/bind"); |
|
|
|
|
request.addParameter("param1", "value1"); |
|
|
|
|
request.addParameter("nestedParam2.param2", "x"); |
|
|
|
|
MockHttpServletResponse response = new MockHttpServletResponse(); |
|
|
|
|
getServlet().service(request, response); |
|
|
|
|
assertThat(response.getContentAsString()).isEqualTo("2:value1-null-x-null"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@PathPatternsParameterizedTest |
|
|
|
|
void nestedDataClassBindingWithDataAndLocalDate(boolean usePathPatterns) throws Exception { |
|
|
|
|
initDispatcherServlet(NestedDataAndDateClassController.class, usePathPatterns); |
|
|
|
|
|
|
|
|
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/bind"); |
|
|
|
|
request.addParameter("param1", "value1"); |
|
|
|
|
request.addParameter("nestedParam2.param1", "nestedValue1"); |
|
|
|
|
request.addParameter("nestedParam2.param2", "true"); |
|
|
|
|
request.addParameter("nestedParam2.optionalParam", "8"); |
|
|
|
|
request.addParameter("nestedParam3.date", "2010-01-01"); |
|
|
|
|
MockHttpServletResponse response = new MockHttpServletResponse(); |
|
|
|
|
getServlet().service(request, response); |
|
|
|
|
assertThat(response.getContentAsString()).isEqualTo("2010-01-01"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
void routerFunction() throws ServletException, IOException { |
|
|
|
|
GenericWebApplicationContext wac = new GenericWebApplicationContext(); |
|
|
|
|
@ -4164,7 +4270,7 @@ class ServletAnnotationControllerHandlerMethodTests extends AbstractServletHandl
@@ -4164,7 +4270,7 @@ class ServletAnnotationControllerHandlerMethodTests extends AbstractServletHandl
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static record DataRecord(String param1, boolean param2, int param3) { |
|
|
|
|
record DataRecord(String param1, boolean param2, int param3) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@RestController |
|
|
|
|
@ -4176,4 +4282,145 @@ class ServletAnnotationControllerHandlerMethodTests extends AbstractServletHandl
@@ -4176,4 +4282,145 @@ class ServletAnnotationControllerHandlerMethodTests extends AbstractServletHandl
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static class NestedDataClass { |
|
|
|
|
|
|
|
|
|
@NotNull |
|
|
|
|
private final String param1; |
|
|
|
|
|
|
|
|
|
@Valid |
|
|
|
|
private final DataClass nestedParam2; |
|
|
|
|
|
|
|
|
|
public NestedDataClass(@NotNull String param1, DataClass nestedParam2) { |
|
|
|
|
this.param1 = param1; |
|
|
|
|
this.nestedParam2 = nestedParam2; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public String getParam1() { |
|
|
|
|
return this.param1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public DataClass getNestedParam2() { |
|
|
|
|
return this.nestedParam2; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@RestController |
|
|
|
|
static class NestedDataClassController { |
|
|
|
|
|
|
|
|
|
@RequestMapping("/bind") |
|
|
|
|
public String handle(NestedDataClass data) { |
|
|
|
|
DataClass nestedParam2 = data.nestedParam2; |
|
|
|
|
return (data.param1 + "-" + nestedParam2.param1 + "-" + nestedParam2.param2 + "-" + nestedParam2.param3); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@RestController |
|
|
|
|
static class NestedValidatedDataClassController { |
|
|
|
|
|
|
|
|
|
@InitBinder |
|
|
|
|
public void initBinder(WebDataBinder binder) { |
|
|
|
|
binder.setConversionService(new DefaultFormattingConversionService()); |
|
|
|
|
binder.registerCustomEditor(String.class, new StringTrimmerEditor(true)); |
|
|
|
|
LocalValidatorFactoryBean vf = new LocalValidatorFactoryBean(); |
|
|
|
|
vf.afterPropertiesSet(); |
|
|
|
|
binder.setValidator(vf); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@RequestMapping("/bind") |
|
|
|
|
public NestedBindStatusView handle(@Valid NestedDataClass data, BindingResult result) { |
|
|
|
|
assertThat(data).isNotNull(); |
|
|
|
|
if (result.hasErrors()) { |
|
|
|
|
String content = result.getErrorCount() + ":" + result.getFieldValue("param1"); |
|
|
|
|
content += "-" + result.getFieldValue("nestedParam2.param1"); |
|
|
|
|
content += "-" + result.getFieldValue("nestedParam2.param2"); |
|
|
|
|
content += "-" + result.getFieldValue("nestedParam2.param3"); |
|
|
|
|
return new NestedBindStatusView(content); |
|
|
|
|
} |
|
|
|
|
DataClass nested = data.nestedParam2; |
|
|
|
|
return new NestedBindStatusView( |
|
|
|
|
data.param1 + "-" + nested.param1 + "-" + nested.param2 + "-" + nested.param3); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static class NestedBindStatusView extends AbstractView { |
|
|
|
|
|
|
|
|
|
private final String content; |
|
|
|
|
|
|
|
|
|
NestedBindStatusView(String content) { |
|
|
|
|
this.content = content; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
protected void renderMergedOutputModel( |
|
|
|
|
Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception { |
|
|
|
|
RequestContext rc = new RequestContext(request, model); |
|
|
|
|
rc.getBindStatus("nestedDataClass"); |
|
|
|
|
rc.getBindStatus("nestedDataClass.param1"); |
|
|
|
|
rc.getBindStatus("nestedDataClass.nestedParam2"); |
|
|
|
|
rc.getBindStatus("nestedDataClass.nestedParam2.param1"); |
|
|
|
|
rc.getBindStatus("nestedDataClass.nestedParam2.param2"); |
|
|
|
|
rc.getBindStatus("nestedDataClass.nestedParam2.param3"); |
|
|
|
|
response.getWriter().write(this.content); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static class NestedDataAndDateClass { |
|
|
|
|
|
|
|
|
|
@NotNull |
|
|
|
|
private final String param1; |
|
|
|
|
|
|
|
|
|
@Valid |
|
|
|
|
private final DataClass nestedParam2; |
|
|
|
|
|
|
|
|
|
@Valid |
|
|
|
|
private final DateClass nestedParam3; |
|
|
|
|
|
|
|
|
|
public NestedDataAndDateClass( |
|
|
|
|
@NotNull String param1, DataClass nestedParam2, DateClass nestedParam3) { |
|
|
|
|
|
|
|
|
|
this.param1 = param1; |
|
|
|
|
this.nestedParam2 = nestedParam2; |
|
|
|
|
this.nestedParam3 = nestedParam3; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public String getParam1() { |
|
|
|
|
return this.param1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public DataClass getNestedParam2() { |
|
|
|
|
return this.nestedParam2; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public DateClass getNestedParam3() { |
|
|
|
|
return this.nestedParam3; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@RestController |
|
|
|
|
static class NestedDataAndDateClassController { |
|
|
|
|
|
|
|
|
|
@InitBinder |
|
|
|
|
public void initBinder(WebDataBinder binder) { |
|
|
|
|
binder.initDirectFieldAccess(); |
|
|
|
|
binder.setConversionService(new DefaultFormattingConversionService()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@RequestMapping("/bind") |
|
|
|
|
public String handle(NestedDataAndDateClass data, BindingResult result) { |
|
|
|
|
if (result.hasErrors()) { |
|
|
|
|
return result.getFieldError().toString(); |
|
|
|
|
} |
|
|
|
|
assertThat(data).isNotNull(); |
|
|
|
|
assertThat(data.getParam1()).isEqualTo("value1"); |
|
|
|
|
assertThat(data.getNestedParam2().param1).isEqualTo("nestedValue1"); |
|
|
|
|
assertThat(data.getNestedParam2().param2).isTrue(); |
|
|
|
|
assertThat(data.getNestedParam2().param3).isEqualTo(8); |
|
|
|
|
assertThat(data.getNestedParam3().date).isNotNull(); |
|
|
|
|
assertThat(data.getNestedParam3().date.getYear()).isEqualTo(2010); |
|
|
|
|
assertThat(data.getNestedParam3().date.getMonthValue()).isEqualTo(1); |
|
|
|
|
assertThat(data.getNestedParam3().date.getDayOfMonth()).isEqualTo(1); |
|
|
|
|
return result.getFieldValue("nestedParam3.date").toString(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|