validation of nested Optional object throws class cast exception, if the getter is Optional but field
for example: following code ends with class cast exception:
{code} private class X {
@Valid private Y y;
public void setY(Y y) { this.y = y; }
public Optional<Y> getY() { return Optional.ofNullable(y); } }
private class Y {
@Valid private Z z;
public void setZ(Z z) { this.z = z; }
public Optional<Z> z() { return Optional.ofNullable(z); } }
private class Z {
@NotNull private String karel;
@NotNull(groups = Group1.class) private String johny;
@NotNull private Integer test;
public String getKarel() { return karel; }
public void setKarel(String karel) { this.karel = karel; }
public String getJohny() { return johny; }
public void setJohny(String johny) { this.johny = johny; }
public Optional<Integer> getTest() { return null; } }
private interface Group1 {
}
private ValidationService validationService = validationService();
private ValidationService validationService() {
ValidationServiceImpl service = new ValidationServiceImpl(); return service; }
@Test public void test_1() {
X x = new X(); x.y = new Y(); x.y.z = new Z(); x.y.z.test = 1;
Assert.assertEquals(2, validationService.getConstraintViolations(x, Group1.class).size()); } {code}
The problem is that code tries to unwrap that Optional without checking, if the original field value is really Optional (it probably checks only getter)
{color:red}*Workaround exist*{color}
if you explicitly change your classes to "do not unwrap", the validation is successfully finished but I would expected that in this case it should work in this way automatically without that annotation.
{code} private class X {
@Valid @UnwrapValidatedValue(false) private Y y;
public void setY(Y y) { this.y = y; }
public Optional<Y> getY() { return Optional.ofNullable(y); } }
private class Y {
@Valid @UnwrapValidatedValue(false) private Z z;
public void setZ(Z z) { this.z = z; }
public Optional<Z> z() { return Optional.ofNullable(z); } }
private class Z {
@NotNull private String karel;
@NotNull(groups = Group1.class) private String johny;
@NotNull @UnwrapValidatedValue(false) private Integer test;
public String getKarel() { return karel; }
public void setKarel(String karel) { this.karel = karel; }
public String getJohny() { return johny; }
public void setJohny(String johny) { this.johny = johny; }
public Optional<Integer> getTest() { return null; } }
private interface Group1 {
}
private ValidationService validationService = validationService();
private ValidationService validationService() {
ValidationServiceImpl service = new ValidationServiceImpl(); return service; }
@Test public void test_1() {
X x = new X(); x.y = new Y(); x.y.z = new Z(); x.y.z.test = 1;
Assert.assertEquals(2, validationService.getConstraintViolations(x, Group1.class).size()); } {code} |
|