【问题标题】:Validation with an EJB service call, possible with JSF validator or JSR303 bean validation?使用 EJB 服务调用进行验证,是否可以使用 JSF 验证器或 JSR303 bean 验证?
【发布时间】:2013-12-07 09:40:27
【问题描述】:

我想使用选择来验证我的用户名。如果用户名已经 存在于数据库中,验证失败。

我发现了一些像这样的 primefaces 注释:

@Size(min=2,max=5)  
private String name; 

我没有找到类似这样的注释解决方案:

try {
    dao.findUserByUserName(userName);

    message = new FacesMessage ("Invalid username!", "Username Validation Error");
    message.setDetail("Username already exists!");
    message.setSeverity(FacesMessage.SEVERITY_ERROR);

    throw new ValidatorException(message);
} catch (NoSuchUserException e) {}

我必须使用自定义验证器还是有注释?

【问题讨论】:

    标签: validation jsf-2 ejb bean-validation


    【解决方案1】:

    我必须使用自定义验证器还是有注释?

    这两种方式都可以。

    在自定义 JSF 验证器的情况下,您只需要了解 EJB 不能注入到 @FacesValidator 中。您基本上有 3 个选择:

    1. manually obtain it from JNDI
    2. or, make it a @ManagedBean instead of @FacesValidator
    3. or, install OmniFaces which adds transparent support for @EJB and @Inject in @FacesValidator

    最终,假设您采用@ManagedBean 方法,您最终会是这样:

    @ManagedBean
    @RequestScoped
    public class UsernameValidator implements Validator {
    
        @EJB
        private UserService service;
    
        public void validate(FacesContext context, UIComponent component, Object submittedValue) throws ValidatorException {
            if (submittedValue == null) {
                return; // Let required="true" handle.
            }
    
            String username = (String) submittedValue;
    
            if (service.exist(username) {
                throw new ValidatorException(new FacesMessage("Username already in use, choose another"));
            }
        }
    
    }
    

    具体用法如下:

    <h:inputText ... validator="#{usernameValidator}" />
    

    在 JSR303 bean 验证的情况下,您需要创建 custom @Constraint annotationcustom ConstraintValidator。您需要确保您至少使用 CDI 1.1,否则您无法在 ConstraintValidator 中注入 EJB,您需要通过 initialize() 方法从 JNDI 手动获取它。您无法通过将其设为托管 bean 来解决它,甚至 OmniFaces 对此也没有任何魔力。

    例如

    @Constraint(validatedBy = UsernameValidator.class)
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE})
    public @interface Username {
        String message() default "Username already in use, choose another";
        Class<?>[] groups() default {};
        Class<? extends Payload>[] payload() default {};
    }
    

    public class UsernameValidator implements ConstraintValidator<Username, String> {
    
        @EJB
        private UserService service;
    
        @Override
        public void initialize(Username constraintAnnotation) {
            // If not on CDI 1.1 yet, then you need to manually grab EJB from JNDI here.
        }
    
        Override
        public boolean isValid(String username, ConstraintValidatorContext context) {
            return !service.exist(username);
        }
    
    }
    

    在模型中

    @Username
    private String username;
    

    【讨论】:

    • 嗯。我将验证类的注释更改为 '@Named' 和 '@SessionScoped' 并将 validator="#{usernameValidator}" 插入到我的 inputText 并得到以下信息: javax.el.E​​LException: Identity 'usernameValidator' does not reference a MethodExpression 实例
    • 以前没见过这个。如果你改用&lt;f:validator binding="#{usernameValidator}"/&gt; 会怎样?
    • 如果我这样做,他说 Parent 不是 EditableValueHolder 的实例:javax.faces.component.html.HtmlPanelGrid。我的表单在一个面板网格内,它应该保持这样 ^^
    • 您应该将其嵌套在EditableValueHolder 组件中,例如&lt;h:inputText&gt;。将其嵌套在与您最初使用 validator 属性的位置完全相同的标签内。
    • 非常感谢您的反馈。
    猜你喜欢
    • 1970-01-01
    • 2016-09-09
    • 2011-11-11
    • 2011-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-13
    • 2013-01-23
    相关资源
    最近更新 更多