Главная » Ошибки » Обработка исключений Spring Boot REST API

Обработка исключений Spring Boot REST API

Приложение

Обрабатывать исключения будем в простом Spring Boot приложении из первой части. Оно предоставляет REST API для сущности Person:

@Entity
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Size(min = 3, max = 10)
private String name;

}

Только в этот раз поле name аннотировано javax.validation.constraints.Size.

А также перед аргументом Person в методах контроллера стоит аннотация @Valid:

@RestController
@RequestMapping(“/persons”)
public class PersonController {

@Autowired
private PersonRepository personRepository;

@GetMapping
public List

listAllPersons() {
List

persons = personRepository.findAll();
return persons;
}

@GetMapping(value = “/{personId}”)
public Person getPerson(@PathVariable(“personId”) long personId) {
return personRepository.findById(personId).orElseThrow(() -> new MyEntityNotFoundException(personId));
}

@PostMapping
public Person createPerson(@RequestBody @Valid Person person) {
return personRepository.save(person);
}

@PutMapping(“/{id}”)
public Person updatePerson(@RequestBody @Valid Person person, @PathVariable long id) {
Person oldPerson = personRepository.getOne(id);
oldPerson.setName(person.getName());
return personRepository.save(oldPerson);
}

}

Аннотация @Valid заставляет Spring проверять валидность полей объекта Person, например условие @Size(min = 3, max = 10). Если пришедший в контроллер объект не соответствует условиям, то будет выброшено MethodArgumentNotValidException — то самое, для которого в ResponseEntityExceptionHandler уже задан обработчик. Правда, он выдает пустое тело ответа. Вообще все обработчики из ResponseEntityExceptionHandler выдают корректный код ответа, но пустое тело.

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

Итак, ApiError по сравнению с 1-ой частью теперь содержит еще список errors:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class ApiError {
private String message;
private String debugMessage;

@JsonInclude(JsonInclude.Include.NON_NULL)
private List errors;

public ApiError(String message, String debugMessage){
this.message=message;
this.debugMessage=debugMessage;
}
}

Благодаря аннотации @JsonInclude(JsonInclude.Include.NON_NULL) этот список будет включен в ответ только в том случае, если мы его зададим. Иначе ответ будет содержать только message и debugMessage, как в первой части.

Как исправить ошибку Not Found

Выбор конкретного решения зависит от причины ошибки:

  1. Ссылка ведёт в никуда из-за неверного URL. Для решения проблемы замените ошибочную ссылку на правильный адрес, чтобы сервер отдавал код 200 OK.
  2. Битая ссылка. Подобная ситуация не редкость при внутренней перелинковке страниц. К примеру, ссылка есть, а саму страницу давно удалили. Решений два: удалить ссылку или заменить её на другую.

Удалять и менять ссылки вручную удобно только на небольших сайтах. Исправление ошибок на крупных порталах лучше автоматизировать. Например, с помощью специальных плагинов для внутренней перелинковки (Terms Description, Dagon Design Sitemap Generator) и для автоматического формирования адресов страниц (Cyr-To-Lat).

Чтобы ошибки 404 появлялись как можно реже, достаточно соблюдать простые рекомендации:

  • Не присваивайте сложные адреса основным разделам сайта. Это снизит число ошибок, связанных с опечатками в URL.
  • Не меняйте адреса страниц слишком часто. Это неудобно для пользователей и вводит в заблуждение поисковых роботов.
  • Размещайте сайт на надёжном сервере. Это предотвратит ошибки, возникающие из-за неработоспособности сервера.

Мы разобрались, как найти и исправить ошибки Not Found внутри сайта. Но неработающая ссылка может быть расположена и на стороннем ресурсе. Допустим, когда-то на другом сайте разместили рекламную публикацию со ссылкой на определённую страницу. Спустя какое-то время страницу удалили. В этом случае появится ошибка 404. Устранить её можно, связавшись с администрацией ссылающегося сайта. Если же удалить/исправить ссылку нельзя, постарайтесь использовать ошибку с выгодой.

Download Source Code

$ git clone https://github.com/mkyong/spring-boot.git
$ cd spring-rest-error-handling
$ mvn spring-boot:run

Открывается только главная страница сайта, на внутренних страницах ошибка 404 или 500

Рассмотрим, что значит и как исправить ошибку отображения внутренних страниц сайта (error 404 или 500). Причиной проблемы является отсутствие файла .htaccess (либо он пустой, либо в нем не хватает необходимых директив для работы CMS). Решить проблему может замена текущего файла .htaccess стандартным для данной CMS.

На хостинге Linux

Если у вас ISPmanager, проверьте, не включены ли Автоподдомены. Если они включены, отключите их, проверьте актуальность проблемы.

В остальных случаях для устранения внутренней ошибки 404 или 500, перейдите в корневую папку сайта: Как узнать корневую папку сайта
Создайте файл .htaccess (или замените его) со следующим содержимым:

Файл .htaccess для Joomla
##

# @version $Id: htaccess.txt 14401 2010-01-26 14:10:00Z louis $
# @package Joomla
# @copyright Copyright (C) 2005 – 2010 Open Source Matters. All rights reserved.
# @license http://www.gnu.org/copyleft/gpl.html GNU/GPL
# Joomla! is Free Software
##
#####################################################
# READ THIS COMPLETELY IF YOU CHOOSE TO USE THIS FILE
#
# The line just below this section: ‘Options +FollowSymLinks’ may cause problems
# with some server configurations. It is required for use of mod_rewrite, but may already
# be set by your server administrator in a way that dissallows changing it in
# your .htaccess file. If using it causes your server to error out, comment it out (add # to
# beginning of line), reload your site in your browser and test your sef url’s. If they work,
# it has been set by your server administrator and you do not need it set here.
#
#####################################################

## Can be commented out if causes errors, see notes above.
Options +FollowSymLinks

#
# mod_rewrite in use

RewriteEngine On

########## Begin – Rewrite rules to block out some common exploits
## If you experience problems on your site block out the operations listed below
## This attempts to block the most common type of exploit `attempts` to Joomla!
#
## Deny access to extension xml files (uncomment out to activate)
#
#Order allow,deny
#Deny from all
#Satisfy all
#

## End of deny access to extension xml files
RewriteCond %{QUERY_STRING} mosConfig_[a-zA-Z_]{1,21}(=|%3D) [OR] # Block out any script trying to base64_encode crap to send via URL
RewriteCond %{QUERY_STRING} base64_encode.*(.*) [OR] # Block out any script that includes a

Если у вас хостинг Windows

На хостинге Windows файл .htaccess не поддерживается. Его функцию выполняет файл web.config. Если вы наблюдаете внутреннюю ошибку 404 или 500 на хостинге Windows, рекомендуем обратиться к разработчикам сайта или на тематические форумы с вопросом, как убрать 404, заменив файл web.config.

Как находить и мониторить код ошибки 404?

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

  • Яндекс.Вебмастер,
  • Google Search Console,
  • Screaming Frog.

Ниже мы описали, как работать с каждым из них.

Яндекс.Вебмастер

  1. Авторизуйтесь в Яндекс.Вебмастер.

  2. Перейдите в раздел Индексирование — Страницы в поиске:

мониторинг ошибки 404 1
HTTP status 404 — что это

  1. Выберите Исключенные страницы:

мониторинг ошибки 404 2

  1. Добавьте фильтр, при котором отобразятся результаты с ошибкой «404 page not found»:

мониторинг ошибки 404 3

Google Search Console

  1. Авторизуйтесь в Google Search Console.

  2. Разверните блок Индекс и выберите Покрытие:

мониторинг ошибки 404 4
404 ошибка: что это

  1. Используйте фильтр, который покажет код ошибки 404. Для этого перейдите в раздел Сведения и кликните Отправленный URL не найден (ошибка 404):

мониторинг ошибки 404 5
Ошибка 404: что значит и как исправить

Screaming Frog

  1. Загрузите программу с официального сайта.

  2. Установите её на компьютер.

  3. Откройте программу, введите ссылку на сайт и нажмите Start:

мониторинг ошибки 404 6

  1. Перейдите во вкладку Response Code. Из выпадающего списка выберите фильтр Client Error (4xx):

мониторинг ошибки 404 7

How to fix the error ‘404 Not Found’

A 404 error is rarely a reason to celebrate. At the end of the day, the website’s visitors have not found the content that they were looking for. However the appearance of a 404 page does not necessarily mean that the desired information is not available at all. In many cases, the solution to the original error is easily found and the visitor can be quickly directed to the web page that they were originally looking for. So how exactly can you go about achieving a 404 error fix? Our advice would be to try out these potential solutions (in the order that they are listed):

  • Reload the page: It might be that the error 404 has appeared for the simple reason that the page did not load properly. This can be checked quite easily by clicking on the ‘Refresh’ button in your browser or also by pressing the F5 button.
  • Check the URL: Regardless of whether you have entered the URL address manually or been directed via a link, could be that a mistake has been made. For this reason you should check the specified path of the website. It could be that either you, or the person who entered the link, has mistyped something. Apart from spelling mistakes, it could also be that forward slashes have been left out or misplaced. But bear in mind that this can only really be checked with ‘clean’ URLs, as they contain unreadable words instead of incomprehensible abbreviations, letters, numbers, and symbols.
  • Go back through the directory levels: For example, if a URL of the following structure example.com/Directory1/Directory2/Directory3 causes a 404 error page, then you can always go back to the previous directory level (in this example: example.com/Directory1/Directory2) in order to check whether the desired page is linked there. All you need to do is clear the last directory in the URL. The link for the page you are looking for should be visible on the previous page. If it is not to be found on that page then you can also go back to the previous page and look for the correct link there. But if it so happens that this method is also successful and you eventually end up back on the homepage, then move onto the next tip.
  • Use the website’s search function: Many websites offer a search function as part of their homepage. By entering one or several keywords, it can help you find the specific page that you are looking for.
  • Use a search engine: You also have the possibility of using the website of your choice to find a website. As long as the desired site exists, you should be able to find it by entering the website domain and/or a keyword transcription of the subject matter.
  • Delete the browser cache and cookies: Ifyou can access the website from another device, and the HTTP 404 error only seems to appear on a certain computer, then the problem could lie with your browser. Therefore you should delete the browser cache as well as all cookies for this site, and this may then finally allow you to access the page.
  • Contact the website: If none of the abovementioned tips have been successful then the only remaining option may be to get in touch with the person/people responsible for the website. Contact information can usually be found in the website’s masthead or else on a specific ‘Contact Us’ page. The operators of the website should be able to provide information as to whether the page you are looking for actually exists. It might be the case that the page in question has been moved to a new URL, and in this scenario you will be doing the website operator a big favor. They can then carry out a 404 error fix by introducing a domain redirect, which will automatically direct users from the old web page to the current one.

Cause of HTTP 404 Errors

Technically, an Error 404 is a client-side error, implying that it’s your mistake, either because you typed the URL incorrectly or the page has been moved or removed from the website and you should have known.

Another possibility is if a website has moved a page or resource but did so without redirecting the old URL to the new one. When that happens, you’ll receive a 404 error instead of being automatically routed to the new page.

Microsoft IIS web servers sometimes give more specific information about the cause of 404 Not Found errors by suffixing a number after the 404, as in HTTP Error 404.3 – Not Found, which means MIME type restriction.

How to reproduce this issue

In the spring boot rest controller class, remove one of the url in a method. If you access the url from the browser or postman, This warning will be shown in the log.

package com.yawintutor.application;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {

@RequestMapping(value=”/welcome/”, method=RequestMethod.POST)
public String welcomepage() {
return “Welcome to Yawin Tutorn”;
}
}

Output

$ curl -X GET http://localhost:8080/welcome
{“timestamp”:”2020-12-30T15:19:18.265+0000″,”status”:404,”error”:”Not Found”,”message”:”No message available”,”path”:”/welcome”}

HTTP Request Methods Supported in Spring Boot

The following http request methods are supported in spring boot application. The requested HTTP methods are available in the RequestMethod Enum class. Request methods are used in the @RequestMapping annotation.

public enum RequestMethod {
GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE
}

Return a Generic Error Message using @ResponseStatus

The most basic way of returning an error message from a REST API is to use the @ResponseStatus annotation. We can add the error message in the annotation’s reason field. Although we can only return a generic error message, we can specify exception-specific error messages.

Next is an example of a @ControllerAdvice using @ResponseStatus annotations to return exception-specific error messages.

@ControllerAdvicepublicclassApplicationExceptionHandler{
@ResponseStatus(
value = HttpStatus.NOT_FOUND,
reason = “Requested Student Not Found”)
@ExceptionHandler(StudentNotFoundException.class)
publicvoidhandleException(StudentNotFoundExceptione) {
}

@ResponseStatus(
value = HttpStatus.BAD_REQUEST,
reason = “Received Invalid Input Parameters”)
@ExceptionHandler(InputValidationException.class)
publicvoidhandleException(InputValidationExceptione) {
}

@ResponseStatus(
value = HttpStatus.GATEWAY_TIMEOUT,
reason = “Upstream Service Not Responding, Try Again”)
@ExceptionHandler(ServiceUnavailableException.class)
publicvoidhandleException(ServiceUnavailableExceptione) {
}
}Code language:Java(java)

The Exception handler class has three exception handlers, and each of them returns a specific HTTP Response Status . Each response status specifies a reason field with a particular error message.

To view the error message in the response, make sure you have turned on include-messages in the server configuration. To learn more on Spring Boot server configurations, please visit Spring Boot Embedded Tomcat Configuration .

server:error:include-message:alwaysCode language:YAML(yaml)

Next is an example of a response object the REST API returns. Note that the response object has the specified error message.

{
“timestamp”: ““,
“status”: 404,
“error”: “Not Found”,
“message”: “Requested Student Not Found”,
“path”: “/students/Jack”
}Code language:JSON / JSON with Comments(json)

Although we can specify exception-specific error messages, it is still not informative. Therefore in the following sections, we will learn how to return a more specific error message from Spring REST API.

Handle Request Body Not Readable Exception

Now we will see an example of handling HttpMessageNotReadableException and returning a custom error response. The HttpMessageNotReadableException occurs when the request body is missing or is unreadable.

@ExceptionHandler(HttpMessageNotReadableException.class)
publicResponseEntity<>> handleException(
HttpMessageNotReadableExceptione) throwsIOException{

Map errorResponse = new HashMap<>();
errorResponse.put(“message”, e.getLocalizedMessage());
errorResponse.put(“status”, HttpStatus.BAD_REQUEST.toString());

returnnew ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST);
}Code language:Java(java)

Пользовательская обработка сообщений об ошибках для REST API

Handle Media Type Not Supported Exception

Spring throws HttpMediaTypeNotSupportedException, when a POST, PUT, or a PATCH endpoint on the server cannot handle the content-type sent by the client. The REST Controllers on the server specify the content type they can support. When the media type that a client sends doesn’t match, the client gets this exception back.

To demonstrate, next is an example of handling HttpMediaTypeNotSupportedException and returning a custom error response.

@ExceptionHandler(HttpMediaTypeNotSupportedException.class)
publicResponseEntity<>> handleException(
HttpMediaTypeNotSupportedExceptione) {

String provided = e.getContentType().toString();
List supported = e.getSupportedMediaTypes().stream()
.map(MimeType::toString)
.collect(Collectors.toList());

String error = provided + ” is not one of the supported media types (” +
String.join(“, “, supported) + “)”;

Map errorResponse = new HashMap<>();
errorResponse.put(“error”, error);
errorResponse.put(“message”, e.getLocalizedMessage());
errorResponse.put(“status”, HttpStatus.UNSUPPORTED_MEDIA_TYPE.toString());

returnnew ResponseEntity<>(errorResponse, HttpStatus.UNSUPPORTED_MEDIA_TYPE);
}Code language:Java(java)

As seen in the exception handler above, the instance of HttpMediaTypeNotSupportedException provides detailed information about the incorrect media type that we provided and a list of actually supported media types. Thus, we create a custom error message based on the available information.

{
“error”:”text/plain;charset=UTF-8 is not one of the supported media types (
application/octet-stream,
text/plain, application/xml,
text/xml, application/x-www-form-urlencoded,
application/*+xml,
multipart/form-data,
multipart/mixed,
application/json,
application/*+json, */*)”,
“message”:”Content type ‘text/plain;charset=UTF-8’ not supported”,
“status”:”415 UNSUPPORTED_MEDIA_TYPE”
}Code language:JSON / JSON with Comments(json)

The above snippet shows a client’s sample error response when it sends a request with an invalid media type.

Сделайте страницу 404 полезной

Ошибка 404 (страница не найдена) может появиться в любое время. Важно, чтобы пользователь при входе на эту страницу не потерял доверия к сайту. Страницы с ошибкой 404 можно создавать самостоятельно. Например, если у вас сайт на WordPress или вы пользуетесь услугой REG.Site, страницу с ошибкой можно легко создать с помощью плагина 404page.

Вот несколько советов по созданию страницы:

  • дизайн этой страницы должен соответствовать всему ресурсу (цвет, шрифт, иллюстрации),
  • поместите ссылку на главную страницу,
  • добавьте дайджесты последних публикаций на сайте,
  • поместите контакты организации (номер телефона, адрес) и службы поддержки,
  • можно предложить действия для решения проблемы доступа к странице.

страница ошибка 404

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

Если перечисленные способы не помогли исправить ошибку, обратитесь в службу поддержки REG.RU.

Spring ResponseStatusException

Причины ошибки

Причины, по которым HTTP возвращает ответ 404 Not Found:

  • Неверный адрес. К примеру, при ручном наборе пользователь допустил опечатку в URL либо ссылка ведёт на несуществующую страницу.
  • Битая ссылка. Это нерабочий URL, который никуда не ведёт. Данный вариант иногда возникает при внутренней перелинковке. К примеру, раньше страница существовала, а потом её удалили и забыли убрать ссылку.
  • Удалённая страница. Когда пользователь попытается перейти на удалённую с сервера страницу, он также увидит ошибку 404. Ссылка для перехода может сохраниться в браузерных закладках или на сторонних ресурсах.
  • Неправильный редирект на страницу с изменённым адресом. Допустим, в процессе редизайна URL изменили, но оставили без внимания связанные ссылки.
  • Неполадки на сервере. Это самый редкий вариант.

В большинстве ситуаций ошибка 404 отображается, когда не удаётся обнаружить нужную страницу на доступном сервере.

Несуществующая страница на сайте.

Причины отсутствия страницы на сайте бывают разными

How You Might See the 404 Error

Here are some common ways in which you might see the HTTP 404 error displayed:

  • 404 Error
  • 404 Not Found
  • Error 404
  • The requested URL [URL] was not found on this server
  • HTTP 404
  • Error 404 Not Found
  • 404 File or Directory Not Found
  • HTTP 404 Not Found
  • 404 Page Not Found
  • Error 404. The page you’re looking for can’t be found.

These error messages can appear in any browser or any operating system. Most display inside the browser window just as web pages do.

Google.com 404 error

In Internet Explorer, the message The webpage cannot be found usually indicates an HTTP 404 error but a 400 Bad Request error is another possibility. You can check to see which error IE is referring to by checking for either 404 or 400 in the title bar.

404 errors received when opening links via Microsoft Office applications generate a The Internet site reports that the item you requested could not be found (HTTP/1.0 404) message inside the MS Office program.

When Windows Update produces one, it appears as a code 0x80244019 or as the message WU_E_PT_HTTP_STATUS_NOT_FOUND.

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

Например, на исключение MyEntityNotFoundException ответ не поменяется, обработчик такой же, как в первой части:

@ControllerAdvice
public class RestExceptionHandler extends ResponseEntityExceptionHandler {

@ExceptionHandler({MyEntityNotFoundException.class, EntityNotFoundException.class})
protected ResponseEntityhandleEntityNotFoundEx(MyEntityNotFoundException ex, WebRequest request) {
ApiError apiError = new ApiError(“Entity Not Found Exception”, ex.getMessage());
return new ResponseEntity<>(apiError, HttpStatus.NOT_FOUND);
}

}

Но в отличие от 1 части, теперь RestExceptionHandler расширяет ResponseEntityExceptionHandler.  А значит, он наследует различные обработчики исключений, и мы их можем переопределить. Сейчас они все возвращают пустое тело ответа, хотя и корректный код.

Обработка ошибок для ОТДЫХА с пружиной

HttpMessageNotReadableException

Переопределим обработчик, отвечающий за HttpMessageNotReadableException. Это исключение возникает тогда, когда тело запроса, приходящего в метод контроллер, нечитаемое — например, некорректный JSON.

За это исключение отвечает метод handleHttpMessageNotReadable(), его и переопределим:

@Override
protected ResponseEntityhandleHttpMessageNotReadable(HttpMessageNotReadableException ex,
HttpHeaders хедерs, HttpStatus status, WebRequest request) {
ApiError apiError = new ApiError(“Malformed JSON Request”, ex.getMessage());
return new ResponseEntity(apiError, status);
}

Проверим ответ, сделав запрос с некорректным JSON-телом запроса (он пойдет в метод updatePerson() контроллера):

PUT localhost:8080/persons/1
{
11″name”: “alice”
}

Получаем ответ с кодом 400 (Bad Request) и телом:

{
“message”: “Malformed JSON Request”,
“debugMessage”: “JSON parse error: Unexpected character (‘1’ (code 49)): was expecting double-quote to start field name; nested exception is com.fasterxml.jackson.core.JsonParseException: Unexpected character (‘1’ (code 49)): was expecting double-quote to start field namen at [Source: (PushbackInputStream); line: 2, column: 5]”
}

Теперь ответ содержит не только корректный код, но и тело с информативными сообщениями. Если бы мы не переопределяли обработчик, вернулся бы только код 400.

А если бы не расширяли класс ResponseEntityExceptionHandler, все эти обработчики в принципе не были бы задействованы и вернулся бы стандартный ответ из BasicErrorController:

{
“timestamp”: “2021-03-01T16:53:04.197+00:00”,
“status”: 400,
“error”: “Bad Request”,
“message”: “JSON parse error: Unexpected character (‘1’ (code 49)): was expecting double-quote to start field name; nested exception is com.fasterxml.jackson.core.JsonParseException: Unexpected character (‘1’ (code 49)): was expecting double-quote to start field namen at [Source: (PushbackInputStream); line: 2, column: 5]”,
“path”: “/persons/1”
}

Return Error Message Using Custom Error Object

Let’s create a class representing the error message and the status code. We will return an instance of that in case of errors.

Next is the Error class representing the status code and a String message. We use a couple of Lombok annotations that introduce regular getter and setter methods and a constructor using the final fields.

Custom Response Error Class

@Data@RequiredArgsConstructorpublicclassError{
privatefinal HttpStatus httpStatus;
privatefinal String message;
}Code language:Java(java)

Now that we have an error model created, we will use it to return a detailed error message from Controller Advice.

@ExceptionHandler(StudentNotFoundException.class)
publicResponseEntity handleException(StudentNotFoundExceptione) {
Error error = new Error(HttpStatus.NOT_FOUND, e.getLocalizedMessage());
returnnew ResponseEntity<>(error, error.getHttpStatus());
}Code language:Java(java)

The exception handler returns an instance of the Error class populated with the exception message and HTTP Status Code.

Now, we can throw our Not Found Exception with a custom error message.

thrownew StudentNotFoundException(“Student service failed, studentId : ” + studentId);Code language:Java(java)

When the REST API cannot find the requested resource, we get a detailed error as a response.

{
“httpStatus”: “NOT_FOUND”,
“message”: “Student service failed, studentId : Jack”
}Code language:JSON / JSON with Comments(json)

MethodArgumentNotValidException

Как говорилось выше, чтобы выбросилось это исключение, в контроллер должен прийти некорректный Person. В смысле корректный JSON, но условие @Valid чтоб не выполнялось: например, поле name имело бы неверную длину (а она должна быть от 3 до 10, как указано в аннотации @Size).

Попробуем сделать запрос с коротким name:

POST http://localhost:8080/persons

“name”: “al”
}

Получим ответ:

{
“message”: “Method Argument Not Valid”,
“debugMessage”: “Validation failed for argument [0] in public ru.sysout.model.Person ru.sysout.controller.PersonController.createPerson(ru.sysout.model.Person): [Field error in object ‘person’ on field ‘name’: rejected value [al]; codes [Size.person.name,Size.name,Size.java.lang.String,Size]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [person.name,name]; arguments []; default message [name],10,3]; default message [размер должен находиться в диапазоне от 3 до 10]] “,
“errors”: [
“размер должен находиться в диапазоне от 3 до 10”
] }

Тут пошел в ход список ошибок, который мы добавили в ApiError. Мы его заполняем в переопределенном обработчике исключения:

@Override
protected ResponseEntityhandleMethodArgumentNotValid(MethodArgumentNotValidException ex,
HttpHeaders хедерs, HttpStatus status, WebRequest request) {
List errors = ex.getBindingResult()
.getFieldErrors()
.stream()
.map(x -> x.getDefaultMessage())
.collect(Collectors.toList());

ApiError apiError = new ApiError(“Method Argument Not Valid”, ex.getMessage(), errors);
return new ResponseEntity<>(apiError, status);
}

Вообще говоря, стандартный ответ, выдаваемый BasicErrorController, тоже будет содержать этот список ошибок по полям, если в application.properties включить свойство:

server.error.include-binding-errors=always

В этом случае (при отсутствии нашего RestExceptionHandler  с @ControlleAdvice) ответ будет таким:

{
“timestamp”: “2021-03-01T17:15:37.134+00:00”,
“status”: 400,
“error”: “Bad Request”,
“message”: “Validation failed for object=’person’. Error count: 1”,
“errors”: [
{
“codes”: [
“Size.person.name”,
“Size.name”,
“Size.java.lang.String”,
“Size”
],
“arguments”: [
{
“codes”: [
“person.name”,
“name”
],
“arguments”: null,
“defaultMessage”: “name”,
“code”: “name”
},
10,
3
],
“defaultMessage”: “размер должен находиться в диапазоне от 3 до 10”,
“objectName”: “person”,
“field”: “name”,
“rejectedValue”: “al”,
“bindingFailure”: false,
“code”: “Size”
}
],
“path”: “/persons/”
}

Мы просто сократили информацию.

MethodArgumentTypeMismatchException

Полезно знать еще исключение MethodArgumentTypeMismatchException, оно возникает, если тип аргумента неверный. Например, наш метод контроллера получает Person по id:

@GetMapping(value = “/{personId}”)
public Person getPerson(@PathVariable(“personId”) Long personId) throws EntityNotFoundException {
return personRepository.getOne(personId);
}

А мы передаем не целое, а строковое значение id:

GET http://localhost:8080/persons/mn

Тут то и возникает исключение MethodArgumentTypeMismatchException. Давайте его обработаем:

@ExceptionHandler(MethodArgumentTypeMismatchException.class)
protected ResponseEntityhandleMethodArgumentTypeMismatch(MethodArgumentTypeMismatchException ex,HttpStatus status,
WebRequest request) {
ApiError apiError = new ApiError();
apiError.setMessage(String.format(“The parameter ‘%s’ of value ‘%s’ could not be converted to type ‘%s'”,
ex.getName(), ex.getValue(), ex.getRequiredType().getSimpleName()));
apiError.setDebugMessage(ex.getMessage());
return new ResponseEntity<>(apiError, status);
}

Проверим ответ сервера (код ответа будет 400):

{
“message”: “The parameter ‘personId’ of value ‘mn’ could not be converted to type ‘long'”,
“debugMessage”: “Failed to convert value of type ‘java.lang.String’ to required type ‘long’; nested exception is java.lang.NumberFormatException: For input string: “mn””
}

NoHandlerFoundException

Еще одно полезное исключение — NoHandlerFoundException. Оно возникает, если на данный запрос не найдено обработчика.

Например, сделаем запрос:

GET http://localhost:8080/pers

По данному адресу у нас нет контроллера, так что возникнет NoHandlerFoundException.  Добавим обработку исключения:

@Override
protected ResponseEntityhandleNoHandlerFoundException(NoHandlerFoundException ex, HttpHeaders хедерs,
HttpStatus status, WebRequest request) {
return new ResponseEntity(new ApiError(“No Handler Found”, ex.getMessage()), status);
}

Только учтите, для того, чтобы исключение выбрасывалось, надо задать свойства в файле application.properties:

spring.mvc.throw-exception-if-no-handler-found=true
spring.web.resources.add-mappings=false

Проверим ответ сервера (код ответа 404):

{
“message”: “No Handler Found”,
“debugMessage”: “No handler found for GET /pers”
}

Если же не выбрасывать NoHandlerFoundException и не пользоваться нашим обработчиком, то ответ от BasicErrorController довольно непонятный, хотя код  тоже 404:

{
“timestamp”: “2021-03-01T17:35:59.204+00:00”,
“status”: 404,
“error”: “Not Found”,
“message”: “No message available”,
“path”: “/pers”
}

Примеры оформления страниц 404

Designzillas

Мультяшная страница креативной студии привлекает внимание и её хочется досмотреть до конца. Если прокрутить страницу, можно увидеть, как из яйца вылупится дракон. При этом на странице есть ссылки на все основные разделы сайта.

404 страница на сайте Designzillas

Меню на сайте Designzillas есть и на 404 странице

Domenart Studio

Веб-студия «Домен АРТ» использует красочную страницу 404, оформленную в единой стилистике ресурса. Заблудившимся пользователям предлагают попробовать ещё раз ввести адрес или перейти в нужный раздел.

Страница 404 Domenart Studio.

Контакты, поиск, меню — и всё это на 404 странице Domenart Studio

E-co

«Эко Пауэр», дистрибьютор производителя источников питания, демонстрирует короткое замыкание как символ ошибки. Посетителям предлагают перейти на главную.

Ошибка 404 «Эко Пауэр» выглядит как страница входа

Дом со всем

Компания «Дом со всем», занимающаяся бурением скважин, разместила на странице 404 свои контакты и перечень услуг. Со страницы можно перейти в любой раздел сайта или заказать обратный звонок. С таким наполнением посетителю не нужно искать дополнительную информацию где-то ещё.

Страница 404 «Дом со всем».

Компания «Дом со всем» предлагает заказать обратный звонок

Kualo

Страница 404 на веб-хостинге Kualo может заставить пользователя забыть, зачем он сюда пришёл. Увлекательная игра притягивает внимание. В конце игры посетителю предлагают посмотреть сайт хостинга.

Cтраница 404 Kualo

На странице Kualo можно просто поиграть и заработать скидки

Рано или поздно с ошибкой 404 сталкивается большинство сайтов. При регулярной проверке можно своевременно исправить неработающие ссылки, чтобы в ответ пользователи получали код 200 OK. Но для крупного ресурса лучше настроить оригинальную страницу, которая будет отображаться при появлении ошибки Not Found и подскажет посетителям, что делать дальше.

3. JSR 303 Validation error

3.1 For Spring @valid validation errors, it will throw handleMethodArgumentNotValid

CustomGlobalExceptionHandler.java
package com.mkyong.error;

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolationException;
import java.io.IOException;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@ControllerAdvice
public class CustomGlobalExceptionHandler extends ResponseEntityExceptionHandler {

//…

// @Validate For Validating Path Variables and Request Parameters
@ExceptionHandler(ConstraintViolationException.class)
public void constraintViolationException(HttpServletResponse response) throws IOException {
response.sendError(HttpStatus.BAD_REQUEST.value());
}

// error handle for @Valid
@Override
protected ResponseEntityhandleMethodArgumentNotValid(MethodArgumentNotValidException ex,
HttpHeaders хедерs,
HttpStatus status, WebRequest request) {

Map body = new LinkedHashMap<>();
body.put(“timestamp”, new Date());
body.put(“status”, status.value());

//Get all fields errors
List errors = ex.getBindingResult()
.getFieldErrors()
.stream()
.map(x -> x.getDefaultMessage())
.collect(Collectors.toList());

body.put(“errors”, errors);

return new ResponseEntity<>(body, хедерs, status);

}

}

Источники

  • https://sysout.ru/spring-boot-rest-api-obrabotka-isklyuchenij/
  • https://www.unisender.com/ru/glossary/chto-oznachaet-oshibka-404-na-sajte-i-chto-s-nej-delat/
  • https://mkyong.com/spring-boot/spring-rest-error-handling-example/
  • https://help.reg.ru/hc/ru/articles/4408054456337-%D0%9E%D1%88%D0%B8%D0%B1%D0%BA%D0%B0-404
  • https://www.ionos.com/digitalguide/websites/website-creation/what-does-the-404-not-found-error-mean/
  • https://www.lifewire.com/404-not-found-error-explained-2622936
  • https://www.yawintutor.com/warn-2448-request-method-get-not-supported/
  • https://www.amitph.com/spring-rest-api-custom-error-messages/
[свернуть]
Решите Вашу проблему!


×
Adblock
detector