matrei opened a new issue, #16423:
URL: https://github.com/apache/grails-core/issues/16423

   With `grails-data-hibernate7` 8.0.0-RC1, saving a new instance of a domain 
class annotated with `@ManagedEntity` fails with an `AssertionError` whenever 
JVM assertions are enabled (`-ea`). Gradle's `Test` tasks turn assertions on by 
default, so any integration test that boots the application and saves such an 
entity (e.g. in `BootStrap`) fails to load the application context.
   
   `HibernateEntityTransformation` adds the `$$_hibernate_instanceId` field 
with an initial value of `-1`:
   
   ```groovy
   // 
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/compiler/HibernateEntityTransformation.groovy:187
   FieldNode instanceIdField = classNode.addField(instanceIdFieldName, 
Modifier.PRIVATE | Modifier.TRANSIENT, ClassHelper.int_TYPE, constX(-1))
   ```
   
   Hibernate 7 expects an entity that is not yet associated with a persistence 
context to have an instance id of `0`:
   
   ```java
   // org.hibernate.engine.internal.EntityEntryContext#addEntityEntry 
(hibernate-core 7.4.10.Final, line 98)
   if ( isManagedEntity( entity ) ) {
       final var managed = asManagedEntity( entity );
       assert managed.$$_hibernate_getInstanceId() == 0;
   ```
   
   Hibernate's own bytecode enhancer 
(`EnhancerImpl#addFieldWithGetterAndSetter`) defines this field without an 
initializer, so enhanced entities start at `0`.
   
   When assertions are disabled, the value is overwritten through 
`$$_hibernate_setPersistenceInfo(...)` as soon as the entity is associated, so 
production behavior appears unaffected. The mismatch still violates Hibernate's 
contract, and it breaks any test run with assertions enabled.
   
   The issue is still present on the `8.0.x` and `8.1.x` branches.
   
   ### Expected Behavior
   
   The entity is saved.
   
   ### Actual Behaviour
   
   ```
   Caused by: java.lang.AssertionError
       at 
org.hibernate.engine.internal.EntityEntryContext.addEntityEntry(EntityEntryContext.java:98)
       at 
org.hibernate.engine.internal.StatefulPersistenceContext.addEntry(StatefulPersistenceContext.java:675)
       at 
org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:280)
       ...
       at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:692)
       at 
org.grails.orm.hibernate.HibernateGormInstanceApi$_performPersist_closure6.doCall(HibernateGormInstanceApi.groovy:400)
   ```
   
   ### Steps To Reproduce
   
   1. Create a Grails 8.0.0-RC1 app using `grails-hibernate7-bom` / 
`grails-data-hibernate7`.
   2. Annotate a domain class with 
`@grails.gorm.hibernate.annotation.ManagedEntity`.
   3. Save a new instance, e.g. in `BootStrap`: `new Role(authority: 
'ROLE_USER').save(failOnError: true)`.
   4. Run with assertions enabled, e.g. `./gradlew integrationTest`.
   
   ### Suggested Fix
   
   Initialize the field to `0` (or add it without an initial expression), 
matching Hibernate's enhancer:
   
   ```diff
   -FieldNode instanceIdField = classNode.addField(instanceIdFieldName, 
Modifier.PRIVATE | Modifier.TRANSIENT, ClassHelper.int_TYPE, constX(-1))
   +FieldNode instanceIdField = classNode.addField(instanceIdFieldName, 
Modifier.PRIVATE | Modifier.TRANSIENT, ClassHelper.int_TYPE, constX(0))
   ```
   
   It would also help to have a test in `HibernateEntityTransformationSpec` 
asserting that a new instance returns `0` from `$$_hibernate_getInstanceId()`, 
and to run the hibernate7 test suite with assertions enabled.
   
   ### Workaround
   
   Disable assertions for that Hibernate class in the test JVMs. A 
class-specific `-da:` switch takes precedence over a global `-ea`:
   
   ```groovy
   tasks.withType(Test).configureEach {
       jvmArgs('-da:org.hibernate.engine.internal.EntityEntryContext')
   }
   ```
   
   ### Environment Information
   
   - Hibernate ORM 7.4.10.Final
   - Groovy 5.1.3, Spring Boot 4.1.1
   - JDK 21, Gradle 9.7.1
   
   ### Example Application
   
   _No response_
   
   ### Version
   
   8.0.0-RC1
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to