Hibernate custom Scanner problem in Wildfly

I have set a Scanner in a web application that runs on wildfly 20. All of the settings are Ok and Hibernate bootstrap finds settings and create the scanner class( say ScannerImpl) properly but ScanningCoordinator fails to construct an instance of the ScannerImpl because of, I think, the class-loader mismatch problem. The following code snippets are taken from ScanningCoordinator to describe the problem

private static final Class[] SINGLE_ARG = new Class[] { ArchiveDescriptorFactory.class };

final Constructor<? extends Scanner> constructor = scannerImplClass.getConstructor( SINGLE_ARG );

The ScannerImpl has a constructor with a param of ArchiveDescriptorFactory type, but the above code fails to find the constructor. because :

  • ArchiveDescriptorFactory is loaded with Module Classloader(for org.hibernate module) and
  • ScannerImpl and the ArchiveDescriptorFactory param in the constructor is loaded by TempClassloader via hibernate ClassLoaderService

In the case of no-param constructor of the ScannerImpl, the constructor is found, and an instance of the ScannerImpl is created but because of the same reason, the operation fails in returning the created instance.

How can I fix this problem?

I think you should ask this in the Wildfly forum since it seems to be related to the class loader structure. Do you have a stacktrace to share?

thank you for your advice
as you told, it is a class loading problem but I don’t know how to solve it. I would try Wildfly forum.
however, I put here some portions of the stack trace that are related to this problem

12:02:07,035 ERROR [org.jboss.msc.service.fail] (ServerService Thread Pool -- 80) MSC000001: Failed to start service jboss.persistenceunit."serp.webapp-1.0.1#SERP3PU".__FIRST_PHASE__: org.jboss.msc.service.StartException in service jboss.persistenceunit."serp.webapp-1.0.1#SERP3PU".__FIRST_PHASE__: java.lang.IllegalStateException: Error trying to instantiate custom specified Scanner [serp3.base.xt.entity.jpa.SerpScanner]
	at org.jboss.as.jpa@20.0.1.Final//org.jboss.as.jpa.service.PhaseOnePersistenceUnitServiceImpl$1$1.run(PhaseOnePersistenceUnitServiceImpl.java:128)
	at org.jboss.as.jpa@20.0.1.Final//org.jboss.as.jpa.service.PhaseOnePersistenceUnitServiceImpl$1$1.run(PhaseOnePersistenceUnitServiceImpl.java:104)
	at org.wildfly.security.elytron-private@1.12.1.Final//org.wildfly.security.manager.WildFlySecurityManager.doChecked(WildFlySecurityManager.java:658)
	at org.jboss.as.jpa@20.0.1.Final//org.jboss.as.jpa.service.PhaseOnePersistenceUnitServiceImpl$1.run(PhaseOnePersistenceUnitServiceImpl.java:137)
	at org.jboss.threads@2.3.3.Final//org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
	at org.jboss.threads@2.3.3.Final//org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1982)
	at org.jboss.threads@2.3.3.Final//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1486)
	at org.jboss.threads@2.3.3.Final//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1377)
	at java.base/java.lang.Thread.run(Thread.java:832)
	at org.jboss.threads@2.3.3.Final//org.jboss.threads.JBossThread.run(JBossThread.java:485)
Caused by: java.lang.IllegalStateException: Error trying to instantiate custom specified Scanner [serp3.base.xt.entity.jpa.SerpScanner]
	at org.hibernate@5.3.17.Final//org.hibernate.boot.model.process.internal.ScanningCoordinator.buildScanner(ScanningCoordinator.java:171)
	at org.hibernate@5.3.17.Final//org.hibernate.boot.model.process.internal.ScanningCoordinator.coordinateScan(ScanningCoordinator.java:75)
	at org.hibernate@5.3.17.Final//org.hibernate.boot.model.process.spi.MetadataBuildingProcess.prepare(MetadataBuildingProcess.java:99)
	at org.hibernate@5.3.17.Final//org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.<init>(EntityManagerFactoryBuilderImpl.java:240)
	at org.hibernate@5.3.17.Final//org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.<init>(EntityManagerFactoryBuilderImpl.java:168)
	at org.hibernate@5.3.17.Final//org.hibernate.jpa.boot.spi.Bootstrap.getEntityManagerFactoryBuilder(Bootstrap.java:32)
	at org.hibernate@5.3.17.Final//org.hibernate.jpa.boot.spi.Bootstrap.getEntityManagerFactoryBuilder(Bootstrap.java:89)
	at org.hibernate.jipijapa-hibernate5-3@20.0.1.Final//org.jboss.as.jpa.hibernate5.TwoPhaseBootstrapImpl.<init>(TwoPhaseBootstrapImpl.java:39)
	at org.hibernate.jipijapa-hibernate5-3@20.0.1.Final//org.jboss.as.jpa.hibernate5.HibernatePersistenceProviderAdaptor.getBootstrap(HibernatePersistenceProviderAdaptor.java:252)
	at org.jboss.as.jpa@20.0.1.Final//org.jboss.as.jpa.service.PhaseOnePersistenceUnitServiceImpl.createContainerEntityManagerFactoryBuilder(PhaseOnePersistenceUnitServiceImpl.java:254)
	at org.jboss.as.jpa@20.0.1.Final//org.jboss.as.jpa.service.PhaseOnePersistenceUnitServiceImpl.access$900(PhaseOnePersistenceUnitServiceImpl.java:59)
	at org.jboss.as.jpa@20.0.1.Final//org.jboss.as.jpa.service.PhaseOnePersistenceUnitServiceImpl$1$1.run(PhaseOnePersistenceUnitServiceImpl.java:125)
	... 9 more
Caused by: java.lang.ClassCastException: class serp3.base.xt.entity.jpa.SerpScanner cannot be cast to class org.hibernate.boot.archive.scan.spi.Scanner (serp3.base.xt.entity.jpa.SerpScanner is in unnamed module of loader org.jboss.as.jpa.classloader.TempClassLoader @5204caf3; org.hibernate.boot.archive.scan.spi.Scanner is in unnamed module of loader 'org.hibernate@5.3.17.Final' @4b62348)
	at org.hibernate@5.3.17.Final//org.hibernate.boot.model.process.internal.ScanningCoordinator.buildScanner(ScanningCoordinator.java:166)
	... 20 more

You could try to declare a dependency on the hibernate Wildfly module by providing a jboss-deployment-structure.xml. Does your deployment contain a hibernate JAR? If so, it might be enough to just remove that.

Hi,

  • a module dependency to org.hibernate module is defined in the project.

  • when the Hibernate is included as a lib along with the project, has no any effect on the problem.

I think this is a bug of Hibernate internals. Because, in the case of setting the scanner by class name, the scanner class is loaded with temp class loader but the ScanningCoordinator itself is loaded with module class loader. in this way, all of the time a class cast problem occurs and it is not possible to set scanner with its class name.

however, based on Hibernate’s internal logic(materialized in org.hibernate.boot.internal.ClassLoaderAccessImpl), it is possible to fool the ScanningCoordinator with putting Scanner implementation in package structure starting with org.hibernate or java or javax and bypass the temp class loader usage. in this case class loader service is used for loading the Scanner and this solves the problem.

Please create an issue in the Hibernate issue tracker(https://hibernate.atlassian.net), ideally with a test case(hibernate-test-case-templates/JPAUnitTestCase.java at main · hibernate/hibernate-test-case-templates · GitHub) that reproduces the issue.

  1. the following issue is created :
    [HHH-14712] Hibernate custom Scanner problem in Wildfly - Hibernate JIRA

  2. The test case template is not suitable for this case that Hibernate is bootstrapped by a container. I wonder if is there a test case template for the cases where Hibernate is used in a container ?

Thanks for creating the issue. Maybe you should also create a Wildfly issue and provide an Arquillian test for this scenario. I think you can base the test roughly on what you can find here: wildfly/SessionFactoryTestCase.java at master · wildfly/wildfly · GitHub