Search code examples
bean-validationhibernate-validatorprotobuf-java

Cascaded bean validation on protobuf generated Java object not working


I'm trying to use Bean Validation to validate Java objects generated by the protobuf messages. I'm using Hibernate Validator's Programmatic constraint definition fluent API. It works on the direct object fields (actually I'm validating "getters") but for some reason valid() method is not triggering validation of the cascaded object.

I've tried to create regular Java objects (POJOs with no validation annotations and only getters for fields I'm testing) and apply the same Hibernate validator constraint mappings - it works correctly.

Do you have an idea why this approach is not working with the Java objects generated from the protobuf messages?

// protobuf example
message Car {
  com.mycompany.Driver driver = 1;
  string manufacturer = 2;
  ...
}

message Driver {
  string name = 1;
  ...
}


// Java code
configuration.createConstraintMapping()
  .type(Car.class)
    .getter("driver")
      .valid()
    .getter("manufacturer")
      .constraint(new NotEmptyDef())

  .type(Driver.class)
    .getter("name")
      .constraint(new NotEmptyDef());

 ...

 Car car = new Car();
 car.setDriver(new Driver());

 validator.validate(car);
 // then - validation does not validate Driver object

Solution

  • A colleague found a problem. We had to change the DefaultGetterPropertySelectionStrategy (link to documentation). By default strategy, getter methods are considered methods Object get*(), boolean is*() and boolean has*(). Since the generated Java classes from protobuf contains boolean has*() to indicate if the property is available or not - it was mistakenly used by the Hibernate Validator as a valid getter method.

    So, the solution is to create a custom getter method strategy based on DefaultGetterPropertySelectionStrategy and exclude has*(). Then register it when creating Validator as:

    ...
    Validator validator = configuration.addMapping(configuration.createConstraintMapping())
                    .getterPropertySelectionStrategy(new ProtobufGetterPropertySelectionStrategy())
                    .buildValidatorFactory()
                    .getValidator();