在bean验证消息中插入特定于验证的参数

时间:2011-01-04 17:22:01

标签: java java-ee bean-validation

我有一个自定义bean验证器,用于检查实体上的给定字段是否对某些条件是唯一的。如果验证失败,则消息应包括已存在实体的字段(例如ID)。例如,消息应该是:

"Product 42 already has such a value defined, choose a unique value."

这可以使用bean验证吗?

AFAICS,消息格式可能包含参数,例如:

"Length must be between {min} and {max}."

但是这只能引用验证注释的“静态”属性,在这种情况下:

@Size(min=1, max=16)
private String name;

在我的情况下,该值仅在我的自定义验证器的isValid内知道。

2 个答案:

答案 0 :(得分:2)

你是对的!并且对于你想要的东西!,你可以在isValid()方法中构建约束违规消息。为此,约束Annotation应该特定于应用它的特定类,它应该是类级验证约束。在验证失败之前返回false之前的isValid里面你可以创建包含类实例值的消息。例如:

@check class Test{ int id; @validations...on fields}.

public boolean isValid(Test value, ConstraintValidatorContext context) 
{
// your check logic
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate("It should be different for(custom message) .."+ value.id).addConstraintViolation();
return false; // based on constraint filure.

}

但我认为你想用Field级别的注释做到这一点!我不相信期待你的结果。

答案 1 :(得分:0)

这不是最好的解决方案,但我们最终做的是在我们的顶级异常处理代码中添加如下内容:

String getConstraintViolationMessages(ConstraintViolationException e) {
    StringBuilder sb = new StringBuilder();
    for (ConstraintViolation<?> violation : e.getConstraintViolations()) {
        sb.append(getMessage(violation));
        sb.append("\n");
    }
    sb.setLength(sb.length() - 1);
    return sb.toString();
}

String getMessage(ConstraintViolation<?> violation) {
    String key = violation.getMessageTemplate();
    String messageFormat = localize(key);

    Object entity = violation.getRootBean();
    String identifier;
    if (entity instanceof PrimaryKeyed) {
        identifier = String.valueOf(((PrimaryKeyed) entity).getId());
    } else {
        identifier = entity.toString();
    }

    return MessageFormat.format(messageFormat, identifier);
}

请注意PrimaryKeyed是我们实体上使用的自定义界面。我们还有一些其他接口和自定义处理,如上所示。