SPR-6709 Handle RequestBodyNotValidException and update reference docs
This commit is contained in:
parent
bfecedf5e2
commit
9d2ee7061c
|
|
@ -17,6 +17,7 @@
|
||||||
package org.springframework.web.servlet.mvc.method.annotation.support;
|
package org.springframework.web.servlet.mvc.method.annotation.support;
|
||||||
|
|
||||||
import org.springframework.validation.Errors;
|
import org.springframework.validation.Errors;
|
||||||
|
import org.springframework.validation.ObjectError;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -44,5 +45,15 @@ public class RequestBodyNotValidException extends RuntimeException {
|
||||||
public Errors getErrors() {
|
public Errors getErrors() {
|
||||||
return errors;
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,13 +16,14 @@
|
||||||
|
|
||||||
package org.springframework.web.servlet.mvc.support;
|
package org.springframework.web.servlet.mvc.support;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
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.ConversionNotSupportedException;
|
import org.springframework.beans.ConversionNotSupportedException;
|
||||||
import org.springframework.beans.TypeMismatchException;
|
import org.springframework.beans.TypeMismatchException;
|
||||||
import org.springframework.core.Ordered;
|
import org.springframework.core.Ordered;
|
||||||
|
|
@ -37,6 +38,7 @@ import org.springframework.web.HttpRequestMethodNotSupportedException;
|
||||||
import org.springframework.web.bind.MissingServletRequestParameterException;
|
import org.springframework.web.bind.MissingServletRequestParameterException;
|
||||||
import org.springframework.web.servlet.ModelAndView;
|
import org.springframework.web.servlet.ModelAndView;
|
||||||
import org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver;
|
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;
|
import org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMethodException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -116,6 +118,9 @@ public class DefaultHandlerExceptionResolver extends AbstractHandlerExceptionRes
|
||||||
else if (ex instanceof HttpMessageNotWritableException) {
|
else if (ex instanceof HttpMessageNotWritableException) {
|
||||||
return handleHttpMessageNotWritable((HttpMessageNotWritableException) ex, request, response, handler);
|
return handleHttpMessageNotWritable((HttpMessageNotWritableException) ex, request, response, handler);
|
||||||
}
|
}
|
||||||
|
else if (ex instanceof RequestBodyNotValidException) {
|
||||||
|
return handleRequestBodyNotValidException((RequestBodyNotValidException) ex, request, response, handler);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception handlerException) {
|
catch (Exception handlerException) {
|
||||||
logger.warn("Handling of [" + ex.getClass().getName() + "] resulted in 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();
|
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 <code>null</code> if none chosen
|
||||||
|
* at the time of the exception (for example, if multipart resolution failed)
|
||||||
|
* @return a ModelAndView to render, or <code>null</code> 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();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,9 +23,9 @@ import static org.easymock.EasyMock.isA;
|
||||||
import static org.easymock.EasyMock.replay;
|
import static org.easymock.EasyMock.replay;
|
||||||
import static org.easymock.EasyMock.reset;
|
import static org.easymock.EasyMock.reset;
|
||||||
import static org.easymock.EasyMock.verify;
|
import static org.easymock.EasyMock.verify;
|
||||||
import static org.junit.Assert.*;
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.junit.Assert.fail;
|
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.http.converter.StringHttpMessageConverter;
|
||||||
import org.springframework.mock.web.MockHttpServletRequest;
|
import org.springframework.mock.web.MockHttpServletRequest;
|
||||||
import org.springframework.mock.web.MockHttpServletResponse;
|
import org.springframework.mock.web.MockHttpServletResponse;
|
||||||
import org.springframework.validation.DataBinder;
|
|
||||||
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
|
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
|
||||||
import org.springframework.web.HttpMediaTypeNotAcceptableException;
|
import org.springframework.web.HttpMediaTypeNotAcceptableException;
|
||||||
import org.springframework.web.HttpMediaTypeNotSupportedException;
|
import org.springframework.web.HttpMediaTypeNotSupportedException;
|
||||||
|
|
|
||||||
|
|
@ -1369,9 +1369,18 @@ public void handle(@RequestBody String body, Writer writer) throws IOException {
|
||||||
<bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller"/>
|
<bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller"/>
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
|
||||||
|
<para>An <classname>@RequestBody</classname> method parameter can be annotated with
|
||||||
|
<classname>@Valid</classname>, in which case it will validated using the configured
|
||||||
|
<classname>Validator</classname> 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 <classname>RequestBodyNotValidException</classname>
|
||||||
|
is raised. The exception is handled by the <classname>DefaultHandlerExceptionResolver</classname>
|
||||||
|
and results in a <literal>500</literal> error send back to the client along with
|
||||||
|
a message containing the validation errors.</para>
|
||||||
|
|
||||||
<note>
|
<note>
|
||||||
<para> Also see <xref linkend="mvc-annotation-driven"/> for information on
|
<para> Also see <xref linkend="mvc-annotation-driven"/> for information on
|
||||||
configuring message converters through the MVC namespace.</para>
|
configuring message converters and a validator through the MVC namespace.</para>
|
||||||
</note>
|
</note>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue