Skip to content

Commit

Permalink
HHH-17154 Fix NullPointerException is thrown when constructing Entity…
Browse files Browse the repository at this point in the history
…ManagerFactoryBuilderImpl
  • Loading branch information
beikov committed Sep 1, 2023
1 parent b82d4c3 commit c0fa25a
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 10 deletions.
Expand Up @@ -167,9 +167,14 @@ public void discoverTypes(String className, byte[] originalBytes) {
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) {
Expand Down
Expand Up @@ -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;
}
Expand Up @@ -43,5 +43,5 @@ byte[] transform(
ProtectionDomain protectionDomain,
byte[] classfileBuffer) throws TransformerException;

void discoverTypes(ClassLoader loader, String entityClassName);
void discoverTypes(ClassLoader loader, String className);
}
Expand Up @@ -1861,4 +1861,9 @@ void attemptToAssociateProxyWithTwoOpenSessions(
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);

}
Expand Up @@ -31,6 +31,10 @@
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;
Expand All @@ -50,6 +54,7 @@
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;
Expand Down Expand Up @@ -347,11 +352,34 @@ private EntityManagerFactoryBuilderImpl(
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() );
}
}
}

Expand Down
Expand Up @@ -57,8 +57,8 @@ public byte[] transform(
}

@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) {
Expand Down
Expand Up @@ -42,11 +42,13 @@
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;
Expand Down Expand Up @@ -322,6 +324,22 @@ public void test_bootstrap_bootstrap_native_EntityManagerFactory_example() {
}
}

@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;
}
Expand Down

0 comments on commit c0fa25a

Please sign in to comment.