Skip to content

Commit 399fdea

Browse files
committed
Initial work on reproducing trouble we've seen with RefletionOptimizer caused by a class on the classpath twice (EAR and WAR e.g.)
1 parent 55c5838 commit 399fdea

File tree

5 files changed

+246
-0
lines changed

5 files changed

+246
-0
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.orm.test.bytecode.duplication;
6+
7+
import jakarta.persistence.EntityManagerFactory;
8+
import org.hibernate.engine.spi.SessionFactoryImplementor;
9+
10+
/**
11+
* To be loaded reflectively...
12+
*
13+
* @author Steve Ebersole
14+
*/
15+
public class Client {
16+
public static void execute(EntityManagerFactory emf) {
17+
emf.runInTransaction( (entityManager) -> {
18+
entityManager.persist( new SimpleEntity( 1, "tester" ) );
19+
entityManager.createQuery( "from SimpleEntity" ).getResultList();
20+
} );
21+
}
22+
23+
public static void cleanup(EntityManagerFactory emf) {
24+
emf.unwrap( SessionFactoryImplementor.class ).getSchemaManager().truncateMappedObjects();
25+
}
26+
}
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.orm.test.bytecode.duplication;
6+
7+
import jakarta.persistence.EntityManagerFactory;
8+
import jakarta.persistence.Persistence;
9+
import org.hibernate.dialect.H2Dialect;
10+
import org.hibernate.testing.orm.junit.BaseUnitTest;
11+
import org.hibernate.testing.orm.junit.RequiresDialect;
12+
import org.jboss.shrinkwrap.api.ArchivePath;
13+
import org.jboss.shrinkwrap.api.ArchivePaths;
14+
import org.jboss.shrinkwrap.api.ShrinkWrap;
15+
import org.jboss.shrinkwrap.api.exporter.ZipExporter;
16+
import org.jboss.shrinkwrap.api.spec.JavaArchive;
17+
import org.junit.jupiter.api.AfterEach;
18+
import org.junit.jupiter.api.BeforeEach;
19+
import org.junit.jupiter.api.Test;
20+
import org.junit.jupiter.api.io.TempDir;
21+
22+
import java.io.File;
23+
import java.lang.reflect.InvocationTargetException;
24+
import java.lang.reflect.Method;
25+
import java.net.MalformedURLException;
26+
import java.net.URL;
27+
import java.net.URLClassLoader;
28+
29+
30+
/**
31+
* @author Steve Ebersole
32+
*/
33+
@BaseUnitTest
34+
@RequiresDialect( H2Dialect.class )
35+
public class DuplicateClassTests {
36+
private ClassLoader originalTccl;
37+
38+
@BeforeEach
39+
void storeOriginalTccl() {
40+
originalTccl = Thread.currentThread().getContextClassLoader();
41+
}
42+
43+
@AfterEach
44+
void restoreOriginalTccl() {
45+
Thread.currentThread().setContextClassLoader( originalTccl );
46+
}
47+
48+
@Test
49+
void testSimple(@TempDir File tempDir)
50+
throws MalformedURLException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
51+
ArchivePath path = ArchivePaths.create( "META-INF/persistence.xml" );
52+
53+
JavaArchive jar1 = ShrinkWrap.create( JavaArchive.class, "jar1.jar" );
54+
jar1.addClasses( SimpleEntity.class );
55+
jar1.addAsResource( "units/bytecode/duplication/pu1.xml", path );
56+
File jar1File = new File( tempDir, "jar1.jar" );
57+
jar1.as( ZipExporter.class ).exportTo( jar1File, true );
58+
59+
JavaArchive jar2 = ShrinkWrap.create( JavaArchive.class, "jar2.jar" );
60+
jar2.addClasses( SimpleEntity.class );
61+
jar2.addAsResource( "units/bytecode/duplication/pu2.xml", path );
62+
File jar2File = new File( tempDir, "jar2.jar" );
63+
jar2.as( ZipExporter.class ).exportTo( jar2File, true );
64+
65+
URL[] jarUrls = new URL[] {
66+
jar1File.toURI().toURL(),
67+
jar2File.toURI().toURL()
68+
};
69+
final URLClassLoader classLoader = new URLClassLoader( jarUrls, getClass().getClassLoader() );
70+
Thread.currentThread().setContextClassLoader( classLoader );
71+
72+
try (EntityManagerFactory emf1 = Persistence.createEntityManagerFactory( "unit-1" )) {
73+
executeUseCases( classLoader, emf1 );
74+
}
75+
try (EntityManagerFactory emf2 = Persistence.createEntityManagerFactory( "unit-2" )) {
76+
executeUseCases( classLoader, emf2 );
77+
}
78+
79+
{
80+
JavaArchive jar3 = ShrinkWrap.create( JavaArchive.class, "jar3.jar" );
81+
jar3.addClasses( SimpleEntity.class );
82+
jar3.addAsResource( "units/bytecode/duplication/pu1.xml", path );
83+
File jar3File = new File( tempDir, "jar3.jar" );
84+
jar3.as( ZipExporter.class ).exportTo( jar3File, true );
85+
86+
URL[] secondaryUrls = new URL[] { jar3File.toURI().toURL() };
87+
final URLClassLoader secondaryClassLoader = new URLClassLoader( secondaryUrls, getClass().getClassLoader() );
88+
Thread.currentThread().setContextClassLoader( secondaryClassLoader );
89+
90+
try (EntityManagerFactory emf3 = Persistence.createEntityManagerFactory( "unit-1" )) {
91+
executeUseCases( classLoader, emf3 );
92+
}
93+
}
94+
}
95+
96+
private void executeUseCases(URLClassLoader classLoader, EntityManagerFactory entityManagerFactory)
97+
throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
98+
final Class<?> clientClass = classLoader.loadClass( "org.hibernate.orm.test.bytecode.duplication.Client" );
99+
final Method executeMethod = clientClass.getDeclaredMethod( "execute", EntityManagerFactory.class );
100+
final Method cleanupMethod = clientClass.getDeclaredMethod( "cleanup", EntityManagerFactory.class );
101+
102+
try {
103+
executeMethod.invoke( null, entityManagerFactory );
104+
}
105+
finally {
106+
cleanupMethod.invoke( null, entityManagerFactory );
107+
}
108+
109+
}
110+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.orm.test.bytecode.duplication;
6+
7+
import jakarta.persistence.Entity;
8+
import jakarta.persistence.Id;
9+
10+
/**
11+
* @author Steve Ebersole
12+
*/
13+
@Entity
14+
public class SimpleEntity {
15+
@Id
16+
private Integer id;
17+
private String name;
18+
19+
public SimpleEntity() {
20+
}
21+
22+
public SimpleEntity(Integer id, String name) {
23+
this.id = id;
24+
this.name = name;
25+
}
26+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<!--
2+
~ SPDX-License-Identifier: Apache-2.0
3+
~ Copyright Red Hat Inc. and Hibernate Authors
4+
-->
5+
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
6+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
7+
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
8+
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
9+
version="2.1">
10+
11+
<persistence-unit name="unit-1">
12+
<description>
13+
Persistence unit for Hibernate User Guide
14+
</description>
15+
16+
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
17+
18+
<class>org.hibernate.orm.test.bytecode.duplication.SimpleEntity</class>
19+
20+
<properties>
21+
<property name="jakarta.persistence.jdbc.driver"
22+
value="org.h2.Driver" />
23+
24+
<property name="jakarta.persistence.jdbc.url"
25+
value="jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1" />
26+
27+
<property name="jakarta.persistence.jdbc.user"
28+
value="sa" />
29+
30+
<property name="jakarta.persistence.jdbc.password"
31+
value="" />
32+
33+
<property name="hibernate.show_sql"
34+
value="true" />
35+
36+
<property name="hibernate.hbm2ddl.auto"
37+
value="update" />
38+
</properties>
39+
40+
</persistence-unit>
41+
42+
</persistence>
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<!--
2+
~ SPDX-License-Identifier: Apache-2.0
3+
~ Copyright Red Hat Inc. and Hibernate Authors
4+
-->
5+
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
6+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
7+
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
8+
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
9+
version="2.1">
10+
11+
<persistence-unit name="unit-2">
12+
<description>
13+
Persistence unit for Hibernate User Guide
14+
</description>
15+
16+
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
17+
18+
<class>org.hibernate.orm.test.bytecode.duplication.SimpleEntity</class>
19+
20+
<properties>
21+
<property name="jakarta.persistence.jdbc.driver"
22+
value="org.h2.Driver" />
23+
24+
<property name="jakarta.persistence.jdbc.url"
25+
value="jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1" />
26+
27+
<property name="jakarta.persistence.jdbc.user"
28+
value="sa" />
29+
30+
<property name="jakarta.persistence.jdbc.password"
31+
value="" />
32+
33+
<property name="hibernate.show_sql"
34+
value="true" />
35+
36+
<property name="hibernate.hbm2ddl.auto"
37+
value="update" />
38+
</properties>
39+
40+
</persistence-unit>
41+
42+
</persistence>

0 commit comments

Comments
 (0)