Как преобразовать ошибку ConstraintViolationException 500 в неверный запрос 400? - PullRequest
1 голос
/ 29 октября 2019

Если я использую ограничение типа @NotNull, а затем в контроллере

public User createUser(
            @Validated
            @RequestBody User user) {}

Это дает действительно хорошее 400 исключение с деталями.

Но если я использую свой собственный валидатор, подобный этому:

public User createUser(
            @UserConstraint
            @RequestBody User user) {}

Он выдает ошибку 500, например, так:

javax.validation.ConstraintViolationException: createUser.user: Error with field: 'test35'
    at org.springframework.validation.beanvalidation.MethodValidationInterceptor.invoke(MethodValidationInterceptor.java:117) ~[spring-context-5.1.10.RELEASE.jar:5.1.10.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.10.RELEASE.jar:5.1.10.RELEASE]
    at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:69) ~[spring-security-core-5.1.6.RELEASE.jar:5.1.6.RELEASE]

Есть ли способ получитьхорошее сообщение 400 к ответу?

В идеале сообщение 400 должно совпадать с валидацией Spring JSON

{
    "timestamp": "2019-10-30T02:33:15.489+0000",
    "status": 400,
    "error": "Bad Request",
    "errors": [
        {
            "codes": [
                "Size.user.lastName",
                "Size.lastName",
                "Size.java.lang.String",
                "Size"
            ],
            "arguments": [
                {
                    "codes": [
                        "user.lastName",
                        "lastName"
                    ],
                    "arguments": null,
                    "defaultMessage": "lastName",
                    "code": "lastName"
                },
                25,
                1
            ],
            "defaultMessage": "size must be between 1 and 25",
            "objectName": "user",
            "field": "lastName",
            "rejectedValue": "",
            "bindingFailure": false,
            "code": "Size"
        }
    ],
    "message": "Validation failed for object='user'. Error count: 1",
    "path": "/api/v1/users"
}

Ответы [ 2 ]

2 голосов
/ 29 октября 2019

Да, вы можете создать custom error handler, тогда вы также можете добавить что угодно в свой ответ и статус. Это простой способ изменить статус:

1.- Простой способ изменить status, когда выброшено ConstraintViolationException.

import javax.validation.ConstraintViolationException;

@ControllerAdvice
public class ChannelErrorHandler {

    @ExceptionHandler(ConstraintViolationException.class)
    public void handleConstraintViolationException(ConstraintViolationException exception,
            ServletWebRequest webRequest) throws IOException {
        webRequest.getResponse().sendError(HttpStatus.NOT_FOUND.value(), exception.getMessage());
    }
}    

2.- Пользовательский способ поставитьответ при ConstraintViolationException.

@ControllerAdvice
public class CustomErrorHandler {

    @ExceptionHandler(ConstraintViolationException.class)
    public ResponseEntity<CustomError> handleConstraintViolationException(ConstraintViolationException exception) {
        CustomError customError = new CustomError();
        customError.setStatus(HttpStatus.BAD_REQUEST);
        customError.setMessage(exception.getMessage());
        customError.addConstraintErrors(exception.getConstraintViolations());
        return ResponseEntity.badRequest().body(customError);
    }
}   
0 голосов
/ 29 октября 2019

Проще говоря, определите метод, обозначенный @ExceptionHandler, в классе, обозначенном @ControllerAdvice:

@ControllerAdvice
public class YourControllerAdvice {

    @ResponseBody
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(ConstraintViolationException.class)
    public void handleConstraintViolationException() {
    // Intentionally left blank
    }
}

Классы, обозначенные @ControllerAdvice, используются для обработки исключений на уровне контроллера.

...