diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/RequestBodyNotValidException.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/RequestBodyNotValidException.java
index ab8482bdc15..3ebdebd2bb2 100644
--- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/RequestBodyNotValidException.java
+++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/RequestBodyNotValidException.java
@@ -17,6 +17,7 @@
package org.springframework.web.servlet.mvc.method.annotation.support;
import org.springframework.validation.Errors;
+import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.RequestBody;
/**
@@ -44,5 +45,15 @@ public class RequestBodyNotValidException extends RuntimeException {
public Errors getErrors() {
return errors;
}
+
+ @Override
+ public String getMessage() {
+ StringBuilder sb = new StringBuilder("Request body content validation failed: ");
+ sb.append(errors.getErrorCount()).append(" errors");
+ for (ObjectError error : errors.getAllErrors()) {
+ sb.append('\n').append(error);
+ }
+ return sb.toString();
+ }
}
diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/support/DefaultHandlerExceptionResolver.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/support/DefaultHandlerExceptionResolver.java
index c33907d0351..9589e65438c 100644
--- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/support/DefaultHandlerExceptionResolver.java
+++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/support/DefaultHandlerExceptionResolver.java
@@ -16,13 +16,14 @@
package org.springframework.web.servlet.mvc.support;
+import java.io.IOException;
import java.util.List;
+
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-
import org.springframework.beans.ConversionNotSupportedException;
import org.springframework.beans.TypeMismatchException;
import org.springframework.core.Ordered;
@@ -37,6 +38,7 @@ import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver;
+import org.springframework.web.servlet.mvc.method.annotation.support.RequestBodyNotValidException;
import org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMethodException;
/**
@@ -116,6 +118,9 @@ public class DefaultHandlerExceptionResolver extends AbstractHandlerExceptionRes
else if (ex instanceof HttpMessageNotWritableException) {
return handleHttpMessageNotWritable((HttpMessageNotWritableException) ex, request, response, handler);
}
+ else if (ex instanceof RequestBodyNotValidException) {
+ return handleRequestBodyNotValidException((RequestBodyNotValidException) ex, request, response, handler);
+ }
}
catch (Exception handlerException) {
logger.warn("Handling of [" + ex.getClass().getName() + "] resulted in Exception", handlerException);
@@ -314,4 +319,20 @@ public class DefaultHandlerExceptionResolver extends AbstractHandlerExceptionRes
return new ModelAndView();
}
+ /**
+ * Handle the case where the object created from the body of a request has failed validation. The default
+ * implementation sends an HTTP 500 error along with a message containing the errors.
+ * @param request current HTTP request
+ * @param response current HTTP response
+ * @param handler the executed handler, or null if none chosen
+ * at the time of the exception (for example, if multipart resolution failed)
+ * @return a ModelAndView to render, or null if handled directly
+ * @throws Exception an Exception that should be thrown as result of the servlet request
+ */
+ protected ModelAndView handleRequestBodyNotValidException(RequestBodyNotValidException ex,
+ HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
+ response.sendError(HttpServletResponse.SC_BAD_REQUEST, ex.getMessage());
+ return new ModelAndView();
+ }
+
}
diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/RequestResponseBodyMethodProcessorTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/RequestResponseBodyMethodProcessorTests.java
index b7d69f3f8d1..9e0d66ab5ff 100644
--- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/RequestResponseBodyMethodProcessorTests.java
+++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/RequestResponseBodyMethodProcessorTests.java
@@ -23,9 +23,9 @@ import static org.easymock.EasyMock.isA;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.reset;
import static org.easymock.EasyMock.verify;
-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.assertTrue;
import static org.junit.Assert.fail;
@@ -49,7 +49,6 @@ import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
-import org.springframework.validation.DataBinder;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
diff --git a/spring-framework-reference/src/mvc.xml b/spring-framework-reference/src/mvc.xml
index 6ac86fdd783..e893fa569f0 100644
--- a/spring-framework-reference/src/mvc.xml
+++ b/spring-framework-reference/src/mvc.xml
@@ -1369,9 +1369,18 @@ public void handle(@RequestBody String body, Writer writer) throws IOException {
<bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller"/>
+ An @RequestBody method parameter can be annotated with
+ @Valid, in which case it will validated using the configured
+ Validator instance. When using the MVC namespace a JSR-303
+ validator is configured automatically assuming a JSR-303 implementation is available
+ on the classpath. If validation fails a RequestBodyNotValidException
+ is raised. The exception is handled by the DefaultHandlerExceptionResolver
+ and results in a 500 error send back to the client along with
+ a message containing the validation errors.
+
Also see for information on
- configuring message converters through the MVC namespace.
+ configuring message converters and a validator through the MVC namespace.