I'm trying to implement activation rules for OVal following their documentation but seem to be running into issues with it finding the variable I'm using for the comparison. Unfortunately other than the small section in their documentation there isn't much online about the topic.
The other part of the issue I'm trying to solve is to also get this working for constructor validation using the @Guarded annotation. This works fine without the constraint rules as described in my answer to this question, but not when I add activation rules in either JavaScript or Groovy.
3.4. Declaring activation rules for constraints
public class BusinessObject
{
private String fieldA;
@NotNull(when = "groovy:_this.fieldA != null")
private String fieldB;
}
I've tried both JS and groovy and tried with and without the _this. Removing it results in: ReferenceError: "someString" is not defined So I assume the way they list in the docs is correct but I'm missing something.
Code for field validation:
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;
}
}
Code for constructor validation:
@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;
}
}
How I'm testing the object:
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);
}
}
I'm not sure why the JavaScript version behaves differently to the groovy one, have tried changing all combinations I could think of including: _this.fieldA, __this.fieldA, window.fieldA, fieldA and __fieldA
UPDATE The JavaScript seems to work for private fields as long as it has a public getter.
I've solved the issue by doing the following and switching to groovy instead of JavaScript as suggested by the developer.
In the first line of my code example the
(checkInvariants = false)is required if the object you're validating has any public getter methods otherwise it will result in aStackOverflowErrorUnfortunately adding the validation in the constructor as I posted in my question doesn't work. So to get around this I needed to add the validation to the field and add the
@PostValidateThisannotation to the constructor.Example Pojo using validation after the constructor is called.
Basic unit test for the above pojo.