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() );
|
ClassLoaderLeakDetector.assertNotLeakingAction( HibernateLoadingTestAction.class.getName() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void hibernateDoesNotLeakClassloaderWithCallbacks() {
|
||||||
|
ClassLoaderLeakDetector.assertNotLeakingAction( HibernateCallbacksTestAction.class.getName() );
|
||||||
|
}
|
||||||
|
|
||||||
private static void cleanup(Driver driver) {
|
private static void cleanup(Driver driver) {
|
||||||
System.out.println( "Attempting de-registration of driver: " + driver );
|
System.out.println( "Attempting de-registration of driver: " + driver );
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -9,9 +9,12 @@ package org.hibernate.orm.test.bootstrap.registry.classloading;
|
||||||
import java.sql.Driver;
|
import java.sql.Driver;
|
||||||
import java.sql.DriverManager;
|
import java.sql.DriverManager;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.hibernate.SessionFactory;
|
||||||
import org.hibernate.jpa.boot.spi.Bootstrap;
|
import org.hibernate.jpa.boot.spi.Bootstrap;
|
||||||
import org.hibernate.orm.test.jpa.BaseEntityManagerFunctionalTestCase;
|
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
|
* this is meant to test against classloader leaks, so needs
|
||||||
* to be packaged as a Runnable rather than using our usual
|
* to be packaged as a Runnable rather than using our usual
|
||||||
* testing facilities.
|
* testing facilities.
|
||||||
|
* @see HibernateClassLoaderLeaksTest
|
||||||
*/
|
*/
|
||||||
public class HibernateLoadingTestAction extends NotLeakingTestAction implements Runnable {
|
public class HibernateLoadingTestAction extends NotLeakingTestAction implements Runnable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public final void run() {
|
||||||
super.run(); //for basic sanity self-check
|
super.run(); //for basic sanity self-check
|
||||||
final Map config = new HashMap();
|
final Map config = new HashMap();
|
||||||
EntityManagerFactory emf = Bootstrap.getEntityManagerFactoryBuilder(
|
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
|
config
|
||||||
).build();
|
).build();
|
||||||
try {
|
try {
|
||||||
emf.close();
|
checkExpectedClassLoader( emf.unwrap( SessionFactory.class ).getClass() );
|
||||||
|
actionOnHibernate( emf );
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
cleanupJDBCDrivers();
|
try {
|
||||||
|
emf.close();
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
cleanupJDBCDrivers();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void actionOnHibernate(EntityManagerFactory emf) {
|
||||||
|
//no-op
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<String> getManagedClassNames() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
private void cleanupJDBCDrivers() {
|
private void cleanupJDBCDrivers() {
|
||||||
DriverManager.drivers().forEach( this::deregister );
|
DriverManager.drivers().forEach( this::deregister );
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,11 @@ public class NotLeakingTestAction implements Runnable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
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" ) ) {
|
if ( !owningClassloader.getName().equals( "TestIsolatedIsolatedClassLoader" ) ) {
|
||||||
throw new IllegalStateException( "Not being loaded by the expected classloader" );
|
throw new IllegalStateException( "Not being loaded by the expected classloader" );
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue