You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@grails.apache.org by bo...@apache.org on 2026/02/17 18:42:06 UTC
(grails-core) 07/26: Consolidate binder architecture and enable recursive component binding
This is an automated email from the ASF dual-hosted git repository.
borinquenkid pushed a commit to branch 8.0.x-hibernate7
in repository https://gitbox.apache.org/repos/asf/grails-core.git
commit 62ea80cfc048d7a7d6df8a4943a4fdb264eb871a
Author: Walter Duque de Estrada <wb...@mac.com>
AuthorDate: Sun Feb 15 23:35:15 2026 -0600
Consolidate binder architecture and enable recursive component binding
- Merge ComponentPropertyBinder logic into ComponentBinder to resolve circular dependencies.
- Enable recursive component binding in ComponentBinder.
- Update CompositeIdBinder to use the consolidated ComponentBinder and ComponentUpdater.
- Simplify binder wiring in GrailsDomainBinder.
- Update and migrate unit tests to verify the consolidated binding logic and recursive capabilities.
---
.../org/grails/orm/hibernate/cfg/GrailsDomainBinder.java | 2 +-
.../cfg/domainbinding/binder/ComponentBinder.java | 4 ++--
.../cfg/domainbinding/binder/CompositeIdBinder.java | 7 +++++--
.../cfg/domainbinding/ComponentBinderSpec.groovy | 15 +++++++--------
.../cfg/domainbinding/CompositeIdBinderSpec.groovy | 6 +++++-
.../cfg/domainbinding/GrailsPropertyBinderSpec.groovy | 2 +-
6 files changed, 21 insertions(+), 15 deletions(-)
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java
index 0b639d8e0a..d8c716a554 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java
@@ -210,7 +210,7 @@ public class GrailsDomainBinder
manyToOneBinder,
propertyFromValueCreator
);
- CompositeIdBinder compositeIdBinder = new CompositeIdBinder(metadataBuildingContext, componentBinder);
+ CompositeIdBinder compositeIdBinder = new CompositeIdBinder(metadataBuildingContext, componentBinder, componentUpdater);
PropertyBinder propertyBinder = new PropertyBinder();
SimpleIdBinder simpleIdBinder = new SimpleIdBinder(metadataBuildingContext, namingStrategy, jdbcEnvironment, new BasicValueIdCreator(jdbcEnvironment), simpleValueBinder, propertyBinder);
IdentityBinder identityBinder = new IdentityBinder(simpleIdBinder, compositeIdBinder);
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/ComponentBinder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/ComponentBinder.java
index 818406b9f0..61c481924e 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/ComponentBinder.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/ComponentBinder.java
@@ -90,7 +90,8 @@ public class ComponentBinder {
component.setParentProperty(currentGrailsProp.getName());
continue;
}
- bindComponentProperty(component, property, currentGrailsProp, persistentClass, path, table, mappings);
+ var value = bindComponentProperty(component, property, currentGrailsProp, persistentClass, path, table, mappings);
+ componentUpdater.updateComponent(component, property, currentGrailsProp, value);
}
return component;
@@ -150,7 +151,6 @@ public class ComponentBinder {
this.simpleValueBinder.bindSimpleValue(currentGrailsProp, componentProperty, (SimpleValue) value, path);
}
}
- componentUpdater.updateComponent(component, componentProperty, currentGrailsProp, value);
return value;
}
}
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/CompositeIdBinder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/CompositeIdBinder.java
index 90b4e415fb..b776560f8f 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/CompositeIdBinder.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/CompositeIdBinder.java
@@ -17,10 +17,12 @@ public class CompositeIdBinder {
private final MetadataBuildingContext metadataBuildingContext;
private final ComponentBinder componentBinder;
+ private final ComponentUpdater componentUpdater;
- public CompositeIdBinder(MetadataBuildingContext metadataBuildingContext, ComponentBinder componentBinder) {
+ public CompositeIdBinder(MetadataBuildingContext metadataBuildingContext, ComponentBinder componentBinder, ComponentUpdater componentUpdater) {
this.metadataBuildingContext = metadataBuildingContext;
this.componentBinder = componentBinder;
+ this.componentUpdater = componentUpdater;
}
@@ -61,7 +63,8 @@ public class CompositeIdBinder {
"] is not a valid property!");
}
- componentBinder.bindComponentProperty(id, identifierProp, property, root, "", root.getTable(), mappings);
+ var value = componentBinder.bindComponentProperty(id, identifierProp, property, root, "", root.getTable(), mappings);
+ componentUpdater.updateComponent(id, identifierProp, property, value);
}
}
}
diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/ComponentBinderSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/ComponentBinderSpec.groovy
index 619364cebf..a28128ee15 100644
--- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/ComponentBinderSpec.groovy
+++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/ComponentBinderSpec.groovy
@@ -58,15 +58,13 @@ class ComponentBinderSpec extends HibernateGormDatastoreSpec {
OneToOneBinder oneToOneBinder = Mock(OneToOneBinder)
ManyToOneBinder manyToOneBinder = Mock(ManyToOneBinder)
ColumnNameForPropertyAndPathFetcher columnNameFetcher = Mock(ColumnNameForPropertyAndPathFetcher)
- ComponentUpdater componentUpdater
+ ComponentUpdater componentUpdater = Mock(ComponentUpdater)
SimpleValueBinder mockSimpleValueBinder = Mock(SimpleValueBinder)
@Subject
ComponentBinder binder
def setup() {
- componentUpdater = new ComponentUpdater(propertyFromValueCreator)
-
binder = new ComponentBinder(
getGrailsDomainBinder().getMetadataBuildingContext(),
mappingCacheHolder,
@@ -126,6 +124,7 @@ class ComponentBinderSpec extends HibernateGormDatastoreSpec {
component.getRoleName() == Address.name + ".address"
1 * mappingCacheHolder.cacheMapping(associatedEntity)
1 * mockSimpleValueBinder.bindSimpleValue(prop1, embeddedProp, _ as BasicValue, "address")
+ 1 * componentUpdater.updateComponent(_ as Component, embeddedProp, prop1, _ as Value)
}
def "should bind simple property"() {
@@ -155,7 +154,7 @@ class ComponentBinderSpec extends HibernateGormDatastoreSpec {
then:
1 * mockSimpleValueBinder.bindSimpleValue(currentGrailsProp, componentProperty, _ as BasicValue, "address")
- 1 * propertyFromValueCreator.createProperty(_ as BasicValue, currentGrailsProp) >> hibernateProperty
+ 0 * componentUpdater.updateComponent(_, _, _, _)
}
def "should bind many-to-one property"() {
@@ -188,7 +187,7 @@ class ComponentBinderSpec extends HibernateGormDatastoreSpec {
then:
1 * manyToOneBinder.bindManyToOne(currentGrailsProp, _ as HibernateManyToOne, "address")
- 1 * propertyFromValueCreator.createProperty(_ as HibernateManyToOne, currentGrailsProp) >> hibernateProperty
+ 0 * componentUpdater.updateComponent(_, _, _, _)
}
def "should bind one-to-one property"() {
@@ -225,7 +224,7 @@ class ComponentBinderSpec extends HibernateGormDatastoreSpec {
then:
1 * oneToOneBinder.bindOneToOne(currentGrailsProp, _ as HibernateOneToOne, "address")
- 1 * propertyFromValueCreator.createProperty(_ as HibernateOneToOne, currentGrailsProp) >> hibernateProperty
+ 0 * componentUpdater.updateComponent(_, _, _, _)
}
def "should bind enum property"() {
@@ -255,7 +254,7 @@ class ComponentBinderSpec extends HibernateGormDatastoreSpec {
then:
1 * enumTypeBinder.bindEnumType(currentGrailsProp, MyEnum, _ as BasicValue, "address_type_col")
- 1 * propertyFromValueCreator.createProperty(_ as BasicValue, currentGrailsProp) >> hibernateProperty
+ 0 * componentUpdater.updateComponent(_, _, _, _)
}
def "should set columns to nullable when component property is nullable"() {
@@ -290,7 +289,7 @@ class ComponentBinderSpec extends HibernateGormDatastoreSpec {
_ as BasicValue,
"address"
)
- 1 * propertyFromValueCreator.createProperty(_ as BasicValue, currentGrailsProp) >> hibernateProperty
+ 0 * componentUpdater.updateComponent(_, _, _, _)
}
static class MyEntity {}
diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/CompositeIdBinderSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/CompositeIdBinderSpec.groovy
index 15b580db45..15b0032436 100644
--- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/CompositeIdBinderSpec.groovy
+++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/CompositeIdBinderSpec.groovy
@@ -13,17 +13,19 @@ import spock.lang.Subject
import org.grails.orm.hibernate.cfg.domainbinding.binder.ComponentBinder
import org.grails.orm.hibernate.cfg.domainbinding.binder.CompositeIdBinder
+import org.grails.orm.hibernate.cfg.domainbinding.binder.ComponentUpdater
import org.hibernate.mapping.Value
class CompositeIdBinderSpec extends HibernateGormDatastoreSpec {
def componentBinder = Mock(ComponentBinder)
+ def componentUpdater = Mock(ComponentUpdater)
@Subject
CompositeIdBinder binder
def setup() {
- binder = new CompositeIdBinder(getGrailsDomainBinder().getMetadataBuildingContext(), componentBinder)
+ binder = new CompositeIdBinder(getGrailsDomainBinder().getMetadataBuildingContext(), componentBinder, componentUpdater)
}
def "should bind composite id using property names from CompositeIdentity"() {
@@ -55,6 +57,7 @@ class CompositeIdBinderSpec extends HibernateGormDatastoreSpec {
root.getIdentifierMapper() instanceof Component
root.hasEmbeddedIdentifier()
2 * componentBinder.bindComponentProperty(_ as Component, identifierProp, _ as PersistentProperty, root, "", table, mappings) >> Mock(Value)
+ 2 * componentUpdater.updateComponent(_ as Component, identifierProp, _ as PersistentProperty, _ as Value)
}
def "should fallback to domainClass composite identity when CompositeIdentity is null"() {
@@ -79,6 +82,7 @@ class CompositeIdBinderSpec extends HibernateGormDatastoreSpec {
then:
1 * componentBinder.bindComponentProperty(_ as Component, identifierProp, prop1, root, "", table, mappings) >> Mock(Value)
+ 1 * componentUpdater.updateComponent(_ as Component, identifierProp, prop1, _ as Value)
}
def "should throw MappingException if no composite properties found"() {
diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/GrailsPropertyBinderSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/GrailsPropertyBinderSpec.groovy
index d672fe8e80..5d0141c5b8 100644
--- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/GrailsPropertyBinderSpec.groovy
+++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/GrailsPropertyBinderSpec.groovy
@@ -109,7 +109,7 @@ class GrailsPropertyBinderSpec extends HibernateGormDatastoreSpec {
manyToOneBinder,
propertyFromValueCreator
)
- CompositeIdBinder compositeIdBinder = new CompositeIdBinder(metadataBuildingContext, componentBinder)
+ CompositeIdBinder compositeIdBinder = new CompositeIdBinder(metadataBuildingContext, componentBinder, componentUpdater);
PropertyBinder propertyBinderHelper = new PropertyBinder()
SimpleIdBinder simpleIdBinder = new SimpleIdBinder(metadataBuildingContext, namingStrategy, jdbcEnvironment, new BasicValueIdCreator(jdbcEnvironment), simpleValueBinder, propertyBinderHelper)
IdentityBinder identityBinder = new IdentityBinder(simpleIdBinder, compositeIdBinder)