BindingResult support for constructor argument mismatch on immutable data object

Issue: SPR-15542
This commit is contained in:
Juergen Hoeller
2017-08-17 11:02:40 +02:00
parent b8f5e97ae5
commit 61cdc842e0
4 changed files with 415 additions and 345 deletions

View File

@@ -20,11 +20,13 @@ import java.beans.ConstructorProperties;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.util.Map; import java.util.Map;
import java.util.Optional;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.beans.TypeMismatchException;
import org.springframework.core.DefaultParameterNameDiscoverer; import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.MethodParameter; import org.springframework.core.MethodParameter;
import org.springframework.core.ParameterNameDiscoverer; import org.springframework.core.ParameterNameDiscoverer;
@@ -32,7 +34,9 @@ import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.validation.BindException; import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Errors; import org.springframework.validation.Errors;
import org.springframework.validation.FieldError;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.ModelAttribute;
@@ -110,9 +114,6 @@ public class ModelAttributeMethodProcessor implements HandlerMethodArgumentResol
Assert.state(binderFactory != null, "ModelAttributeMethodProcessor requires WebDataBinderFactory"); Assert.state(binderFactory != null, "ModelAttributeMethodProcessor requires WebDataBinderFactory");
String name = ModelFactory.getNameForParameter(parameter); String name = ModelFactory.getNameForParameter(parameter);
Object attribute = (mavContainer.containsAttribute(name) ? mavContainer.getModel().get(name) :
createAttribute(name, parameter, binderFactory, webRequest));
if (!mavContainer.isBindingDisabled(name)) { if (!mavContainer.isBindingDisabled(name)) {
ModelAttribute ann = parameter.getParameterAnnotation(ModelAttribute.class); ModelAttribute ann = parameter.getParameterAnnotation(ModelAttribute.class);
if (ann != null && !ann.binding()) { if (ann != null && !ann.binding()) {
@@ -120,51 +121,113 @@ public class ModelAttributeMethodProcessor implements HandlerMethodArgumentResol
} }
} }
WebDataBinder binder = binderFactory.createBinder(webRequest, attribute, name); Object attribute = null;
if (binder.getTarget() != null) { BindingResult bindingResult = null;
if (!mavContainer.isBindingDisabled(name)) {
bindRequestParameters(binder, webRequest); if (mavContainer.containsAttribute(name)) {
attribute = mavContainer.getModel().get(name);
}
else {
// Create attribute instance
try {
attribute = createAttribute(name, parameter, binderFactory, webRequest);
} }
validateIfApplicable(binder, parameter); catch (BindException ex) {
if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) { if (isBindExceptionRequired(parameter)) {
throw new BindException(binder.getBindingResult()); // No BindingResult parameter -> fail with BindException
throw ex;
}
// Otherwise, expose null/empty value and associated BindingResult
if (parameter.getParameterType() == Optional.class) {
attribute = Optional.empty();
}
bindingResult = ex.getBindingResult();
} }
} }
if (bindingResult == null) {
// Bean property binding and validation;
// skipped in case of binding failure on construction.
WebDataBinder binder = binderFactory.createBinder(webRequest, attribute, name);
if (binder.getTarget() != null) {
if (!mavContainer.isBindingDisabled(name)) {
bindRequestParameters(binder, webRequest);
}
validateIfApplicable(binder, parameter);
if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) {
throw new BindException(binder.getBindingResult());
}
}
// Value type adaptation, also covering java.util.Optional
if (!parameter.getParameterType().isInstance(attribute)) {
attribute = binder.convertIfNecessary(binder.getTarget(), parameter.getParameterType(), parameter);
}
bindingResult = binder.getBindingResult();
}
// Add resolved attribute and BindingResult at the end of the model // Add resolved attribute and BindingResult at the end of the model
Map<String, Object> bindingResultModel = binder.getBindingResult().getModel(); Map<String, Object> bindingResultModel = bindingResult.getModel();
mavContainer.removeAttributes(bindingResultModel); mavContainer.removeAttributes(bindingResultModel);
mavContainer.addAllAttributes(bindingResultModel); mavContainer.addAllAttributes(bindingResultModel);
return (parameter.getParameterType().isInstance(attribute) ? attribute : return attribute;
binder.convertIfNecessary(binder.getTarget(), parameter.getParameterType(), parameter));
} }
/** /**
* Extension point to create the model attribute if not found in the model, * Extension point to create the model attribute if not found in the model,
* with subsequent parameter binding through bean properties (unless suppressed). * with subsequent parameter binding through bean properties (unless suppressed).
* <p>The default implementation uses the unique public no-arg constructor, if any, * <p>The default implementation typically uses the unique public no-arg constructor
* which may have arguments: It understands the JavaBeans {@link ConstructorProperties} * if available but also handles a "primary constructor" approach for data classes:
* annotation as well as runtime-retained parameter names in the bytecode, * It understands the JavaBeans {@link ConstructorProperties} annotation as well as
* associating request parameters with constructor arguments by name. If no such * runtime-retained parameter names in the bytecode, associating request parameters
* constructor is found, the default constructor will be used (even if not public), * with constructor arguments by name. If no such constructor is found, the default
* assuming subsequent bean property bindings through setter methods. * constructor will be used (even if not public), assuming subsequent bean property
* bindings through setter methods.
* @param attributeName the name of the attribute (never {@code null}) * @param attributeName the name of the attribute (never {@code null})
* @param parameter the method parameter declaration * @param parameter the method parameter declaration
* @param binderFactory for creating WebDataBinder instance * @param binderFactory for creating WebDataBinder instance
* @param webRequest the current request * @param webRequest the current request
* @return the created model attribute (never {@code null}) * @return the created model attribute (never {@code null})
* @throws BindException in case of constructor argument binding failure
* @throws Exception in case of constructor invocation failure
* @see #constructAttribute(Constructor, String, WebDataBinderFactory, NativeWebRequest)
* @see BeanUtils#findPrimaryConstructor(Class)
*/ */
protected Object createAttribute(String attributeName, MethodParameter parameter, protected Object createAttribute(String attributeName, MethodParameter parameter,
WebDataBinderFactory binderFactory, NativeWebRequest webRequest) throws Exception { WebDataBinderFactory binderFactory, NativeWebRequest webRequest) throws Exception {
Class<?> type = parameter.getParameterType(); MethodParameter nestedParameter = parameter.nestedIfOptional();
Class<?> type = nestedParameter.getNestedParameterType();
Constructor<?> ctor = BeanUtils.findPrimaryConstructor(type); Constructor<?> ctor = BeanUtils.findPrimaryConstructor(type);
if (ctor == null) { if (ctor == null) {
throw new IllegalStateException("No primary constructor found for " + type.getName()); throw new IllegalStateException("No primary constructor found for " + type.getName());
} }
Object attribute = constructAttribute(ctor, attributeName, binderFactory, webRequest);
if (parameter != nestedParameter) {
attribute = Optional.of(attribute);
}
return attribute;
}
/**
* Construct a new attribute instance with the given constructor.
* <p>Called from
* {@link #createAttribute(String, MethodParameter, WebDataBinderFactory, NativeWebRequest)}
* after constructor resolution.
* @param ctor the constructor to use
* @param attributeName the name of the attribute (never {@code null})
* @param binderFactory for creating WebDataBinder instance
* @param webRequest the current request
* @return the created model attribute (never {@code null})
* @throws BindException in case of constructor argument binding failure
* @throws Exception in case of constructor invocation failure
* @since 5.0
*/
protected Object constructAttribute(Constructor<?> ctor, String attributeName,
WebDataBinderFactory binderFactory, NativeWebRequest webRequest) throws Exception {
if (ctor.getParameterCount() == 0) { if (ctor.getParameterCount() == 0) {
// A single default constructor -> clearly a standard JavaBeans arrangement. // A single default constructor -> clearly a standard JavaBeans arrangement.
return BeanUtils.instantiateClass(ctor); return BeanUtils.instantiateClass(ctor);
@@ -179,10 +242,22 @@ public class ModelAttributeMethodProcessor implements HandlerMethodArgumentResol
() -> "Invalid number of parameter names: " + paramNames.length + " for constructor " + ctor); () -> "Invalid number of parameter names: " + paramNames.length + " for constructor " + ctor);
Object[] args = new Object[paramTypes.length]; Object[] args = new Object[paramTypes.length];
WebDataBinder binder = binderFactory.createBinder(webRequest, null, attributeName); WebDataBinder binder = binderFactory.createBinder(webRequest, null, attributeName);
boolean bindingFailure = false;
for (int i = 0; i < paramNames.length; i++) { for (int i = 0; i < paramNames.length; i++) {
String[] parameterValues = webRequest.getParameterValues(paramNames[i]); String[] paramValues = webRequest.getParameterValues(paramNames[i]);
args[i] = (parameterValues != null ? binder.convertIfNecessary(parameterValues, paramTypes[i], try {
new MethodParameter(ctor, i)) : null); args[i] = (paramValues != null ?
binder.convertIfNecessary(paramValues, paramTypes[i], new MethodParameter(ctor, i)) : null);
}
catch (TypeMismatchException ex) {
bindingFailure = true;
binder.getBindingResult().addError(new FieldError(
binder.getObjectName(), paramNames[i], ex.getValue(), true,
new String[] {ex.getErrorCode()}, null, ex.getLocalizedMessage()));
}
}
if (bindingFailure) {
throw new BindException(binder.getBindingResult());
} }
return BeanUtils.instantiateClass(ctor, args); return BeanUtils.instantiateClass(ctor, args);
} }
@@ -219,11 +294,23 @@ public class ModelAttributeMethodProcessor implements HandlerMethodArgumentResol
/** /**
* Whether to raise a fatal bind exception on validation errors. * Whether to raise a fatal bind exception on validation errors.
* <p>The default implementation delegates to {@link #isBindExceptionRequired(MethodParameter)}.
* @param binder the data binder used to perform data binding * @param binder the data binder used to perform data binding
* @param parameter the method parameter declaration * @param parameter the method parameter declaration
* @return {@code true} if the next method argument is not of type {@link Errors} * @return {@code true} if the next method parameter is not of type {@link Errors}
* @see #isBindExceptionRequired(MethodParameter)
*/ */
protected boolean isBindExceptionRequired(WebDataBinder binder, MethodParameter parameter) { protected boolean isBindExceptionRequired(WebDataBinder binder, MethodParameter parameter) {
return isBindExceptionRequired(parameter);
}
/**
* Whether to raise a fatal bind exception on validation errors.
* @param parameter the method parameter declaration
* @return {@code true} if the next method parameter is not of type {@link Errors}
* @since 5.0
*/
protected boolean isBindExceptionRequired(MethodParameter parameter) {
int i = parameter.getParameterIndex(); int i = parameter.getParameterIndex();
Class<?>[] paramTypes = parameter.getExecutable().getParameterTypes(); Class<?>[] paramTypes = parameter.getExecutable().getParameterTypes();
boolean hasBindingResult = (paramTypes.length > (i + 1) && Errors.class.isAssignableFrom(paramTypes[i + 1])); boolean hasBindingResult = (paramTypes.length > (i + 1) && Errors.class.isAssignableFrom(paramTypes[i + 1]));

View File

@@ -45,6 +45,7 @@ import org.springframework.web.servlet.HandlerMapping;
* model attribute name and there is an appropriate type conversion strategy. * model attribute name and there is an appropriate type conversion strategy.
* *
* @author Rossen Stoyanchev * @author Rossen Stoyanchev
* @author Juergen Hoeller
* @since 3.1 * @since 3.1
*/ */
public class ServletModelAttributeMethodProcessor extends ModelAttributeMethodProcessor { public class ServletModelAttributeMethodProcessor extends ModelAttributeMethodProcessor {
@@ -68,19 +69,19 @@ public class ServletModelAttributeMethodProcessor extends ModelAttributeMethodPr
* @see #createAttributeFromRequestValue * @see #createAttributeFromRequestValue
*/ */
@Override @Override
protected final Object createAttribute(String attributeName, MethodParameter methodParam, protected final Object createAttribute(String attributeName, MethodParameter parameter,
WebDataBinderFactory binderFactory, NativeWebRequest request) throws Exception { WebDataBinderFactory binderFactory, NativeWebRequest request) throws Exception {
String value = getRequestValueForAttribute(attributeName, request); String value = getRequestValueForAttribute(attributeName, request);
if (value != null) { if (value != null) {
Object attribute = createAttributeFromRequestValue( Object attribute = createAttributeFromRequestValue(
value, attributeName, methodParam, binderFactory, request); value, attributeName, parameter, binderFactory, request);
if (attribute != null) { if (attribute != null) {
return attribute; return attribute;
} }
} }
return super.createAttribute(attributeName, methodParam, binderFactory, request); return super.createAttribute(attributeName, parameter, binderFactory, request);
} }
/** /**
@@ -120,7 +121,7 @@ public class ServletModelAttributeMethodProcessor extends ModelAttributeMethodPr
* {@link Converter} that can perform the conversion. * {@link Converter} that can perform the conversion.
* @param sourceValue the source value to create the model attribute from * @param sourceValue the source value to create the model attribute from
* @param attributeName the name of the attribute (never {@code null}) * @param attributeName the name of the attribute (never {@code null})
* @param methodParam the method parameter * @param parameter the method parameter
* @param binderFactory for creating WebDataBinder instance * @param binderFactory for creating WebDataBinder instance
* @param request the current request * @param request the current request
* @return the created model attribute, or {@code null} if no suitable * @return the created model attribute, or {@code null} if no suitable
@@ -129,16 +130,16 @@ public class ServletModelAttributeMethodProcessor extends ModelAttributeMethodPr
*/ */
@Nullable @Nullable
protected Object createAttributeFromRequestValue(String sourceValue, String attributeName, protected Object createAttributeFromRequestValue(String sourceValue, String attributeName,
MethodParameter methodParam, WebDataBinderFactory binderFactory, NativeWebRequest request) MethodParameter parameter, WebDataBinderFactory binderFactory, NativeWebRequest request)
throws Exception { throws Exception {
DataBinder binder = binderFactory.createBinder(request, null, attributeName); DataBinder binder = binderFactory.createBinder(request, null, attributeName);
ConversionService conversionService = binder.getConversionService(); ConversionService conversionService = binder.getConversionService();
if (conversionService != null) { if (conversionService != null) {
TypeDescriptor source = TypeDescriptor.valueOf(String.class); TypeDescriptor source = TypeDescriptor.valueOf(String.class);
TypeDescriptor target = new TypeDescriptor(methodParam); TypeDescriptor target = new TypeDescriptor(parameter);
if (conversionService.canConvert(source, target)) { if (conversionService.canConvert(source, target)) {
return binder.convertIfNecessary(sourceValue, methodParam.getParameterType(), methodParam); return binder.convertIfNecessary(sourceValue, parameter.getParameterType(), parameter);
} }
} }
return null; return null;

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -35,9 +35,9 @@ import static org.junit.Assert.*;
/** /**
* Base class for tests using on the DispatcherServlet and HandlerMethod infrastructure classes: * Base class for tests using on the DispatcherServlet and HandlerMethod infrastructure classes:
* <ul> * <ul>
* <li>RequestMappingHandlerMapping * <li>RequestMappingHandlerMapping
* <li>RequestMappingHandlerAdapter * <li>RequestMappingHandlerAdapter
* <li>ExceptionHandlerExceptionResolver * <li>ExceptionHandlerExceptionResolver
* </ul> * </ul>
* *
* @author Rossen Stoyanchev * @author Rossen Stoyanchev
@@ -46,21 +46,23 @@ public abstract class AbstractServletHandlerMethodTests {
private DispatcherServlet servlet; private DispatcherServlet servlet;
@After
public void tearDown() {
this.servlet = null;
}
protected DispatcherServlet getServlet() { protected DispatcherServlet getServlet() {
assertNotNull("DispatcherServlet not initialized", servlet); assertNotNull("DispatcherServlet not initialized", servlet);
return servlet; return servlet;
} }
@After
public void tearDown() {
this.servlet = null;
}
/** /**
* Initialize a DispatcherServlet instance registering zero or more controller classes. * Initialize a DispatcherServlet instance registering zero or more controller classes.
*/ */
protected WebApplicationContext initServletWithControllers(final Class<?>... controllerClasses) protected WebApplicationContext initServletWithControllers(final Class<?>... controllerClasses)
throws ServletException { throws ServletException {
return initServlet(null, controllerClasses); return initServlet(null, controllerClasses);
} }
@@ -82,22 +84,17 @@ public abstract class AbstractServletHandlerMethodTests {
wac.registerBeanDefinition(clazz.getSimpleName(), new RootBeanDefinition(clazz)); wac.registerBeanDefinition(clazz.getSimpleName(), new RootBeanDefinition(clazz));
} }
Class<?> mappingType = RequestMappingHandlerMapping.class; RootBeanDefinition mappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class);
RootBeanDefinition beanDef = new RootBeanDefinition(mappingType); mappingDef.getPropertyValues().add("removeSemicolonContent", "false");
beanDef.getPropertyValues().add("removeSemicolonContent", "false"); wac.registerBeanDefinition("handlerMapping", mappingDef);
wac.registerBeanDefinition("handlerMapping", beanDef);
Class<?> adapterType = RequestMappingHandlerAdapter.class; wac.registerBeanDefinition("handlerAdapter", new RootBeanDefinition(RequestMappingHandlerAdapter.class));
wac.registerBeanDefinition("handlerAdapter", new RootBeanDefinition(adapterType));
Class<?> resolverType = ExceptionHandlerExceptionResolver.class; wac.registerBeanDefinition("requestMappingResolver", new RootBeanDefinition(ExceptionHandlerExceptionResolver.class));
wac.registerBeanDefinition("requestMappingResolver", new RootBeanDefinition(resolverType));
resolverType = ResponseStatusExceptionResolver.class; wac.registerBeanDefinition("responseStatusResolver", new RootBeanDefinition(ResponseStatusExceptionResolver.class));
wac.registerBeanDefinition("responseStatusResolver", new RootBeanDefinition(resolverType));
resolverType = DefaultHandlerExceptionResolver.class; wac.registerBeanDefinition("defaultResolver", new RootBeanDefinition(DefaultHandlerExceptionResolver.class));
wac.registerBeanDefinition("defaultResolver", new RootBeanDefinition(resolverType));
if (initializer != null) { if (initializer != null) {
initializer.initialize(wac); initializer.initialize(wac);

View File

@@ -42,10 +42,10 @@ import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Optional;
import java.util.Set; import java.util.Set;
import javax.servlet.ServletConfig; import javax.servlet.ServletConfig;
import javax.servlet.ServletContext; import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie; import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
@@ -66,7 +66,6 @@ import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer; import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.propertyeditors.CustomDateEditor; import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.annotation.AnnotationConfigUtils; import org.springframework.context.annotation.AnnotationConfigUtils;
import org.springframework.core.MethodParameter; import org.springframework.core.MethodParameter;
import org.springframework.core.convert.converter.Converter; import org.springframework.core.convert.converter.Converter;
@@ -131,7 +130,6 @@ import org.springframework.web.bind.support.WebBindingInitializer;
import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.WebRequest; import org.springframework.web.context.request.WebRequest;
import org.springframework.web.context.support.GenericWebApplicationContext;
import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.multipart.support.StringMultipartFileEditor; import org.springframework.web.multipart.support.StringMultipartFileEditor;
import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.ModelAndView;
@@ -142,14 +140,7 @@ import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import org.springframework.web.servlet.support.RequestContextUtils; import org.springframework.web.servlet.support.RequestContextUtils;
import org.springframework.web.servlet.view.InternalResourceViewResolver; import org.springframework.web.servlet.view.InternalResourceViewResolver;
import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.*;
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;
/** /**
* @author Rossen Stoyanchev * @author Rossen Stoyanchev
@@ -247,13 +238,10 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
@Test @Test
public void defaultExpressionParameters() throws Exception { public void defaultExpressionParameters() throws Exception {
initServlet(new ApplicationContextInitializer<GenericWebApplicationContext>() { initServlet(wac -> {
@Override RootBeanDefinition ppc = new RootBeanDefinition(PropertyPlaceholderConfigurer.class);
public void initialize(GenericWebApplicationContext context) { ppc.getPropertyValues().add("properties", "myKey=foo");
RootBeanDefinition ppc = new RootBeanDefinition(PropertyPlaceholderConfigurer.class); wac.registerBeanDefinition("ppc", ppc);
ppc.getPropertyValues().add("properties", "myKey=foo");
context.registerBeanDefinition("ppc", ppc);
}
}, DefaultExpressionValueParamController.class); }, DefaultExpressionValueParamController.class);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myApp/myPath.do"); MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myApp/myPath.do");
@@ -271,17 +259,14 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
@Test @Test
public void typeNestedSetBinding() throws Exception { public void typeNestedSetBinding() throws Exception {
initServlet(new ApplicationContextInitializer<GenericWebApplicationContext>() { initServlet(wac -> {
@Override RootBeanDefinition csDef = new RootBeanDefinition(FormattingConversionServiceFactoryBean.class);
public void initialize(GenericWebApplicationContext context) { csDef.getPropertyValues().add("converters", new TestBeanConverter());
RootBeanDefinition csDef = new RootBeanDefinition(FormattingConversionServiceFactoryBean.class); RootBeanDefinition wbiDef = new RootBeanDefinition(ConfigurableWebBindingInitializer.class);
csDef.getPropertyValues().add("converters", new TestBeanConverter()); wbiDef.getPropertyValues().add("conversionService", csDef);
RootBeanDefinition wbiDef = new RootBeanDefinition(ConfigurableWebBindingInitializer.class); RootBeanDefinition adapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);
wbiDef.getPropertyValues().add("conversionService", csDef); adapterDef.getPropertyValues().add("webBindingInitializer", wbiDef);
RootBeanDefinition adapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class); wac.registerBeanDefinition("handlerAdapter", adapterDef);
adapterDef.getPropertyValues().add("webBindingInitializer", wbiDef);
context.registerBeanDefinition("handlerAdapter", adapterDef);
}
}, NestedSetController.class); }, NestedSetController.class);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath.do"); MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath.do");
@@ -293,17 +278,14 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
@Test // SPR-12903 @Test // SPR-12903
public void pathVariableWithCustomConverter() throws Exception { public void pathVariableWithCustomConverter() throws Exception {
initServlet(new ApplicationContextInitializer<GenericWebApplicationContext>() { initServlet(wac -> {
@Override RootBeanDefinition csDef = new RootBeanDefinition(FormattingConversionServiceFactoryBean.class);
public void initialize(GenericWebApplicationContext context) { csDef.getPropertyValues().add("converters", new AnnotatedExceptionRaisingConverter());
RootBeanDefinition csDef = new RootBeanDefinition(FormattingConversionServiceFactoryBean.class); RootBeanDefinition wbiDef = new RootBeanDefinition(ConfigurableWebBindingInitializer.class);
csDef.getPropertyValues().add("converters", new AnnotatedExceptionRaisingConverter()); wbiDef.getPropertyValues().add("conversionService", csDef);
RootBeanDefinition wbiDef = new RootBeanDefinition(ConfigurableWebBindingInitializer.class); RootBeanDefinition adapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);
wbiDef.getPropertyValues().add("conversionService", csDef); adapterDef.getPropertyValues().add("webBindingInitializer", wbiDef);
RootBeanDefinition adapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class); wac.registerBeanDefinition("handlerAdapter", adapterDef);
adapterDef.getPropertyValues().add("webBindingInitializer", wbiDef);
context.registerBeanDefinition("handlerAdapter", adapterDef);
}
}, PathVariableWithCustomConverterController.class); }, PathVariableWithCustomConverterController.class);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath/1"); MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath/1");
@@ -335,13 +317,10 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
@Test @Test
public void emptyParameterListHandleMethod() throws Exception { public void emptyParameterListHandleMethod() throws Exception {
initServlet(new ApplicationContextInitializer<GenericWebApplicationContext>() { initServlet(wac -> {
@Override RootBeanDefinition vrDef = new RootBeanDefinition(InternalResourceViewResolver.class);
public void initialize(GenericWebApplicationContext context) { vrDef.getPropertyValues().add("suffix", ".jsp");
RootBeanDefinition vrDef = new RootBeanDefinition(InternalResourceViewResolver.class); wac.registerBeanDefinition("viewResolver", vrDef);
vrDef.getPropertyValues().add("suffix", ".jsp");
context.registerBeanDefinition("viewResolver", vrDef);
}
}, EmptyParameterListHandlerMethodController.class); }, EmptyParameterListHandlerMethodController.class);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/emptyParameterListHandler"); MockHttpServletRequest request = new MockHttpServletRequest("GET", "/emptyParameterListHandler");
@@ -356,12 +335,9 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
@Test @Test
public void sessionAttributeExposure() throws Exception { public void sessionAttributeExposure() throws Exception {
initServlet(new ApplicationContextInitializer<GenericWebApplicationContext>() { initServlet(
@Override wac -> wac.registerBeanDefinition("viewResolver", new RootBeanDefinition(ModelExposingViewResolver.class)),
public void initialize(GenericWebApplicationContext context) { MySessionAttributesController.class);
context.registerBeanDefinition("viewResolver", new RootBeanDefinition(ModelExposingViewResolver.class));
}
}, MySessionAttributesController.class);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPage"); MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPage");
MockHttpServletResponse response = new MockHttpServletResponse(); MockHttpServletResponse response = new MockHttpServletResponse();
@@ -387,15 +363,12 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
@Test @Test
public void sessionAttributeExposureWithInterface() throws Exception { public void sessionAttributeExposureWithInterface() throws Exception {
initServlet(new ApplicationContextInitializer<GenericWebApplicationContext>() { initServlet(wac -> {
@Override wac.registerBeanDefinition("viewResolver", new RootBeanDefinition(ModelExposingViewResolver.class));
public void initialize(GenericWebApplicationContext context) { DefaultAdvisorAutoProxyCreator autoProxyCreator = new DefaultAdvisorAutoProxyCreator();
context.registerBeanDefinition("viewResolver", new RootBeanDefinition(ModelExposingViewResolver.class)); autoProxyCreator.setBeanFactory(wac.getBeanFactory());
DefaultAdvisorAutoProxyCreator autoProxyCreator = new DefaultAdvisorAutoProxyCreator(); wac.getBeanFactory().addBeanPostProcessor(autoProxyCreator);
autoProxyCreator.setBeanFactory(context.getBeanFactory()); wac.getBeanFactory().registerSingleton("advisor", new DefaultPointcutAdvisor(new SimpleTraceInterceptor()));
context.getBeanFactory().addBeanPostProcessor(autoProxyCreator);
context.getBeanFactory().registerSingleton("advisor", new DefaultPointcutAdvisor(new SimpleTraceInterceptor()));
}
}, MySessionAttributesControllerImpl.class); }, MySessionAttributesControllerImpl.class);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPage"); MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPage");
@@ -422,12 +395,9 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
@Test @Test
public void parameterizedAnnotatedInterface() throws Exception { public void parameterizedAnnotatedInterface() throws Exception {
initServlet(new ApplicationContextInitializer<GenericWebApplicationContext>() { initServlet(
@Override wac -> wac.registerBeanDefinition("viewResolver", new RootBeanDefinition(ModelExposingViewResolver.class)),
public void initialize(GenericWebApplicationContext context) { MyParameterizedControllerImpl.class);
context.registerBeanDefinition("viewResolver", new RootBeanDefinition(ModelExposingViewResolver.class));
}
}, MyParameterizedControllerImpl.class);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPage"); MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPage");
MockHttpServletResponse response = new MockHttpServletResponse(); MockHttpServletResponse response = new MockHttpServletResponse();
@@ -455,12 +425,9 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
@Test @Test
public void parameterizedAnnotatedInterfaceWithOverriddenMappingsInImpl() throws Exception { public void parameterizedAnnotatedInterfaceWithOverriddenMappingsInImpl() throws Exception {
initServlet(new ApplicationContextInitializer<GenericWebApplicationContext>() { initServlet(
@Override wac -> wac.registerBeanDefinition("viewResolver", new RootBeanDefinition(ModelExposingViewResolver.class)),
public void initialize(GenericWebApplicationContext context) { MyParameterizedControllerImplWithOverriddenMappings.class);
context.registerBeanDefinition("viewResolver", new RootBeanDefinition(ModelExposingViewResolver.class));
}
}, MyParameterizedControllerImplWithOverriddenMappings.class);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPage"); MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPage");
MockHttpServletResponse response = new MockHttpServletResponse(); MockHttpServletResponse response = new MockHttpServletResponse();
@@ -540,12 +507,9 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
@Test @Test
public void formController() throws Exception { public void formController() throws Exception {
initServlet(new ApplicationContextInitializer<GenericWebApplicationContext>() { initServlet(
@Override wac -> wac.registerBeanDefinition("viewResolver", new RootBeanDefinition(TestViewResolver.class)),
public void initialize(GenericWebApplicationContext wac) { MyFormController.class);
wac.registerBeanDefinition("viewResolver", new RootBeanDefinition(TestViewResolver.class));
}
}, MyFormController.class);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath.do"); MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath.do");
request.addParameter("name", "name1"); request.addParameter("name", "name1");
@@ -557,12 +521,9 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
@Test @Test
public void modelFormController() throws Exception { public void modelFormController() throws Exception {
initServlet(new ApplicationContextInitializer<GenericWebApplicationContext>() { initServlet(
@Override wac -> wac.registerBeanDefinition("viewResolver", new RootBeanDefinition(TestViewResolver.class)),
public void initialize(GenericWebApplicationContext wac) { MyModelFormController.class);
wac.registerBeanDefinition("viewResolver", new RootBeanDefinition(TestViewResolver.class));
}
}, MyModelFormController.class);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath.do"); MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath.do");
request.addParameter("name", "name1"); request.addParameter("name", "name1");
@@ -574,16 +535,13 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
@Test @Test
public void proxiedFormController() throws Exception { public void proxiedFormController() throws Exception {
initServlet(new ApplicationContextInitializer<GenericWebApplicationContext>() { initServlet(wac -> {
@Override wac.registerBeanDefinition("viewResolver", new RootBeanDefinition(TestViewResolver.class));
public void initialize(GenericWebApplicationContext wac) { DefaultAdvisorAutoProxyCreator autoProxyCreator = new DefaultAdvisorAutoProxyCreator();
wac.registerBeanDefinition("viewResolver", new RootBeanDefinition(TestViewResolver.class)); autoProxyCreator.setBeanFactory(wac.getBeanFactory());
DefaultAdvisorAutoProxyCreator autoProxyCreator = new DefaultAdvisorAutoProxyCreator(); wac.getBeanFactory().addBeanPostProcessor(autoProxyCreator);
autoProxyCreator.setBeanFactory(wac.getBeanFactory()); wac.getBeanFactory()
wac.getBeanFactory().addBeanPostProcessor(autoProxyCreator); .registerSingleton("advisor", new DefaultPointcutAdvisor(new SimpleTraceInterceptor()));
wac.getBeanFactory()
.registerSingleton("advisor", new DefaultPointcutAdvisor(new SimpleTraceInterceptor()));
}
}, MyFormController.class); }, MyFormController.class);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath.do"); MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath.do");
@@ -596,14 +554,11 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
@Test @Test
public void commandProvidingFormControllerWithCustomEditor() throws Exception { public void commandProvidingFormControllerWithCustomEditor() throws Exception {
initServlet(new ApplicationContextInitializer<GenericWebApplicationContext>() { initServlet(wac -> {
@Override wac.registerBeanDefinition("viewResolver", new RootBeanDefinition(TestViewResolver.class));
public void initialize(GenericWebApplicationContext wac) { RootBeanDefinition adapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);
wac.registerBeanDefinition("viewResolver", new RootBeanDefinition(TestViewResolver.class)); adapterDef.getPropertyValues().add("webBindingInitializer", new MyWebBindingInitializer());
RootBeanDefinition adapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class); wac.registerBeanDefinition("handlerAdapter", adapterDef);
adapterDef.getPropertyValues().add("webBindingInitializer", new MyWebBindingInitializer());
wac.registerBeanDefinition("handlerAdapter", adapterDef);
}
}, MyCommandProvidingFormController.class); }, MyCommandProvidingFormController.class);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath.do"); MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath.do");
@@ -617,17 +572,14 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
@Test @Test
public void typedCommandProvidingFormController() throws Exception { public void typedCommandProvidingFormController() throws Exception {
initServlet(new ApplicationContextInitializer<GenericWebApplicationContext>() { initServlet(wac -> {
@Override wac.registerBeanDefinition("viewResolver", new RootBeanDefinition(TestViewResolver.class));
public void initialize(GenericWebApplicationContext wac) { RootBeanDefinition adapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);
wac.registerBeanDefinition("viewResolver", new RootBeanDefinition(TestViewResolver.class)); adapterDef.getPropertyValues().add("webBindingInitializer", new MyWebBindingInitializer());
RootBeanDefinition adapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class); List<HandlerMethodArgumentResolver> argumentResolvers = new ArrayList<>();
adapterDef.getPropertyValues().add("webBindingInitializer", new MyWebBindingInitializer()); argumentResolvers.add(new ServletWebArgumentResolverAdapter(new MySpecialArgumentResolver()));
List<HandlerMethodArgumentResolver> argumentResolvers = new ArrayList<>(); adapterDef.getPropertyValues().add("customArgumentResolvers", argumentResolvers);
argumentResolvers.add(new ServletWebArgumentResolverAdapter(new MySpecialArgumentResolver())); wac.registerBeanDefinition("handlerAdapter", adapterDef);
adapterDef.getPropertyValues().add("customArgumentResolvers", argumentResolvers);
wac.registerBeanDefinition("handlerAdapter", adapterDef);
}
}, MyTypedCommandProvidingFormController.class); }, MyTypedCommandProvidingFormController.class);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath.do"); MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath.do");
@@ -657,12 +609,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
@Test @Test
public void binderInitializingCommandProvidingFormController() throws Exception { public void binderInitializingCommandProvidingFormController() throws Exception {
initServlet(new ApplicationContextInitializer<GenericWebApplicationContext>() { initServlet(wac -> wac.registerBeanDefinition("viewResolver", new RootBeanDefinition(TestViewResolver.class)), MyBinderInitializingCommandProvidingFormController.class);
@Override
public void initialize(GenericWebApplicationContext wac) {
wac.registerBeanDefinition("viewResolver", new RootBeanDefinition(TestViewResolver.class));
}
}, MyBinderInitializingCommandProvidingFormController.class);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath.do"); MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath.do");
request.addParameter("defaultName", "myDefaultName"); request.addParameter("defaultName", "myDefaultName");
@@ -675,12 +622,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
@Test @Test
public void specificBinderInitializingCommandProvidingFormController() throws Exception { public void specificBinderInitializingCommandProvidingFormController() throws Exception {
initServlet(new ApplicationContextInitializer<GenericWebApplicationContext>() { initServlet(wac -> wac.registerBeanDefinition("viewResolver", new RootBeanDefinition(TestViewResolver.class)), MySpecificBinderInitializingCommandProvidingFormController.class);
@Override
public void initialize(GenericWebApplicationContext wac) {
wac.registerBeanDefinition("viewResolver", new RootBeanDefinition(TestViewResolver.class));
}
}, MySpecificBinderInitializingCommandProvidingFormController.class);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath.do"); MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath.do");
request.addParameter("defaultName", "myDefaultName"); request.addParameter("defaultName", "myDefaultName");
@@ -696,15 +638,12 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
final MockServletContext servletContext = new MockServletContext(); final MockServletContext servletContext = new MockServletContext();
final MockServletConfig servletConfig = new MockServletConfig(servletContext); final MockServletConfig servletConfig = new MockServletConfig(servletContext);
WebApplicationContext webAppContext = WebApplicationContext webAppContext =
initServlet(new ApplicationContextInitializer<GenericWebApplicationContext>() { initServlet(wac -> {
@Override wac.setServletContext(servletContext);
public void initialize(GenericWebApplicationContext wac) { AnnotationConfigUtils.registerAnnotationConfigProcessors(wac);
wac.setServletContext(servletContext); wac.getBeanFactory().registerResolvableDependency(ServletConfig.class, servletConfig);
AnnotationConfigUtils.registerAnnotationConfigProcessors(wac); }, MyParameterDispatchingController.class);
wac.getBeanFactory().registerResolvableDependency(ServletConfig.class, servletConfig);
}
}, MyParameterDispatchingController.class);
MockHttpServletRequest request = new MockHttpServletRequest(servletContext, "GET", "/myPath.do"); MockHttpServletRequest request = new MockHttpServletRequest(servletContext, "GET", "/myPath.do");
MockHttpServletResponse response = new MockHttpServletResponse(); MockHttpServletResponse response = new MockHttpServletResponse();
@@ -830,7 +769,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
} }
@Test @Test
public void pathOrdering() throws ServletException, IOException { public void pathOrdering() throws Exception {
initServletWithControllers(PathOrderingController.class); initServletWithControllers(PathOrderingController.class);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/dir/myPath1.do"); MockHttpServletRequest request = new MockHttpServletRequest("GET", "/dir/myPath1.do");
@@ -840,7 +779,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
} }
@Test @Test
public void requestBodyResponseBody() throws ServletException, IOException { public void requestBodyResponseBody() throws Exception {
initServletWithControllers(RequestResponseBodyController.class); initServletWithControllers(RequestResponseBodyController.class);
MockHttpServletRequest request = new MockHttpServletRequest("PUT", "/something"); MockHttpServletRequest request = new MockHttpServletRequest("PUT", "/something");
@@ -855,7 +794,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
} }
@Test @Test
public void httpPatch() throws ServletException, IOException { public void httpPatch() throws Exception {
initServletWithControllers(RequestResponseBodyController.class); initServletWithControllers(RequestResponseBodyController.class);
MockHttpServletRequest request = new MockHttpServletRequest("PATCH", "/something"); MockHttpServletRequest request = new MockHttpServletRequest("PATCH", "/something");
@@ -870,15 +809,12 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
} }
@Test @Test
public void responseBodyNoAcceptableMediaType() throws ServletException, IOException { public void responseBodyNoAcceptableMediaType() throws Exception {
initServlet(new ApplicationContextInitializer<GenericWebApplicationContext>() { initServlet(wac -> {
@Override RootBeanDefinition adapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);
public void initialize(GenericWebApplicationContext wac) { StringHttpMessageConverter converter = new StringHttpMessageConverter();
RootBeanDefinition adapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class); adapterDef.getPropertyValues().add("messageConverters", converter);
StringHttpMessageConverter converter = new StringHttpMessageConverter(); wac.registerBeanDefinition("handlerAdapter", adapterDef);
adapterDef.getPropertyValues().add("messageConverters", converter);
wac.registerBeanDefinition("handlerAdapter", adapterDef);
}
}, RequestResponseBodyProducesController.class); }, RequestResponseBodyProducesController.class);
MockHttpServletRequest request = new MockHttpServletRequest("PUT", "/something"); MockHttpServletRequest request = new MockHttpServletRequest("PUT", "/something");
@@ -892,7 +828,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
} }
@Test @Test
public void responseBodyWildCardMediaType() throws ServletException, IOException { public void responseBodyWildCardMediaType() throws Exception {
initServletWithControllers(RequestResponseBodyController.class); initServletWithControllers(RequestResponseBodyController.class);
MockHttpServletRequest request = new MockHttpServletRequest("PUT", "/something"); MockHttpServletRequest request = new MockHttpServletRequest("PUT", "/something");
@@ -906,14 +842,11 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
} }
@Test @Test
public void unsupportedRequestBody() throws ServletException, IOException { public void unsupportedRequestBody() throws Exception {
initServlet(new ApplicationContextInitializer<GenericWebApplicationContext>() { initServlet(wac -> {
@Override RootBeanDefinition adapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);
public void initialize(GenericWebApplicationContext wac) { adapterDef.getPropertyValues().add("messageConverters", new ByteArrayHttpMessageConverter());
RootBeanDefinition adapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class); wac.registerBeanDefinition("handlerAdapter", adapterDef);
adapterDef.getPropertyValues().add("messageConverters", new ByteArrayHttpMessageConverter());
wac.registerBeanDefinition("handlerAdapter", adapterDef);
}
}, RequestResponseBodyController.class); }, RequestResponseBodyController.class);
MockHttpServletRequest request = new MockHttpServletRequest("PUT", "/something"); MockHttpServletRequest request = new MockHttpServletRequest("PUT", "/something");
@@ -927,7 +860,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
} }
@Test @Test
public void responseBodyNoAcceptHeader() throws ServletException, IOException { public void responseBodyNoAcceptHeader() throws Exception {
initServletWithControllers(RequestResponseBodyController.class); initServletWithControllers(RequestResponseBodyController.class);
MockHttpServletRequest request = new MockHttpServletRequest("PUT", "/something"); MockHttpServletRequest request = new MockHttpServletRequest("PUT", "/something");
@@ -941,14 +874,11 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
} }
@Test @Test
public void badRequestRequestBody() throws ServletException, IOException { public void badRequestRequestBody() throws Exception {
initServlet(new ApplicationContextInitializer<GenericWebApplicationContext>() { initServlet(wac -> {
@Override RootBeanDefinition adapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);
public void initialize(GenericWebApplicationContext wac) { adapterDef.getPropertyValues().add("messageConverters", new NotReadableMessageConverter());
RootBeanDefinition adapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class); wac.registerBeanDefinition("handlerAdapter", adapterDef);
adapterDef.getPropertyValues().add("messageConverters", new NotReadableMessageConverter());
wac.registerBeanDefinition("handlerAdapter", adapterDef);
}
}, RequestResponseBodyController.class); }, RequestResponseBodyController.class);
MockHttpServletRequest request = new MockHttpServletRequest("PUT", "/something"); MockHttpServletRequest request = new MockHttpServletRequest("PUT", "/something");
@@ -961,7 +891,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
} }
@Test @Test
public void httpEntity() throws ServletException, IOException { public void httpEntity() throws Exception {
initServletWithControllers(ResponseEntityController.class); initServletWithControllers(ResponseEntityController.class);
MockHttpServletRequest request = new MockHttpServletRequest("POST", "/foo"); MockHttpServletRequest request = new MockHttpServletRequest("POST", "/foo");
@@ -983,23 +913,16 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
assertEquals(404, response.getStatus()); assertEquals(404, response.getStatus());
} }
@Test // SPR-6877
/* public void overlappingMessageConvertersRequestBody() throws Exception {
* See SPR-6877 initServlet(wac -> {
*/ RootBeanDefinition adapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);
@Test List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
public void overlappingMessageConvertersRequestBody() throws ServletException, IOException { messageConverters.add(new StringHttpMessageConverter());
initServlet(new ApplicationContextInitializer<GenericWebApplicationContext>() { messageConverters
@Override .add(new SimpleMessageConverter(new MediaType("application","json"), MediaType.ALL));
public void initialize(GenericWebApplicationContext wac) { adapterDef.getPropertyValues().add("messageConverters", messageConverters);
RootBeanDefinition adapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class); wac.registerBeanDefinition("handlerAdapter", adapterDef);
List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
messageConverters.add(new StringHttpMessageConverter());
messageConverters
.add(new SimpleMessageConverter(new MediaType("application","json"), MediaType.ALL));
adapterDef.getPropertyValues().add("messageConverters", messageConverters);
wac.registerBeanDefinition("handlerAdapter", adapterDef);
}
}, RequestResponseBodyController.class); }, RequestResponseBodyController.class);
MockHttpServletRequest request = new MockHttpServletRequest("PUT", "/something"); MockHttpServletRequest request = new MockHttpServletRequest("PUT", "/something");
@@ -1012,7 +935,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
} }
@Test @Test
public void responseBodyVoid() throws ServletException, IOException { public void responseBodyVoid() throws Exception {
initServletWithControllers(ResponseBodyVoidController.class); initServletWithControllers(ResponseBodyVoidController.class);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/something"); MockHttpServletRequest request = new MockHttpServletRequest("GET", "/something");
@@ -1023,24 +946,21 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
} }
@Test @Test
public void responseBodyArgMismatch() throws ServletException, IOException { public void responseBodyArgMismatch() throws Exception {
initServlet(new ApplicationContextInitializer<GenericWebApplicationContext>() { initServlet(wac -> {
@Override Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
public void initialize(GenericWebApplicationContext wac) { marshaller.setClassesToBeBound(A.class, B.class);
Jaxb2Marshaller marshaller = new Jaxb2Marshaller(); try {
marshaller.setClassesToBeBound(A.class, B.class); marshaller.afterPropertiesSet();
try {
marshaller.afterPropertiesSet();
}
catch (Exception ex) {
throw new BeanCreationException(ex.getMessage(), ex);
}
MarshallingHttpMessageConverter messageConverter = new MarshallingHttpMessageConverter(marshaller);
RootBeanDefinition adapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);
adapterDef.getPropertyValues().add("messageConverters", messageConverter);
wac.registerBeanDefinition("handlerAdapter", adapterDef);
} }
catch (Exception ex) {
throw new BeanCreationException(ex.getMessage(), ex);
}
MarshallingHttpMessageConverter messageConverter = new MarshallingHttpMessageConverter(marshaller);
RootBeanDefinition adapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);
adapterDef.getPropertyValues().add("messageConverters", messageConverter);
wac.registerBeanDefinition("handlerAdapter", adapterDef);
}, RequestBodyArgMismatchController.class); }, RequestBodyArgMismatchController.class);
MockHttpServletRequest request = new MockHttpServletRequest("PUT", "/something"); MockHttpServletRequest request = new MockHttpServletRequest("PUT", "/something");
@@ -1054,7 +974,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
@Test @Test
public void contentTypeHeaders() throws ServletException, IOException { public void contentTypeHeaders() throws Exception {
initServletWithControllers(ContentTypeHeadersController.class); initServletWithControllers(ContentTypeHeadersController.class);
MockHttpServletRequest request = new MockHttpServletRequest("POST", "/something"); MockHttpServletRequest request = new MockHttpServletRequest("POST", "/something");
@@ -1077,7 +997,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
} }
@Test @Test
public void consumes() throws ServletException, IOException { public void consumes() throws Exception {
initServletWithControllers(ConsumesController.class); initServletWithControllers(ConsumesController.class);
MockHttpServletRequest request = new MockHttpServletRequest("POST", "/something"); MockHttpServletRequest request = new MockHttpServletRequest("POST", "/something");
@@ -1100,7 +1020,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
} }
@Test @Test
public void negatedContentTypeHeaders() throws ServletException, IOException { public void negatedContentTypeHeaders() throws Exception {
initServletWithControllers(NegatedContentTypeHeadersController.class); initServletWithControllers(NegatedContentTypeHeadersController.class);
MockHttpServletRequest request = new MockHttpServletRequest("POST", "/something"); MockHttpServletRequest request = new MockHttpServletRequest("POST", "/something");
@@ -1117,7 +1037,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
} }
@Test @Test
public void acceptHeaders() throws ServletException, IOException { public void acceptHeaders() throws Exception {
initServletWithControllers(AcceptHeadersController.class); initServletWithControllers(AcceptHeadersController.class);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/something"); MockHttpServletRequest request = new MockHttpServletRequest("GET", "/something");
@@ -1152,7 +1072,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
} }
@Test @Test
public void produces() throws ServletException, IOException { public void produces() throws Exception {
initServletWithControllers(ProducesController.class); initServletWithControllers(ProducesController.class);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/something"); MockHttpServletRequest request = new MockHttpServletRequest("GET", "/something");
@@ -1187,7 +1107,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
} }
@Test @Test
public void responseStatus() throws ServletException, IOException { public void responseStatus() throws Exception {
initServletWithControllers(ResponseStatusController.class); initServletWithControllers(ResponseStatusController.class);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/something"); MockHttpServletRequest request = new MockHttpServletRequest("GET", "/something");
@@ -1199,15 +1119,12 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
} }
@Test @Test
public void mavResolver() throws ServletException, IOException { public void mavResolver() throws Exception {
initServlet(new ApplicationContextInitializer<GenericWebApplicationContext>() { initServlet(wac -> {
@Override RootBeanDefinition adapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);
public void initialize(GenericWebApplicationContext wac) { ModelAndViewResolver[] mavResolvers = new ModelAndViewResolver[] {new MyModelAndViewResolver()};
RootBeanDefinition adapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class); adapterDef.getPropertyValues().add("modelAndViewResolvers", mavResolvers);
ModelAndViewResolver[] mavResolvers = new ModelAndViewResolver[] {new MyModelAndViewResolver()}; wac.registerBeanDefinition("handlerAdapter", adapterDef);
adapterDef.getPropertyValues().add("modelAndViewResolvers", mavResolvers);
wac.registerBeanDefinition("handlerAdapter", adapterDef);
}
}, ModelAndViewResolverController.class); }, ModelAndViewResolverController.class);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/"); MockHttpServletRequest request = new MockHttpServletRequest("GET", "/");
@@ -1218,7 +1135,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
} }
@Test @Test
public void bindingCookieValue() throws ServletException, IOException { public void bindingCookieValue() throws Exception {
initServletWithControllers(BindingCookieValueController.class); initServletWithControllers(BindingCookieValueController.class);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/test"); MockHttpServletRequest request = new MockHttpServletRequest("GET", "/test");
@@ -1229,7 +1146,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
} }
@Test @Test
public void ambiguousParams() throws ServletException, IOException { public void ambiguousParams() throws Exception {
initServletWithControllers(AmbiguousParamsController.class); initServletWithControllers(AmbiguousParamsController.class);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/test"); MockHttpServletRequest request = new MockHttpServletRequest("GET", "/test");
@@ -1327,14 +1244,11 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
@Test @Test
public void requestMappingInterfaceWithProxy() throws Exception { public void requestMappingInterfaceWithProxy() throws Exception {
initServlet(new ApplicationContextInitializer<GenericWebApplicationContext>() { initServlet(wac -> {
@Override DefaultAdvisorAutoProxyCreator autoProxyCreator = new DefaultAdvisorAutoProxyCreator();
public void initialize(GenericWebApplicationContext wac) { autoProxyCreator.setBeanFactory(wac.getBeanFactory());
DefaultAdvisorAutoProxyCreator autoProxyCreator = new DefaultAdvisorAutoProxyCreator(); wac.getBeanFactory().addBeanPostProcessor(autoProxyCreator);
autoProxyCreator.setBeanFactory(wac.getBeanFactory()); wac.getBeanFactory().registerSingleton("advisor", new DefaultPointcutAdvisor(new SimpleTraceInterceptor()));
wac.getBeanFactory().addBeanPostProcessor(autoProxyCreator);
wac.getBeanFactory().registerSingleton("advisor", new DefaultPointcutAdvisor(new SimpleTraceInterceptor()));
}
}, IMyControllerImpl.class); }, IMyControllerImpl.class);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/handle"); MockHttpServletRequest request = new MockHttpServletRequest("GET", "/handle");
@@ -1465,16 +1379,13 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
@Test @Test
public void parameterCsvAsStringArray() throws Exception { public void parameterCsvAsStringArray() throws Exception {
initServlet(new ApplicationContextInitializer<GenericWebApplicationContext>() { initServlet(wac -> {
@Override RootBeanDefinition csDef = new RootBeanDefinition(FormattingConversionServiceFactoryBean.class);
public void initialize(GenericWebApplicationContext wac) { RootBeanDefinition wbiDef = new RootBeanDefinition(ConfigurableWebBindingInitializer.class);
RootBeanDefinition csDef = new RootBeanDefinition(FormattingConversionServiceFactoryBean.class); wbiDef.getPropertyValues().add("conversionService", csDef);
RootBeanDefinition wbiDef = new RootBeanDefinition(ConfigurableWebBindingInitializer.class); RootBeanDefinition adapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);
wbiDef.getPropertyValues().add("conversionService", csDef); adapterDef.getPropertyValues().add("webBindingInitializer", wbiDef);
RootBeanDefinition adapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class); wac.registerBeanDefinition("handlerAdapter", adapterDef);
adapterDef.getPropertyValues().add("webBindingInitializer", wbiDef);
wac.registerBeanDefinition("handlerAdapter", adapterDef);
}
}, CsvController.class); }, CsvController.class);
MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletRequest request = new MockHttpServletRequest();
@@ -1595,13 +1506,10 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
@Test @Test
public void prototypeController() throws Exception { public void prototypeController() throws Exception {
initServlet(new ApplicationContextInitializer<GenericWebApplicationContext>() { initServlet(wac -> {
@Override RootBeanDefinition beanDef = new RootBeanDefinition(PrototypeController.class);
public void initialize(GenericWebApplicationContext context) { beanDef.setScope(BeanDefinition.SCOPE_PROTOTYPE);
RootBeanDefinition beanDef = new RootBeanDefinition(PrototypeController.class); wac.registerBeanDefinition("controller", beanDef);
beanDef.setScope(BeanDefinition.SCOPE_PROTOTYPE);
context.registerBeanDefinition("controller", beanDef);
}
}); });
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/"); MockHttpServletRequest request = new MockHttpServletRequest("GET", "/");
@@ -1652,15 +1560,12 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
@Test @Test
public void responseBodyAsHtml() throws Exception { public void responseBodyAsHtml() throws Exception {
initServlet(new ApplicationContextInitializer<GenericWebApplicationContext>() { initServlet(wac -> {
@Override ContentNegotiationManagerFactoryBean factoryBean = new ContentNegotiationManagerFactoryBean();
public void initialize(GenericWebApplicationContext wac) { factoryBean.afterPropertiesSet();
ContentNegotiationManagerFactoryBean factoryBean = new ContentNegotiationManagerFactoryBean(); RootBeanDefinition adapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);
factoryBean.afterPropertiesSet(); adapterDef.getPropertyValues().add("contentNegotiationManager", factoryBean.getObject());
RootBeanDefinition adapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class); wac.registerBeanDefinition("handlerAdapter", adapterDef);
adapterDef.getPropertyValues().add("contentNegotiationManager", factoryBean.getObject());
wac.registerBeanDefinition("handlerAdapter", adapterDef);
}
}, TextRestController.class); }, TextRestController.class);
byte[] content = "alert('boo')".getBytes(StandardCharsets.ISO_8859_1); byte[] content = "alert('boo')".getBytes(StandardCharsets.ISO_8859_1);
@@ -1678,15 +1583,12 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
@Test @Test
public void responseBodyAsHtmlWithSuffixPresent() throws Exception { public void responseBodyAsHtmlWithSuffixPresent() throws Exception {
initServlet(new ApplicationContextInitializer<GenericWebApplicationContext>() { initServlet(wac -> {
@Override ContentNegotiationManagerFactoryBean factoryBean = new ContentNegotiationManagerFactoryBean();
public void initialize(GenericWebApplicationContext wac) { factoryBean.afterPropertiesSet();
ContentNegotiationManagerFactoryBean factoryBean = new ContentNegotiationManagerFactoryBean(); RootBeanDefinition adapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);
factoryBean.afterPropertiesSet(); adapterDef.getPropertyValues().add("contentNegotiationManager", factoryBean.getObject());
RootBeanDefinition adapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class); wac.registerBeanDefinition("handlerAdapter", adapterDef);
adapterDef.getPropertyValues().add("contentNegotiationManager", factoryBean.getObject());
wac.registerBeanDefinition("handlerAdapter", adapterDef);
}
}, TextRestController.class); }, TextRestController.class);
byte[] content = "alert('boo')".getBytes(StandardCharsets.ISO_8859_1); byte[] content = "alert('boo')".getBytes(StandardCharsets.ISO_8859_1);
@@ -1704,15 +1606,12 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
@Test @Test
public void responseBodyAsHtmlWithProducesCondition() throws Exception { public void responseBodyAsHtmlWithProducesCondition() throws Exception {
initServlet(new ApplicationContextInitializer<GenericWebApplicationContext>() { initServlet(wac -> {
@Override ContentNegotiationManagerFactoryBean factoryBean = new ContentNegotiationManagerFactoryBean();
public void initialize(GenericWebApplicationContext wac) { factoryBean.afterPropertiesSet();
ContentNegotiationManagerFactoryBean factoryBean = new ContentNegotiationManagerFactoryBean(); RootBeanDefinition adapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);
factoryBean.afterPropertiesSet(); adapterDef.getPropertyValues().add("contentNegotiationManager", factoryBean.getObject());
RootBeanDefinition adapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class); wac.registerBeanDefinition("handlerAdapter", adapterDef);
adapterDef.getPropertyValues().add("contentNegotiationManager", factoryBean.getObject());
wac.registerBeanDefinition("handlerAdapter", adapterDef);
}
}, TextRestController.class); }, TextRestController.class);
byte[] content = "alert('boo')".getBytes(StandardCharsets.ISO_8859_1); byte[] content = "alert('boo')".getBytes(StandardCharsets.ISO_8859_1);
@@ -1730,15 +1629,12 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
@Test @Test
public void responseBodyAsTextWithCssExtension() throws Exception { public void responseBodyAsTextWithCssExtension() throws Exception {
initServlet(new ApplicationContextInitializer<GenericWebApplicationContext>() { initServlet(wac -> {
@Override ContentNegotiationManagerFactoryBean factoryBean = new ContentNegotiationManagerFactoryBean();
public void initialize(GenericWebApplicationContext wac) { factoryBean.afterPropertiesSet();
ContentNegotiationManagerFactoryBean factoryBean = new ContentNegotiationManagerFactoryBean(); RootBeanDefinition adapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);
factoryBean.afterPropertiesSet(); adapterDef.getPropertyValues().add("contentNegotiationManager", factoryBean.getObject());
RootBeanDefinition adapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class); wac.registerBeanDefinition("handlerAdapter", adapterDef);
adapterDef.getPropertyValues().add("contentNegotiationManager", factoryBean.getObject());
wac.registerBeanDefinition("handlerAdapter", adapterDef);
}
}, TextRestController.class); }, TextRestController.class);
byte[] content = "body".getBytes(StandardCharsets.ISO_8859_1); byte[] content = "body".getBytes(StandardCharsets.ISO_8859_1);
@@ -1779,7 +1675,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
} }
@Test @Test
public void httpHead() throws ServletException, IOException { public void httpHead() throws Exception {
initServletWithControllers(ResponseEntityController.class); initServletWithControllers(ResponseEntityController.class);
MockHttpServletRequest request = new MockHttpServletRequest("HEAD", "/baz"); MockHttpServletRequest request = new MockHttpServletRequest("HEAD", "/baz");
@@ -1803,7 +1699,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
} }
@Test @Test
public void httpHeadExplicit() throws ServletException, IOException { public void httpHeadExplicit() throws Exception {
initServletWithControllers(ResponseEntityController.class); initServletWithControllers(ResponseEntityController.class);
MockHttpServletRequest request = new MockHttpServletRequest("HEAD", "/stores"); MockHttpServletRequest request = new MockHttpServletRequest("HEAD", "/stores");
@@ -1815,7 +1711,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
} }
@Test @Test
public void httpOptions() throws ServletException, IOException { public void httpOptions() throws Exception {
initServletWithControllers(ResponseEntityController.class); initServletWithControllers(ResponseEntityController.class);
MockHttpServletRequest request = new MockHttpServletRequest("OPTIONS", "/baz"); MockHttpServletRequest request = new MockHttpServletRequest("OPTIONS", "/baz");
@@ -1828,7 +1724,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
} }
@Test @Test
public void dataClassBinding() throws ServletException, IOException { public void dataClassBinding() throws Exception {
initServletWithControllers(DataClassController.class); initServletWithControllers(DataClassController.class);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/bind"); MockHttpServletRequest request = new MockHttpServletRequest("GET", "/bind");
@@ -1840,7 +1736,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
} }
@Test @Test
public void dataClassBindingWithAdditionalSetter() throws ServletException, IOException { public void dataClassBindingWithAdditionalSetter() throws Exception {
initServletWithControllers(DataClassController.class); initServletWithControllers(DataClassController.class);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/bind"); MockHttpServletRequest request = new MockHttpServletRequest("GET", "/bind");
@@ -1852,6 +1748,66 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
assertEquals("value1-2-3", response.getContentAsString()); assertEquals("value1-2-3", response.getContentAsString());
} }
@Test
public void dataClassBindingWithResult() throws Exception {
initServletWithControllers(ValidatedDataClassController.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());
}
@Test
public void dataClassBindingWithConversionError() throws Exception {
initServletWithControllers(ValidatedDataClassController.class);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/bind");
request.addParameter("param2", "x");
MockHttpServletResponse response = new MockHttpServletResponse();
getServlet().service(request, response);
assertTrue(response.getContentAsString().contains("field 'param2'"));
}
@Test
public void dataClassBindingWithValidationError() throws Exception {
initServletWithControllers(ValidatedDataClassController.class);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/bind");
request.addParameter("param2", "2");
request.addParameter("param3", "3");
MockHttpServletResponse response = new MockHttpServletResponse();
getServlet().service(request, response);
assertTrue(response.getContentAsString().contains("field 'param1'"));
}
@Test
public void dataClassBindingWithOptional() throws Exception {
initServletWithControllers(OptionalDataClassController.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());
}
@Test
public void dataClassBindingWithOptionalAndConversionError() throws Exception {
initServletWithControllers(OptionalDataClassController.class);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/bind");
request.addParameter("param2", "x");
MockHttpServletResponse response = new MockHttpServletResponse();
getServlet().service(request, response);
assertTrue(response.getContentAsString().contains("field 'param2'"));
}
@Controller @Controller
static class ControllerWithEmptyValueMapping { static class ControllerWithEmptyValueMapping {
@@ -2195,11 +2151,8 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
@Controller @Controller
static class MyCommandProvidingFormController<T, TB, TB2> extends MyFormController { static class MyCommandProvidingFormController<T, TB, TB2> extends MyFormController {
@SuppressWarnings("unused")
@ModelAttribute("myCommand") @ModelAttribute("myCommand")
private ValidTestBean createTestBean(@RequestParam T defaultName, public ValidTestBean createTestBean(@RequestParam T defaultName, Map<String, Object> model, @RequestParam Date date) {
Map<String, Object> model,
@RequestParam Date date) {
model.put("myKey", "myOriginalValue"); model.put("myKey", "myOriginalValue");
ValidTestBean tb = new ValidTestBean(); ValidTestBean tb = new ValidTestBean();
tb.setName(defaultName.getClass().getSimpleName() + ":" + defaultName.toString()); tb.setName(defaultName.getClass().getSimpleName() + ":" + defaultName.toString());
@@ -2253,9 +2206,8 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
static class MyBinderInitializingCommandProvidingFormController static class MyBinderInitializingCommandProvidingFormController
extends MyCommandProvidingFormController<String, TestBean, ITestBean> { extends MyCommandProvidingFormController<String, TestBean, ITestBean> {
@SuppressWarnings("unused")
@InitBinder @InitBinder
private void initBinder(WebDataBinder binder) { public void initBinder(WebDataBinder binder) {
binder.initBeanPropertyAccess(); binder.initBeanPropertyAccess();
binder.setRequiredFields("sex"); binder.setRequiredFields("sex");
LocalValidatorFactoryBean vf = new LocalValidatorFactoryBean(); LocalValidatorFactoryBean vf = new LocalValidatorFactoryBean();
@@ -2280,9 +2232,8 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
static class MySpecificBinderInitializingCommandProvidingFormController static class MySpecificBinderInitializingCommandProvidingFormController
extends MyCommandProvidingFormController<String, TestBean, ITestBean> { extends MyCommandProvidingFormController<String, TestBean, ITestBean> {
@SuppressWarnings("unused")
@InitBinder({"myCommand", "date"}) @InitBinder({"myCommand", "date"})
private void initBinder(WebDataBinder binder, String date, @RequestParam("date") String[] date2) { public void initBinder(WebDataBinder binder, String date, @RequestParam("date") String[] date2) {
LocalValidatorFactoryBean vf = new LocalValidatorFactoryBean(); LocalValidatorFactoryBean vf = new LocalValidatorFactoryBean();
vf.afterPropertiesSet(); vf.afterPropertiesSet();
binder.setValidator(vf); binder.setValidator(vf);
@@ -3382,6 +3333,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
public static class DataClass { public static class DataClass {
@NotNull
public final String param1; public final String param1;
public final int param2; public final int param2;
@@ -3408,4 +3360,37 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
} }
} }
@RestController
public static class ValidatedDataClassController {
@InitBinder
public void initBinder(WebDataBinder binder) {
LocalValidatorFactoryBean vf = new LocalValidatorFactoryBean();
vf.afterPropertiesSet();
binder.setValidator(vf);
}
@RequestMapping("/bind")
public String handle(@Valid DataClass data, BindingResult result) {
if (result.hasErrors()) {
return result.toString();
}
return data.param1 + "-" + data.param2 + "-" + data.param3;
}
}
@RestController
public static class OptionalDataClassController {
@RequestMapping("/bind")
public String handle(Optional<DataClass> optionalData, BindingResult result) {
if (result.hasErrors()) {
assertNotNull(optionalData);
assertFalse(optionalData.isPresent());
return result.toString();
}
return optionalData.map(data -> data.param1 + "-" + data.param2 + "-" + data.param3).orElse("");
}
}
} }