jdaugherty commented on PR #16624:
URL: https://github.com/apache/grails-core/pull/16624#issuecomment-6325625840

   @matrei
   
   Thanks for the thorough probe. All of 1, 2, 4 and the smaller points are 
addressed in the amended commit; the approach changed in one respect that also 
answers @jamesfredley's fields plugin point.
   
   **Design change.** The validator `JakartaValidatorRegistry` registers for an 
annotated entity is now `JakartaPersistentEntityValidator`, a 
`PersistentEntityValidator` subclass, rather than a `GormValidatorAdapter` 
carrying one. It validates the `constraints` block and cascades as the base 
class does, then runs Bean Validation (without cascading) through a new 
protected hook, `PersistentEntityValidator.validateBeyondConstraints(obj, 
errors)`, which the base class calls for the root object and, in 
`cascadeValidationToOne`, for each associated object under the nested path of 
its association. So every consumer that does `validator instanceof 
PersistentEntityValidator` (the cascade itself, `DomainPropertyImpl` in 
grails-fields, `PersistentGraphQLProperty`, and any plugin outside this repo) 
sees the merged constraints without a change. `GormValidatorAdapter` is back to 
its 8.0.0 shape.
   
   1. **Cascading.** `cascadeValidationToOne` now validates an annotated 
associated entity with the constraints its validator *validates* (a new 
protected `getValidatedConstrainedProperties()`, the evaluated block with the 
nullability relaxed) rather than the merged ones it *exposes*, so the 
translated metadata is not checked a second time, and then calls the hook, so 
the annotations of the child are checked under `lines[0].label`. One cycle 
guard (`validatedObjects`), Bean Validation never cascades. Covered for an 
annotated parent, a plain parent, a single execution and `deepValidate: false` 
in the new TCK spec, the `DataTest` spec and `JakartaValidatorRegistrySpec`.
   2. **Groups.** `JakartaConstraintsTranslator` now reads the `BeanDescriptor` 
of the class and keeps only the constraints whose groups intersect the default 
group of the class (`Default`, plus the groups of a `@GroupSequence` redefining 
it), both for the nullability delegation and for the description. A 
`@NotNull(groups = OnPublish)` leaves `nullable: false` of the block in force: 
`validate()` and `save()` reject the null with `nullable`, and the metadata 
still says required. The guide says "annotations of the default group" now.
   3. **8.0.x.** The upgrade note now separates the rules that already shaped 
the schema (`nullable`, `unique`, `maxSize`, a failure moves from flush to 
`validate()`) from the ones enforced for the first time (`validator`, 
`matches`, `inList`, `min`/`max`, `email`, `blank`, and the global 
`grails.gorm.default.constraints`), and asks to review the block and the global 
defaults of each annotated class.
   4. **Class level constraints.** Bullet dropped, the commit message and the 
description corrected, and the `propertyName == null` branch of the resolver 
kept as a guard with a comment saying Hibernate Validator does not consult it 
for a class level constraint (the spec test is renamed accordingly). The TCK 
spec pins the behaviour with a class level constraint.
   5. Smaller points:
      - the link is `link:validation.html#constraints[constraint]` now;
      - the Hibernate 5 and 7 additions are replaced by 
`org.apache.grails.data.testing.tck.tests.BeanValidationSpec` (six domains 
under `tck/domains`), which runs on Hibernate 5, Hibernate 7, MongoDB and Neo4j 
and is ignored on the simple datastore of the core suite, which registers no 
validator;
      - a getter without a backing field (`isRangeValid()`) is validated but no 
longer described, unless the block constrains it; reading the descriptors also 
means a composed constraint is described with its `@OverridesAttribute` applied;
      - `grails-openapi` gets `BeanValidationSchemaSpec` (the fixture now 
builds the registry through `ValidatorRegistries`, as the datastores do), and 
the upgrade note mentions the OpenAPI descriptions next to scaffolding and the 
fields plugin.
   
   Run locally: `PersistentEntityValidatorSpec`, the `jakarta` specs of 
grails-datamapping-core, the `DataTest` spec, 
`EntityValidatorDomainPropertySpec` (grails-fields, new case through 
`JakartaValidatorRegistry`), the grails-openapi suite, and the TCK 
`BeanValidationSpec` on Hibernate 5, Hibernate 7 and MongoDB. Neo4j is left to 
CI.
   
   @jamesfredley on the fields plugin (`DomainPropertyImpl` line 57):
   
   Addressed by the design change rather than an edit to `DomainPropertyImpl`: 
the validator of an annotated entity is now a `PersistentEntityValidator` 
subclass, so the `instanceof` check on line 57 passes and the fields plugin 
reads the merged constraints as they are. `EntityValidatorDomainPropertySpec` 
has a new case that builds the validator through `JakartaValidatorRegistry` and 
checks `isRequired()` and `constrained.maxSize` for an annotated class. The 
same holds for `PersistentGraphQLProperty` and for any plugin outside this 
repository that checks the type.
   
   The three inline threads have their own replies.
   


-- 
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]

Reply via email to