Basic error controller spring

declaration: package: org.springframework.boot.autoconfigure.web.servlet.error, class: BasicErrorController

All Implemented Interfaces:
ErrorController

Basic global error @Controller, rendering ErrorAttributes.
More specific errors can be handled either using Spring MVC abstractions (e.g.
@ExceptionHandler) or by adding servlet
server error pages.

Since:
1.0.0
Author:
Dave Syer, Phillip Webb, Michael Stummvoll, Stephane Nicoll, Scott Frederick
See Also:
  • ErrorAttributes
  • ErrorProperties
  • Constructor Summary

    Constructors

  • Method Summary

    Provide access to the error properties.

    protected boolean

    Determine if the errors attribute should be included.

    protected boolean

    Determine if the message attribute should be included.

    protected boolean

    Determine if the stacktrace attribute should be included.

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

  • Constructor Details

    • BasicErrorController

      Parameters:
      errorAttributes — the error attributes
      errorProperties — configuration properties
    • BasicErrorController

      Parameters:
      errorAttributes — the error attributes
      errorProperties — configuration properties
      errorViewResolvers — error view resolvers
  • Method Details

    • errorHtml

    • error

    • mediaTypeNotAcceptable

    • getErrorAttributeOptions

    • isIncludeStackTrace

      Determine if the stacktrace attribute should be included.

      Parameters:
      request — the source request
      produces — the media type produced (or MediaType.ALL)
      Returns:
      if the stacktrace attribute should be included
    • isIncludeMessage

      Determine if the message attribute should be included.

      Parameters:
      request — the source request
      produces — the media type produced (or MediaType.ALL)
      Returns:
      if the message attribute should be included
    • isIncludeBindingErrors

      Determine if the errors attribute should be included.

      Parameters:
      request — the source request
      produces — the media type produced (or MediaType.ALL)
      Returns:
      if the errors attribute should be included
    • getErrorProperties

      Provide access to the error properties.

      Returns:
      the error properties

/* * Copyright 2012-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the «License»); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an «AS IS» BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.boot.autoconfigure.web.servlet.error; import java.util.Collections; import java.util.List; import java.util.Map; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.springframework.boot.autoconfigure.web.ErrorProperties; import org.springframework.boot.web.error.ErrorAttributeOptions; import org.springframework.boot.web.error.ErrorAttributeOptions.Include; import org.springframework.boot.web.servlet.error.ErrorAttributes; import org.springframework.boot.web.servlet.server.AbstractServletWebServerFactory; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.util.Assert; import org.springframework.web.HttpMediaTypeNotAcceptableException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; /** * Basic global error {@link Controller @Controller}, rendering {@link ErrorAttributes}. * More specific errors can be handled either using Spring MVC abstractions (e.g. * {@code @ExceptionHandler}) or by adding servlet * {@link AbstractServletWebServerFactory#setErrorPages server error pages}. * * @author Dave Syer * @author Phillip Webb * @author Michael Stummvoll * @author Stephane Nicoll * @author Scott Frederick * @since 1.0.0 * @see ErrorAttributes * @see ErrorProperties */ @Controller @RequestMapping(«${server.error.path:${error.path:/error}}») public class BasicErrorController extends AbstractErrorController { private final ErrorProperties errorProperties; /** * Create a new {@link BasicErrorController} instance. * @param errorAttributes the error attributes * @param errorProperties configuration properties */ public BasicErrorController(ErrorAttributes errorAttributes, ErrorProperties errorProperties) { this(errorAttributes, errorProperties, Collections.emptyList()); } /** * Create a new {@link BasicErrorController} instance. * @param errorAttributes the error attributes * @param errorProperties configuration properties * @param errorViewResolvers error view resolvers */ public BasicErrorController(ErrorAttributes errorAttributes, ErrorProperties errorProperties, List<ErrorViewResolver> errorViewResolvers) { super(errorAttributes, errorViewResolvers); Assert.notNull(errorProperties, «ErrorProperties must not be null»); this.errorProperties = errorProperties; } @RequestMapping(produces = MediaType.TEXT_HTML_VALUE) public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) { HttpStatus status = getStatus(request); Map<String, Object> model = Collections .unmodifiableMap(getErrorAttributes(request, getErrorAttributeOptions(request, MediaType.TEXT_HTML))); response.setStatus(status.value()); ModelAndView modelAndView = resolveErrorView(request, response, status, model); return (modelAndView != null) ? modelAndView : new ModelAndView(«error», model); } @RequestMapping public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) { HttpStatus status = getStatus(request); if (status == HttpStatus.NO_CONTENT) { return new ResponseEntity<>(status); } Map<String, Object> body = getErrorAttributes(request, getErrorAttributeOptions(request, MediaType.ALL)); return new ResponseEntity<>(body, status); } @ExceptionHandler(HttpMediaTypeNotAcceptableException.class) public ResponseEntity<String> mediaTypeNotAcceptable(HttpServletRequest request) { HttpStatus status = getStatus(request); return ResponseEntity.status(status).build(); } protected ErrorAttributeOptions getErrorAttributeOptions(HttpServletRequest request, MediaType mediaType) { ErrorAttributeOptions options = ErrorAttributeOptions.defaults(); if (this.errorProperties.isIncludeException()) { options = options.including(Include.EXCEPTION); } if (isIncludeStackTrace(request, mediaType)) { options = options.including(Include.STACK_TRACE); } if (isIncludeMessage(request, mediaType)) { options = options.including(Include.MESSAGE); } if (isIncludeBindingErrors(request, mediaType)) { options = options.including(Include.BINDING_ERRORS); } return options; } /** * Determine if the stacktrace attribute should be included. * @param request the source request * @param produces the media type produced (or {@code MediaType.ALL}) * @return if the stacktrace attribute should be included */ protected boolean isIncludeStackTrace(HttpServletRequest request, MediaType produces) { return switch (getErrorProperties().getIncludeStacktrace()) { case ALWAYS -> true; case ON_PARAM -> getTraceParameter(request); default -> false; }; } /** * Determine if the message attribute should be included. * @param request the source request * @param produces the media type produced (or {@code MediaType.ALL}) * @return if the message attribute should be included */ protected boolean isIncludeMessage(HttpServletRequest request, MediaType produces) { return switch (getErrorProperties().getIncludeMessage()) { case ALWAYS -> true; case ON_PARAM -> getMessageParameter(request); default -> false; }; } /** * Determine if the errors attribute should be included. * @param request the source request * @param produces the media type produced (or {@code MediaType.ALL}) * @return if the errors attribute should be included */ protected boolean isIncludeBindingErrors(HttpServletRequest request, MediaType produces) { return switch (getErrorProperties().getIncludeBindingErrors()) { case ALWAYS -> true; case ON_PARAM -> getErrorsParameter(request); default -> false; }; } /** * Provide access to the error properties. * @return the error properties */ protected ErrorProperties getErrorProperties() { return this.errorProperties; } }

Содержание

  1. Spring Boot and Spring MVC: how to handle controller exceptions properly
  2. Spring Boot auto-configuration for error handling
  3. Error page customization
  4. Customizing global error handler
  5. Customizing error view page
  6. More customization: fine grained exception handlers
  7. Spring MVC exception handlers standard configuration
  8. Convenient base class for centralized exception handling
  9. Takeaways
  10. Обработка ошибок в веб-API ASP.NET Core
  11. Страница со сведениями об исключении для разработчика
  12. Обработчик исключений
  13. Изменение ответа с помощью исключений
  14. Ответ в случае ошибки при сбое проверки
  15. Ответ при ошибке клиента
  16. Ответ со сведениями о проблеме по умолчанию
  17. Служба сведений о проблеме
  18. Настройка сведений о проблеме с помощью CustomizeProblemDetails
  19. Реализуйте ProblemDetailsFactory
  20. Используйте ApiBehaviorOptions.ClientErrorMapping .
  21. Дополнительные ресурсы
  22. Страница со сведениями об исключении для разработчика
  23. Обработчик исключений
  24. Изменение ответа с помощью исключений
  25. Ответ в случае ошибки при сбое проверки
  26. Ответ при ошибке клиента
  27. Реализуйте ProblemDetailsFactory
  28. Используйте ApiBehaviorOptions.ClientErrorMapping .
  29. Пользовательское ПО промежуточного слоя для обработки исключений
  30. Создание полезных данных ProblemDetails для исключений
  31. Дополнительные ресурсы
  32. Страница со сведениями об исключении для разработчика
  33. Обработчик исключений
  34. Изменение ответа с помощью исключений
  35. Ответ в случае ошибки при сбое проверки
  36. Ответ при ошибке клиента
  37. Реализуйте ProblemDetailsFactory
  38. Использование ApiBehaviorOptions.ClientErrorMapping
  39. Пользовательское ПО промежуточного слоя для обработки исключений

Spring Boot and Spring MVC: how to handle controller exceptions properly

TL;DR In depth explanation of exception handling for Spring MVC in a Spring Boot application: exception handler types, handlers ordering, available customization means.

Table of contents

Spring Boot auto-configuration for error handling

Spring Boot application has a default configuration for error handling — ErrorMvcAutoConfiguration.

What it basically does, if no additional configuration provided:

  • it creates default global error controller — BasicErrorController
  • it creates default ‘error’ static view ‘Whitelabel Error Page’.

BasicErrorController is wired to ‘/error’ view by default. If there is no customized ‘error’ view in the application, in case of an exception thrown from any controller, the user lands to /error whitelabel page, filled with information by BasicErrorController.

Error page customization

As we saw earlier, Spring MVC’ default error page is /error . Default controller behind /error endpoint is BasicErrorController . Let’s look how we can customize error handling.

Customizing global error handler

BasicErrorController is a basic error controller rendering ErrorAttributes . It can either render an html page or provide a serialized ErrorAttributes object.

There are several ways to customize the behavior of error handling and/or the contents of the error view:

  1. The Spring Boot application can provide its own error handling controller. It must implement ErrorController interface to automatically replace BasicErrorController .
  2. The application can provide custom view servlet server page(s) and custom view content. For an html view, the page format can be either jps or html with Thymleaf to render model attributes filled by the error controller.
  3. The application can do both: customize the behavior by implementing ErrorController and customize the error page view and/or error model object.

Customizing error view page

The default error page, which you already saw perhaps, is a ‘Whitelabel error page’ static view (created in the code directly) configured within ErrorMvcAutoConfiguration . It is served by default by /error endpoint.

You can keep the endpoint and just replace the static view by a custom page. For it to be picked automatically without any configuration, the page must be called error.html and it must be placed in src/main/resources/templates folder.

And here is an example of a view we could come up to:

once you have replaced the default static view, you can disable id with server.error.whitelabel.enabled=false in the application.properties.

if you with to name your global error page differently, you can use server.error.path application property. For example: server.error.path=/oups , which should have the corresponding oups.html view.

Another approach for error handling is to have several error views, each for a particular error. It is always preferable to provide error details as accurate as possible for user to understand and to respond accordingly. For example, we can provide pages for particular errors: 400.html , 404.html , 500.html and a generic error.html view.

In this case we can either redirect to these pages from the error controller:

Or we can redirect from our application business controllers directly, if the expected result is a page:

More customization: fine grained exception handlers

BasicErrorController or ErrorController implementation is a global error handler. To handle more specific errors, Spring documentation suggest to use @ExceptionHandler method annotations or @ResponseStatus exception class annotations.

So we have a global error handler, @ExceptionHandler methods and @ResponseStatus exception classes working together. But in which order? Which one has the effect first?

Let’s see in details how it works.

Spring MVC exception handlers standard configuration

WebMvcConfigurationSupport provides configuration behind the Spring MVC Java config, which is enabled by @EnableWebMvc.

This class registers several beans including the exception handler bean — HandlerExceptionResolverComposite. The composite exception resolver delegates exception handling to the the list of handlers it holds. Exception is passed through the list of handlers until one of them returns a result (something which is not null ). This result is considered as the final result of error processing. WebMvcConfigurationSupport adds the following exception handlers into HandlerExceptionResolverComposite in the following order:

  1. ExceptionHandlerExceptionResolver — for handling exceptions through @ExceptionHandler annotated methods.
  2. ResponseStatusExceptionResolver — for exceptions annotated with @ResponseStatus
  3. DefaultHandlerExceptionResolver — for resolving known Spring exception types (e.g. HttpRequestMethodNotSupportedException )

If none of these handlers returns a result, the exception is passed to the underlying container.

The underlying container forwards the exception to the registered error page. In our case this is error . Starting from this point we already know how the exception is handled afterwards. Great!

Here is a diagram summarizing Spring MVC default behavior for handling application exceptions:

Spring MVC exception handling — default configuration

Convenient base class for centralized exception handling

To simplify exception handling using @ExceptionHandler, Spring proposes ResponseEntityExceptionHandler

A convenient base class for @ControllerAdvice classes that wish to provide centralized exception handling across all @RequestMapping methods through @ExceptionHandler methods. This base class provides an @ExceptionHandler method for handling internal Spring MVC exceptions.

In other words, if we want centralized exception handling, e.g. everything in one class, we can use ResponseEntityExceptionHandler as a base class. We can use as is or override Spring MVC exception handlers provided by ResponseEntityExceptionHandler . For our custom class to work, it must be annotated with @ControllerAdvice .

Classes annotated with @ControllerAdvice can be used at the same time as the global error handler ( BasicErrorController or ErrorController implementation). If our @ControllerAdvice annotated class (which can/or not extend ResponseEntityExceptionHandler ) doesn’t handle some exception, the exception goes to the global error handler.

Takeaways

If application has a controller implementing ErrorController it replaces BasicErrorController .

Источник

Обработка ошибок в веб-API ASP.NET Core

В этой статье описывается обработка ошибок и настройка обработки ошибок с помощью ASP.NET Core веб-API.

Страница со сведениями об исключении для разработчика

На странице исключений для разработчиков отображаются подробные трассировки стека ошибок сервера. Он использует DeveloperExceptionPageMiddleware для записи синхронных и асинхронных исключений из конвейера HTTP и для создания ответов об ошибках. Например, рассмотрим следующее действие контроллера, которое создает исключение:

Когда страница исключений разработчика обнаруживает необработанное исключение, она создает ответ в виде обычного текста по умолчанию, аналогичный следующему примеру:

Если клиент запрашивает ответ в формате HTML, страница исключений разработчика создает ответ, аналогичный следующему примеру:

Чтобы запросить ответ в формате HTML, задайте для заголовка Accept HTTP-запроса значение text/html .

Не включайте страницу исключений для разработчиков, если приложение не запущено в среде разработки. Не публикуйте подробные сведения об исключениях, когда приложение выполняется в рабочей среде. Дополнительные сведения о настройке сред см. в статье Использование нескольких сред в ASP.NET Core.

Обработчик исключений

В средах, не относящихся к разработке, используйте ПО промежуточного слоя для обработки исключений , чтобы создать полезные данные об ошибке:

В Program.cs вызовите UseExceptionHandler , чтобы добавить ПО промежуточного слоя для обработки исключений:

Настройте действие контроллера для ответа на маршрут /error :

Предыдущее действие HandleError отправляет клиенту полезные данные, соответствующие RFC 7807.

Не следует помечать метод действия обработки ошибок атрибутами метода HTTP, например HttpGet . Из-за использования явных команд некоторые запросы могут не передаваться в метод действия.

Для веб-API, использующих Swagger или OpenAPI, пометьте действие обработчика ошибок атрибутом [ApiExplorerSettings] и задайте для его IgnoreApi свойства значение true . Эта конфигурация атрибута исключает действие обработчика ошибок из спецификации OpenAPI приложения:

Разрешите анонимный доступ к методу, если пользователи без проверки подлинности должны увидеть ошибку.

ПО промежуточного слоя для обработки исключений также можно использовать в среде разработки для создания согласованного формата полезных данных во всех средах:

В Program.cs зарегистрируйте экземпляры ПО промежуточного слоя обработки исключений для конкретной среды:

В приведенном выше коде ПО промежуточного слоя регистрируется с помощью внедрения зависимостей.

  • Маршрут /error-development в среде разработки.
  • Маршрут в средах /error , не относящихся к разработке.

Добавьте действия контроллера как для маршрутов Разработки, так и для маршрутов, не относящихся к разработке:

Изменение ответа с помощью исключений

Содержимое ответа можно изменить за пределами контроллера с помощью настраиваемого исключения и фильтра действий:

Создайте известный тип исключения с именем HttpResponseException :

Создайте фильтр действий с именем HttpResponseExceptionFilter :

Предыдущий фильтр указывает Order максимальное целочисленное значение минус 10. Это Order позволяет выполнять другие фильтры в конце конвейера.

В Program.cs добавьте фильтр действий в коллекцию фильтров:

Ответ в случае ошибки при сбое проверки

В контроллерах веб-API MVC отвечает с помощью типа ответа ValidationProblemDetails при сбое проверки модели. MVC использует результаты InvalidModelStateResponseFactory для создания ответа в случае ошибки при сбое проверки. В следующем примере фабрика по умолчанию заменяется реализацией, которая также поддерживает форматирование ответов в формате XML в Program.cs :

Ответ при ошибке клиента

Результат ошибки определяется как результат с кодом состояния HTTP 400 или выше. Для контроллеров веб-API MVC преобразует результат ошибки для создания ProblemDetails.

Автоматическое создание ProblemDetails для кодов состояния ошибок включено по умолчанию, но ответы на ошибки можно настроить одним из следующих способов:

Ответ со сведениями о проблеме по умолчанию

Следующий Program.cs файл был создан шаблонами веб-приложений для контроллеров API:

Рассмотрим следующий контроллер, который возвращает BadRequest , если входные данные недопустимы:

Ответ со сведениями о проблеме создается с помощью предыдущего кода, если применяется любое из следующих условий:

  • Конечная /api/values2/divide точка вызывается с нулевым знаменателем.
  • Конечная /api/values2/squareroot точка вызывается с radicand меньше нуля.

Текст ответа на сведения о проблеме по умолчанию имеет следующие type значения , title и status :

Служба сведений о проблеме

Следующий код настраивает приложение для создания ответа со сведениями о проблеме для всех ответов об ошибках HTTP-клиента и сервера, у которых еще нет содержимого текста:

Рассмотрим контроллер API из предыдущего раздела, который возвращает, BadRequest если входные данные недопустимы:

Ответ со сведениями о проблеме создается с помощью предыдущего кода, если применяется любое из следующих условий:

  • Указан недопустимый вход.
  • Универсальный код ресурса (URI) не имеет совпадающей конечной точки.
  • Возникает необработанное исключение.

Отключить автоматическое создание ProblemDetails для кодов состояния ошибок можно, задав свойству SuppressMapClientErrors значение true :

Используя приведенный выше код, когда контроллер API возвращает BadRequest , возвращается состояние ответа HTTP 400 без текста ответа. SuppressMapClientErrors предотвращает ProblemDetails создание ответа даже при вызове WriteAsync конечной точки контроллера API. WriteAsync объясняется далее в этой статье.

В следующем разделе показано, как настроить текст ответа со сведениями о проблеме с помощью CustomizeProblemDetails, чтобы получить более полезный ответ. Дополнительные параметры настройки см. в разделе Настройка сведений о проблеме.

Настройка сведений о проблеме с помощью CustomizeProblemDetails

Обновленный контроллер API:

Следующий код содержит MathErrorFeature и MathErrorType , которые используются в предыдущем примере:

Ответ со сведениями о проблеме создается с помощью предыдущего кода, если применяется любое из следующих условий:

  • Конечная /divide точка вызывается с нулевым знаменателем.
  • Конечная /squareroot точка вызывается с radicand меньше нуля.
  • Универсальный код ресурса (URI) не имеет совпадающей конечной точки.

Текст ответа сведений о проблеме содержит следующее, если любая из squareroot конечных точек вызывается с radicand меньше нуля:

Реализуйте ProblemDetailsFactory

Чтобы настроить ответ с подробными сведениями о проблемах, зарегистрируйте пользовательскую реализацию ProblemDetailsFactory в Program.cs :

Используйте ApiBehaviorOptions.ClientErrorMapping .

Используйте свойство ClientErrorMapping, чтобы настроить содержимое ответа ProblemDetails . Например, следующий код в Link обновляет свойство Program.cs для ответов 404:

Дополнительные ресурсы

В этой статье описывается обработка ошибок и настройка обработки ошибок с помощью ASP.NET Core веб-API.

Страница со сведениями об исключении для разработчика

На странице исключений для разработчиков отображаются подробные трассировки стека ошибок сервера. Он использует DeveloperExceptionPageMiddleware для записи синхронных и асинхронных исключений из конвейера HTTP и для создания ответов об ошибках. Например, рассмотрим следующее действие контроллера, которое создает исключение:

Когда страница исключений разработчика обнаруживает необработанное исключение, она создает ответ в виде обычного текста по умолчанию, аналогичный следующему примеру:

Если клиент запрашивает ответ в формате HTML, страница исключений разработчика создает ответ, аналогичный следующему примеру:

Чтобы запросить ответ в формате HTML, задайте для заголовка Accept HTTP-запроса значение text/html .

Не включайте страницу исключений для разработчиков, если приложение не запущено в среде разработки. Не публикуйте подробные сведения об исключениях, когда приложение выполняется в рабочей среде. Дополнительные сведения о настройке сред см. в статье Использование нескольких сред в ASP.NET Core.

Обработчик исключений

В средах, не относящихся к разработке, используйте ПО промежуточного слоя для обработки исключений , чтобы создать полезные данные об ошибке:

В Program.cs вызовите UseExceptionHandler , чтобы добавить ПО промежуточного слоя для обработки исключений:

Настройте действие контроллера для ответа на маршрут /error :

Предыдущее действие HandleError отправляет клиенту полезные данные, соответствующие RFC 7807.

Не следует помечать метод действия обработки ошибок атрибутами метода HTTP, например HttpGet . Из-за использования явных команд некоторые запросы могут не передаваться в метод действия.

Для веб-API, использующих Swagger или OpenAPI, пометьте действие обработчика ошибок атрибутом [ApiExplorerSettings] и задайте для его IgnoreApi свойства значение true . Эта конфигурация атрибута исключает действие обработчика ошибок из спецификации OpenAPI приложения:

Разрешите анонимный доступ к методу, если пользователи без проверки подлинности должны увидеть ошибку.

ПО промежуточного слоя для обработки исключений также можно использовать в среде разработки для создания согласованного формата полезных данных во всех средах:

В Program.cs зарегистрируйте экземпляры ПО промежуточного слоя обработки исключений для конкретной среды:

В приведенном выше коде ПО промежуточного слоя регистрируется с помощью внедрения зависимостей.

  • Маршрут /error-development в среде разработки.
  • Маршрут в средах /error , не относящихся к разработке.

Добавьте действия контроллера как для маршрутов Разработки, так и для маршрутов, не относящихся к разработке:

Изменение ответа с помощью исключений

Содержимое ответа можно изменить за пределами контроллера с помощью настраиваемого исключения и фильтра действий:

Создайте известный тип исключения с именем HttpResponseException :

Создайте фильтр действий с именем HttpResponseExceptionFilter :

Предыдущий фильтр указывает Order максимальное целочисленное значение минус 10. Это Order позволяет выполнять другие фильтры в конце конвейера.

В Program.cs добавьте фильтр действий в коллекцию фильтров:

Ответ в случае ошибки при сбое проверки

В контроллерах веб-API MVC отвечает с помощью типа ответа ValidationProblemDetails при сбое проверки модели. MVC использует результаты InvalidModelStateResponseFactory для создания ответа в случае ошибки при сбое проверки. В следующем примере фабрика по умолчанию заменяется реализацией, которая также поддерживает форматирование ответов в формате XML в Program.cs :

Ответ при ошибке клиента

Результат ошибки определяется как результат с кодом состояния HTTP 400 или выше. Для контроллеров веб-API MVC преобразует результат ошибки для создания ProblemDetails.

Ответ при ошибке можно настроить одним из следующих способов:

Реализуйте ProblemDetailsFactory

Чтобы настроить ответ с подробными сведениями о проблемах, зарегистрируйте пользовательскую реализацию ProblemDetailsFactory в Program.cs :

Используйте ApiBehaviorOptions.ClientErrorMapping .

Используйте свойство ClientErrorMapping, чтобы настроить содержимое ответа ProblemDetails . Например, следующий код в Link обновляет свойство Program.cs для ответов 404:

Пользовательское ПО промежуточного слоя для обработки исключений

Значения по умолчанию в ПО промежуточного слоя для обработки исключений хорошо работают для большинства приложений. Для приложений, требующих специализированной обработки исключений, рассмотрите возможность настройки ПО промежуточного слоя для обработки исключений.

Создание полезных данных ProblemDetails для исключений

ASP.NET Core не создает стандартизированные полезные данные ошибок при возникновении необработанного исключения. В сценариях, в которых желательно возвращать клиенту стандартизованный ответ ProblemDetails , ПО промежуточного слоя ProblemDetails можно использовать для сопоставления исключений и 404 ответов с полезными данными ProblemDetails . ПО промежуточного слоя для обработки исключений ProblemDetails также можно использовать для возврата полезных данных для необработанных исключений.

Дополнительные ресурсы

В этой статье описывается обработка и настройка обработки ошибок с помощью веб-API ASP.NET Core.

Страница со сведениями об исключении для разработчика

Страница со сведениями об исключении для разработчика — это полезное средство, с помощью которого можно получить подробные трассировки стека для ошибок сервера. Он использует DeveloperExceptionPageMiddleware для записи синхронных и асинхронных исключений из конвейера HTTP и для создания ответов об ошибках. Для иллюстрации рассмотрим следующее действие контроллера:

Выполните следующую команду curl , чтобы проверить предыдущее действие:

Страница исключений разработчика отображает ответ в виде обычного текста, если клиент не запрашивает выходные данные в формате HTML. Отображаются следующие результаты:

Чтобы вместо этого отображался отформатированный HTML-запрос, задайте для заголовка HTTP-запроса Accept тип носителя text/html . Пример:

Рассмотрим следующий фрагмент HTTP-ответа:

Отформатированный HTML-ответ полезен при тестировании с помощью таких инструментов, как Postman. На следующем снимке экрана показаны ответы в виде обычного текста и в формате HTML в Postman:

Включать страницу исключений для разработчика следует только тогда, когда приложение выполняется в среде разработки. Не публикуйте подробные сведения об исключениях, когда приложение выполняется в рабочей среде. Дополнительные сведения о настройке сред см. в статье Использование нескольких сред в ASP.NET Core.

Не следует помечать метод действия обработки ошибок атрибутами метода HTTP, например HttpGet . Из-за использования явных команд некоторые запросы могут не передаваться в метод действия. Разрешите анонимный доступ к методу, если пользователи без проверки подлинности должны увидеть ошибку.

Обработчик исключений

В средах, не относящихся к разработке, для получения полезных данных об ошибках можно использовать ПО промежуточного слоя для обработки исключений.

В Startup.Configure вызовите UseExceptionHandler, чтобы использовать ПО промежуточного слоя:

Настройте действие контроллера для ответа на маршрут /error :

Предыдущее действие Error отправляет клиенту полезные данные, соответствующие RFC 7807.

ПО промежуточного слоя для обработки исключений также может предоставлять более подробные данные, согласованные с содержимым, в локальной среде разработки. Чтобы создать согласованный формат полезных данных в среде разработки и рабочей среде, сделайте следующее:

В Startup.Configure зарегистрируйте экземпляры ПО промежуточного слоя обработки исключений для конкретной среды:

В приведенном выше коде ПО промежуточного слоя регистрируется с помощью внедрения зависимостей.

  • Маршрут /error-local-development в среде разработки.
  • Маршрут /error в средах, не имеющих отношения к разработке.

Примените маршрутизацию атрибутов к действиям контроллера:

Приведенный выше код вызывает ControllerBase.Problem для создания ProblemDetails ответа.

Изменение ответа с помощью исключений

Содержимое ответа можно изменить за пределами контроллера. В веб-API ASP.NET 4.x один из способов это сделать — использовать тип HttpResponseException. ASP.NET Core не содержит эквивалентный тип. Поддержку HttpResponseException можно добавить, сделав следующее:

Создайте известный тип исключения с именем HttpResponseException :

Создайте фильтр действий с именем HttpResponseExceptionFilter :

Предыдущий фильтр задает Order значение максимального целого числа минус 10. Это Order позволяет выполнять другие фильтры в конце конвейера.

В Startup.ConfigureServices добавьте фильтр действий в коллекцию фильтров:

Ответ в случае ошибки при сбое проверки

В контроллерах веб-API MVC отвечает с помощью типа ответа ValidationProblemDetails при сбое проверки модели. MVC использует результаты InvalidModelStateResponseFactory для создания ответа в случае ошибки при сбое проверки. В следующем примере в Startup.ConfigureServices для изменения типа ответа по умолчанию на SerializableError используется фабрика:

Ответ при ошибке клиента

Результат ошибки определяется как результат с кодом состояния HTTP 400 или выше. В контроллерах веб-API платформа MVC преобразует результат ошибки в результат с ProblemDetails.

Ответ при ошибке можно настроить одним из следующих способов:

Реализуйте ProblemDetailsFactory

Чтобы настроить ответ с подробными сведениями о проблемах, зарегистрируйте пользовательскую реализацию ProblemDetailsFactory в Startup.ConfigureServices :

Использование ApiBehaviorOptions.ClientErrorMapping

Используйте свойство ClientErrorMapping, чтобы настроить содержимое ответа ProblemDetails . Например, следующий код в type обновляет свойство Startup.ConfigureServices для ответов 404:

Пользовательское ПО промежуточного слоя для обработки исключений

Значения по умолчанию в ПО промежуточного слоя для обработки исключений хорошо работают для большинства приложений. Для приложений, требующих специализированной обработки исключений, рассмотрите возможность настройки ПО промежуточного слоя для обработки исключений.

Источник

TL;DR In depth explanation of exception handling for Spring MVC in a Spring Boot application: exception handler types, handlers ordering, available customization means.

Table of contents

  • Spring Boot auto-configuration for error handling
  • Error page customization

    • Customizing global error handler
    • Customizing error view page
  • More customization: fine grained exception handlers

    • Spring MVC exception handlers standard configuration
    • Convenient base class for centralized exception handling
  • Takeaways

Spring Boot auto-configuration for error handling

Spring Boot application has a default configuration for error handling — ErrorMvcAutoConfiguration.

What it basically does, if no additional configuration provided:

  • it creates default global error controller — BasicErrorController
  • it creates default ‘error’ static view ‘Whitelabel Error Page’.

BasicErrorController is wired to ‘/error’ view by default. If there is no customized ‘error’ view in the application, in case of an exception thrown from any controller, the user lands to /error whitelabel page, filled with information by BasicErrorController.

Error page customization

As we saw earlier, Spring MVC’ default error page is /error. Default controller behind /error endpoint is BasicErrorController.
Let’s look how we can customize error handling.

Customizing global error handler

BasicErrorController is a basic error controller rendering ErrorAttributes.
It can either render an html page or provide a serialized ErrorAttributes object.

There are several ways to customize the behavior of error handling and/or the contents of the error view:

  1. The Spring Boot application can provide its own error handling controller. It must implement ErrorController interface to automatically replace BasicErrorController.
  2. The application can provide custom view servlet server page(s) and custom view content. For an html view, the page format can be either jps or html with Thymleaf to render model attributes filled by the error controller.
  3. The application can do both: customize the behavior by implementing ErrorController and customize the error page view and/or error model object.

Customizing error view page

The default error page, which you already saw perhaps, is a ‘Whitelabel error page’ static view (created in the code directly) configured within ErrorMvcAutoConfiguration. It is served by default by /error endpoint.

You can keep the endpoint and just replace the static view by a custom page.
For it to be picked automatically without any configuration, the page must be called error.html and it must be placed in src/main/resources/templatesfolder.

And here is an example of a view we could come up to:

<!DOCTYPE html>
<html>
    <body>
        <h1>Oups! An error has occurred trying to process your request. </h1>
        <h2>No panic. We are already working on it!</h2>
        <a href="/">Back to Home</a>
    </body>
</html>

:bulb: once you have replaced the default static view, you can disable id with server.error.whitelabel.enabled=false in the application.properties.

:bulb: if you with to name your global error page differently, you can use server.error.path application property. For example: server.error.path=/oups, which should have the corresponding oups.html view.

Another approach for error handling is to have several error views, each for a particular error. It is always preferable to provide error details as accurate as possible for user to understand and to respond accordingly.
For example, we can provide pages for particular errors: 400.html, 404.html, 500.html and a generic error.html view.

In this case we can either redirect to these pages from the error controller:

@Controller
@RequestMapping("${server.error.path:${error.path:/error}}")
CustomizedErrorController implements ErrorController {
    ...
    @GetMapping(produces = MediaType.TEXT_HTML_VALUE)
    public String handleError(HttpServletRequest request, Model model) {
        ...
        //retrieving http error status code set by the underlying container
        Object status = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);

        if (status != null) {
            HttpStatus httpStatus = HttpStatus.resolve((int) status);
            switch(httpStatus) {
                case HttpStatus.BAD_REQUEST:
                    return "400";
                case HttpStatus.NOT_FOUND:
                    return "404";
                case HttpStatus.INTERNAL_SERVER_ERROR:
                    return "500";
            }
        }
        return "error";
    }
}

Or we can redirect from our application business controllers directly, if the expected result is a page:

@Controller
@RequestMapping("/user}")
UserController implements ErrorController {
    ...
    @GetMapping(produces = MediaType.TEXT_HTML_VALUE)
    public String getUser(HttpServletRequest request, Model model) {
        User user = getUser();
        if(user == null) {
            return "404";
        }
        model.addAttribute("user", user);
        return "user"; // user information page
    }
}

More customization: fine grained exception handlers

BasicErrorController or ErrorController implementation is a global error handler. To handle more specific errors, Spring documentation suggest to use @ExceptionHandler method annotations or @ResponseStatus exception class annotations.

So we have a global error handler, @ExceptionHandler methods and @ResponseStatus exception classes working together.
But in which order? Which one has the effect first?

Let’s see in details how it works.

Spring MVC exception handlers standard configuration

WebMvcConfigurationSupport provides configuration behind the Spring MVC Java config, which is enabled by @EnableWebMvc.

This class registers several beans including the exception handler bean — HandlerExceptionResolverComposite.
The composite exception resolver delegates exception handling to the the list of handlers it holds. Exception is passed through the list of handlers until one of them returns a result (something which is not null). This result is considered as the final result of error processing.
WebMvcConfigurationSupport adds the following exception handlers into HandlerExceptionResolverComposite in the following order:

  1. ExceptionHandlerExceptionResolver — for handling exceptions through @ExceptionHandler annotated methods.
  2. ResponseStatusExceptionResolver — for exceptions annotated with @ResponseStatus
  3. DefaultHandlerExceptionResolver — for resolving known Spring exception types (e.g. HttpRequestMethodNotSupportedException)

If none of these handlers returns a result, the exception is passed to the underlying container.

The underlying container forwards the exception to the registered error page. In our case this is error.
Starting from this point we already know how the exception is handled afterwards. Great!

Here is a diagram summarizing Spring MVC default behavior for handling application exceptions:

Spring MVC exception handling - default configuration

Spring MVC exception handling — default configuration

Convenient base class for centralized exception handling

To simplify exception handling using @ExceptionHandler, Spring proposes ResponseEntityExceptionHandler

A convenient base class for @ControllerAdvice classes that wish to provide centralized exception handling across all @RequestMapping methods through @ExceptionHandler methods.
This base class provides an @ExceptionHandler method for handling internal Spring MVC exceptions.

In other words, if we want centralized exception handling, e.g. everything in one class, we can use ResponseEntityExceptionHandler as a base class. We can use as is or override Spring MVC exception handlers provided by ResponseEntityExceptionHandler. For our custom class to work, it must be annotated with @ControllerAdvice.

Classes annotated with @ControllerAdvice can be used at the same time as the global error handler (BasicErrorController or ErrorController implementation). If our @ControllerAdvice annotated class (which can/or not extend ResponseEntityExceptionHandler) doesn’t handle some exception, the exception goes to the global error handler.

Takeaways

If application has a controller implementing ErrorController it replaces BasicErrorController.

If any exception occurs in error handling controller, it will go through Spring exception handlers filter and finally if nothing is found this exception will be handled by the underlying application container, e.g. Tomcat. The underlying container will handle the exception and show some error page/message depending on its implementation.

Spring exception handlers default order:

  1. First Spring searches for an exception handler (a method annotated with @ExceptionHandler) within the classes annotated with @ControllerAdvice. This behavior is implemented in ExceptionHandlerExceptionResolver.
  2. Then it checks if the thrown exception is annotated with @ResponseStatus or if it derives from ResponseStatusException. If so it is handled by ResponseStatusExceptionResolver.
  3. Then it goes through Spring MVC exceptions’ default handlers. These are in DefaultHandlerExceptionResolver.
  4. And at the end if nothing is found, the control is forwarded to the configured error page view with the global error handler behind it. This step is not executed if the exception comes from the error handler itself.
  5. If no error view is found (e.g. global error handler is disabled) or step 4 is skipped, then the exception is handled by the container.

Editor’s note: This article was updated on September 5, 2022, by our editorial team. It has been modified to include recent sources and to align with our current editorial standards.

The ability to handle errors correctly in APIs while providing meaningful error messages is a desirable feature, as it can help the API client respond to issues. The default behavior returns stack traces that are hard to understand and ultimately useless for the API client. Partitioning the error information into fields enables the API client to parse it and provide better error messages to the user. In this article, we cover how to implement proper Spring Boot exception handling when building a REST API .

Building REST APIs with Spring became the standard approach for Java developers. Using Spring Boot helps substantially, as it removes a lot of boilerplate code and enables auto-configuration of various components. We assume that you’re familiar with the basics of API development with those technologies. If you are unsure about how to develop a basic REST API, you should start with this article about Spring MVC or this article about building a Spring REST Service.

Making Error Responses Clearer

We’ll use the source code hosted on GitHub as an example application that implements a REST API for retrieving objects that represent birds. It has the features described in this article and a few more examples of error handling scenarios. Here’s a summary of endpoints implemented in that application:

GET /birds/{birdId} Gets information about a bird and throws an exception if not found.
GET /birds/noexception/{birdId} This call also gets information about a bird, except it doesn’t throw an exception when a bird doesn’t exist with that ID.
POST /birds Creates a bird.

The Spring framework MVC module has excellent features for error handling. But it is left to the developer to use those features to treat the exceptions and return meaningful responses to the API client.

Let’s look at an example of the default Spring Boot answer when we issue an HTTP POST to the /birds endpoint with the following JSON object that has the string “aaa” on the field “mass,” which should be expecting an integer:

{
 "scientificName": "Common blackbird",
 "specie": "Turdus merula",
 "mass": "aaa",
 "length": 4
}

The Spring Boot default answer, without proper error handling, looks like this:

{
 "timestamp": 1658551020,
 "status": 400,
 "error": "Bad Request",
 "exception": "org.springframework.http.converter.HttpMessageNotReadableException",
 "message": "JSON parse error: Unrecognized token 'three': was expecting ('true', 'false' or 'null'); nested exception is com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'aaa': was expecting ('true', 'false' or 'null')n at [Source: java.io.PushbackInputStream@cba7ebc; line: 4, column: 17]",
 "path": "/birds"
}

The Spring Boot DefaultErrorAttributes-generated response has some good fields, but it is too focused on the exception. The timestamp field is an integer that doesn’t carry information about its measurement unit. The exception field is only valuable to Java developers, and the message leaves the API consumer lost in implementation details that are irrelevant to them. What if there were more details we could extract from the exception? Let’s learn how to handle exceptions in Spring Boot properly and wrap them into a better JSON representation to make life easier for our API clients.

As we’ll be using Java date and time classes, we first need to add a Maven dependency for the Jackson JSR310 converters. They convert Java date and time classes to JSON representation using the @JsonFormat annotation:

<dependency>
   <groupId>com.fasterxml.jackson.datatype</groupId>
   <artifactId>jackson-datatype-jsr310</artifactId>
</dependency>

Next, let’s define a class for representing API errors. We’ll create a class called ApiError with enough fields to hold relevant information about errors during REST calls:

class ApiError {

   private HttpStatus status;
   @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy hh:mm:ss")
   private LocalDateTime timestamp;
   private String message;
   private String debugMessage;
   private List<ApiSubError> subErrors;

   private ApiError() {
       timestamp = LocalDateTime.now();
   }

   ApiError(HttpStatus status) {
       this();
       this.status = status;
   }

   ApiError(HttpStatus status, Throwable ex) {
       this();
       this.status = status;
       this.message = "Unexpected error";
       this.debugMessage = ex.getLocalizedMessage();
   }

   ApiError(HttpStatus status, String message, Throwable ex) {
       this();
       this.status = status;
       this.message = message;
       this.debugMessage = ex.getLocalizedMessage();
   }
}
  • The status property holds the operation call status, which will be anything from 4xx to signal client errors or 5xx to signal server errors. A typical scenario is an HTTP code 400: BAD_REQUEST when the client, for example, sends an improperly formatted field, like an invalid email address.

  • The timestamp property holds the date-time instance when the error happened.

  • The message property holds a user-friendly message about the error.

  • The debugMessage property holds a system message describing the error in detail.

  • The subErrors property holds an array of suberrors when there are multiple errors in a single call. An example would be numerous validation errors in which multiple fields have failed. The ApiSubError class encapsulates this information:

abstract class ApiSubError {

}

@Data
@EqualsAndHashCode(callSuper = false)
@AllArgsConstructor
class ApiValidationError extends ApiSubError {
   private String object;
   private String field;
   private Object rejectedValue;
   private String message;

   ApiValidationError(String object, String message) {
       this.object = object;
       this.message = message;
   }
}

The ApiValidationError is a class that extends ApiSubError and expresses validation problems encountered during the REST call.

Below, you’ll see examples of JSON responses generated after implementing these improvements.

Here is a JSON example returned for a missing entity while calling endpoint GET /birds/2:

{
 "apierror": {
   "status": "NOT_FOUND",
   "timestamp": "22-07-2022 06:20:19",
   "message": "Bird was not found for parameters {id=2}"
 }
}

Here is another example of JSON returned when issuing a POST /birds call with an invalid value for the bird’s mass:

{
 "apierror": {
   "status": "BAD_REQUEST",
   "timestamp": "22-07-2022 06:49:25",
   "message": "Validation errors",
   "subErrors": [
     {
       "object": "bird",
       "field": "mass",
       "rejectedValue": 999999,
       "message": "must be less or equal to 104000"
     }
   ]
 }
}

Spring Boot Error Handler

Let’s explore some Spring annotations used to handle exceptions.

RestController is the base annotation for classes that handle REST operations.

ExceptionHandler is a Spring annotation that provides a mechanism to treat exceptions thrown during execution of handlers (controller operations). This annotation, if used on methods of controller classes, will serve as the entry point for handling exceptions thrown within this controller only.

Altogether, the most common implementation is to use @ExceptionHandler on methods of @ControllerAdvice classes so that the Spring Boot exception handling will be applied globally or to a subset of controllers.

ControllerAdvice is an annotation in Spring and, as the name suggests, is “advice” for multiple controllers. It enables the application of a single ExceptionHandler to multiple controllers. With this annotation, we can define how to treat such an exception in a single place, and the system will call this handler for thrown exceptions on classes covered by this ControllerAdvice.

The subset of controllers affected can be defined by using the following selectors on @ControllerAdvice: annotations(), basePackageClasses(), and basePackages(). ControllerAdvice is applied globally to all controllers if no selectors are provided

By using @ExceptionHandler and @ControllerAdvice, we’ll be able to define a central point for treating exceptions and wrapping them in an ApiError object with better organization than is possible with the default Spring Boot error-handling mechanism.

Handling Exceptions

Next, we’ll create the class that will handle the exceptions. For simplicity, we call it RestExceptionHandler, which must extend from Spring Boot’s ResponseEntityExceptionHandler. We’ll be extending ResponseEntityExceptionHandler, as it already provides some basic handling of Spring MVC exceptions. We’ll add handlers for new exceptions while improving the existing ones.

Overriding Exceptions Handled in ResponseEntityExceptionHandler

If you take a look at the source code of ResponseEntityExceptionHandler, you’ll see a lot of methods called handle******(), like handleHttpMessageNotReadable() or handleHttpMessageNotWritable(). Let’s see how can we extend handleHttpMessageNotReadable() to handle HttpMessageNotReadableException exceptions. We just have to override the method handleHttpMessageNotReadable() in our RestExceptionHandler class:

@Order(Ordered.HIGHEST_PRECEDENCE)
@ControllerAdvice
public class RestExceptionHandler extends ResponseEntityExceptionHandler {

   @Override
   protected ResponseEntity<Object> handleHttpMessageNotReadable(HttpMessageNotReadableException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
       String error = "Malformed JSON request";
       return buildResponseEntity(new ApiError(HttpStatus.BAD_REQUEST, error, ex));
   }

   private ResponseEntity<Object> buildResponseEntity(ApiError apiError) {
       return new ResponseEntity<>(apiError, apiError.getStatus());
   }

   //other exception handlers below

}

We have declared that in case of a thrownHttpMessageNotReadableException, the error message will be “Malformed JSON request” and the error will be encapsulated in the ApiError object. Below, we can see the answer of a REST call with this new method overridden:

{
 "apierror": {
   "status": "BAD_REQUEST",
   "timestamp": "22-07-2022 03:53:39",
   "message": "Malformed JSON request",
   "debugMessage": "JSON parse error: Unrecognized token 'aaa': was expecting ('true', 'false' or 'null'); nested exception is com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'aaa': was expecting ('true', 'false' or 'null')n at [Source: java.io.PushbackInputStream@7b5e8d8a; line: 4, column: 17]"
 }
}

Implementing Custom Exceptions

Next, we’ll create a method that handles an exception not yet declared inside Spring Boot’s ResponseEntityExceptionHandler.

A common scenario for a Spring application that handles database calls is to provide a method that returns a record by its ID using a repository class. But if we look into the CrudRepository.findOne() method, we’ll see that it returns null for an unknown object. If our service calls this method and returns directly to the controller, we’ll get an HTTP code 200 (OK) even if the resource isn’t found. In fact, the proper approach is to return a HTTP code 404 (NOT FOUND) as specified in the HTTP/1.1 spec.

We’ll create a custom exception called EntityNotFoundException to handle this case. This one is different from javax.persistence.EntityNotFoundException, as it provides some constructors that ease the object creation, and one may choose to handle the javax.persistence exception differently.

That said, let’s create an ExceptionHandler for this newly created EntityNotFoundException in our RestExceptionHandler class. Create a method called handleEntityNotFound() and annotate it with @ExceptionHandler, passing the class object EntityNotFoundException.class to it. This declaration signalizes Spring that every time EntityNotFoundException is thrown, Spring should call this method to handle it.

When annotating a method with @ExceptionHandler, a wide range of auto-injected parameters like WebRequest, Locale, and others may be specified as described here. We’ll provide the exception EntityNotFoundException as a parameter for this handleEntityNotFound method:

@Order(Ordered.HIGHEST_PRECEDENCE)
@ControllerAdvice
public class RestExceptionHandler extends ResponseEntityExceptionHandler {
  
   //other exception handlers
  
   @ExceptionHandler(EntityNotFoundException.class)
   protected ResponseEntity<Object> handleEntityNotFound(
           EntityNotFoundException ex) {
       ApiError apiError = new ApiError(NOT_FOUND);
       apiError.setMessage(ex.getMessage());
       return buildResponseEntity(apiError);
   }
}

Great! In the handleEntityNotFound() method, we set the HTTP status code to NOT_FOUND and usethe new exception message. Here is what the response for the GET /birds/2 endpoint looks like now:

{
 "apierror": {
   "status": "NOT_FOUND",
   "timestamp": "22-07-2022 04:02:22",
   "message": "Bird was not found for parameters {id=2}"
 }
}

The Importance of Spring Boot Exception Handling

It is important to control exception handling so we can properly map exceptions to the ApiError object and inform API clients appropriately. Additionally, we would need to create more handler methods (the ones with @ExceptionHandler) for thrown exceptions within the application code. The GitHub code provides more more examples for other common exceptions like MethodArgumentTypeMismatchException, ConstraintViolationException.

Here are some additional resources that helped in the composition of this article:

  • Error Handling for REST With Spring

  • Exception Handling in Spring MVC

Further Reading on the Toptal Engineering Blog:

  • Top 10 Most Common Spring Framework Mistakes
  • Spring Security with JWT for REST API
  • Using Spring Boot for OAuth2 and JWT REST Protection
  • Building an MVC Application With Spring Framework: A Beginner’s Tutorial
  • Spring Batch Tutorial: Batch Processing Made Easy with Spring

Understanding the basics

  • Why should the API have a uniform error format?

    A uniform error format allows an API client to parse error objects. A more complex error could implement the ApiSubError class and provide more details about the problem so the client can know which actions to take.

  • How does Spring know which ExceptionHandler to use?

    The Spring MVC class, ExceptionHandlerExceptionResolver, performs most of the work in its doResolveHandlerMethodException() method.

  • What information is important to provide to API consumers?

    Usually, it is helpful to include the error origination, the input parameters, and some guidance on how to fix the failing call.

  • java.lang.Object
    • org.springframework.boot.autoconfigure.web.servlet.error.AbstractErrorController
      • org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController
  • All Implemented Interfaces:
    org.springframework.boot.web.servlet.error.ErrorController

    @Controller
    @RequestMapping("${server.error.path:${error.path:/error}}")
    public class BasicErrorController
    extends AbstractErrorController

    Basic global error Controller, rendering ErrorAttributes. More specific errors can be handled either using Spring MVC abstractions (e.g. @ExceptionHandler) or by adding servlet server error pages.

    See Also:
    ErrorAttributes, ErrorProperties
    • Constructor Summary

    • Method Summary

      All Methods Instance Methods Concrete Methods 

      Modifier and Type Method Description
      org.springframework.http.ResponseEntity<Map<String,​Object>> error​(javax.servlet.http.HttpServletRequest request)  
      org.springframework.web.servlet.ModelAndView errorHtml​(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response)  
      String getErrorPath()  
      protected ErrorProperties getErrorProperties()

      Provide access to the error properties.

      protected boolean isIncludeStackTrace​(javax.servlet.http.HttpServletRequest request, org.springframework.http.MediaType produces)

      Determine if the stacktrace attribute should be included.

      • Methods inherited from class org.springframework.boot.autoconfigure.web.servlet.error.AbstractErrorController

        getErrorAttributes, getStatus, getTraceParameter, resolveErrorView

      • Methods inherited from class java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

    • Constructor Detail

      • BasicErrorController

        public BasicErrorController​(org.springframework.boot.web.servlet.error.ErrorAttributes errorAttributes,
                                    ErrorProperties errorProperties)
        Parameters:
        errorAttributes — the error attributes
        errorProperties — configuration properties
      • BasicErrorController

        public BasicErrorController​(org.springframework.boot.web.servlet.error.ErrorAttributes errorAttributes,
                                    ErrorProperties errorProperties,
                                    List<ErrorViewResolver> errorViewResolvers)
        Parameters:
        errorAttributes — the error attributes
        errorProperties — configuration properties
        errorViewResolvers — error view resolvers
    • Method Detail

      • getErrorPath

        public String getErrorPath()
      • errorHtml

        @RequestMapping(produces="text/html")
        public org.springframework.web.servlet.ModelAndView errorHtml​(javax.servlet.http.HttpServletRequest request,
                                                                      javax.servlet.http.HttpServletResponse response)
      • error

        @RequestMapping
        public org.springframework.http.ResponseEntity<Map<String,​Object>> error​(javax.servlet.http.HttpServletRequest request)
      • isIncludeStackTrace

        protected boolean isIncludeStackTrace​(javax.servlet.http.HttpServletRequest request,
                                              org.springframework.http.MediaType produces)

        Determine if the stacktrace attribute should be included.

        Parameters:
        request — the source request
        produces — the media type produced (or MediaType.ALL)
        Returns:
        if the stacktrace attribute should be included
      • getErrorProperties

        protected ErrorProperties getErrorProperties()

        Provide access to the error properties.

        Returns:
        the error properties

Понравилась статья? Поделить с друзьями:
  • Bash trap error
  • Bash throw error
  • Bash syntax error unterminated quoted string
  • Bash syntax error operand expected error token is
  • Bash syntax error near unexpected token перевод