# spring-rest-exception-handler **Repository Path**: mirrors_gspandy/spring-rest-exception-handler ## Basic Information - **Project Name**: spring-rest-exception-handler - **Description**: A convenient Spring MVC exception handler for RESTful APIs. - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-09-24 - **Last Updated**: 2025-12-07 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README = Spring REST Exception handler :source-language: java // Project meta :name: spring-rest-exception-handler :version: 1.2.0 :group-id: cz.jirutka.spring :artifact-id: {name} :gh-name: jirutka/{name} :gh-branch: master :codacy-id: ca5dbac87d564725b6640a67b2b7ea35 // URIs :src-base: link:src/main/java/cz/jirutka/spring/exhandler :spring-jdoc-uri: https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework ifdef::env-github[] image:https://travis-ci.org/{gh-name}.svg?branch={gh-branch}["Build Status", link="https://travis-ci.org/{gh-name}"] image:https://coveralls.io/repos/github/{gh-name}/badge.svg?branch={gh-branch}[Coverage Status, link="https://coveralls.io/github/{gh-name}"] image:https://api.codacy.com/project/badge/grade/{codacy-id}["Codacy code quality", link="https://www.codacy.com/app/{gh-name}"] image:https://maven-badges.herokuapp.com/maven-central/{group-id}/{artifact-id}/badge.svg[Maven Central, link="https://maven-badges.herokuapp.com/maven-central/{group-id}/{artifact-id}"] endif::env-github[] The aim of this project is to provide a convenient exception handler (resolver) for RESTful APIs that meets a best-practices for error responses without repeating yourself. It’s very easy to handle custom exceptions, customize error responses and even localize them. Also solves some pitfalls footnote:[Nothing terrible, Spring MVC is still a far better then JAX-RS for RESTful APIs! ;)] in Spring MVC with a content negotiation when producing error responses. == Error message Error messages generated by `ErrorMessageRestExceptionHandler` follows the http://tools.ietf.org/html/draft-nottingham-http-problem-06[Problem Details for HTTP APIs] specification. For example, the following error message describes a validation exception. *In JSON format:* [source, json] ---- { "type": "http://example.org/errors/validation-failed", "title": "Validation Failed", "status": 422, "detail": "The content you've send contains 2 validation errors.", "errors": [{ "field": "title", "message": "must not be empty" }, { "field": "quantity", "rejected": -5, "message": "must be greater than zero" }] } ---- *… or in XML:* [source,xml] ---- http://example.org/errors/validation-failed Validation Failed 422 The content you've send contains 2 validation errors. title must not be empty quantity -5 must be greater than zero ---- == How does it work? === RestHandlerExceptionResolver The core class of this library that resolves all exceptions is {src-base}/RestHandlerExceptionResolver.java[RestHandlerExceptionResolver]. It holds a registry of `RestExceptionHandlers`. When your controller throws an exception, the `RestHandlerExceptionResolver` will: . Find an exception handler by the thrown exception type (or its supertype, supertype of the supertype… up to the `Exception` class if no more specific handler is found) and invoke it. . Find the best matching media type to produce (using {spring-jdoc-uri}/web/accept/ContentNegotiationManager.html[ContentNegotiationManager], utilises _Accept_ header by default). When the requested media type is not supported, then fallback to the configured default media type. . Write the response. === RestExceptionHandler Implementations of the {src-base}/handlers/RestExceptionHandler.java[RestExceptionHandler] interface are responsible for converting the exception into Spring’s {spring-jdoc-uri}/http/ResponseEntity.html[ResponseEntity] instance that contains a body, headers and a HTTP status code. The main implementation is {src-base}/handlers/ErrorMessageRestExceptionHandler.java[ErrorMessageRestExceptionHandler] that produces the `ErrorMessage` body (see above for example). All the attributes (besides status) are loaded from a properties file (see the section <>). This class also logs the exception (see the <> section). == Configuration === Java-based configuration [source] ---- @EnableWebMvc @Configuration public class RestContextConfig extends WebMvcConfigurerAdapter { @Override public void configureHandlerExceptionResolvers(List resolvers) { resolvers.add( exceptionHandlerExceptionResolver() ); // resolves @ExceptionHandler resolvers.add( restExceptionResolver() ); } @Bean public RestHandlerExceptionResolver restExceptionResolver() { return RestHandlerExceptionResolver.builder() .messageSource( httpErrorMessageSource() ) .defaultContentType(MediaType.APPLICATION_JSON) .addErrorMessageHandler(EmptyResultDataAccessException.class, HttpStatus.NOT_FOUND) .addHandler(MyException.class, new MyExceptionHandler()) .build(); } @Bean public MessageSource httpErrorMessageSource() { ReloadableResourceBundleMessageSource m = new ReloadableResourceBundleMessageSource(); m.setBasename("classpath:/org/example/messages"); m.setDefaultEncoding("UTF-8"); return m; } @Bean public ExceptionHandlerExceptionResolver exceptionHandlerExceptionResolver() { ExceptionHandlerExceptionResolver resolver = new ExceptionHandlerExceptionResolver(); resolver.setMessageConverters(HttpMessageConverterUtils.getDefaultHttpMessageConverters()); return resolver; } } ---- === XML-based configuration [source, xml] ---- ---- === Another resolvers The {spring-jdoc-uri}/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.html[ExceptionHandlerExceptionResolver] is used to resolve exceptions through {spring-jdoc-uri}/web/bind/annotation/ExceptionHandler.html[@ExceptionHandler] methods. It must be registered _before_ the RestHandlerExceptionResolver. If you don’t have any `@ExceptionHandler` methods, then you can omit the `exceptionHandlerExceptionResolver` bean declaration. === Default handlers Builder and FactoryBean registers a set of the default handlers by default. This can be disabled by setting `withDefaultHandlers` to false. === Localizable error messages Message values are read from a _properties_ file through the provided {spring-jdoc-uri}/context/MessageSource.html[MessageSource], so it can be simply customized and localized. Library contains a default link:src/main/resources/cz/jirutka/spring/exhandler/messages.properties[messages.properties] file that is implicitly set as a parent (i.e. fallback) of the provided message source. This can be disabled by setting `withDefaultMessageSource` to false (on a builder or factory bean). The key name is prefixed with a fully qualified class name of the Java exception, or `default` for the default value; this is used when no value for a particular exception class exists (even in the parent message source). Value is a message template that may contain https://docs.spring.io/spring/docs/current/spring-framework-reference/html/expressions.html[SpEL] expressions delimited by `#{` and `}`. Inside an expression, you can access the exception being handled and the current request (instance of http://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpServletRequest.html[HttpServletRequest]) under the `ex`, resp. `req` variables. *For example:* [source, properties] ---- org.springframework.web.HttpMediaTypeNotAcceptableException.type=http://httpstatus.es/406 org.springframework.web.HttpMediaTypeNotAcceptableException.title=Not Acceptable org.springframework.web.HttpMediaTypeNotAcceptableException.detail=\ This resource provides #{ex.supportedMediaTypes}, but you've requested #{req.getHeader('Accept')}. ---- === Exception logging Exceptions handled with status code 5×× are logged on ERROR level (incl. stack trace), other exceptions are logged on INFO level without a stack trace, or on DEBUG level with a stack trace if enabled. The logger name is `cz.jirutka.spring.exhandler.handlers.RestExceptionHandler` and a Marker is set to the exception’s full qualified name. === Why is 404 bypassing exception handler? When the {spring-jdoc-uri}/web/servlet/DispatcherServlet.html[DispatcherServlet] is unable to determine a corresponding handler for an incoming HTTP request, it sends 404 directly without bothering to call an exception handler (see http://stackoverflow.com/a/22751886/2217862[on StackOverflow]). This behaviour can be changed, *since Spring 4.0.0*, using `throwExceptionIfNoHandlerFound` init parameter. You should set this to true for a consistent error responses. *When using WebApplicationInitializer:* [source] ---- public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { protected void customizeRegistration(ServletRegistration.Dynamic reg) { reg.setInitParameter("throwExceptionIfNoHandlerFound", "true"); } ... } ---- *…or classic web.xml:* [source, xml] ---- rest-dispatcher org.springframework.web.servlet.DispatcherServlet throwExceptionIfNoHandlerFound true ... ---- == How to get it? Released versions are available in jCenter and the Central Repository. Just add this artifact to your project: ._Maven_ [source, xml, subs="verbatim, attributes"] ---- {group-id} {artifact-id} {version} ---- ._Gradle_ [source, groovy, subs="verbatim, attributes"] compile '{group-id}:{artifact-id}:{version}' However if you want to use the last snapshot version, you have to add the JFrog OSS repository: ._Maven_ [source, xml] ---- jfrog-oss-snapshot-local JFrog OSS repository for snapshots https://oss.jfrog.org/oss-snapshot-local true ---- ._Gradle_ [source, groovy] ---- repositories { maven { url 'https://oss.jfrog.org/oss-snapshot-local' } } ---- == Requirements * Spring 3.2.0.RELEASE and newer is supported, but 4.× is highly recommended. * Jackson 1.× and 2.× are both supported and optional. == References * http://www.jayway.com/2012/09/23/improve-your-spring-rest-api-part-ii[Improve Your Spring REST API by M. Severson] * https://stormpath.com/blog/spring-mvc-rest-exception-handling-best-practices-part-1/[Spring MVC REST Exception Handling Best Practices by L. Hazlewood] * http://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc[Exception Handling in Spring MVC by P. Chapman] * http://tools.ietf.org/html/draft-nottingham-http-problem-06[IETF draft Problem Details for HTTP APIs by M. Nottingham] == License This project is licensed under http://www.apache.org/licenses/LICENSE-2.0.html[Apache License 2.0].