Skip to Content
Жора К

3 мин чтения


Почему Spring Boot возвращает 500 Internal Eror статус вместо 404 после обновления

Разбираеся почему после обновления Spring на версию 6.1+ в java приложении возникает ошибка 500 Internal Error вместо ожидаемого 404 Not Found для несуществующих API вызово и как это исправить.


Введение

В этой заметке рассмотрим почему возникает ошибка 500 Internal Error вместо ожидаемого 404 Not Found после обновления Spring или Spring Boot в java приложении и как это исправить. Данная статья касается ошибок при обновлении на версии Spring 6.1+ и Spring Boot 3.2+ с более ранних версий.

Что могло пойти не так?

После обновления версии Spring или Spring Boot в вашем приложении, вы можете заметить, что при запросе несуществующего ресурса возвращается 500 Internal Error вместо ожидаемого 404 статуса как это было ранее:

{
  "timestamp": "2024-10-22T12:34:56.789Z",
  "status": 404,
  "error": "Not Found",
  "path": "/adabracadabra"
}

В Spring 6.1+ и Spring Boot 3.2+ было внесено изменение в поведение обработки исключения NoResourceFoundException в ResourceHttpRequestHandler классе. Теперь это исключение обрабатывается не spring-ом, а обработчиком ошибок, который задает разработчик.

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

@ExceptionHandler(Exception.class)
public ResponseEntity handleAll(Exception ex, WebRequest request) {
    log.error(ex.getMessage(), ex);
    return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(ex.getMessage());
}

Когда в приложении происходит любое исключение, этот метод перехватывает его, логирует и возвращает ответ с кодом 500 и сообщением об ошибке. В новой версии Spring NoResourceFoundException тоже попадает в этот обработчик, и вместо стандартного 404 возвращается 500 статус.

Как исправить?

Для исправления данной проблемы, необходимо добавить обработчик исключения NoResourceFoundException в контроллере и вернуть 404 статус или создать отдельный обратчик исключения NoResourceFoundException:

import lombok.Builder;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.resource.NoResourceFoundException;
 
import java.time.Instant;
 
@Slf4j
@ControllerAdvice
public class CustomExceptionHandler {
    // ...
 
    @ExceptionHandler(NoResourceFoundException.class)
    public ResponseEntity<CustomErrorResource> handleNoResourceFoundException(NoResourceFoundException exception) {
        log.error("Resource not found", exception);
        CustomErrorResource resource = CustomErrorResource.builder()
                .timestamp(Instant.now().toString())
                .status(exception.getStatusCode().value())
                .error(exception.getMessage())
                .path(exception.getResourcePath())
                .build();
        return ResponseEntity
                .status(exception.getStatusCode())
                .body(resource);
    }
 
    @Data
    @Builder
    public static class CustomErrorResource {
        private String timestamp;
        private int status;
        private String error;
        private String path;
    }
 
    // ...
}
 

Теперь статус ошибки и тело ответа приобретает прежний вид.
PROFIT!

Полезные ссылки