#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);
}