Возвращать код ответа как 400, если проверка @notnull не удалась - PullRequest
1 голос
/ 18 марта 2020

Я использую javax и реализацию Hibernate для проверки полезной нагрузки моего запроса.

версия - org.hibernate: hibernate-validator: 5.4.1.final

Пример Pojo :

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.io.Serializable;

    public class Customer implements Serializable{

        @NotNull(message="name is null")
        @Size(min = 1)
        public String name;
        @NotNull(message="country is null")
        @Size(min = 1)
        public String country;
    }

Пример контроллера:

    @RequestMapping(value = {"/customer"}, method = RequestMethod.POST)
    @ResponseBody
    public Customer doAdd(@RequestBody @Valid Customer inData){
        //some logic
return outData
    }

Пример ввода json:

{
"country":"canada"
}

Исключение консоли:

org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument at index 0 in method: ........ model.request.Customer,java.lang.String,java.lang.String,javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse), with 1 error(s): [Field error in object 'Customer' on field 'name': rejected value [null]; codes [NotNull.Customer.name,NotNull.name,NotNull.java.lang.String,NotNull]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [Customer.name,name]; arguments []; default message [name]]; default message [name is null]]

Здесь, когда customer.name имеет значение NULL, я получаю код ответа как 422 (необработанный объект). Но я хочу вернуть 400 (плохой запрос). Как я могу переопределить код ответа здесь? Буду признателен за любую ссылку на документ.

примечание - я не хочу делать эту проверку на стороне контроллера, где я могу проверить и отправить код ответа соответствующим образом. Как этот - Как вернуть 400 http код состояния с @NotNull?

Обновление - проблема была решена -------

Для меня проблема решена. Спасибо всем за ваш ответ.

Позвольте мне объяснить, что вызвало это,

HttpRequest ----> @Valid on RequestBody ----> Javax validation on Request object-----> If any of the validation fails, **MethodArgumentNotValidException** exception is thrown.

Разработчик обязан перехватить это исключение и выдать соответствующий http-код ответа. В моем случае обработчик исключений уже был там, и он перехватывал это MethodArgumentNotValidException и возвращал HttpStatus.UNPROCESSABLE_ENTITY. Вот почему я видел код ошибки 422.

Теперь я изменил обработчик исключений, как показано ниже,

@ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<ErrorResource>
    handleMethodArgumentNotValidException(MethodArgumentNotValidException exception, HttpServletRequest request) {

        List<FieldErrorResource> fieldErrorResources = new ArrayList<>();
        BindingResult bindingResult = exception.getBindingResult();
        for (FieldError constraintViolation : bindingResult.getFieldErrors()) {
            fieldErrorResources.add(FieldErrorResource.builder()
                    .field(constraintViolation.getField())
                    .resource(request.getContextPath())
                    .message(constraintViolation.getDefaultMessage()).build());
        }

        return responseEntityFor(HttpStatus.BAD_REQUEST,
                "The content you've sent contains " + bindingResult.getErrorCount() + " validation errors.", fieldErrorResources);
    }

Ответы [ 2 ]

0 голосов
/ 18 марта 2020

Вы можете использовать RestControllerAdvice для того же

@RestControllerAdvice
public class ExceptionRestControllerAdvice {

    @ExceptionHandler({ConstraintViolationException.class})
    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    public ExceptionResponseMessage handleInvalidParameterException(RuntimeException ex) {

        return sendResponse(HttpStatus.BAD_REQUEST, ex);
    }

    private ExceptionResponseMessage sendResponse(HttpStatus status, RuntimeException ex) {

        return new ExceptionResponseMessage(Instant.now(), status.value(), status.getReasonPhrase(),
                ex.getClass().toString(), ex.getMessage());
    }
}

public class ExceptionResponseMessage {

    private Instant time;
    private int status;
    private String error;
    private String exception;
    private String message;

    // setter and getter and constructor

0 голосов
/ 18 марта 2020

Вы должны установить BindingResult сразу после вашего Customer. Нравится:

@RequestMapping(value = {"/customer"}, method = RequestMethod.POST)
@ResponseBody
public Customer doAdd(@RequestBody @Valid Customer inData, BindingResult bindingResult){
    //some logic
    return outData
}
...