HHH-17154 Fix NullPointerException is thrown when constructing EntityManagerFactoryBuilderImpl

This commit is contained in:
Christian Beikov 2023-09-01 11:38:39 +02:00
parent b82d4c3c74
commit c0fa25ade6
7 changed files with 77 additions and 10 deletions

View File

@ -167,9 +167,14 @@ public class EnhancerImpl implements Enhancer {
if ( originalBytes != null ) {
classFileLocator.setClassNameAndBytes( className, originalBytes );
}
final TypeDescription typeDescription = typePool.describe( className ).resolve();
enhancementContext.registerDiscoveredType( typeDescription, Type.PersistenceType.ENTITY );
enhancementContext.discoverCompositeTypes( typeDescription, typePool );
try {
final TypeDescription typeDescription = typePool.describe( className ).resolve();
enhancementContext.registerDiscoveredType( typeDescription, Type.PersistenceType.ENTITY );
enhancementContext.discoverCompositeTypes( typeDescription, typePool );
}
catch (RuntimeException e) {
throw new EnhancementException( "Failed to discover types for class " + className, e );
}
}
private TypePool buildTypePool(final ClassFileLocator classFileLocator) {

View File

@ -31,5 +31,16 @@ public interface Enhancer {
*/
byte[] enhance(String className, byte[] originalBytes) throws EnhancementException;
void discoverTypes(String className, byte[] originalBytes);
/**
* Discovers types prior to enhancement.
*
* It is possible to invoke this method concurrently.
*
* @param className The name of the class whose bytecode is being analyzed for type discovery.
* @param originalBytes The class's original (pre-enhancement) byte code
*
* @throws EnhancementException Indicates a problem during type discovery
* @since 6.3
*/
void discoverTypes(String className, byte[] originalBytes) throws EnhancementException;
}

View File

@ -43,5 +43,5 @@ public interface ClassTransformer extends jakarta.persistence.spi.ClassTransform
ProtectionDomain protectionDomain,
byte[] classfileBuffer) throws TransformerException;
void discoverTypes(ClassLoader loader, String entityClassName);
void discoverTypes(ClassLoader loader, String className);
}

View File

@ -1861,4 +1861,9 @@ public interface CoreMessageLogger extends BasicLogger {
id = 515)
HibernateException nullIdentitySelectString();
@LogMessage(level = WARN)
@Message(value = "Failed to discover types for enhancement from class: %s",
id = 516)
void enhancementDiscoveryFailed(String className, @Cause Throwable cause);
}

View File

@ -31,6 +31,10 @@ import org.hibernate.boot.beanvalidation.BeanValidationIntegrator;
import org.hibernate.boot.cfgxml.spi.CfgXmlAccessService;
import org.hibernate.boot.cfgxml.spi.LoadedConfig;
import org.hibernate.boot.cfgxml.spi.MappingReference;
import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmHibernateMapping;
import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmRootEntityType;
import org.hibernate.boot.jaxb.spi.BindableMappingDescriptor;
import org.hibernate.boot.jaxb.spi.Binding;
import org.hibernate.boot.model.TypeContributor;
import org.hibernate.boot.model.convert.internal.ClassBasedConverterDescriptor;
import org.hibernate.boot.model.convert.spi.ConverterDescriptor;
@ -50,6 +54,7 @@ import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.boot.spi.SessionFactoryBuilderImplementor;
import org.hibernate.bytecode.enhance.spi.DefaultEnhancementContext;
import org.hibernate.bytecode.enhance.spi.EnhancementContext;
import org.hibernate.bytecode.enhance.spi.EnhancementException;
import org.hibernate.bytecode.enhance.spi.UnloadedClass;
import org.hibernate.bytecode.enhance.spi.UnloadedField;
import org.hibernate.bytecode.spi.ClassTransformer;
@ -347,11 +352,34 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
if ( classLoader == null ) {
throw persistenceException( "Enhancement requires a temp class loader, but none was given." );
}
for ( PersistentClass entityBinding : metadata.getEntityBindings() ) {
if ( entityBinding.getClassName() != null ) {
classTransformer.discoverTypes( classLoader, entityBinding.getClassName() );
for ( Binding<BindableMappingDescriptor> binding : metadataSources.getXmlBindings() ) {
final BindableMappingDescriptor root = binding.getRoot();
if ( root instanceof JaxbHbmHibernateMapping ) {
final JaxbHbmHibernateMapping hibernateMapping = (JaxbHbmHibernateMapping) root;
final String packageName = hibernateMapping.getPackage();
for ( JaxbHbmRootEntityType clazz : hibernateMapping.getClazz() ) {
final String className;
if ( packageName == null || packageName.isEmpty() ) {
className = clazz.getName();
}
else {
className = packageName + '.' + clazz.getName();
}
try {
classTransformer.discoverTypes( classLoader, className );
}
catch (EnhancementException ex) {
LOG.enhancementDiscoveryFailed( className, ex );
}
}
}
}
for ( String annotatedClassName : metadataSources.getAnnotatedClassNames() ) {
classTransformer.discoverTypes( classLoader, annotatedClassName );
}
for ( Class<?> annotatedClass : metadataSources.getAnnotatedClasses() ) {
classTransformer.discoverTypes( classLoader, annotatedClass.getName() );
}
}
}

View File

@ -57,8 +57,8 @@ public class EnhancingClassTransformerImpl implements ClassTransformer {
}
@Override
public void discoverTypes(ClassLoader loader, String entityClassName) {
getEnhancer( loader ).discoverTypes( entityClassName, null );
public void discoverTypes(ClassLoader loader, String className) {
getEnhancer( loader ).discoverTypes( className, null );
}
private Enhancer getEnhancer(ClassLoader loader) {

View File

@ -42,11 +42,13 @@ import org.hibernate.integrator.spi.Integrator;
import org.hibernate.jpa.HibernatePersistenceProvider;
import org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl;
import org.hibernate.jpa.boot.internal.PersistenceUnitInfoDescriptor;
import org.hibernate.jpa.boot.spi.EntityManagerFactoryBuilder;
import org.hibernate.orm.test.mapping.basic.bitset.BitSetType;
import org.hibernate.orm.test.mapping.basic.bitset.BitSetUserType;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.spi.SessionFactoryServiceRegistry;
import org.hibernate.testing.orm.junit.JiraKey;
import org.junit.Test;
import jakarta.persistence.AttributeConverter;
@ -322,6 +324,22 @@ public class BootstrapTest {
}
}
@Test
@JiraKey("HHH-17154")
public void build_EntityManagerFactory_with_NewTempClassLoader() {
new EntityManagerFactoryBuilderImpl(
new PersistenceUnitInfoDescriptor(
new PersistenceUnitInfoImpl( "", new ArrayList<>(), new Properties() ) {
@Override
public ClassLoader getNewTempClassLoader() {
return Thread.currentThread().getContextClassLoader();
}
}
),
new HashMap<>()
).cancel();
}
public Object getBeanManager() {
return null;
}