This is an automated email from the ASF dual-hosted git repository.
borinquenkid pushed a commit to branch 8.0.x-hibernate7-dev
in repository https://gitbox.apache.org/repos/asf/grails-core.git
The following commit(s) were added to refs/heads/8.0.x-hibernate7-dev by this
push:
new 427a910068 hibernate 7: Partial ByteBuddy implementation 2
427a910068 is described below
commit 427a9100687354413a7675f78a32f482eb6b17f6
Author: Walter Duque de Estrada <[email protected]>
AuthorDate: Sat Mar 21 00:56:08 2026 -0500
hibernate 7:
Partial ByteBuddy implementation 2
---
grails-data-hibernate7/core/build.gradle | 1 +
.../cfg/HibernateMappingContextConfiguration.java | 7 ++
.../proxy/ByteBuddyGroovyProxyFactory.java | 23 +++++--
.../hibernate/proxy/GrailsBytecodeProvider.java | 74 ++++++++++++++++++++++
.../hibernate/proxy/GrailsProxyFactoryFactory.java | 49 ++++++++++++++
5 files changed, 148 insertions(+), 6 deletions(-)
diff --git a/grails-data-hibernate7/core/build.gradle
b/grails-data-hibernate7/core/build.gradle
index 188fa62be9..8c34e5400d 100644
--- a/grails-data-hibernate7/core/build.gradle
+++ b/grails-data-hibernate7/core/build.gradle
@@ -46,6 +46,7 @@ dependencies {
api 'org.apache.groovy:groovy'
api project(':grails-datamapping-core')
api 'org.springframework:spring-orm'
+ implementation "net.bytebuddy:byte-buddy:1.18.7"
api "org.hibernate.orm:hibernate-core:$hibernate7Version", {
exclude group:'commons-logging', module:'commons-logging'
exclude group:'com.h2database', module:'h2'
diff --git
a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContextConfiguration.java
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContextConfiguration.java
index cd3e5bb7f1..e592c3c713 100644
---
a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContextConfiguration.java
+++
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContextConfiguration.java
@@ -49,6 +49,7 @@ import
org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.boot.spi.AdditionalMappingContributor;
import org.hibernate.cfg.AvailableSettings;
+import org.hibernate.cfg.BytecodeSettings;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.cfg.JdbcSettings;
@@ -265,6 +266,12 @@ public class HibernateMappingContextConfiguration extends
Configuration
*/
@Override
public SessionFactory buildSessionFactory() throws HibernateException {
+ // 1. FORCE the custom bytecode provider instance right before
bootstrap
+ // This bypasses the ServiceLoader and ensures your
GrailsBytecodeProvider is used.
+ getProperties().put(
+ BytecodeSettings.BYTECODE_PROVIDER_INSTANCE,
+ new org.grails.orm.hibernate.proxy.GrailsBytecodeProvider()
+ );
// set the class loader to load Groovy classes
diff --git
a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/proxy/ByteBuddyGroovyProxyFactory.java
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/proxy/ByteBuddyGroovyProxyFactory.java
index d2d9f1df42..3ebdfd373d 100644
---
a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/proxy/ByteBuddyGroovyProxyFactory.java
+++
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/proxy/ByteBuddyGroovyProxyFactory.java
@@ -73,8 +73,13 @@ public class ByteBuddyGroovyProxyFactory extends
ByteBuddyProxyFactory {
this.setIdentifierMethod = setIdentifierMethod;
this.componentIdType = componentIdType;
this.overridesEquals = ReflectHelper.overridesEquals(persistentClass);
+
+ // Build the proxy class using the helper
this.proxyClass = byteBuddyProxyHelper.buildProxy(persistentClass,
this.interfaces);
- super.postInstantiate(entityName, persistentClass, interfaces,
getIdentifierMethod, setIdentifierMethod, componentIdType);
+
+ // DO NOT call super.postInstantiate(entityName, ...)
+ // because it will try to initialize the standard Hibernate
ProxyFactory fields
+ // which might conflict with your custom getProxy() logic.
}
@Override
@@ -92,12 +97,18 @@ public class ByteBuddyGroovyProxyFactory extends
ByteBuddyProxyFactory {
overridesEquals
);
- final PrimeAmongSecondarySupertypes instance =
(PrimeAmongSecondarySupertypes) proxyClass.getConstructor().newInstance();
- final HibernateProxy hibernateProxy = instance.asHibernateProxy();
-
hibernateProxy.asProxyConfiguration().$$_hibernate_set_interceptor(interceptor);
- return hibernateProxy;
+ // 1. Create the instance
+ final Object instance =
proxyClass.getDeclaredConstructor().newInstance();
+
+ // 2. Cast to ProxyConfiguration to set the custom interceptor
+ // Hibernate 7 proxies implement ProxyConfiguration
+ if (instance instanceof org.hibernate.proxy.ProxyConfiguration) {
+ ((org.hibernate.proxy.ProxyConfiguration)
instance).$$_hibernate_set_interceptor(interceptor);
+ }
+
+ return (HibernateProxy) instance;
} catch (Throwable t) {
- throw new HibernateException("Unable to generate proxy", t);
+ throw new HibernateException("Unable to generate proxy for " +
entityName, t);
}
}
}
diff --git
a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/proxy/GrailsBytecodeProvider.java
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/proxy/GrailsBytecodeProvider.java
new file mode 100644
index 0000000000..43044f3fd7
--- /dev/null
+++
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/proxy/GrailsBytecodeProvider.java
@@ -0,0 +1,74 @@
+/*
+ * 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
+ *
+ * https://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.
+ */
+package org.grails.orm.hibernate.proxy;
+
+import java.util.Map;
+
+import org.hibernate.bytecode.enhance.spi.Enhancer;
+import org.hibernate.bytecode.enhance.spi.EnhancementContext;
+import org.hibernate.bytecode.spi.BytecodeProvider;
+import org.hibernate.bytecode.spi.ProxyFactoryFactory;
+import org.hibernate.bytecode.spi.ReflectionOptimizer;
+import org.hibernate.proxy.pojo.bytebuddy.ByteBuddyProxyHelper;
+import org.hibernate.property.access.spi.PropertyAccess;
+
+/**
+ * A {@link BytecodeProvider} implementation for Hibernate 7 that provides
Groovy-aware proxies.
+ *
+ * @author Graeme Rocher
+ * @since 7.0
+ */
+public class GrailsBytecodeProvider implements BytecodeProvider {
+
+ private final ByteBuddyProxyHelper proxyHelper;
+
+ public GrailsBytecodeProvider() {
+ this.proxyHelper = new ByteBuddyProxyHelper(new
org.hibernate.bytecode.internal.bytebuddy.ByteBuddyState());
+ }
+
+ public ByteBuddyProxyHelper getProxyHelper() {
+ return proxyHelper;
+ }
+
+ @Override
+ public ProxyFactoryFactory getProxyFactoryFactory() {
+ return new GrailsProxyFactoryFactory(this);
+ }
+
+ @Override
+ public ReflectionOptimizer getReflectionOptimizer(
+ Class clazz,
+ String[] getterNames,
+ String[] setterNames,
+ Class[] types) {
+ return null;
+ }
+
+ @Override
+ public ReflectionOptimizer getReflectionOptimizer(
+ Class<?> clazz,
+ Map<String, PropertyAccess> propertyAccessMap) {
+ return null;
+ }
+
+ @Override
+ public Enhancer getEnhancer(EnhancementContext enhancementContext) {
+ return null;
+ }
+}
diff --git
a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/proxy/GrailsProxyFactoryFactory.java
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/proxy/GrailsProxyFactoryFactory.java
new file mode 100644
index 0000000000..1453c8958f
--- /dev/null
+++
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/proxy/GrailsProxyFactoryFactory.java
@@ -0,0 +1,49 @@
+/*
+ * 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
+ *
+ * https://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.
+ */
+package org.grails.orm.hibernate.proxy;
+
+import org.hibernate.bytecode.spi.BasicProxyFactory;
+import org.hibernate.bytecode.spi.ProxyFactoryFactory;
+import org.hibernate.engine.spi.SessionFactoryImplementor;
+import org.hibernate.proxy.ProxyFactory;
+
+/**
+ * A {@link ProxyFactoryFactory} implementation for Hibernate 7 that provides
Groovy-aware proxies.
+ *
+ * @author Graeme Rocher
+ * @since 7.0
+ */
+public class GrailsProxyFactoryFactory implements ProxyFactoryFactory {
+
+ private final GrailsBytecodeProvider grailsBytecodeProvider;
+
+ public GrailsProxyFactoryFactory(GrailsBytecodeProvider
grailsBytecodeProvider) {
+ this.grailsBytecodeProvider = grailsBytecodeProvider;
+ }
+
+ @Override
+ public ProxyFactory buildProxyFactory(SessionFactoryImplementor
sessionFactory) {
+ return new
ByteBuddyGroovyProxyFactory(grailsBytecodeProvider.getProxyHelper());
+ }
+
+ @Override
+ public BasicProxyFactory buildBasicProxyFactory(Class
superClassOrInterface) {
+ return null;
+ }
+}