Fix inheritance of an explicit bindable:true constraint on id/version declared in an abstract @DirtyCheck base#15796
Fix inheritance of an explicit bindable:true constraint on id/version declared in an abstract @DirtyCheck base#15796jdaugherty wants to merge 2 commits into
Conversation
jamesfredley
left a comment
There was a problem hiding this comment.
there's no positive multi-level case - a @DirtyCheck grandparent with id bindable:true, a plain abstract class in between, and the domain subclass binding id while still excluding version. Existing tests cover direct-inherited-true, direct-false-override, and multi-level-without-explicit, but not explicit opt-in propagating through an intermediate level. The code handles it correctly; adding the test would just lock that path. Purely optional - not a blocker for merge.
@sbglasius I think you should get final review since the original issue was one you submitted.
|
@jamesfredley I've added the test you suggested (and also updated the issue number in comments) |
✅ All tests passed ✅🏷️ Commit: b38bd68 Learn more about TestLens at testlens.app. |
Description
When an abstract base class — for example a
@DirtyCheckclass insrc/main/groovy— declares anexplicit
bindable: trueconstraint on one of the default-excluded special properties(
id,version,dateCreated,lastUpdated), a concrete domain subclass that does not redeclarethe constraint failed to inherit it. The property was silently excluded from data binding even though
the parent explicitly opted it in.
This is a regression introduced by the fix for #15681 (PR #15699).
Root cause
PR #15699 added a filter in
DefaultASTDatabindingHelper.getPropertyNamesToIncludeInWhiteListthatstrips the default-excluded special properties from the inherited parent whitelist for any domain
class. That correctly stops GORM-injected
id/versionfrom leaking out of a non-domain@DirtyCheckbase, but the filter was unconditional: it could not distinguish a special property that landed in the
parent whitelist by default from one the parent made bindable via an explicit
bindable: trueconstraint. As a result the explicit constraint was discarded.
Fix
The helper now tracks which excluded-by-default special properties were made bindable via an explicit
constraint, propagates that set down the inheritance hierarchy, and only skips an inherited special
property when it was not explicitly opted in:
whitelist by default are still not inherited.
bindable: falseoverride still wins over an inheritedbindable: true.Tests
DefaultASTDatabindingHelperDomainClassSpecialPropertiesSpec): an explicitbindable: trueon
iddeclared in a@DirtyCheckabstract base is inherited by the domain subclass (this case failswithout the fix), and a subclass
bindable: falseoverride beats the inheritedbindable: true.grails-test-examples-gorm/DirtyCheckBindingSpec): a new@DirtyCheckbase(
AbstractBindableIdRecord) optingidinto binding, an inheriting domain class (BindableIdRecord),a controller action, and an end-to-end HTTP assertion that the inherited
idis bound whileversionremains unbound.
Fixes #15795
Contributor Checklist
Issue and Scope
7.0.x): Bug fixes only. No new features or API changes.Code Quality
./gradlew build --rerun-tasks../gradlew codeStyleand resolved any violations.Licensing and Attribution
Documentation