SPR-8447 Provide sufficient contextwherever possible when exceptions are raised in new @MVC classes.

This commit is contained in:
Rossen Stoyanchev
2011-06-29 15:36:18 +00:00
parent 3a87d8e7cb
commit 0dae1a6bd8
23 changed files with 376 additions and 186 deletions

View File

@@ -93,10 +93,6 @@ public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
ModelAndViewContainer mavContainer,
Object...providedArgs) throws Exception {
if (!returnValueHandlers.supportsReturnType(getReturnType())) {
throw new IllegalStateException("No suitable HandlerMethodReturnValueHandler for method " + toString());
}
Object returnValue = invokeForRequest(request, mavContainer, providedArgs);
setResponseStatus((ServletWebRequest) request);
@@ -110,9 +106,25 @@ public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
mavContainer.setResolveView(true);
returnValueHandlers.handleReturnValue(returnValue, getReturnType(), mavContainer, request);
try {
returnValueHandlers.handleReturnValue(returnValue, getReturnType(), mavContainer, request);
} catch (Exception ex) {
if (logger.isTraceEnabled()) {
logger.trace(getReturnValueHandlingErrorMessage("Error handling return value", returnValue), ex);
}
throw ex;
}
}
private String getReturnValueHandlingErrorMessage(String message, Object returnValue) {
StringBuilder sb = new StringBuilder(message);
if (returnValue != null) {
sb.append(" [type=" + returnValue.getClass().getName() + "] ");
}
sb.append("[value=" + returnValue + "]");
return getDetailedErrorMessage(sb.toString());
}
/**
* Set the response status according to the {@link ResponseStatus} annotation.
*/

View File

@@ -101,8 +101,10 @@ public class DefaultMethodReturnValueHandler implements HandlerMethodReturnValue
return;
}
else {
// should not happen
throw new UnsupportedOperationException();
// should not happen..
Method method = returnType.getMethod();
String returnTypeName = returnType.getParameterType().getName();
throw new UnsupportedOperationException("Unknown return type: " + returnTypeName + " in method: " + method);
}
}

View File

@@ -19,6 +19,7 @@ package org.springframework.web.servlet.mvc.method.annotation.support;
import java.io.IOException;
import java.lang.reflect.Array;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
@@ -74,9 +75,9 @@ public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodPro
return new HttpEntity<Object>(body, inputMessage.getHeaders());
}
private Class<?> getHttpEntityType(MethodParameter methodParam) {
Assert.isAssignable(HttpEntity.class, methodParam.getParameterType());
ParameterizedType type = (ParameterizedType) methodParam.getGenericParameterType();
private Class<?> getHttpEntityType(MethodParameter parameter) {
Assert.isAssignable(HttpEntity.class, parameter.getParameterType());
ParameterizedType type = (ParameterizedType) parameter.getGenericParameterType();
if (type.getActualTypeArguments().length == 1) {
Type typeArgument = type.getActualTypeArguments()[0];
if (typeArgument instanceof Class) {
@@ -91,8 +92,8 @@ public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodPro
}
}
}
throw new IllegalArgumentException(
"HttpEntity parameter (" + methodParam.getParameterName() + ") is not parameterized");
throw new IllegalArgumentException("HttpEntity parameter (" + parameter.getParameterName() + ") "
+ "in method " + parameter.getMethod() + "is not parameterized");
}
public void handleReturnValue(Object returnValue,

View File

@@ -65,24 +65,24 @@ public class RequestPartMethodArgumentResolver extends AbstractMessageConverterM
public Object resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
NativeWebRequest request,
WebDataBinderFactory binderFactory) throws Exception {
ServletRequest servletRequest = webRequest.getNativeRequest(ServletRequest.class);
MultipartHttpServletRequest multipartServletRequest =
ServletRequest servletRequest = request.getNativeRequest(ServletRequest.class);
MultipartHttpServletRequest multipartRequest =
WebUtils.getNativeRequest(servletRequest, MultipartHttpServletRequest.class);
if (multipartServletRequest == null) {
if (multipartRequest == null) {
throw new IllegalStateException(
"Current request is not of type " + MultipartRequest.class.getName());
"Current request is not of type [" + MultipartRequest.class.getName() + "]: " + request);
}
String partName = getPartName(parameter);
HttpInputMessage inputMessage = new RequestPartServletServerHttpRequest(multipartServletRequest, partName);
HttpInputMessage inputMessage = new RequestPartServletServerHttpRequest(multipartRequest, partName);
Object arg = readWithMessageConverters(inputMessage, parameter, parameter.getParameterType());
if (isValidationApplicable(arg, parameter)) {
WebDataBinder binder = binderFactory.createBinder(webRequest, arg, partName);
WebDataBinder binder = binderFactory.createBinder(request, arg, partName);
binder.validate();
Errors errors = binder.getBindingResult();
if (errors.hasErrors()) {

View File

@@ -19,6 +19,7 @@ package org.springframework.web.servlet.mvc.method.annotation.support;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.lang.reflect.Method;
import java.security.Principal;
import java.util.Locale;
@@ -101,8 +102,9 @@ public class ServletRequestMethodArgumentResolver implements HandlerMethodArgume
return request.getReader();
}
else {
// should not happen
throw new UnsupportedOperationException();
// should never happen..
Method method = parameter.getMethod();
throw new UnsupportedOperationException("Unknown parameter type: " + paramType + " in method: " + method);
}
}

View File

@@ -19,6 +19,7 @@ package org.springframework.web.servlet.mvc.method.annotation.support;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
import java.lang.reflect.Method;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
@@ -66,25 +67,26 @@ public class ServletResponseMethodArgumentResolver implements HandlerMethodArgum
mavContainer.setResolveView(false);
HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);
Class<?> parameterType = parameter.getParameterType();
Class<?> paramType = parameter.getParameterType();
if (ServletResponse.class.isAssignableFrom(parameterType)) {
Object nativeResponse = webRequest.getNativeResponse(parameterType);
if (ServletResponse.class.isAssignableFrom(paramType)) {
Object nativeResponse = webRequest.getNativeResponse(paramType);
if (nativeResponse == null) {
throw new IllegalStateException(
"Current response is not of type [" + parameterType.getName() + "]: " + response);
"Current response is not of type [" + paramType.getName() + "]: " + response);
}
return nativeResponse;
}
else if (OutputStream.class.isAssignableFrom(parameterType)) {
else if (OutputStream.class.isAssignableFrom(paramType)) {
return response.getOutputStream();
}
else if (Writer.class.isAssignableFrom(parameterType)) {
else if (Writer.class.isAssignableFrom(paramType)) {
return response.getWriter();
}
else {
// should not happen
throw new UnsupportedOperationException();
Method method = parameter.getMethod();
throw new UnsupportedOperationException("Unknown parameter type: " + paramType + " in method: " + method);
}
}

View File

@@ -16,6 +16,8 @@
package org.springframework.web.servlet.mvc.method.annotation.support;
import java.lang.reflect.Method;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.ResponseBody;
@@ -62,7 +64,9 @@ public class ViewMethodReturnValueHandler implements HandlerMethodReturnValueHan
}
else {
// should not happen
throw new UnsupportedOperationException();
Method method = returnType.getMethod();
String returnTypeName = returnType.getParameterType().getName();
throw new UnsupportedOperationException("Unknown return type: " + returnTypeName + " in method: " + method);
}
}

View File

@@ -344,7 +344,7 @@ public class DefaultHandlerExceptionResolver extends AbstractHandlerExceptionRes
/**
* Handle the case where the object created from the body of a request has failed validation.
* The default implementation sends an HTTP 400 error along with a message containing the errors.
* The default implementation sends an HTTP 400 error.
* @param request current HTTP request
* @param response current HTTP response
* @param handler the executed handler
@@ -353,13 +353,13 @@ public class DefaultHandlerExceptionResolver extends AbstractHandlerExceptionRes
*/
protected ModelAndView handleRequestBodyNotValidException(RequestBodyNotValidException ex,
HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
response.sendError(HttpServletResponse.SC_BAD_REQUEST, ex.getMessage());
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return new ModelAndView();
}
/**
* Handle the case where the object created from the part of a multipart request has failed validation.
* The default implementation sends an HTTP 400 error along with a message containing the errors.
* The default implementation sends an HTTP 400 error.
* @param request current HTTP request
* @param response current HTTP response
* @param handler the executed handler
@@ -368,7 +368,7 @@ public class DefaultHandlerExceptionResolver extends AbstractHandlerExceptionRes
*/
protected ModelAndView handleRequestPartNotValidException(RequestPartNotValidException ex,
HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
response.sendError(HttpServletResponse.SC_BAD_REQUEST, ex.getMessage());
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return new ModelAndView();
}