Support for populating model attributes through data class constructors
Includes a new overloaded ModelAndView constructor with an HttpStatus argument, as well as a HandlerMethodArgumentResolverSupport refactoring (revised checkParameterType signature, actually implementing the HandlerMethodArgumentResolver interface). Issue: SPR-15199
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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,6 +16,7 @@
|
||||
|
||||
package org.springframework.web.servlet.mvc.method.annotation;
|
||||
|
||||
import java.beans.ConstructorProperties;
|
||||
import java.beans.PropertyEditorSupport;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
@@ -140,14 +141,7 @@ import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
||||
import org.springframework.web.servlet.support.RequestContextUtils;
|
||||
import org.springframework.web.servlet.view.InternalResourceViewResolver;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Rossen Stoyanchev
|
||||
@@ -283,15 +277,13 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
|
||||
}, NestedSetController.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath.do");
|
||||
request.addParameter("testBeanSet", new String[] {"1", "2"});
|
||||
request.addParameter("testBeanSet", "1", "2");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
getServlet().service(request, response);
|
||||
assertEquals("[1, 2]-org.springframework.tests.sample.beans.TestBean", response.getContentAsString());
|
||||
}
|
||||
|
||||
// SPR-12903
|
||||
|
||||
@Test
|
||||
@Test // SPR-12903
|
||||
public void pathVariableWithCustomConverter() throws Exception {
|
||||
initServlet(new ApplicationContextInitializer<GenericWebApplicationContext>() {
|
||||
@Override
|
||||
@@ -1244,9 +1236,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
|
||||
assertEquals("myParam-42", response.getContentAsString());
|
||||
}
|
||||
|
||||
// SPR-9062
|
||||
|
||||
@Test
|
||||
@Test // SPR-9062
|
||||
public void ambiguousPathAndRequestMethod() throws Exception {
|
||||
initServletWithControllers(AmbiguousPathAndRequestMethodController.class);
|
||||
|
||||
@@ -1498,9 +1488,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
|
||||
assertEquals(405, response.getStatus());
|
||||
}
|
||||
|
||||
// SPR-8536
|
||||
|
||||
@Test
|
||||
@Test // SPR-8536
|
||||
public void testHeadersCondition() throws Exception {
|
||||
initServletWithControllers(HeadersConditionController.class);
|
||||
|
||||
@@ -1571,7 +1559,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
|
||||
assertTrue(RequestContextUtils.getOutputFlashMap(request).isEmpty());
|
||||
}
|
||||
|
||||
@Test // SPR-15176
|
||||
@Test // SPR-15176
|
||||
public void flashAttributesWithResponseEntity() throws Exception {
|
||||
initServletWithControllers(RedirectAttributesController.class);
|
||||
|
||||
@@ -1831,6 +1819,31 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
|
||||
assertTrue(response.getContentAsByteArray().length == 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dataClassBinding() throws ServletException, IOException {
|
||||
initServletWithControllers(DataClassController.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/bind");
|
||||
request.addParameter("param1", "value1");
|
||||
request.addParameter("param2", "2");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
getServlet().service(request, response);
|
||||
assertEquals("value1-2-0", response.getContentAsString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dataClassBindingWithAdditionalSetter() throws ServletException, IOException {
|
||||
initServletWithControllers(DataClassController.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/bind");
|
||||
request.addParameter("param1", "value1");
|
||||
request.addParameter("param2", "2");
|
||||
request.addParameter("param3", "3");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
getServlet().service(request, response);
|
||||
assertEquals("value1-2-3", response.getContentAsString());
|
||||
}
|
||||
|
||||
|
||||
@Controller
|
||||
static class ControllerWithEmptyValueMapping {
|
||||
@@ -2727,15 +2740,12 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
|
||||
|
||||
@XmlRootElement
|
||||
public static class A {
|
||||
|
||||
}
|
||||
|
||||
@XmlRootElement
|
||||
public static class B {
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static class NotReadableMessageConverter implements HttpMessageConverter<Object> {
|
||||
|
||||
@Override
|
||||
@@ -3313,7 +3323,6 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
|
||||
public HttpHeaders createNoHeader() throws URISyntaxException {
|
||||
return new HttpHeaders();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@RestController
|
||||
@@ -3345,7 +3354,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
|
||||
|
||||
@RequestMapping("/path")
|
||||
public ModelAndView methodWithHttpStatus(MyEntity object) {
|
||||
return new ModelAndView("view", new ModelMap(), HttpStatus.UNPROCESSABLE_ENTITY);
|
||||
return new ModelAndView("view", HttpStatus.UNPROCESSABLE_ENTITY);
|
||||
}
|
||||
|
||||
@RequestMapping("/exception")
|
||||
@@ -3355,7 +3364,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
|
||||
|
||||
@ExceptionHandler(TestException.class)
|
||||
public ModelAndView handleException() {
|
||||
return new ModelAndView("view", new ModelMap(), HttpStatus.UNPROCESSABLE_ENTITY);
|
||||
return new ModelAndView("view", HttpStatus.UNPROCESSABLE_ENTITY);
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@@ -3363,4 +3372,32 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
|
||||
}
|
||||
}
|
||||
|
||||
public static class DataClass {
|
||||
|
||||
public final String param1;
|
||||
|
||||
public final int param2;
|
||||
|
||||
public int param3;
|
||||
|
||||
@ConstructorProperties({"param1", "param2"})
|
||||
public DataClass(String param1, int p2) {
|
||||
this.param1 = param1;
|
||||
this.param2 = p2;
|
||||
}
|
||||
|
||||
public void setParam3(int param3) {
|
||||
this.param3 = param3;
|
||||
}
|
||||
}
|
||||
|
||||
@RestController
|
||||
public static class DataClassController {
|
||||
|
||||
@RequestMapping("/bind")
|
||||
public String handle(DataClass data) {
|
||||
return data.param1 + "-" + data.param2 + "-" + data.param3;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user