OVal激活规则用于不起作用的约束

时间:2017-05-16 07:10:45

标签: javascript java validation groovy oval

我正在尝试在documentation之后为OVal实施激活规则,但似乎遇到了问题找到我正在用于比较的变量。不幸的是,除了文档中的小部分之外,关于该主题的在线并不多。

我正在尝试解决的问题的另一部分是使用@Guarded注释来使构造函数验证工作。这在我对this question的回答中没有约束规则的情况下工作正常,但在我在 JavaScript Groovy 中添加激活规则时却没有。

  

3.4。声明约束的激活规则

public class BusinessObject
{
    private String fieldA;

    @NotNull(when = "groovy:_this.fieldA != null")
    private String fieldB;
}

我尝试了JS和groovy,并尝试使用和不使用_this。删除它会导致:ReferenceError: "someString" is not defined所以我假设他们在文档中列出的方式是正确的,但我遗漏了一些东西。

现场验证代码:

public class BusinessObject {
    private String fieldA;

    //@NotNull(when = "groovy:_this.fieldA != null") //works for public & private
    @NotNull(when = "javascript:_this.fieldA != null") //only works when fieldA is public
    private String fieldB;

    public BusinessObject(){}

    public BusinessObject(String fieldA, String fieldB) {
        this.fieldA = fieldA;
        this.fieldB = fieldB;
    }
}

构造函数验证代码:

@Guarded
public class BusinessObjectConstructorValidation {
    private String fieldA;
    private String fieldB;

    public BusinessObjectConstructorValidation(
            String fieldA,
            @NotNull(when = "groovy:_this.fieldA != null") String fieldB) {

        this.fieldA = fieldA;
        this.fieldB = fieldB;
    }
}

我如何测试对象:

public class BusinessObjectTest {

    @Test
    public void fieldANullFieldBNotValidatedNoViolations() {
        BusinessObject businessObject = new BusinessObject(null, null);
        Validator validator = new Validator();
        validator.validate(businessObject);
    }

    //This test will fail if the fields are private and using javascript
    //If it's public or using groovy it passes
    @Test
    public void fieldANotNullFieldBValidatedViolationsSizeIsOne() {
        BusinessObject businessObject = new BusinessObject("A", null);
        Validator validator = new Validator();
        List<ConstraintViolation> errors = validator.validate(businessObject);
        System.out.println(errors.size());
        assertThat(errors.size(), is(1));
    }

    @Test
    public void fieldANullFieldBNotNullNoViolations() {
        BusinessObject businessObject = new BusinessObject(null, "B");
        Validator validator = new Validator();
        validator.validate(businessObject);
    }
}

我不确定为什么JavaScript版本与groovy版本的行为不同,尝试更改我能想到的所有组合,包括:_this.fieldA__this.fieldAwindow.fieldA,{{ 1}}和fieldA

更新 只要它具有公共getter,JavaScript似乎适用于私有字段。

1 个答案:

答案 0 :(得分:0)

我通过执行以下操作解决了这个问题,并按照developer的建议切换到groovy而不是JavaScript。

  

JavaScript引擎Rhino无法直接访问私有字段。例如。无论私有字段的值如何,“javascript:_this.myPrivateField!= null&amp;&amp; _this.myPrivateField.length&gt; 10”之类的内容将始终返回false。如果Rhino无法访问私有领域,显然不会引发异常。

     

我建议你使用groovy而不是javascript进行约束激活。   对于大多数脚本运行时(包括JavaScript),语句_this.someVariable将导致调用_this.getSomeVariable()getter,而不是直接访问具有相同名称的私有字段。

在我的代码示例的第一行中,如果您要验证的对象具有任何公共getter方法,则需要(checkInvariants = false),否则将导致StackOverflowError

不幸的是,我在我的问题中发布的构造函数中添加验证不起作用。因此,为了解决这个问题,我需要将验证添加到字段中,并将@PostValidateThis注释添加到构造函数中。

示例Pojo在调用构造函数后使用验证。

@Guarded(checkInvariants = false)// removing this results in StackOverflowError
public class User {
    private final String firstName;
    private final String lastName;
    @NotNull(when = "groovy:_this.lastName != null")
    private final Integer age;

    @PostValidateThis
    public User(String firstName, String lastName, Integer age) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
    }

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public Integer getAge() {
        return age;
    }
}

以上pojo的基本单元测试。

public class UserTest {
    @Test
    public void userValidParamsNoException() throws Exception {
        User user = new User("foo","bar",123);
        assertThat(user, is(not(nullValue())));
        assertThat(user.getFirstName(), is("foo"));
        assertThat(user.getLastName(), is("bar"));
        assertThat(user.getAge(), is(123));
    }

    @Test
    public void userLastNameNullNoException() throws Exception {
        User user = new User("foo",null, null);
        assertThat(user, is(not(nullValue())));
        assertThat(user.getFirstName(), is("foo"));
    }

    @Test(expected = ConstraintsViolatedException.class)
    public void userLastNameNotNullAgeNullThrowsException() throws Exception {
        User user = new User("foo","bar", null);
    }
}