Comments 11
А как на счет кейса, когда мне нужно использовать ResponseEntity<> не только в случае ошибки. Например: при успешном создании объекта нам необходимо вернуть не 200 OK, а 201 CREATED. Что тогда? Придется его явно прописывать опять?
Предполагается, что для создания/изменения/удаления и просмотра вы используете разные эндпоинты
@ResponseStatus(HttpStatus.CREATED)
В случае ошибки при создании, например при уже существующем объекте, все равно придется заново прописывать явные исключения. В итоге вместо использования ResponseEntity, получаем гору классов-исключений.
"Гора" исключений на самом деле не гора, а структура для ответа ошибок. Ответы в одном месте, ошибки в другом. ResponseEntity
- это конечный объект, кастомный exception - это то, что содержит объект запроса (например) и далее обрабатывается по своей логике. Постоянно наблюдаю в концепции ResponseEntity
разные форматы ошибок (как одна из болей) для одной одинаковой ситуации в разных эндпоинтах. Ну и ломание дженериков вообще попахивает не очень))) В целом исчерпывающая статья https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc
В ControllerAdvice тоже можно избавиться от ResponseEntity (если хочется, конечно), применив аннотации ResponseBody и ResponseStatus. Пример:
@ResponseStatus(HttpStatus.NOT_FOUND)
@ExceptionHandler(ResourceNotFoundException.class)
@ResponseBody
public AppError handle(ResourceNotFoundException ex) {
...
}
Все конечно замечательно, но зачем?
Рубрика "вредные советы". Сами создали проблему, сами героически пытаетесь ее решить непонятным образом.
Что здесь происходит? Вместо строгого типа Product, мы ставим ResponseEntity<?>, где под ? понимается любой Java объект.
Почему Вы сами не поставили параметр типа ответа а вместо него "?" и жалуетесь что не понятен тип?
public Product findById(Long id) {
return productsRepository.findById(id).orElseThrow(
() -> new ResourceNotFoundException("Product with id " + id + " not found"));
}
Вы когда логику вынесли в сервисы и радостно выбрасываете исключение, конечно же не подумали что если ресурс не найден то это не ошибка. Это вполне ожидаемое поведение. По нормальному нужно возвращать из метода Optional<Product> , и уже пользователь этого метода должен решать что делать если ресурса нет. А он может не просто бросить исключение а например:
- использовать значение по умолчанию
- попробовать выполнить альтернативный сценарий
В вашем сценарии все прибито гвоздями.
{
"statusCode": 404,
"message": "Product with id 299 nor found"
}
Т.е. фронт отправил запрос для получения Product по id=299 и когда ему приходит 404, он ну никак не сможет догадается о том что когда пошел за ресурсом Product по id=299 и получил статус код 404 - что ресурс не найден, обязательно нужно сообщение: "Product with id 299 nor found"?
Дополню ещё, что может захотеться успешные ответы обернуть во что-нибудь.
Для этого пригодится ResponseBodyAdvice, но он срабатывает и после обработчика ошибок, что надо будет учесть при реализации.
Если хотите добавить месседж эксепшена в респонс то в буте уже всё есть
server.include-message=always
Просто выбрасывайте их наверх
А ResponseEntity можно юзать для настройки респонса да и он банально удобен. Не вижу смысла от него избавляться
Так вот откуда имя класса GlobalExceptionHandler в моём проекте!
Изучаем ResponseEntity<?> и избавляемся от него в контроллерах Spring