@ -506,6 +506,109 @@ declare it as an <<mvc-ann-controller-advice>> bean or configure it directly on
@@ -506,6 +506,109 @@ declare it as an <<mvc-ann-controller-advice>> bean or configure it directly on
[[mvc-exceptionhandlers]]
=== Exception Resolution
If an exception occurs during the mapping or the invocation of a request handler (e.g. an
`@Controller`), the `DispatcherServlet` delegates to a chain of `HandlerExceptionResolver`
beans to try and resolve the exception and to provide alternative handling for it, which
typically means preparing an error response whether an HTML error page, an error status,
or both.
The table below lists the available `HandlerExceptionResolver` implementations:
[cols="1,2", options="header"]
.HandlerExceptionResolver implementations
|===
| HandlerExceptionResolver| Description
| `SimpleMappingExceptionResolver`
| A mapping between exception class names and error view names. Useful for rendering
The Servlet API does not provide a way to create error page mappings in Java. You can
however use both an `WebApplicationInitializer` and a minimal `web.xml`.
====
[[mvc-viewresolver]]
=== View Resolution
[.small]#<<web-reactive.adoc#webflux-viewresolution,Same in Spring WebFlux>>#
@ -515,7 +618,7 @@ models in a browser without tying you to a specific view technology. `ViewResolv
@@ -515,7 +618,7 @@ models in a browser without tying you to a specific view technology. `ViewResolv
provides a mapping between view names and actual views. `View` addresses the preparation
of data before handing over to a specific view technology.
This table below provides more details on the `ViewResolver` hierarchy:
The table below provides more details on the `ViewResolver` hierarchy:
[[mvc-view-resolvers-tbl]]
.ViewResolver implementations
@ -575,9 +678,9 @@ The contract of a `ViewResolver` specifies that it __can__ return null to indica
@@ -575,9 +678,9 @@ The contract of a `ViewResolver` specifies that it __can__ return null to indica
view could not be found. However in the case of JSPs, and `InternalResourceViewResolver`,
the only way to figure out if a JSP exists is to perform a dispatch through
`RequestDispatcher`. Therefore an `InternalResourceViewResolver` must always be configured
to be last in the overal order of view resolvers.
to be last in the overall order of view resolvers.
To configure view resolution is as simple as adding a `ViewResolver` beans to your Spring
To configure view resolution is as simple as adding `ViewResolver` beans to your Spring
configuration. The <<mvc-config>> provides provides a dedicated configuration API for
<<mvc-config-view-resolvers>> and also for adding logic-less
<<mvc-config-view-controller,View Controllers>> which are useful for HTML template
which provides handling for exceptions that Spring MVC raises along with hooks to
customize the response body. To make use of this, create a sub-class of
`ResponseEntityExceptionHandler`, annotate with `@ControllerAdvice`, override the
necessary methods, and declare it as a Spring bean.
[[mvc-ann-controller-advice]]
=== Controller Advice
[.small]#<<web-reactive.adoc#webflux-ann-controller-advice,Same in Spring WebFlux>>#
@ -2929,265 +3093,6 @@ in order to use a specific instance of `MvcUriComponentsBuilder` with a custom b
@@ -2929,265 +3093,6 @@ in order to use a specific instance of `MvcUriComponentsBuilder` with a custom b
[[mvc-exceptionhandlers]]
== Exception Handling
[[mvc-exceptionhandlers-overview]]
=== Overview
Spring `HandlerExceptionResolver` implementations deal with unexpected exceptions that
occur during controller execution. A `HandlerExceptionResolver` somewhat resembles the
exception mappings you can define in the web application descriptor `web.xml`. However,
they provide a more flexible way to do so. For example they provide information about
which handler was executing when the exception was thrown. Furthermore, a programmatic
way of handling exceptions gives you more options for responding appropriately before
the request is forwarded to another URL (the same end result as when you use the Servlet
specific exception mappings).
Besides implementing the `HandlerExceptionResolver` interface, which is only a matter of
implementing the `resolveException(Exception, Handler)` method and returning a
`ModelAndView`, you may also use the provided `SimpleMappingExceptionResolver` or create
`@ExceptionHandler` methods. The `SimpleMappingExceptionResolver` enables you to take
the class name of any exception that might be thrown and map it to a view name. This is
functionally equivalent to the exception mapping feature from the Servlet API, but it is
also possible to implement more finely grained mappings of exceptions from different
handlers. The `@ExceptionHandler` annotation on the other hand can be used on methods
that should be invoked to handle an exception. Such methods may be defined locally
within an `@Controller` or may apply to many `@Controller` classes when defined within an
`@ControllerAdvice` class. The following sections explain this in more detail.
[[mvc-ann-exceptionhandler]]
=== @ExceptionHandler
The `HandlerExceptionResolver` interface and the `SimpleMappingExceptionResolver`
implementations allow you to map Exceptions to specific views declaratively along with
some optional Java logic before forwarding to those views. However, in some cases,
especially when relying on `@ResponseBody` methods rather than on view resolution, it
may be more convenient to directly set the status of the response and optionally write
error content to the body of the response.
You can do that with `@ExceptionHandler` methods. When declared within a controller such
methods apply to exceptions raised by `@RequestMapping` methods of that controller (or
any of its subclasses). You can also declare an `@ExceptionHandler` method within an
`@ControllerAdvice` class in which case it handles exceptions from `@RequestMapping`
methods from many controllers. Below is an example of a controller-local
`@ExceptionHandler` method:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@Controller
public class SimpleController {
// @RequestMapping methods omitted ...
@ExceptionHandler(IOException.class)
public ResponseEntity<String> handleIOException(IOException ex) {
// prepare responseEntity
return responseEntity;
}
}
----
The `@ExceptionHandler` value can be set to an array of Exception types. If an exception
is thrown that matches one of the types in the list, then the method annotated with the
matching `@ExceptionHandler` will be invoked. If the annotation value is not set then
the exception types listed as method arguments are used.
[TIP]
====
For `@ExceptionHandler` methods, a root exception match will be preferred to just
matching a cause of the current exception, among the handler methods of a particular
controller or advice bean. However, a cause match on a higher-priority `@ControllerAdvice`
will still be preferred to a any match (whether root or cause level) on a lower-priority
advice bean. As a consequence, when using a multi-advice arrangement, please declare your
primary root exception mappings on a prioritized advice bean with a corresponding order!
====
Much like standard controller methods annotated with a `@RequestMapping` annotation, the
method arguments and return values of `@ExceptionHandler` methods can be flexible. For
example, the `HttpServletRequest` can be accessed in Servlet environments. The return
type can be a `String`, which is interpreted as a view name, a `ModelAndView` object,
a `ResponseEntity`, or you can also add the `@ResponseBody` to have the method return
value converted with message converters and written to the response stream.
[[mvc-ann-rest-spring-mvc-exceptions]]
=== Framework exceptions
Spring MVC may raise a number of exceptions while processing a request. The
`SimpleMappingExceptionResolver` can easily map any exception to a default error view as
needed. However, when working with clients that interpret responses in an automated way
you will want to set specific status code on the response. Depending on the exception
raised the status code may indicate a client error (4xx) or a server error (5xx).
The `DefaultHandlerExceptionResolver` translates Spring MVC exceptions to specific error
status codes. It is registered by default with the MVC namespace, the MVC Java config,
and also by the `DispatcherServlet` (i.e. when not using the MVC namespace or Java
config). Listed below are some of the exceptions handled by this resolver and the
corresponding status codes:
|===
| Exception| HTTP Status Code
| `BindException`
| 400 (Bad Request)
| `ConversionNotSupportedException`
| 500 (Internal Server Error)
| `HttpMediaTypeNotAcceptableException`
| 406 (Not Acceptable)
| `HttpMediaTypeNotSupportedException`
| 415 (Unsupported Media Type)
| `HttpMessageNotReadableException`
| 400 (Bad Request)
| `HttpMessageNotWritableException`
| 500 (Internal Server Error)
| `HttpRequestMethodNotSupportedException`
| 405 (Method Not Allowed)
| `MethodArgumentNotValidException`
| 400 (Bad Request)
| `MissingPathVariableException`
| 500 (Internal Server Error)
| `MissingServletRequestParameterException`
| 400 (Bad Request)
| `MissingServletRequestPartException`
| 400 (Bad Request)
| `NoHandlerFoundException`
| 404 (Not Found)
| `NoSuchRequestHandlingMethodException`
| 404 (Not Found)
| `TypeMismatchException`
| 400 (Bad Request)
|===
The `DefaultHandlerExceptionResolver` works transparently by setting the status of the
response. However, it stops short of writing any error content to the body of the
response while your application may need to add developer-friendly content to every
error response for example when providing a REST API. You can prepare a `ModelAndView`
and render error content through view resolution -- i.e. by configuring a
`ContentNegotiatingViewResolver`, `MappingJackson2JsonView`, and so on. However, you may
prefer to use `@ExceptionHandler` methods instead.
If you prefer to write error content via `@ExceptionHandler` methods you can extend
`ResponseEntityExceptionHandler` instead. This is a convenient base for
`@ControllerAdvice` classes providing an `@ExceptionHandler` method to handle standard
Spring MVC exceptions and return `ResponseEntity`. That allows you to customize the
response and write error content with message converters. See the
`ResponseEntityExceptionHandler` javadocs for more details.
[[mvc-ann-rest-exceptions]]
=== REST API exceptions
An `@RestController` may use `@ExceptionHandler` methods that return a
`ResponseEntity` to provide both a response status and error details in the body
of the response. Such methods may also be added to `@ControllerAdvice`
classes for exception handling across a subset or all controllers.
A common requirement is to include error details in the body of the response.
Spring does not automatically do this (although Spring Boot does) because the
representation of error details in the response body is application specific.
Applications that wish to implement a global exception handling strategy with
error details in the response body should consider extending the abstract base
class `ResponseEntityExceptionHandler` which provides handling for the exceptions
that Spring MVC raises and provides hooks to customize the response body as
well as to handle other exceptions. Simply declare the extension class as a
Spring bean and annotate it with `@ControllerAdvice`. For more details see
See `ResponseEntityExceptionHandler`.
[[mvc-ann-annotated-exceptions]]
=== Annotated Exception
A business exception can be annotated with `@ResponseStatus`. When the exception is
raised, the `ResponseStatusExceptionResolver` handles it by setting the status of the
response accordingly. By default the `DispatcherServlet` registers the
`ResponseStatusExceptionResolver` and it is available for use.
[[mvc-ann-customer-servlet-container-error-page]]
=== Container error page
When the status of the response is set to an error status code and the body of the
response is empty, Servlet containers commonly render an HTML formatted error page. To
customize the default error page of the container, you can declare an `<error-page>`
element in `web.xml`. Up until Servlet 3, that element had to be mapped to a specific
status code or exception type. Starting with Servlet 3 an error page does not need to be
mapped, which effectively means the specified location customizes the default Servlet
container error page.
[source,xml,indent=0]
[subs="verbatim,quotes"]
----
<error-page>
<location>/error</location>
</error-page>
----
Note that the actual location for the error page can be a JSP page or some other URL
within the container including one handled through an `@Controller` method:
When writing error information, the status code and the error message set on the
`HttpServletResponse` can be accessed through request attributes in a controller: