NullPointerException during enhancement when using the default BytecodeProvider in Wildfly

Description

https://issues.redhat.com/browse/WFLY-18989 is for upgrading WildFly to Hibernate ORM 6.4.3 but I noticed a few failures with WildFly tests that enable bytecode enhancement. See full exceptions in WFLY-18989.

Tests org.jboss.as.test.integration.jpa.resourceref.DataSourceResourceReferenceTestCase + org.jboss.as.test.integration.jpa.datasourcedefinition.DataSourceDefinitionJPATestCase are failing due to:

Caused by: java.lang.IllegalStateException: WFLYJPA0073: Bytecode rewrite (transformation) of class org/jboss/as/test/integration/jpa/datasourcedefinition/SFSBXPC$Proxy$_$$_Weld$EnterpriseProxy$ failed"}}}}

and

Caused by: java.lang.ClassFormatError: WFLYJPA0073: Bytecode rewrite (transformation) of class org/jboss/as/test/integration/jpa/resourceref/MyEjb$Proxy$_$$_Weld$EnterpriseProxy$ failed

We only see this problem with Hibernate ORM 6.4.3 on my branch which I created to upgrade to 6.4.3.

 

Steps to recreate with WildFly:

 

  1. git clone https://github.com/scottmarlow/wildfly

  2. cd wildfly

  3. git checkout WFLY-18989_orm6.4.3

  4. ./build.sh clean install -DskipTests=true

  5. cd testsuite/integration/basic/

  6. mvn clean install -Dtest=org.jboss.as.test.integration.jpa.resourceref.DataSourceResourceReferenceTestCase

  7. mvn clean install -Dtest=org.jboss.as.test.integration.jpa.datasourcedefinition.DataSourceDefinitionJPATestCase

Activity

Show:

Sanne Grinovero February 5, 2024 at 10:17 AM

Hi , my knowledge of JBoss Modules is a bit rusty, but I believe we might need to ensure that the new service is visible?

I suspect adding services="export" on the module.xml of the Hibernate could help? I’m trying to test it but the amount of dependencies that Maven wants me to download… it’s going to take some time :)

I’m NOT sure we’d want to universally export all services to everyone; perhaps - assuming the above suggestion confirms being on the right path - we’d want the specific WildFly module which is performing the enhancement to import this particular service only: narrow the scope to the miminum we need.

Marco Belladelli February 2, 2024 at 9:58 PM

Thanks for the suggestion , that’s exactly what I did. From my testing, we previously relied on a static method that always returned a new instance of the Byte Buddy implementation for BytecodeProvider. That method now tries loading the service from the current thread’s context ClassLoader, but doesn’t find anything so it defaults to the non-enhancing provider - this eventually causes the test failure further down the line.

Now, I’m not sure why in that call there is no BytecodeProvider service available (specifically this is in EnhancingClassTransformerImpl’s constructor), but looking at logs we later initialize the service through BytecodeProviderInitiator#initiateService that uses Hibernate's custom ClassLoaderService and we are able to find the Byte Buddy provider instance then. My best guess is either we’re supposed to use a different class loader the first time or we should just default to the “enhancing” implementation (i.i. Byte Buddy) for that specific case.

WDYT ?

Scott Marlow February 2, 2024 at 8:25 PM

The two unit tests that are failing are the only tests configured to run with entity bytecode enhancement enabled via WildFly persistence unit property hint :

<property name="jboss.as.jpa.classtransformer" value="true"/>

I think that the test is failing because something changed that causes Hibernate ORM to enhance additional application classes including the Weld (CDI related) proxy classes mentioned in the error message. For example “org/jboss/as/test/integration/jpa/datasourcedefinition/SFSBXPC$Proxy$_$$_Weld$EnterpriseProxy$" which is generated during application deployment to support CDI requirements. This particular generated (Weld) class is for application source file https://github.com/wildfly/wildfly/blob/main/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/jpa/datasourcedefinition/SFSBXPC.java which references application entity classes but is not an entity class itself (it is an EJB bean).

Is it possible that the change is somehow causing some other code in Hibernate ORM to enhance more application classes than we were previously?

My best guess to get to the bottom of understanding why this is happening is to instrument the ORM enhancement code with “prints of class being enhanced” + “Thread.dumpStack()” so we might see the call stack involved with enhancing the datasourcedefinition/SFSBXPC$Proxy$_$$_Weld$EnterpriseProxy$ class.

Marco Belladelli February 2, 2024 at 8:04 PM

Small update, ran the tests again with a modified Hibernate version and confirmed we’re finding the Byte Buddy implementation of BytecodeProvider as a service.

Marco Belladelli February 2, 2024 at 7:47 PM

I tried running the tests with a locally modified version of Hibernate 6.4.3 after removing only the 2 commits related to the Jira we mentioned and indeed it seems that’s the culprit of the error.

Within that Jira we changed how Hibernate determines the default bytecode provider to use: from always defaulting to the Byte Buddy bytecode provider implementation, unless the hibernate.bytecode.provider configuration property was explicitly set to none, we now load the instance through ServiceLoader.load( BytecodeProvider.class ). If no service is found, we now default to the "empty" bytecode provider. Within hibernate-core we expose a provider configuration file that should result in applications defaulting to Byte Buddy even after this change.

This was done to circumvent some issues related to native image compilation, as suggested by . Do you happen to have an idea why this might be a problem in Wildfly?

Fixed

Details

Assignee

Reporter

Components

Sprint

Fix versions

Priority

Created February 2, 2024 at 3:33 PM
Updated March 27, 2024 at 1:11 PM
Resolved February 5, 2024 at 4:18 PM
Loading...