jdaugherty commented on PR #16624: URL: https://github.com/apache/grails-core/pull/16624#issuecomment-6481662509
Thanks for the second pass. The cascade edge case and the two smaller points are addressed in 051efbe12c ([diff against d3f8ba5600](https://github.com/apache/grails-core/compare/d3f8ba5600..051efbe12c)). ### 1. A class-level constraint on an associated domain class The fix is in `GormValidatorAdapter`, not in `JakartaPersistentEntityValidator.validateBeyondConstraints`: - The field is built inside `SpringValidatorAdapter.processConstraintViolations`. - The hooks that build the code and the arguments (`determineField`, `determineErrorCode`, `getArgumentsForConstraint`) are protected, so only a subclass of the adapter can report the violation differently. The adapter now overrides `processConstraintViolations`, and the override acts only when the errors have a nested path: - A violation with an empty field is reported with `rejectValue('', …)`, so it lands on `ranges[0]`. Its arguments are built for that path. - Property violations still go through Spring unchanged. - Without a nested path nothing changes, so a class-level violation of the validated object is still a global error. Regressions: - **TCK `BeanValidationSpec`** (run locally on Hibernate 5, Hibernate 7, MongoDB and Neo4j): `BeanValidatedPair` is now owned by a plain `BeanValidatedPairing`. A pair violating its class-level `@DistinctLabels` makes the pairing report exactly one field error, on `pairs[0]`. - **`GormValidatorAdapterSpec`**: validates a `PriceRange` under the nested path `range`. It compares the error with the one Spring reports when it cascades from the holder through `@Valid`, with the same field, codes, arguments and message. It also pins the global error of the validated object. Both fail without the adapter change. ### 2. Smaller points - **Upgrade note:** - Flush-time enforcement of `nullable`, `unique` and `maxSize` is now stated for a schema that GORM for Hibernate generated from the mapping. - With GORM for MongoDB and GORM for Neo4j, `nullable` and `maxSize` are enforced for the first time. This includes the `nullable: false` that `grails.gorm.default.nullable = false` gives every property without a nullability rule of its own. - **Message codes:** the guide now says that the codes of an annotation error found through an association name the validated class and the path, while the codes of the block keep the class of the associated instance. So `NotBlank.com.example.InvoiceLine.label` applies only to a line validated on its own, while `NotBlank.lines.label`, `NotBlank.label` and `NotBlank` apply both ways. It also says that a class-level constraint of the associated class is reported on the association path itself. - **`no ci` label:** removed, so this head gets a full CI run. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
