Close

Spring MVC - Ordering and customization of default HandlerExceptionResolvers

[Last Updated: Sep 15, 2026]

In previous tutorials we went through various implementations of HandlerExceptionResolver. Here's a quick review:

HandlerExceptionResolver
Implementation
Active
by default
Purpose
DefaultHandlerExceptionResolver Yes It translates internal Spring exceptions into specific HTTP status codes.
ExceptionHandlerExceptionResolver Yes Allows the use of @ExceptionHandler on a controller's methods. When an exception is thrown, the method whose declared exception type matches is called.
ResponseStatusExceptionResolver Yes Allows the use of @ResponseStatus on exception classes so that an unhandled exception is returned with the specified HTTP status code.
SimpleMappingExceptionResolver No Allows mapping exception types to view names, mapping view names to HTTP status codes, and setting a default error view name and a default HTTP status code.
HandlerExceptionResolverComposite N/A If an exception is thrown, this resolver delegates the exception handling to a list of other HandlerExceptionResolvers.

In this tutorial we look at how DispatcherServlet processes the default and application-registered HandlerExceptionResolvers, and how to customize the default settings.


The processing order of HandlerExceptionResolvers

DispatcherServlet uses the following method to sort the list of default and application-registered HandlerExceptionResolvers:

AnnotationAwareOrderComparator.sort(this.handlerExceptionResolvers);

AnnotationAwareOrderComparator is an extension of OrderComparator, which sorts a collection's elements in ascending order of the element's order value. The order value is provided by Ordered, an interface which can optionally be implemented by the collection elements. Any element that does not implement this interface is implicitly assigned a value of Ordered.LOWEST_PRECEDENCE (=Integer.MAX_VALUE), thus ending up at the end of the collection. Objects that have the same order value are sorted in arbitrary order relative to other equally-valued elements.

HandlerExceptionResolverComposite's delegates are not sorted in any order; their original list order is maintained.

The default order

The Spring MVC framework initializes the default exception resolvers in WebMvcConfigurationSupport, the main class behind the MVC Java config and @EnableWebMvc.

To get a good understanding, here's a snippet showing how the resolvers are registered as a bean:

public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
 ................
 @Bean
 public HandlerExceptionResolver handlerExceptionResolver(
		@Qualifier("mvcContentNegotiationManager") 
               ContentNegotiationManager contentNegotiationManager) {
   List<HandlerExceptionResolver> exceptionResolvers = new ArrayList<>();
   configureHandlerExceptionResolvers(exceptionResolvers);
   if (exceptionResolvers.isEmpty()) {
	addDefaultHandlerExceptionResolvers(exceptionResolvers, 
						contentNegotiationManager);
   }
   extendHandlerExceptionResolvers(exceptionResolvers);
   HandlerExceptionResolverComposite composite = 
			new HandlerExceptionResolverComposite();
   composite.setOrder(0);
   composite.setExceptionResolvers(exceptionResolvers);
   return composite;
 }
............
}

By default, only one HandlerExceptionResolverComposite is registered, with order value '0', containing the following delegates in exactly this order:

ExceptionHandlerExceptionResolver
ResponseStatusExceptionResolver
DefaultHandlerExceptionResolver

DispatcherServlet keeps a list of the above default HandlerExceptionResolverComposite plus any HandlerExceptionResolvers registered by the application client. This list is sorted as described above.

If an exception is thrown while processing a request, DispatcherServlet handles it by iterating through the list of resolvers. The first resolver whose HandlerExceptionResolver#resolveException call returns a non-null ModelAndView wins. If none of the resolvers handle the exception, it goes unhandled.

Note: this default chain (ExceptionHandlerExceptionResolver, ResponseStatusExceptionResolver, DefaultHandlerExceptionResolver) has been the standard since Spring 3.2, regardless of whether configuration is done via @EnableWebMvc or via the older MVC XML namespace (<mvc:annotation-driven/>). The legacy AnnotationMethodHandlerExceptionResolver, which older XML-based Spring 3.0/3.1 configurations registered instead of ExceptionHandlerExceptionResolver, was deprecated in Spring 3.2 and removed entirely in Spring 5.0. It no longer exists in current versions of Spring.


The order of application-registered HandlerExceptionResolvers

If an application client registers an 'Ordered' HandlerExceptionResolver with an order value greater than 0, it is processed after the default resolver; otherwise it is processed before the default resolver. If the application resolver doesn't implement the 'Ordered' interface, it is processed last.

An application client can also register multiple HandlerExceptionResolvers.


Replacing the default resolvers

In the WebMvcConfigurationSupport snippet above, the default HandlerExceptionResolver is registered under the name 'handlerExceptionResolver' (the factory method handlerExceptionResolver() is used as the bean name unless a different name is specified via @Bean("beanName")). If we register a HandlerExceptionResolver bean with exactly this same name, it overrides the default one.

Another way to replace the default exception resolver is to call DispatcherServlet#setDetectAllHandlerExceptionResolvers(false) and register exactly one bean named DispatcherServlet#HANDLER_EXCEPTION_RESOLVER_BEAN_NAME. This mode ignores HandlerExceptionResolver beans with any other name, so only a single HandlerExceptionResolver can be registered this way.


Examples

Customizing Spring default HandlerExceptionResolvers functionality
Replacing Spring default HandlerExceptionResolvers


See Also

Join