【问题标题】:Javax Validation: Constraint Violations for MapJavax 验证:地图的约束违规
【发布时间】:2012-07-25 23:52:21
【问题描述】:

我将 Map 用于本地化值,将语言环境作为键,将字符串作为值。对于必填字段,我需要检查至少设置了必需的语言环境 - 或者至少设置了一些值。我已经实现了要在此类 Map 字段和相应的验证器上使用的验证注释。问题是,如何报告缺失值? UI中用于绑定字段错误/值的属性路径,每次都会出错:

// Domain object:
@LocalizationRequired
private Map<Locale, String> field;


// LocalizationRequiredValidator:
public boolean isValid(Map<Locale, String> map, ConstraintValidatorContext context) {
    if (requiredLocales.isEmpty()) {
        // Check that there exists any not null value
    } else {
        context.disableDefaultConstraintViolation();
        boolean valid = true;
        for (Locale requiredLocale : requiredLocales) { 
            if (map.get(requiredLocale) == null) { // e.g. fi
                valid = false;
                context.buildConstraintViolationWithTemplate("LocalizationRequired")
                // These end up in wrong property path:
                // .addNode(requiredLocale) 
                //    --> field.fi
                // .addNode("[" + requiredLocale + "]") 
                //    --> field.[fi]
                // .addNode(null).addNode(requiredLocale).inIterable() 
                //    --> field.fi
                // .addNode(null).addNode(null).inIterable().atKey(requiredLocale)
                //   --> field
                .addConstraintViolation();
            }
        }
        return valid;
    }
}

此错误的正确路径是“field[fi]”,但似乎我只能访问索引子属性。在这种情况下,对象本身被索引。我正在使用 Hibernate Validator。

【问题讨论】:

    标签: java validation map bean-validation hibernate-validator


    【解决方案1】:

    我无法找到在元素级别报告索引字段错误的方法。 - 规范中是否忽略了这一点?

    这就是我所做的:

    我没有使用 Map,而是使用了一个“可嵌入”bean,其中包含所有支持的语言环境的实际字段(例如 LocalizedString(String fi, String en 等)。然后报告如下违规行为:

    context.buildConstraintViolationWithTemplate("LocalizationRequired")
    .addNode(requiredLocale)
    .addConstraintViolation();
    

    这在我们的案例中是可行的,因为我们有一组预定义的受支持语言,但它不能扩展到具有任意索引的索引字段。

    此外,Spring 的 LocalValidatorFactoryBean 或 Hibernate Validator 都不能正确支持嵌入的验证。由于在不同的地方使用相同的组件具有不同的验证要求,因此我不能在组件本身内使用带有实际验证注释的 @Valid - 至少在不支持 @Valid 上的验证组的情况下是这样。

    Spring 的 LocalValidatorFactoryBean 或 Hibernate Validator 的问题在于,ConstraintViolationinvalidValue 是 LocalizedString(“field”),而不是报告的错误嵌套字段(“field.fi”)的值。幸运的是,这可以通过覆盖LocalValidatorFactoryBean.processConstraintViolations 来解决,方法是删除“使用来自 ConstraintViolation 的无效值的自定义 FieldError 注册”并简单地报告错误

    errors.rejectValue(field, errorCode, errorArgs, violation.getMessage());
    

    这样,Spring 使用给定的field 解析invalidValue

    【讨论】:

      【解决方案2】:

      这是一个非常有趣的问题。现在我没有时间自己测试它:(但是这里的这个人:

      Validation of a Collection

      似乎能够验证元素的集合。 因此,如果您切换到 Collection 而不是 Map(这应该很容易),例如:

       class LocaleToString {
            private Locale locale;
            private String language;
       }
      
       @LocalizationRequired
       List<LocaleToString> locales;
      

      我认为你应该能够实现你想要的。

      【讨论】:

      • 差异是实际验证错误绑定到的路径。 集合验证报告集合级别(语言环境)而不是元素级别(语言环境[1])的所有错误。我试图获得更具体的错误(对于 Spring 绑定)。我有一种强烈的感觉,这种用例在规范中被忽略了......即必须使用 bean 而不是索引文件。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-15
      • 2020-03-28
      • 1970-01-01
      • 2011-07-31
      • 1970-01-01
      • 2011-04-19
      相关资源
      最近更新 更多