Skip to content

Commit a19c955

Browse files
committed
Support new Hibernate proxy class naming scheme in ClassUtils isProxy/isProxyClass
The naming scheme changed in 6.6.12: https://hibernate.atlassian.net/browse/HHH-14694
1 parent 3de7789 commit a19c955

File tree

5 files changed

+104
-6
lines changed

5 files changed

+104
-6
lines changed

build.gradle

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,6 @@ dependencies {
4545
}
4646
}
4747

48-
dependencyLocking {
49-
lockAllConfigurations()
50-
}
51-
5248
jacocoTestReport {
5349
reports {
5450
xml.required = true
@@ -159,6 +155,9 @@ dependencies {
159155
testImplementation "org.javassist:javassist:latest.release"
160156
testImplementation "nl.jqno.equalsverifier:equalsverifier:latest.release"
161157

158+
testImplementation 'org.hibernate.orm:hibernate-core:latest.release'
159+
testRuntimeOnly 'com.h2database:h2:latest.release'
160+
162161
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
163162

164163
testImplementation "org.openjdk.jmh:jmh-core:latest.release"
@@ -167,4 +166,14 @@ dependencies {
167166
// no real transitive dependency but we use it to annotate method contracts to help the IDE understand the code
168167
compileOnly "org.jetbrains:annotations:latest.release"
169168
testCompileOnly "org.jetbrains:annotations:latest.release"
169+
170+
dependencyLocking {
171+
lockAllConfigurations()
172+
}
173+
174+
components.all { ComponentMetadataDetails details ->
175+
if (details.id.version =~ /(?i).+(-|\.)(CANDIDATE|RC|BETA|ALPHA|PR|M\d+|CR\d+).*/) {
176+
details.status = 'milestone'
177+
}
178+
}
170179
}

gradle.lockfile

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,36 @@
11
# This is a Gradle generated file for dependency locking.
22
# Manual edits can break the build and are not advised.
33
# This file is expected to be part of source control.
4+
com.fasterxml:classmate:1.7.0=testRuntimeClasspath
5+
com.h2database:h2:2.3.232=testRuntimeClasspath
6+
com.sun.istack:istack-commons-runtime:4.1.2=testRuntimeClasspath
7+
jakarta.activation:jakarta.activation-api:2.1.3=testRuntimeClasspath
8+
jakarta.inject:jakarta.inject-api:2.0.1=testRuntimeClasspath
9+
jakarta.persistence:jakarta.persistence-api:3.2.0=testCompileClasspath,testRuntimeClasspath
10+
jakarta.transaction:jakarta.transaction-api:2.0.1=testCompileClasspath,testRuntimeClasspath
411
jakarta.validation:jakarta.validation-api:3.1.1=testCompileClasspath,testRuntimeClasspath
12+
jakarta.xml.bind:jakarta.xml.bind-api:4.0.2=testRuntimeClasspath
513
net.bytebuddy:byte-buddy-agent:1.17.5=testCompileClasspath,testRuntimeClasspath
614
net.bytebuddy:byte-buddy:1.17.6=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
715
net.sf.jopt-simple:jopt-simple:5.0.4=testCompileClasspath,testRuntimeClasspath
816
nl.jqno.equalsverifier:equalsverifier:4.0.7=testCompileClasspath,testRuntimeClasspath
17+
org.antlr:antlr4-runtime:4.13.2=testRuntimeClasspath
918
org.apache.commons:commons-lang3:3.18.0=testCompileClasspath,testRuntimeClasspath
1019
org.apache.commons:commons-math3:3.6.1=testCompileClasspath,testRuntimeClasspath
1120
org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath
1221
org.assertj:assertj-core:3.27.3=testCompileClasspath,testRuntimeClasspath
22+
org.eclipse.angus:angus-activation:2.0.2=testRuntimeClasspath
23+
org.glassfish.jaxb:jaxb-core:4.0.5=testRuntimeClasspath
24+
org.glassfish.jaxb:jaxb-runtime:4.0.5=testRuntimeClasspath
25+
org.glassfish.jaxb:txw2:4.0.5=testRuntimeClasspath
26+
org.hibernate.models:hibernate-models:1.0.0=testRuntimeClasspath
27+
org.hibernate.orm:hibernate-core:7.0.8.Final=testCompileClasspath,testRuntimeClasspath
1328
org.jacoco:org.jacoco.agent:0.8.13=jacocoAgent,jacocoAnt
1429
org.jacoco:org.jacoco.ant:0.8.13=jacocoAnt
1530
org.jacoco:org.jacoco.core:0.8.13=jacocoAnt
1631
org.jacoco:org.jacoco.report:0.8.13=jacocoAnt
1732
org.javassist:javassist:3.30.2-GA=testCompileClasspath,testRuntimeClasspath
33+
org.jboss.logging:jboss-logging:3.6.1.Final=testRuntimeClasspath
1834
org.jetbrains:annotations:26.0.2=compileClasspath,testCompileClasspath
1935
org.junit.jupiter:junit-jupiter-api:5.13.4=testCompileClasspath,testRuntimeClasspath
2036
org.junit.jupiter:junit-jupiter-engine:5.13.4=testRuntimeClasspath

src/main/java/de/cronn/reflection/util/ClassUtils.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ public final class ClassUtils {
1919

2020
private static final String JAVASSIST_CLASS_SEPARATOR = "$$";
2121
private static final String BYTE_BUDDY_CLASS_SEPARATOR = "$ByteBuddy$";
22-
private static final String HIBERNATE_PROXY_CLASS_SEPARATOR = "$HibernateProxy$";
22+
private static final String HIBERNATE_OLD_PROXY_CLASS_SEPARATOR = "$HibernateProxy$";
23+
private static final String HIBERNATE_NEW_PROXY_CLASS_SUFFIX = "$HibernateProxy";
2324

2425
private static final ClassValue<Set<MethodSignature>> methodsSignaturesCache = ClassValues.create(ClassUtils::getAllDeclaredMethodSignatures);
2526

@@ -167,7 +168,8 @@ public static boolean isProxyClass(Class<?> clazz) {
167168
static boolean matchesWellKnownProxyClassNamePattern(String className) {
168169
return className.contains(BYTE_BUDDY_CLASS_SEPARATOR)
169170
|| className.contains(JAVASSIST_CLASS_SEPARATOR)
170-
|| className.contains(HIBERNATE_PROXY_CLASS_SEPARATOR);
171+
|| className.contains(HIBERNATE_OLD_PROXY_CLASS_SEPARATOR)
172+
|| className.endsWith(HIBERNATE_NEW_PROXY_CLASS_SUFFIX);
171173
}
172174

173175
public static boolean haveSameSignature(Method oneMethod, Method otherMethod) {

src/test/java/de/cronn/reflection/util/ClassUtilsTest.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import java.util.stream.Collectors;
1515
import java.util.stream.Stream;
1616

17+
import org.hibernate.proxy.HibernateProxy;
1718
import org.junit.jupiter.api.Test;
1819
import org.junit.jupiter.params.ParameterizedTest;
1920
import org.junit.jupiter.params.provider.Arguments;
@@ -256,6 +257,17 @@ void testIsProxyClass() throws Exception {
256257
assertThat(ClassUtils.isProxyClass(null)).isFalse();
257258
}
258259

260+
@Test
261+
void testIsProxyClass_Hibernate() throws Exception {
262+
HibernateProxyTestUtil.runWithHibernateProxy(personProxy -> {
263+
assertThat(personProxy).isInstanceOf(HibernateProxy.class);
264+
assertThat(personProxy.getClass().getSimpleName()).endsWith("$Person$HibernateProxy");
265+
266+
assertThat(ClassUtils.isProxy(personProxy)).isTrue();
267+
assertThat(ClassUtils.isProxyClass(personProxy.getClass())).isTrue();
268+
});
269+
}
270+
259271
@Test
260272
void testHasMethodWithSameSignature_happyPath_shouldMatchMethodSignature_whenReturnTypeAndNameAndParametersAreEqual() throws Exception {
261273
Method targetMethod = findMethod(SomeClass.class, "doWork", int.class);
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package de.cronn.reflection.util;
2+
3+
import java.util.function.Consumer;
4+
5+
import org.hibernate.Session;
6+
import org.hibernate.SessionFactory;
7+
import org.hibernate.boot.MetadataSources;
8+
import org.hibernate.boot.registry.StandardServiceRegistry;
9+
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
10+
11+
import jakarta.persistence.Entity;
12+
import jakarta.persistence.GeneratedValue;
13+
import jakarta.persistence.Id;
14+
15+
class HibernateProxyTestUtil {
16+
17+
@Entity
18+
public static class Person {
19+
20+
@Id
21+
@GeneratedValue
22+
private Long id;
23+
24+
private String name;
25+
26+
public Long getId() {
27+
return id;
28+
}
29+
30+
public String getName() {
31+
return name;
32+
}
33+
34+
public void setName(String name) {
35+
this.name = name;
36+
}
37+
}
38+
39+
static void runWithHibernateProxy(Consumer<Person> hibernateProxyConsumer) {
40+
StandardServiceRegistry registry = new StandardServiceRegistryBuilder()
41+
.applySetting("hibernate.connection.driver_class", "org.h2.Driver")
42+
.applySetting("hibernate.connection.url", "jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1")
43+
.applySetting("hibernate.dialect", "org.hibernate.dialect.H2Dialect")
44+
.applySetting("hibernate.hbm2ddl.auto", "create-drop")
45+
.build();
46+
47+
SessionFactory sessionFactory = new MetadataSources(registry)
48+
.addAnnotatedClass(Person.class)
49+
.buildMetadata()
50+
.buildSessionFactory();
51+
52+
try (Session session = sessionFactory.openSession()) {
53+
Person personProxy = session.getReference(Person.class, 123L);
54+
hibernateProxyConsumer.accept(personProxy);
55+
} finally {
56+
sessionFactory.close();
57+
}
58+
}
59+
}

0 commit comments

Comments
 (0)