JSR303: Попытка настроить нарушение ограничения для связывания с подпутем в валидаторе ограничения отношений на уровне класса - PullRequest
6 голосов
/ 08 февраля 2011

Я использую JSR303 и создал ограничение на уровне класса, которое сравнивает пароль и его подтверждение в форме, которую я назову здесь ограничением @SameAs. В идеале я хотел бы связать ограничение с намеченной целью (verifyPassword), но очевидно, что включающий bean-компонент недоступен для извлечения реквизита пароля. - следовательно, ограничение уровня класса.

Я с интересом прочитал другие публикации, демонстрирующие, как использовать ограничения на уровне класса для проверки отношений, но не могу найти ничего, объясняющего, как можно настроить нарушение ограничения, чтобы связать его с подпутем, в данном случае одним из два поля в отношениях.

У меня следующий вопрос: как бы я связал сообщение о нарушении ограничения с полем «verifyPassword» вместо объекта верхнего уровня? Я пытался использовать контекстный параметр javax.Validator.validate (target, context), но добавление узла в валидаторе для @SameAs вызывает исключение для следующего ограничения в каскаде (при попытке извлечь свойство verifyPassword -> orderNumber вместо order -> orderNumber) в результате.

На данный момент я прибег к уродливому кладжу, создав дополнительное свойство, в котором хранится сообщение об ограничении, которое извлекается для использования рядом с полем ввода verifyPassword на веб-слое.

Конечно, я что-то здесь упускаю .... см. Пример ниже

Спасибо за любые комментарии

Пример

@Constraint( validatedBy = { SamePwdAsValidator.class})
public interface SamePwdAs {//...
}

//Using passwords in an order doesn't make sense - only for demo purpose
@SamePwdAs( message = "Password and confirmation must match" ...)
public class Order {

    @NotNull
    @Size(....)
    String pwd;

    //where I would really like to use @SameAs, and associate a violation 
    String pwdConfirm;

    @NotNull (...)
    @Pattern (....)
    String orderNumber;

    //...getters/setters
}

public class SamePwdAsValidator implements javax.validation.Validator {
//...
  public boolean isValid( Object target, ValidationContext ctx) {
   String tgt = target.getPwd(), other = target.getPwdConfirm()
   boolean isValid = tgt.equals( other);

   if ( !isValid) {
      //try to configure the context subpath for pwdConfirm to associate this constraint violation with: I tried 
      //ctx.addNode( 'pwdConfirm').addConstraintViolation() which doesn't work, as the next validator will
      //bump into trying to extract Order.pwdConfirm.orderNumber and throw a NoPropertyFoundException or the like
   }

   return isValid;
}

1 Ответ

5 голосов
/ 14 июня 2011

Я собираюсь дать 2 ответа.

Ответ 1 , который пытается ответить на ваш вопрос:

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

public static final void recreateConstraintViolation(ConstraintValidatorContext constraintValidatorContext, String errorCode, String fieldName) {
        constraintValidatorContext.disableDefaultConstraintViolation();
        constraintValidatorContext.buildConstraintViolationWithTemplate(errorCode).
        addNode(fieldName).addConstraintViolation();

}

А затем в вашем валидаторе, где вы сравниваете два пароля:

if ( !isValid) {
    for (String fieldName : fieldNames) {
        CustomConstraintUtils.recreateConstraintViolation(constraintValidatorContext, "password.password2.mismatch", fieldName);
    }
    return false;
}

Ответ 2

Я бы предложил вам использоватьструктура безопасности, такая как Spring Security, для обеспечения соответствия паролей, так как я предполагаю, что ваш сценарий использования имеет дело с входом пользователя в систему.

...