Skip to content

Commit a1b7a31

Browse files
committed
Add BindException to DefaultHandlerExceptionResolver
Previously DefaultHandlerExceptionResolver did not handle BindException but after this change it does. A BindException is raised when an @ModelAttribute annotated argument is not followed by a BindingResult argument. Hence this is unlikely to affect browser rendering. For programmatic clients however this change ensures an unhandled BindException is at least turned into a 400 error. Issue: SPR-9310
1 parent e860fa9 commit a1b7a31

File tree

3 files changed

+43
-6
lines changed

3 files changed

+43
-6
lines changed

spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/support/DefaultHandlerExceptionResolver.java

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2010 the original author or authors.
2+
* Copyright 2002-2012 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -32,12 +32,15 @@
3232
import org.springframework.http.converter.HttpMessageNotWritableException;
3333
import org.springframework.util.CollectionUtils;
3434
import org.springframework.util.StringUtils;
35+
import org.springframework.validation.BindException;
36+
import org.springframework.validation.BindingResult;
3537
import org.springframework.web.HttpMediaTypeNotAcceptableException;
3638
import org.springframework.web.HttpMediaTypeNotSupportedException;
3739
import org.springframework.web.HttpRequestMethodNotSupportedException;
3840
import org.springframework.web.bind.MethodArgumentNotValidException;
3941
import org.springframework.web.bind.MissingServletRequestParameterException;
4042
import org.springframework.web.bind.ServletRequestBindingException;
43+
import org.springframework.web.bind.annotation.ModelAttribute;
4144
import org.springframework.web.bind.annotation.RequestBody;
4245
import org.springframework.web.bind.annotation.RequestPart;
4346
import org.springframework.web.multipart.MultipartFile;
@@ -65,6 +68,9 @@
6568
* @see #handleHttpMessageNotReadable
6669
* @see #handleHttpMessageNotWritable
6770
* @see #handleMethodArgumentNotValidException
71+
* @see #handleMissingServletRequestParameter
72+
* @see #handleMissingServletRequestPart
73+
* @see #handleBindException
6874
*/
6975
public class DefaultHandlerExceptionResolver extends AbstractHandlerExceptionResolver {
7076

@@ -136,6 +142,9 @@ else if (ex instanceof MethodArgumentNotValidException) {
136142
else if (ex instanceof MissingServletRequestPartException) {
137143
return handleMissingServletRequestPartException((MissingServletRequestPartException) ex, request, response, handler);
138144
}
145+
else if (ex instanceof BindException) {
146+
return handleBindException((BindException) ex, request, response, handler);
147+
}
139148
}
140149
catch (Exception handlerException) {
141150
logger.warn("Handling of [" + ex.getClass().getName() + "] resulted in Exception", handlerException);
@@ -346,8 +355,8 @@ protected ModelAndView handleHttpMessageNotWritable(HttpMessageNotWritableExcept
346355
}
347356

348357
/**
349-
* Handle the case where an argument annotated with {@code @Valid} such as
350-
* an {@link RequestBody} or {@link RequestPart} argument fails validation.
358+
* Handle the case where an argument annotated with {@code @Valid} such as
359+
* an {@link RequestBody} or {@link RequestPart} argument fails validation.
351360
* An HTTP 400 error is sent back to the client.
352361
* @param request current HTTP request
353362
* @param response current HTTP response
@@ -362,8 +371,8 @@ protected ModelAndView handleMethodArgumentNotValidException(MethodArgumentNotVa
362371
}
363372

364373
/**
365-
* Handle the case where an @{@link RequestPart}, a {@link MultipartFile},
366-
* or a {@code javax.servlet.http.Part} argument is required but missing.
374+
* Handle the case where an {@linkplain RequestPart @RequestPart}, a {@link MultipartFile},
375+
* or a {@code javax.servlet.http.Part} argument is required but is missing.
367376
* An HTTP 400 error is sent back to the client.
368377
* @param request current HTTP request
369378
* @param response current HTTP response
@@ -377,4 +386,21 @@ protected ModelAndView handleMissingServletRequestPartException(MissingServletRe
377386
return new ModelAndView();
378387
}
379388

389+
/**
390+
* Handle the case where an {@linkplain ModelAttribute @ModelAttribute} method
391+
* argument has binding or validation errors and is not followed by another
392+
* method argument of type {@link BindingResult}.
393+
* By default an HTTP 400 error is sent back to the client.
394+
* @param request current HTTP request
395+
* @param response current HTTP response
396+
* @param handler the executed handler
397+
* @return an empty ModelAndView indicating the exception was handled
398+
* @throws IOException potentially thrown from response.sendError()
399+
*/
400+
protected ModelAndView handleBindException(BindException ex, HttpServletRequest request,
401+
HttpServletResponse response, Object handler) throws IOException {
402+
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
403+
return new ModelAndView();
404+
}
405+
380406
}

spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/support/DefaultHandlerExceptionResolverTests.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2009 the original author or authors.
2+
* Copyright 2002-2012 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -33,6 +33,7 @@
3333
import org.springframework.mock.web.MockHttpServletRequest;
3434
import org.springframework.mock.web.MockHttpServletResponse;
3535
import org.springframework.validation.BeanPropertyBindingResult;
36+
import org.springframework.validation.BindException;
3637
import org.springframework.web.HttpMediaTypeNotSupportedException;
3738
import org.springframework.web.HttpRequestMethodNotSupportedException;
3839
import org.springframework.web.bind.MethodArgumentNotValidException;
@@ -157,6 +158,15 @@ public void handleMissingServletRequestPartException() throws Exception {
157158
assertEquals("Invalid status code", 400, response.getStatus());
158159
}
159160

161+
@Test
162+
public void handleBindException() throws Exception {
163+
BindException ex = new BindException(new Object(), "name");
164+
ModelAndView mav = exceptionResolver.resolveException(request, response, null, ex);
165+
assertNotNull("No ModelAndView returned", mav);
166+
assertTrue("No Empty ModelAndView returned", mav.isEmpty());
167+
assertEquals("Invalid status code", 400, response.getStatus());
168+
}
169+
160170
public void handle(String arg) {
161171
}
162172

src/dist/changelog.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Changes in version 3.2 M2 (2012-08-xx)
2121
* add defaultCharset property to StringHttpMessageConverter
2222
* add @ExceptionResolver annotation to detect classes with @ExceptionHandler methods
2323
* move RSS/Atom message converter registration ahead of jackson/jaxb2
24+
* handle BindException in DefaultHandlerExceptionResolver
2425

2526

2627
Changes in version 3.2 M1 (2012-05-28)

0 commit comments

Comments
 (0)