LINUX.ORG.RU

SpringMVC - валидация кастомных едиторов. Валидация на уровне raw input

 , ,


0

1

Раньше никогда не пользовался кастомными Editors, а теперь вдруг припекло.

Можно посмотреть, что имею в виду, на примере стандартного класса CustomDateEditior

Регаю их в контролере вот так:

    @InitBinder
    protected void initBinder(WebDataBinder binder) {
        DateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy");
        binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
        binder.registerCustomEditor(MyTime.class, new CustomMyTimeEditor(true));
    }

Так вот если в дату или время вписать чушь (asdasdasd), то вместо нормальной валидации вылетает binding error - type mismatch. Ну понятно, он пытается распасить дату, у него вылетает экзепшен, и приплыли.

(Причем по привычке он пишет просто Bad Request, и чтобы распечатать ошибку на странице - нужно провести небольшую работу)

Я подсмотрел, какие коды он ждёт в бандле с мессаджами ошибок, и добавил эти коды, например:

typeMismatch.formDto.dateFrom=В этом поле должна быть дата, а не фигня всякая

К сожалению, он всё так же просто кидает binding exception, и сообщение не юзает.

При этом если не произойдет binding exception и едитор отдаст нормальный объект, все остальные валидаторы (работающие уже на уровне объекта) работают ОК.

Не могли бы вы подсказать, как правильно прописать валидацию в custom property editor?

Возможно можно как-то отвалидировать строку еще до попадания её в едитор? Чтобы отвалидировать «строку как строку», raw input, - всякими регэкспами, например.

★★★★☆

Ответ на: комментарий от sad_but_true1

Validator в метод validate принимает на вход Object нужного типа:

validate(Object target, Errors errors)

А у меня этот объект еще не создан - не может быть создан, потому что PropertyEditor который его создаёт - бросает ошибку.

Эту проблему нужно отловить еще до того, как начнут работать валидаторы.

Наверное, можно было бы зарегистрировать formatter/converter вместо CustomPropertyEditor, но у меня уже есть куча этих сраных едиторов, и их надо как-то заставить заработать

stevejobs ★★★★☆
() автор топика
Ответ на: комментарий от sad_but_true1

В смысле строку?

Объясню подробнее

Ты регаешь едитор, и он умеет превращать текст с формы в объект, а объект в текст формы. Совершенно автоматически. Если он не может распарсить объект, то бросает экзепшен.

Т.е. по сути форматтер-конвертер, но завёрнутый внуторь одного класса и подсоединяющийся на ините контроллера.

Мну кажется, что это чуть ли не первоочередная фича. Не будешь же ты постоянно руками парсить тестовое поле «ФИО», если можно написать класс, который будет разбирать это самое фио. И во всех дто'шках потом можно хранить поле с типом FIO, а не String.

Проблема в том, что даже те едиторы, которые в спринге искаропки (н-р CustomDateEditor), бросают тупые экзепшены, когда не могут отконвертить строку в объект. Т.е. скопипастать правильного коду неоткуда.

stevejobs ★★★★☆
() автор топика
Последнее исправление: stevejobs (всего исправлений: 1)
Ответ на: комментарий от sad_but_true1

Я ДИБИЛ,

как и предполагалось

ошибка вылезает потмоу, что проворонил, что в неправильном месте написан binding result

вот так неправильно:

@RequestMapping(value = "/api/{id}/edit", method = RequestMethod.GET)
public String edit(@PathVariable Long id, @ModelAttribute("formEditDto") @Valid FormEditDto dto, TimeZone timezone, Map<String, Object> map, BindingResult bindingResult) {
...
}

а вот так правильно:

@RequestMapping(value = "/api/{id}/edit", method = RequestMethod.GET)
public String edit(@PathVariable Long id, @ModelAttribute("formEditDto") @Valid FormEditDto dto, BindingResult bindingResult, TimeZone timezone, Map<String, Object> map) {
...
}

binding result должен идти после валидируемого поля. В моем случае валидируется fromDto, а bindingResult у меня идёт после map, и это всё ломает.

непонятно, почему тогда стандартные валидаторы работали ОК. Но в общем, это не так важно уже.

закрываю тему

stevejobs ★★★★☆
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.