Подтверждение даты в прошлом

#java #validation

Вопрос:

Мне нужно подтвердить, что дата рождения осталась в прошлом.

У меня есть следующая форма:

 @Data
public class PersonForm {
    static final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd.MM.yyyy");
    private Long id;
    @NotNull(message = "Name should not be null")
    private String name;
    @NotNull(message = "Date should not be null")
    @Pattern(regexp = "^(0[1-9]|[12][0-9]|3[01])[.](0[1-9]|1[012])[.]((19|2[0-9])[0-9]{2})$", message = "Date format: dd.mm.yyyy")
    private String date;
    @Valid
    private List<CarForm> carForms;
 

Как вы можете видеть, здесь я проверяю, что строка для даты находится в правильном формате.
У меня есть следующая сущность:

 @Data
@Entity
@Table(name = "person")
public class Person {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;
    private String name;
    @Past(message = "Birthdate should be in the past")
    private Date birthdate;
    @OneToMany(cascade = CascadeType.ALL)
    @JoinTable(name = "persons_cars",
    joinColumns = @JoinColumn(name = "person_id"),
    inverseJoinColumns = @JoinColumn(name = "car_id"))
    private List<Car> cars;
}
 

и служебный метод, который преобразует одно в другое:

 public class PersonFormConverter {
    static final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd.MM.yyyy");
    public static Person toPerson(PersonForm personForm) throws ParseException {
        Person person = new Person();
        person.setId(personForm.getId());
        person.setName(personForm.getName());
        person.setBirthdate(simpleDateFormat.parse(personForm.getDate()));
        if(personForm.getCarForms()!=null){
            person.setCars(personForm.getCarForms().stream().map(CarFormConverter::toCar).collect(Collectors.toList()));
        }
        return person;
    }
 

Как вы можете видеть в моем лице класса сущностей, у меня есть ограничение проверки для даты поля, но оно неправильно работает в моем контроллере:

 @PostMapping("/person")
public ResponseEntity<Object> createNew(@RequestBody @Valid PersonForm personForm, BindingResult bindingResult) throws ParseException {
    if(bindingResult.hasErrors()){
        return new ResponseEntity<>(bindingResult.getFieldError().getDefaultMessage(), HttpStatus.BAD_REQUEST);
    }
    return new ResponseEntity<>(personService.createNewPerson(PersonFormConverter.toPerson(personForm)), HttpStatus.OK);
}
 

Если дата ввода в прошлом, сервер возвращает код ошибки 500, а не 400. Я могу понять, почему это происходит, но я не могу понять, как правильно подтвердить, что мое свидание в прошлом. Не могли бы вы сказать мне, каков правильный вариант? Я считаю, что это должно быть простое решение, и я, скорее всего, иду в неправильном направлении.

ИЗМЕНИТЬ: Здесь я добавил свой метод создания из своего класса обслуживания:

 public Person createNewPerson(@Valid Person person) {
    return personRepository.save(person);
}
 

К сожалению, аннотации здесь не помогают

Комментарии:

1. Проверка сущности должна выполняться при вызове personService.createNewPerson(PersonFormConverter.toPerson(personForm)) , и вы, вероятно, получите исключение, если проверка завершится неудачно. Таким образом, вам нужно будет поймать это исключение.

2. Я отредактировал свой пост. Это то, о чем ты говорил?

3. В принципе, да. Попробуйте использовать блок try-catch в своем контроллере, чтобы перехватывать исключения проверки, которые выдает репозиторий (и, следовательно, ваша служба).

4. Это сработало. Если вы добавите свой ответ, я приму его. Спасибо!

Ответ №1:

Ваша проблема здесь:

 return new ResponseEntity<>(personService.createNewPerson(PersonFormConverter.toPerson(personForm)), HttpStatus.OK);
 

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

Чтобы вместо этого вернуть 400, вам нужно обернуть этот вызов в try-catch:

 try {
  return new ResponseEntity<>(personService.createNewPerson(PersonFormConverter.toPerson(personForm)), HttpStatus.OK);
} catch (TheValidationException e) { //don't rememer the exact name of the exception atm
  //if you can, extract information on what is invalid and tell the caller
  return new ResponseEntity<>("Invalid data provided", HttpStatus.BAD_REQUEST);
}