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 70fde10c8257d029d79beef9f02446cd9376ac74
Author: Walter B Duque de Estrada <[email protected]>
AuthorDate: Fri Jan 23 14:09:45 2026 -0600

    update progress
---
 .../orm/hibernate/proxy/HibernateProxyHandler.java |  42 ++++-
 .../proxy/HibernateProxyHandler5Spec.groovy        | 197 ++++++++++++++++++++-
 .../orm/hibernate/proxy/HibernateProxyHandler.java |  89 +++++++---
 .../core/HIBERNATE7-UPGRADE-PROGRESS.md            |  71 +-------
 .../orm/hibernate/proxy/HibernateProxyHandler.java | 121 ++++++++++---
 .../hibernate/HibernateGormStaticApiSpec.groovy    |  18 ++
 6 files changed, 414 insertions(+), 124 deletions(-)

diff --git 
a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/proxy/HibernateProxyHandler.java
 
b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/proxy/HibernateProxyHandler.java
index bb5921e82a..4baa06a419 100644
--- 
a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/proxy/HibernateProxyHandler.java
+++ 
b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/proxy/HibernateProxyHandler.java
@@ -18,6 +18,8 @@
  */
 package org.grails.orm.hibernate.proxy;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import java.io.Serializable;
 
 import groovy.lang.GroovyObject;
@@ -46,20 +48,43 @@ import org.grails.orm.hibernate.GrailsHibernateTemplate;
  */
 public class HibernateProxyHandler implements ProxyHandler, ProxyFactory {
 
+    private static final Logger LOG = 
LoggerFactory.getLogger(HibernateProxyHandler.class);
+
     /**
      * Check if the proxy or persistent collection is initialized.
      * {@inheritDoc}
      */
     @Override
     public boolean isInitialized(Object o) {
+        if (o == null) {
+            LOG.info("isInitialized(Object) - object is null, returning 
false");
+            return false;
+        }
+        LOG.info("isInitialized(Object) - checking object of type: {}", 
o.getClass().getName());
         if (o instanceof EntityProxy) {
-            return ((EntityProxy)o).isInitialized();
+            boolean initialized = ((EntityProxy) o).isInitialized();
+            LOG.info("isInitialized(Object) - object is EntityProxy, 
isInitialized: {}", initialized);
+            return initialized;
+        }
+        if (o instanceof HibernateProxy) {
+            boolean initialized = !((HibernateProxy) 
o).getHibernateLazyInitializer().isUninitialized();
+            LOG.info("isInitialized(Object) - object is HibernateProxy, 
isInitialized: {}", initialized);
+            return initialized;
+        }
+        if (o instanceof PersistentCollection) {
+            boolean initialized = ((PersistentCollection) o).wasInitialized();
+            LOG.info("isInitialized(Object) - object is PersistentCollection, 
wasInitialized: {}", initialized);
+            return initialized;
         }
         ProxyInstanceMetaClass proxyMc = getProxyInstanceMetaClass(o);
         if (proxyMc != null) {
-            return proxyMc.isProxyInitiated();
+            boolean initialized = proxyMc.isProxyInitiated();
+            LOG.info("isInitialized(Object) - object is Groovy Proxy, 
isProxyInitiated: {}", initialized);
+            return initialized;
         }
-        return Hibernate.isInitialized(o);
+        boolean initialized = Hibernate.isInitialized(o);
+        LOG.info("isInitialized(Object) - Hibernate.isInitialized returned: 
{}", initialized);
+        return initialized;
     }
 
     /**
@@ -68,11 +93,15 @@ public class HibernateProxyHandler implements ProxyHandler, 
ProxyFactory {
      */
     @Override
     public boolean isInitialized(Object obj, String associationName) {
+        LOG.info("isInitialized(Object, String) - checking association '{}' on 
object of type: {}", associationName, obj != null ? obj.getClass().getName() : 
"null");
         try {
             Object proxy = ClassPropertyFetcher.getInstancePropertyValue(obj, 
associationName);
-            return isInitialized(proxy);
+            boolean initialized = isInitialized(proxy);
+            LOG.info("isInitialized(Object, String) - association '{}' 
isInitialized: {}", associationName, initialized);
+            return initialized;
         }
         catch (RuntimeException e) {
+            LOG.info("isInitialized(Object, String) - RuntimeException 
occurred while checking association '{}', returning false", associationName);
             return false;
         }
     }
@@ -171,15 +200,20 @@ public class HibernateProxyHandler implements 
ProxyHandler, ProxyFactory {
     }
 
     private ProxyInstanceMetaClass getProxyInstanceMetaClass(Object o) {
+        LOG.info("getProxyInstanceMetaClass() - checking if object is 
GroovyObject: {}", o != null ? o.getClass().getName() : "null");
         if (o instanceof GroovyObject) {
             MetaClass mc = ((GroovyObject) o).getMetaClass();
+            LOG.info("getProxyInstanceMetaClass() - metaClass type: {}", 
mc.getClass().getName());
             if (mc instanceof HandleMetaClass) {
                 mc = ((HandleMetaClass) mc).getAdaptee();
+                LOG.info("getProxyInstanceMetaClass() - handleMetaClass 
adaptee type: {}", mc.getClass().getName());
             }
             if (mc instanceof ProxyInstanceMetaClass) {
+                LOG.info("getProxyInstanceMetaClass() - found 
ProxyInstanceMetaClass");
                 return (ProxyInstanceMetaClass) mc;
             }
         }
+        LOG.info("getProxyInstanceMetaClass() - no ProxyInstanceMetaClass 
found");
         return null;
     }
 
diff --git 
a/grails-data-hibernate5/core/src/test/groovy/org/grails/orm/hibernate/proxy/HibernateProxyHandler5Spec.groovy
 
b/grails-data-hibernate5/core/src/test/groovy/org/grails/orm/hibernate/proxy/HibernateProxyHandler5Spec.groovy
index bdffcd8bfb..d7ecec2b84 100644
--- 
a/grails-data-hibernate5/core/src/test/groovy/org/grails/orm/hibernate/proxy/HibernateProxyHandler5Spec.groovy
+++ 
b/grails-data-hibernate5/core/src/test/groovy/org/grails/orm/hibernate/proxy/HibernateProxyHandler5Spec.groovy
@@ -4,6 +4,8 @@ import org.slf4j.Logger
 import org.slf4j.LoggerFactory
 import grails.gorm.specs.HibernateGormDatastoreSpec
 import org.apache.grails.data.testing.tck.domains.Location
+import org.apache.grails.data.testing.tck.domains.Person
+import org.apache.grails.data.testing.tck.domains.Pet
 import org.hibernate.Hibernate
 import spock.lang.Shared
 import org.grails.datastore.gorm.proxy.GroovyProxyFactory
@@ -14,7 +16,7 @@ class HibernateProxyHandler5Spec extends 
HibernateGormDatastoreSpec {
     @Shared HibernateProxyHandler proxyHandler = new HibernateProxyHandler()
 
     void setupSpec() {
-        manager.addAllDomainClasses([Location])
+        manager.addAllDomainClasses([Location, Person, Pet])
     }
 
     void "test isInitialized for a non-proxied object"() {
@@ -106,4 +108,197 @@ class HibernateProxyHandler5Spec extends 
HibernateGormDatastoreSpec {
         cleanup:
         manager.session.mappingContext.proxyFactory = originalFactory
     }
+
+    void "test isInitialized for null"() {
+        expect:
+        proxyHandler.isInitialized(null) == false
+    }
+
+    void "test isInitialized for a persistent collection"() {
+        given:
+        Person p = new Person(firstName: "Homer", lastName: 
"Simpson").save(flush: true)
+        new Pet(name: "Santa's Little Helper", owner: p).save(flush: true)
+        manager.session.clear()
+        manager.hibernateSession.clear()
+
+        Person loaded = Person.get(p.id)
+        def pets = loaded.pets
+
+        expect:
+        proxyHandler.isInitialized(pets) == false
+
+        when:
+        pets.size()
+
+        then:
+        proxyHandler.isInitialized(pets) == true
+    }
+
+    void "test isInitialized for association name"() {
+        given:
+        Person p = new Person(firstName: "Homer", lastName: 
"Simpson").save(flush: true)
+        new Pet(name: "Santa's Little Helper", owner: p).save(flush: true)
+        manager.session.clear()
+        manager.hibernateSession.clear()
+
+        Person loaded = Person.get(p.id)
+
+        expect:
+        proxyHandler.isInitialized(loaded, 'pets') == false
+
+        when:
+        loaded.pets.size()
+
+        then:
+        proxyHandler.isInitialized(loaded, 'pets') == true
+    }
+
+    void "test isProxy"() {
+        given:
+        Location location = new Location(name: "Test").save(flush: true)
+        manager.session.clear()
+        manager.hibernateSession.clear()
+
+        Location proxy = Location.proxy(location.id)
+
+        expect:
+        proxyHandler.isProxy(proxy) == true
+        proxyHandler.isProxy(location) == false
+        proxyHandler.isProxy(null) == false
+    }
+
+    void "test getIdentifier"() {
+        given:
+        Location location = new Location(name: "Test").save(flush: true)
+        manager.session.clear()
+        manager.hibernateSession.clear()
+
+        Location proxy = Location.proxy(location.id)
+
+        expect:
+        proxyHandler.getIdentifier(proxy) == location.id
+        proxyHandler.getIdentifier(location) == null
+    }
+
+    void "test getProxiedClass"() {
+        given:
+        Location location = new Location(name: "Test").save(flush: true)
+        manager.session.clear()
+        manager.hibernateSession.clear()
+
+        Location proxy = Location.proxy(location.id)
+
+        expect:
+        proxyHandler.getProxiedClass(proxy) == Location
+        proxyHandler.getProxiedClass(location) == Location
+    }
+
+    void "test initialize"() {
+        given:
+        Location location = new Location(name: "Test").save(flush: true)
+        manager.session.clear()
+        manager.hibernateSession.clear()
+
+        Location proxy = Location.proxy(location.id)
+
+        expect:
+        !Hibernate.isInitialized(proxy)
+
+        when:
+        proxyHandler.initialize(proxy)
+
+        then:
+        Hibernate.isInitialized(proxy)
+    }
+
+    void "test unwrap for persistent collection"() {
+        given:
+        Person p = new Person(firstName: "Homer", lastName: 
"Simpson").save(flush: true)
+        new Pet(name: "Santa's Little Helper", owner: p).save(flush: true)
+        manager.session.clear()
+        manager.hibernateSession.clear()
+
+        Person loaded = Person.get(p.id)
+        def pets = loaded.pets
+
+        expect:
+        !proxyHandler.isInitialized(pets)
+
+        when:
+        def unwrapped = proxyHandler.unwrap(pets)
+
+        then:
+        unwrapped == pets
+        proxyHandler.isInitialized(pets)
+    }
+
+    void "test isInitialized for association name with null object"() {
+        expect:
+        proxyHandler.isInitialized(null, 'any') == false
+    }
+
+    void "test createProxy"() {
+        given:
+        Location location = new Location(name: "Test").save(flush: true)
+        manager.session.clear()
+        manager.hibernateSession.clear()
+
+        when:
+        Location proxy = proxyHandler.createProxy(manager.session, Location, 
location.id)
+
+        then:
+        proxy != null
+        proxy instanceof org.hibernate.proxy.HibernateProxy
+        proxy.id == location.id
+        !Hibernate.isInitialized(proxy)
+    }
+
+    void "test createProxy with AssociationQueryExecutor"() {
+        when:
+        proxyHandler.createProxy(manager.session, null, null)
+
+        then:
+        thrown(UnsupportedOperationException)
+    }
+
+    void "test createProxy throws IllegalStateException if native interface is 
not GrailsHibernateTemplate"() {
+        given:
+        def mockSession = Stub(org.grails.datastore.mapping.core.Session)
+        mockSession.getNativeInterface() >> "not a template"
+
+        when:
+        proxyHandler.createProxy(mockSession, Location, 1L)
+
+        then:
+        thrown(IllegalStateException)
+    }
+
+    void "test deprecated unwrapProxy and unwrapIfProxy"() {
+        given:
+        Location location = new Location(name: "Test").save(flush: true)
+        manager.session.clear()
+        manager.hibernateSession.clear()
+
+        Location proxy = Location.proxy(location.id)
+
+        expect:
+        proxyHandler.unwrapProxy(proxy) != proxy
+        proxyHandler.unwrapIfProxy(proxy) != proxy
+        proxyHandler.unwrapProxy(location) == location
+        proxyHandler.unwrapIfProxy(location) == location
+    }
+
+    void "test getAssociationProxy"() {
+        given:
+        Person p = new Person(firstName: "Homer", lastName: 
"Simpson").save(flush: true)
+        Pet pet = new Pet(name: "Santa's Little Helper", owner: p).save(flush: 
true)
+        manager.session.clear()
+        manager.hibernateSession.clear()
+
+        Pet loadedPet = Pet.get(pet.id)
+
+        expect:
+        proxyHandler.getAssociationProxy(loadedPet, 'owner') instanceof 
org.hibernate.proxy.HibernateProxy
+        proxyHandler.getAssociationProxy(loadedPet, 'name') == null
+    }
 }
\ No newline at end of file
diff --git 
a/grails-data-hibernate6/core/src/main/groovy/org/grails/orm/hibernate/proxy/HibernateProxyHandler.java
 
b/grails-data-hibernate6/core/src/main/groovy/org/grails/orm/hibernate/proxy/HibernateProxyHandler.java
index 6c722b8f62..4baa06a419 100644
--- 
a/grails-data-hibernate6/core/src/main/groovy/org/grails/orm/hibernate/proxy/HibernateProxyHandler.java
+++ 
b/grails-data-hibernate6/core/src/main/groovy/org/grails/orm/hibernate/proxy/HibernateProxyHandler.java
@@ -1,37 +1,42 @@
 /*
- * Copyright 2004-2008 the original author or authors.
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
  *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ *    https://www.apache.org/licenses/LICENSE-2.0
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
  */
 package org.grails.orm.hibernate.proxy;
 
-import org.grails.datastore.mapping.core.Session;
-import org.grails.datastore.mapping.engine.AssociationQueryExecutor;
-import org.grails.datastore.mapping.proxy.EntityProxy;
-import org.grails.datastore.mapping.proxy.ProxyFactory;
-import org.grails.datastore.mapping.proxy.ProxyHandler;
-import org.grails.datastore.mapping.reflect.ClassPropertyFetcher;
-import org.hibernate.Hibernate;
-import org.hibernate.collection.spi.PersistentCollection;
-import org.hibernate.proxy.HibernateProxy;
-import org.hibernate.proxy.HibernateProxyHelper;
-
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import java.io.Serializable;
 
 import groovy.lang.GroovyObject;
 import groovy.lang.MetaClass;
 import org.codehaus.groovy.runtime.HandleMetaClass;
+import org.hibernate.Hibernate;
+import org.hibernate.collection.spi.PersistentCollection;
+import org.hibernate.proxy.HibernateProxy;
+import org.hibernate.proxy.HibernateProxyHelper;
+
 import org.grails.datastore.gorm.proxy.ProxyInstanceMetaClass;
+import org.grails.datastore.mapping.core.Session;
+import org.grails.datastore.mapping.engine.AssociationQueryExecutor;
+import org.grails.datastore.mapping.proxy.EntityProxy;
+import org.grails.datastore.mapping.proxy.ProxyFactory;
+import org.grails.datastore.mapping.proxy.ProxyHandler;
+import org.grails.datastore.mapping.reflect.ClassPropertyFetcher;
 import org.grails.orm.hibernate.GrailsHibernateTemplate;
 
 /**
@@ -43,20 +48,43 @@ import org.grails.orm.hibernate.GrailsHibernateTemplate;
  */
 public class HibernateProxyHandler implements ProxyHandler, ProxyFactory {
 
+    private static final Logger LOG = 
LoggerFactory.getLogger(HibernateProxyHandler.class);
+
     /**
      * Check if the proxy or persistent collection is initialized.
      * {@inheritDoc}
      */
     @Override
     public boolean isInitialized(Object o) {
+        if (o == null) {
+            LOG.info("isInitialized(Object) - object is null, returning 
false");
+            return false;
+        }
+        LOG.info("isInitialized(Object) - checking object of type: {}", 
o.getClass().getName());
         if (o instanceof EntityProxy) {
-            return ((EntityProxy)o).isInitialized();
+            boolean initialized = ((EntityProxy) o).isInitialized();
+            LOG.info("isInitialized(Object) - object is EntityProxy, 
isInitialized: {}", initialized);
+            return initialized;
+        }
+        if (o instanceof HibernateProxy) {
+            boolean initialized = !((HibernateProxy) 
o).getHibernateLazyInitializer().isUninitialized();
+            LOG.info("isInitialized(Object) - object is HibernateProxy, 
isInitialized: {}", initialized);
+            return initialized;
+        }
+        if (o instanceof PersistentCollection) {
+            boolean initialized = ((PersistentCollection) o).wasInitialized();
+            LOG.info("isInitialized(Object) - object is PersistentCollection, 
wasInitialized: {}", initialized);
+            return initialized;
         }
         ProxyInstanceMetaClass proxyMc = getProxyInstanceMetaClass(o);
         if (proxyMc != null) {
-            return proxyMc.isProxyInitiated();
+            boolean initialized = proxyMc.isProxyInitiated();
+            LOG.info("isInitialized(Object) - object is Groovy Proxy, 
isProxyInitiated: {}", initialized);
+            return initialized;
         }
-        return Hibernate.isInitialized(o);
+        boolean initialized = Hibernate.isInitialized(o);
+        LOG.info("isInitialized(Object) - Hibernate.isInitialized returned: 
{}", initialized);
+        return initialized;
     }
 
     /**
@@ -65,11 +93,15 @@ public class HibernateProxyHandler implements ProxyHandler, 
ProxyFactory {
      */
     @Override
     public boolean isInitialized(Object obj, String associationName) {
+        LOG.info("isInitialized(Object, String) - checking association '{}' on 
object of type: {}", associationName, obj != null ? obj.getClass().getName() : 
"null");
         try {
             Object proxy = ClassPropertyFetcher.getInstancePropertyValue(obj, 
associationName);
-            return isInitialized(proxy);
+            boolean initialized = isInitialized(proxy);
+            LOG.info("isInitialized(Object, String) - association '{}' 
isInitialized: {}", associationName, initialized);
+            return initialized;
         }
         catch (RuntimeException e) {
+            LOG.info("isInitialized(Object, String) - RuntimeException 
occurred while checking association '{}', returning false", associationName);
             return false;
         }
     }
@@ -168,15 +200,20 @@ public class HibernateProxyHandler implements 
ProxyHandler, ProxyFactory {
     }
 
     private ProxyInstanceMetaClass getProxyInstanceMetaClass(Object o) {
+        LOG.info("getProxyInstanceMetaClass() - checking if object is 
GroovyObject: {}", o != null ? o.getClass().getName() : "null");
         if (o instanceof GroovyObject) {
             MetaClass mc = ((GroovyObject) o).getMetaClass();
+            LOG.info("getProxyInstanceMetaClass() - metaClass type: {}", 
mc.getClass().getName());
             if (mc instanceof HandleMetaClass) {
                 mc = ((HandleMetaClass) mc).getAdaptee();
+                LOG.info("getProxyInstanceMetaClass() - handleMetaClass 
adaptee type: {}", mc.getClass().getName());
             }
             if (mc instanceof ProxyInstanceMetaClass) {
+                LOG.info("getProxyInstanceMetaClass() - found 
ProxyInstanceMetaClass");
                 return (ProxyInstanceMetaClass) mc;
             }
         }
+        LOG.info("getProxyInstanceMetaClass() - no ProxyInstanceMetaClass 
found");
         return null;
     }
 
diff --git a/grails-data-hibernate7/core/HIBERNATE7-UPGRADE-PROGRESS.md 
b/grails-data-hibernate7/core/HIBERNATE7-UPGRADE-PROGRESS.md
index c724428e19..7033b55c71 100644
--- a/grails-data-hibernate7/core/HIBERNATE7-UPGRADE-PROGRESS.md
+++ b/grails-data-hibernate7/core/HIBERNATE7-UPGRADE-PROGRESS.md
@@ -5,77 +5,8 @@ This document summarizes the approaches taken, challenges 
encountered, and futur
 
 ## Resolved Challenges
 
-### 1. Proxy Initialization Behavior
-- **Issue:** In `Hibernate7GroovyProxySpec`, `Location.proxy(id)` returned an 
object that was already reported as initialized 
(`Hibernate.isInitialized(location) == true`) even when it was a lazy Groovy 
proxy.
-- **Cause:** Hibernate 7's `Hibernate.isInitialized()` does not automatically 
recognize GORM's `EntityProxy` interface used by `GroovyProxyFactory`.
-- **Solution:** Updated `org.grails.orm.hibernate.proxy.HibernateProxyHandler` 
to explicitly check for `EntityProxy`. This ensures that `isInitialized()`, 
`unwrap()`, and `getIdentifier()` work correctly for both native Hibernate 
proxies and GORM Groovy proxies.
-- **Verified:** `Hibernate7GroovyProxySpec` now passes.
-
-### 2. Multi-tenancy Many-to-Many
-- **Issue:** `MultiTenancyBidirectionalManyToManySpec` failed with `Found two 
representations of same collection: 
grails.gorm.specs.multitenancy.Department.users`.
-- **Cause:** Complex save logic in test setup caused the same collection to be 
associated with the session multiple times.
-- **Solution:** Simplified `createSomeUsers` in the test to use GORM's 
cascading saves by saving the owner entity (`Department`) once after adding all 
users.
-- **Verified:** `MultiTenancyBidirectionalManyToManySpec` now passes.
-
-### 3. Embedded Component Property Access
-- **Issue:** `HibernateDirtyCheckingSpec` failed with 
`PropertyAccessException: Could not set value of type [java.lang.String]: 
'grails.gorm.specs.dirtychecking.Address.street' (setter)`.
-- **Cause:** `GrailsDomainBinder.createProperty` was incorrectly using the 
parent entity's class name when configuring Hibernate properties for embedded 
components, leading to a type mismatch in Hibernate's reflection-based setters.
-- **Solution:** Updated `createProperty` to use 
`grailsProperty.getOwner().getJavaClass().getName()`, ensuring the correct 
class is used for property accessors in components.
-- **Verified:** The `PropertyAccessException` is resolved. (Remaining issue: 
`hasChanged()` method missing on non-entity embedded classes in test 
environment).
-
-### 4. Disabled Incompatible TCK Tests
-- **Issue:** `NamedQuerySpec` failed with `"No signature of method: static 
org.grails.datastore.gorm.GormEnhancer.createNamedQuery()"`.
-- **Solution:** Disabled `NamedQuerySpec` for Hibernate 7 using `@IgnoreIf({ 
System.getProperty("hibernate7.gorm.suite") == "true" })`.
-- **Status:** Pending proper implementation of named queries in Hibernate 7 
module.
-
 ## Hibernate 7 Key Constraints & Best Practices
 
-### Identifier Generators
-- **Avoid Deprecated `configure`:** Do **not** use the three-parameter 
`configure(Type, Properties, ServiceRegistry)` method in `IdentifierGenerator` 
(or its subclasses like `SequenceStyleGenerator`). It is marked for removal in 
Hibernate 7.
-- **Prefer modern initialization:** Use the `GeneratorCreationContext` 
provided by `setCustomIdGeneratorCreator` to perform initialization.
-
-### GrailsIncrementGenerator Status
-- **Progress:** Table name resolution has been fixed by prioritizing 
`domainClass.getMappedForm().getTableName()`.
-- **Remaining Issue:** `IncrementGenerator` in Hibernate 7 requires explicit 
call to `initialize(SqlStringGenerationContext)` or it throws NPE during 
`generate()`. Current GORM initialization flow needs adjustment to provide this 
context at the right time.
-
 ## Strategy for GrailsDomainBinder Refactoring
 
-### Goal
-To decompose the monolithic `GrailsDomainBinder` (over 2000 lines) into 
smaller, specialized binder classes within the 
`org.grails.orm.hibernate.cfg.domainbinding` package.
-
-### Refactoring Progress
-- [x] `SimpleIdBinder`: Orchestrates binding of simple identifiers.
-- [x] `PropertyBinder`: Binds `PersistentProperty` to Hibernate `Property`.
-- [x] `ManyToOneBinder`: Specialized binder for many-to-one associations.
-- [x] `SimpleValueBinder`: Handles binding of simple values to Hibernate 
`SimpleValue`.
-
-## Future Steps
-
-1.  **Complete Increment Generator Fix:** Implement a mechanism to call 
`initialize()` on `GrailsIncrementGenerator` with a valid 
`SqlStringGenerationContext`.
-2.  **Address `Session.save()` usage:** Systematically find and replace 
`save()` with `persist()` or `merge()` across the codebase and TCK where direct 
Hibernate session access is used.
-3.  **Resolve Dirty Checking Test:** Investigate why `@DirtyCheck` AST 
transformation is not providing `hasChanged()` in the 
`HibernateDirtyCheckingSpec` test environment.
-
-## Current Task: Multi-module Refactoring and Test Fixing
-
-The current task involves extensive modifications and additions across 
multiple `grails-data-hibernate` modules (`hibernate5`, `hibernate6`, and 
`hibernate7`).
-
-**Objective:**
-To align the testing infrastructure and add specific proxy handler tests 
across different Hibernate versions.
-
-**Steps to be completed (blocked by agent's working directory limitations):**
-
-1.  **Add `GrailsDataHibernate5TckManager` to `grails-data-hibernate5`:** 
Create a `GrailsDataHibernate5TckManager.groovy` based on 
`GrailsDataHibernate7TckManager` in 
`grails-data-hibernate5/core/src/test/groovy/org/apache/grails/data/hibernate5/core/`.
-2.  **Add `HibernateGormDatastoreSpec` to `grails-data-hibernate5`:** Create a 
`HibernateGormDatastoreSpec.groovy` based on the existing 
`grails.gorm.specs.HibernateGormDatastoreSpec` in 
`grails-data-hibernate5/core/src/test/groovy/grails/gorm/specs/`, adapted to 
use `GrailsDataHibernate5TckManager`.
-3.  **Add `HibernateProxyHandlerSpec` to `grails-data-hibernate5`, 
`grails-data-hibernate6`, and `grails-data-hibernate7`:**
-    *   For each module, create `HibernateProxyHandlerSpec.groovy` in 
`[module]/core/src/test/groovy/org/grails/orm/hibernate/proxy/`.
-    *   This test will extend the respective module's 
`HibernateGormDatastoreSpec`.
-    *   The test content will validate `isInitialized`, `unwrap`, and 
`getIdentifier` methods of `HibernateProxyHandler`.
-4.  **Make tests pass in sequence:**
-    *   Run and fix tests for `grails-data-hibernate5`.
-    *   Run and fix tests for `grails-data-hibernate6`.
-    *   Run and fix tests for `grails-data-hibernate7`.
-
-**Current Blocking Issue:**
-The `read_file` and `write_file` tools are strictly confined to the agent's 
initial launch directory: 
`/Users/walterduquedeestrada/IdeaProjects/grails-core/grails-data-hibernate7/core`.
-
-To proceed with creating and modifying files in other modules 
(`grails-data-hibernate5`, `grails-data-hibernate6`), the agent's working 
directory needs to be moved to the root of the entire `grails-core` project: 
`/Users/walterduquedeestrada/IdeaProjects/grails-core`.
\ No newline at end of file
+## Future Steps
\ No newline at end of file
diff --git 
a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/proxy/HibernateProxyHandler.java
 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/proxy/HibernateProxyHandler.java
index cd3e9f11a1..4baa06a419 100644
--- 
a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/proxy/HibernateProxyHandler.java
+++ 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/proxy/HibernateProxyHandler.java
@@ -1,33 +1,42 @@
 /*
- * Copyright 2004-2008 the original author or authors.
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
  *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ *    https://www.apache.org/licenses/LICENSE-2.0
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
  */
 package org.grails.orm.hibernate.proxy;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import java.io.Serializable;
+
+import groovy.lang.GroovyObject;
+import groovy.lang.MetaClass;
+import org.codehaus.groovy.runtime.HandleMetaClass;
+import org.hibernate.Hibernate;
+import org.hibernate.collection.spi.PersistentCollection;
+import org.hibernate.proxy.HibernateProxy;
+import org.hibernate.proxy.HibernateProxyHelper;
+
+import org.grails.datastore.gorm.proxy.ProxyInstanceMetaClass;
 import org.grails.datastore.mapping.core.Session;
 import org.grails.datastore.mapping.engine.AssociationQueryExecutor;
 import org.grails.datastore.mapping.proxy.EntityProxy;
 import org.grails.datastore.mapping.proxy.ProxyFactory;
 import org.grails.datastore.mapping.proxy.ProxyHandler;
 import org.grails.datastore.mapping.reflect.ClassPropertyFetcher;
-import org.hibernate.Hibernate;
-import org.hibernate.collection.spi.PersistentCollection;
-import org.hibernate.proxy.HibernateProxy;
-import org.hibernate.proxy.HibernateProxyHelper;
-
-import java.io.Serializable;
-
 import org.grails.orm.hibernate.GrailsHibernateTemplate;
 
 /**
@@ -39,16 +48,43 @@ import org.grails.orm.hibernate.GrailsHibernateTemplate;
  */
 public class HibernateProxyHandler implements ProxyHandler, ProxyFactory {
 
+    private static final Logger LOG = 
LoggerFactory.getLogger(HibernateProxyHandler.class);
+
     /**
      * Check if the proxy or persistent collection is initialized.
      * {@inheritDoc}
      */
     @Override
     public boolean isInitialized(Object o) {
+        if (o == null) {
+            LOG.info("isInitialized(Object) - object is null, returning 
false");
+            return false;
+        }
+        LOG.info("isInitialized(Object) - checking object of type: {}", 
o.getClass().getName());
         if (o instanceof EntityProxy) {
-            return ((EntityProxy)o).isInitialized();
+            boolean initialized = ((EntityProxy) o).isInitialized();
+            LOG.info("isInitialized(Object) - object is EntityProxy, 
isInitialized: {}", initialized);
+            return initialized;
+        }
+        if (o instanceof HibernateProxy) {
+            boolean initialized = !((HibernateProxy) 
o).getHibernateLazyInitializer().isUninitialized();
+            LOG.info("isInitialized(Object) - object is HibernateProxy, 
isInitialized: {}", initialized);
+            return initialized;
         }
-        return Hibernate.isInitialized(o);
+        if (o instanceof PersistentCollection) {
+            boolean initialized = ((PersistentCollection) o).wasInitialized();
+            LOG.info("isInitialized(Object) - object is PersistentCollection, 
wasInitialized: {}", initialized);
+            return initialized;
+        }
+        ProxyInstanceMetaClass proxyMc = getProxyInstanceMetaClass(o);
+        if (proxyMc != null) {
+            boolean initialized = proxyMc.isProxyInitiated();
+            LOG.info("isInitialized(Object) - object is Groovy Proxy, 
isProxyInitiated: {}", initialized);
+            return initialized;
+        }
+        boolean initialized = Hibernate.isInitialized(o);
+        LOG.info("isInitialized(Object) - Hibernate.isInitialized returned: 
{}", initialized);
+        return initialized;
     }
 
     /**
@@ -57,11 +93,15 @@ public class HibernateProxyHandler implements ProxyHandler, 
ProxyFactory {
      */
     @Override
     public boolean isInitialized(Object obj, String associationName) {
+        LOG.info("isInitialized(Object, String) - checking association '{}' on 
object of type: {}", associationName, obj != null ? obj.getClass().getName() : 
"null");
         try {
             Object proxy = ClassPropertyFetcher.getInstancePropertyValue(obj, 
associationName);
-            return isInitialized(proxy);
+            boolean initialized = isInitialized(proxy);
+            LOG.info("isInitialized(Object, String) - association '{}' 
isInitialized: {}", associationName, initialized);
+            return initialized;
         }
         catch (RuntimeException e) {
+            LOG.info("isInitialized(Object, String) - RuntimeException 
occurred while checking association '{}', returning false", associationName);
             return false;
         }
     }
@@ -77,6 +117,10 @@ public class HibernateProxyHandler implements ProxyHandler, 
ProxyFactory {
         if (object instanceof EntityProxy) {
             return ((EntityProxy)object).getTarget();
         }
+        ProxyInstanceMetaClass proxyMc = getProxyInstanceMetaClass(object);
+        if (proxyMc != null) {
+            return proxyMc.getProxyTarget();
+        }
         if (object instanceof PersistentCollection) {
             initialize(object);
             return object;
@@ -93,6 +137,10 @@ public class HibernateProxyHandler implements ProxyHandler, 
ProxyFactory {
         if (o instanceof EntityProxy) {
             return ((EntityProxy)o).getProxyKey();
         }
+        ProxyInstanceMetaClass proxyMc = getProxyInstanceMetaClass(o);
+        if (proxyMc != null) {
+            return proxyMc.getKey();
+        }
         if (o instanceof HibernateProxy) {
             return (Serializable) 
((HibernateProxy)o).getHibernateLazyInitializer().getIdentifier();
         }
@@ -125,6 +173,9 @@ public class HibernateProxyHandler implements ProxyHandler, 
ProxyFactory {
      */
     @Override
     public boolean isProxy(Object o) {
+        if (getProxyInstanceMetaClass(o) != null) {
+            return true;
+        }
         return (o instanceof EntityProxy) || (o instanceof HibernateProxy)  || 
(o instanceof PersistentCollection);
     }
 
@@ -138,8 +189,32 @@ public class HibernateProxyHandler implements 
ProxyHandler, ProxyFactory {
             ((EntityProxy)o).initialize();
         }
         else {
-            Hibernate.initialize(o);
+            ProxyInstanceMetaClass proxyMc = getProxyInstanceMetaClass(o);
+            if (proxyMc != null) {
+                proxyMc.getProxyTarget();
+            }
+            else {
+                Hibernate.initialize(o);
+            }
+        }
+    }
+
+    private ProxyInstanceMetaClass getProxyInstanceMetaClass(Object o) {
+        LOG.info("getProxyInstanceMetaClass() - checking if object is 
GroovyObject: {}", o != null ? o.getClass().getName() : "null");
+        if (o instanceof GroovyObject) {
+            MetaClass mc = ((GroovyObject) o).getMetaClass();
+            LOG.info("getProxyInstanceMetaClass() - metaClass type: {}", 
mc.getClass().getName());
+            if (mc instanceof HandleMetaClass) {
+                mc = ((HandleMetaClass) mc).getAdaptee();
+                LOG.info("getProxyInstanceMetaClass() - handleMetaClass 
adaptee type: {}", mc.getClass().getName());
+            }
+            if (mc instanceof ProxyInstanceMetaClass) {
+                LOG.info("getProxyInstanceMetaClass() - found 
ProxyInstanceMetaClass");
+                return (ProxyInstanceMetaClass) mc;
+            }
         }
+        LOG.info("getProxyInstanceMetaClass() - no ProxyInstanceMetaClass 
found");
+        return null;
     }
 
     @Override
@@ -183,4 +258,4 @@ public class HibernateProxyHandler implements ProxyHandler, 
ProxyFactory {
             return null;
         }
     }
-}
\ No newline at end of file
+}
diff --git 
a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/HibernateGormStaticApiSpec.groovy
 
b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/HibernateGormStaticApiSpec.groovy
index b92fdd5475..acc3718ae1 100644
--- 
a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/HibernateGormStaticApiSpec.groovy
+++ 
b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/HibernateGormStaticApiSpec.groovy
@@ -13,6 +13,24 @@ class HibernateGormStaticApiSpec extends 
HibernateGormDatastoreSpec {
         manager.addAllDomainClasses([HibernateGormStaticApiEntity,Club])
     }
 
+    void "proxy test"() {
+        given:
+        def entity = new Club(name: "test").save(flush: true, failOnError: 
true)
+        println "SAVED ENTITY"
+        manager.session.clear()
+        println "CLEARED SESSION"
+        when:
+        println "CALLING PROXY"
+        def same = Club.proxy(entity.id)
+        println "CALLED PROXY"
+        then:
+        same != null
+        println "CHECKING INITIALIZED"
+        !datastore.mappingContext.proxyFactory.isInitialized(same)
+        println "CHECKED INITIALIZED"
+        same.id == entity.id
+    }
+
     void "Test that get returns the correct instance"() {
         given:
         def entity = new HibernateGormStaticApiEntity(name: 
"test").save(flush: true, failOnError: true)


Reply via email to