HHH-16911 Integration test for SessionFactory using callbacks to not leak ClassLoader
This commit is contained in:
parent
6ff15ff3fb
commit
f3e11f1610
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.orm.test.bootstrap.registry.classloading;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.EntityManagerFactory;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.PrePersist;
|
||||
import jakarta.persistence.Transient;
|
||||
|
||||
/**
|
||||
* A test scenario to be used with {@link HibernateClassLoaderLeaksTest};
|
||||
* the crucial aspect is that we're triggering a lookup of a JPA callback
|
||||
* method.
|
||||
*/
|
||||
public class HibernateCallbacksTestAction extends HibernateLoadingTestAction {
|
||||
|
||||
protected void actionOnHibernate(EntityManagerFactory emf) {
|
||||
try (final EntityManager entityManager = emf.createEntityManager() ) {
|
||||
Booking b = new Booking();
|
||||
b.id = Long.valueOf( 1l );
|
||||
entityManager.persist( b ); //to trigger the @PrePersist invocation
|
||||
}
|
||||
}
|
||||
|
||||
protected List<String> getManagedClassNames() {
|
||||
return Collections.singletonList( Booking.class.getName() );
|
||||
}
|
||||
|
||||
@Entity(name = "booking")
|
||||
private static class Booking {
|
||||
@Id Long id;
|
||||
@Transient String legacyIdentifier;
|
||||
|
||||
@PrePersist
|
||||
public void computeLegacyIdentifier() {
|
||||
//Details are not important, just making something up.
|
||||
if ( legacyIdentifier == null && id != null ) {
|
||||
this.legacyIdentifier = id.toString();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -58,6 +58,11 @@ public class HibernateClassLoaderLeaksTest {
|
|||
ClassLoaderLeakDetector.assertNotLeakingAction( HibernateLoadingTestAction.class.getName() );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hibernateDoesNotLeakClassloaderWithCallbacks() {
|
||||
ClassLoaderLeakDetector.assertNotLeakingAction( HibernateCallbacksTestAction.class.getName() );
|
||||
}
|
||||
|
||||
private static void cleanup(Driver driver) {
|
||||
System.out.println( "Attempting de-registration of driver: " + driver );
|
||||
try {
|
||||
|
|
|
@ -9,9 +9,12 @@ package org.hibernate.orm.test.bootstrap.registry.classloading;
|
|||
import java.sql.Driver;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.jpa.boot.spi.Bootstrap;
|
||||
import org.hibernate.orm.test.jpa.BaseEntityManagerFunctionalTestCase;
|
||||
|
||||
|
@ -22,25 +25,50 @@ import jakarta.persistence.EntityManagerFactory;
|
|||
* this is meant to test against classloader leaks, so needs
|
||||
* to be packaged as a Runnable rather than using our usual
|
||||
* testing facilities.
|
||||
* @see HibernateClassLoaderLeaksTest
|
||||
*/
|
||||
public class HibernateLoadingTestAction extends NotLeakingTestAction implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
public final void run() {
|
||||
super.run(); //for basic sanity self-check
|
||||
final Map config = new HashMap();
|
||||
EntityManagerFactory emf = Bootstrap.getEntityManagerFactoryBuilder(
|
||||
new BaseEntityManagerFunctionalTestCase.TestingPersistenceUnitDescriptorImpl( getClass().getSimpleName() ),
|
||||
new BaseEntityManagerFunctionalTestCase.TestingPersistenceUnitDescriptorImpl( getClass().getSimpleName() ) {
|
||||
@Override
|
||||
public boolean isExcludeUnlistedClasses() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getManagedClassNames() {
|
||||
return HibernateLoadingTestAction.this.getManagedClassNames();
|
||||
}
|
||||
},
|
||||
config
|
||||
).build();
|
||||
try {
|
||||
emf.close();
|
||||
checkExpectedClassLoader( emf.unwrap( SessionFactory.class ).getClass() );
|
||||
actionOnHibernate( emf );
|
||||
}
|
||||
finally {
|
||||
cleanupJDBCDrivers();
|
||||
try {
|
||||
emf.close();
|
||||
}
|
||||
finally {
|
||||
cleanupJDBCDrivers();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void actionOnHibernate(EntityManagerFactory emf) {
|
||||
//no-op
|
||||
}
|
||||
|
||||
protected List<String> getManagedClassNames() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private void cleanupJDBCDrivers() {
|
||||
DriverManager.drivers().forEach( this::deregister );
|
||||
}
|
||||
|
|
|
@ -14,7 +14,11 @@ public class NotLeakingTestAction implements Runnable {
|
|||
|
||||
@Override
|
||||
public void run() {
|
||||
final ClassLoader owningClassloader = getClass().getClassLoader();
|
||||
checkExpectedClassLoader( getClass() );
|
||||
}
|
||||
|
||||
protected void checkExpectedClassLoader(Class aClass) {
|
||||
final ClassLoader owningClassloader = aClass.getClassLoader();
|
||||
if ( !owningClassloader.getName().equals( "TestIsolatedIsolatedClassLoader" ) ) {
|
||||
throw new IllegalStateException( "Not being loaded by the expected classloader" );
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue