NullPointerException during enhancement when using the default BytecodeProvider in Wildfly
Description
caused by
Activity
Sanne Grinovero February 5, 2024 at 10:17 AM
Hi @Scott Marlow , 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 @Scott Marlow, 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 @Sanne Grinovero?
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 https://hibernate.atlassian.net/browse/HHH-17643 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
@Scott Marlow 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 @Sanne Grinovero. Do you happen to have an idea why this might be a problem in Wildfly?
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 https://github.com/scottmarlow/wildfly/tree/WFLY-18989_orm6.4.3 branch which I created to upgrade to 6.4.3.
Steps to recreate with WildFly:
git clone https://github.com/scottmarlow/wildfly
cd wildfly
git checkout WFLY-18989_orm6.4.3
./build.sh clean install
-DskipTests=true
cd testsuite/integration/basic/
mvn clean install -Dtest=org.jboss.as.test.integration.jpa.resourceref.DataSourceResourceReferenceTestCase
mvn clean install -Dtest=org.jboss.as.test.integration.jpa.datasourcedefinition.DataSourceDefinitionJPATestCase