Я использую Spring для ввода и проверки формы. Команда контроллера формы содержит модель, которая редактируется. Некоторые атрибуты модели являются настраиваемым. Например, номер социального страхования человека является настраиваемым типом SSN.
public class Person {
public String getName() {...}
public void setName(String name) {...}
public SSN getSocialSecurtyNumber() {...}
public void setSocialSecurtyNumber(SSN ssn) {...}
}
и перенос лица в команду редактирования формы Spring:
public class EditPersonCommand {
public Person getPerson() {...}
public void setPerson(Person person) {...}
}
Так как Spring не знает, как преобразовать текст в SSN, я регистрирую редактор клиента с помощью связующего устройства формы:
public class EditPersonController extends SimpleFormController {
protected void initBinder(HttpServletRequest req, ServletRequestDataBinder binder) {
super.initBinder(req, binder);
binder.registerCustomEditor(SSN.class, "person.ssn", new SsnEditor());
}
}
и SsnEditor - это обычная java.beans.PropertyEditor, которая может преобразовывать текст в объект SSN:
public class SsnEditor extends PropertyEditorSupport {
public String getAsText() {...} // converts SSN to text
public void setAsText(String str) {
// converts text to SSN
// throws IllegalArgumentException for invalid text
}
}
Если setAsText обнаруживает недопустимый текст и не может быть преобразован в SSN, он выдает IllegalArgumentException (за PropertyEditor setAsText спецификацию). Проблема, с которой я сталкиваюсь, заключается в том, что преобразование текста в объект (через PropertyEditor.setAsText()) имеет место до, вызывающий мой Spring валидатор. Когда setAsText throws IllegalArgumentException, Spring просто отображает общее сообщение об ошибке, определенное в errors.properties. То, что я хочу, является конкретным сообщением об ошибке, которое зависит от точной причины, по которой введенный SSN недействителен. PropertyEditor.setAsText() будет определять причину. Я попытался встроить текст причины ошибки в текст IllegalArgumentException, но Spring просто рассматривает его как общую ошибку.
Есть ли решение? Повторяю то, что я хочу, это конкретное сообщение об ошибке, сгенерированное PropertyEditor для отображения сообщения об ошибке в форме Spring. Единственной альтернативой, о которой я могу думать, является сохранение SSN в виде текста в команде и выполнение проверки в валидаторе. Преобразование текста в объект SSN будет иметь вид onSubmit. Это менее желательно, так как моя форма (и модель) имеет много свойств, и я не хочу создавать и поддерживать команду, которая имеет атрибут каждой модели как текстовое поле.
Вышеприведенный пример - мой фактический код не является Person/SSN, поэтому нет необходимости отвечать "почему бы не хранить SSN как текст..."