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

   **Expected Behavior**
   
   Reading and writing a trait-backed property through 
`TraitPropertyAccessStrategy` works. The
   strategy resolves the property to the private, name-mangled field that 
Groovy generates on the
   implementing class and builds a field-based `Getter`/`Setter` over it, so it 
must make that field
   accessible before the accessors are used.
   
   **Actual Behaviour**
   
   The first read or write through the strategy fails:
   
   ```
   org.hibernate.PropertyAccessException: Could not set field value [value] 
value by reflection :
       [class ...FieldAccessProbeEntity.probeField]
       at 
org.hibernate.property.access.spi.SetterFieldImpl.set(SetterFieldImpl.java:72)
   Caused by: java.lang.IllegalAccessException: class 
org.hibernate.property.access.spi.SetterFieldImpl
       cannot access a member of class ...FieldAccessProbeEntity with modifiers 
"private"
   ```
   
   `grails-data-hibernate7` reproduces the same failure (Hibernate 7 reports it 
as
   `Could not set value of type [java.lang.String]`).
   
   **Steps To Reproduce**
   
   On `8.0.x` (verified at `0e8fd03e56c2574e87ac824cd7831221e803873d`; the 
`grails-data-hibernate5`
   strategy is identical on `7.0.x`):
   
   ```groovy
   trait FieldAccessProbe {
       String probeField
   }
   
   class FieldAccessProbeEntity implements FieldAccessProbe { }
   
   def "field-based access to a trait property reads back what the setter 
wrote"() {
       given:
       def entity = new FieldAccessProbeEntity()
       def access = new TraitPropertyAccessStrategy()
               .buildPropertyAccess(FieldAccessProbeEntity, 'probeField')
   
       when:
       access.setter.set(entity, 'value') // h5: set(entity, 'value', null)
   
       then:
       access.getter.get(entity) == 'value'
   }
   ```
   
   **Environment Information**
   
   - Operating System: Linux x86_64
   - JDK Version: 21 (`8.0.x`), 17 (`7.0.x`)
   - Gradle: wrapper 9.8.0 (`8.0.x`), 8.14.5 (`7.0.x`)
   - Hibernate: 5.6 (`grails-data-hibernate5`), 7.x (`grails-data-hibernate7`)
   
   **Version**
   
   `8.0.x` (verified). The `grails-data-hibernate5` code is identical on 
`7.0.x`, `7.1.x`, `7.2.x`,
   `8.1.x` and `9.0.x`.
   
   **Root cause and notes**
   
   - `TraitPropertyAccessStrategy#buildPropertyAccess` obtains the generated 
field with Spring's
     `ReflectionUtils.findField` and never makes it accessible, unlike 
Hibernate's field access path
     (`ReflectHelper.findField`) and Grails' 
`FieldEntityAccess.ReaderAndWriterMaker`, which both call
     `makeAccessible` for the same field.
   - The standard GORM flow can mask this: on `grails-data-hibernate5`,
     `FieldEntityAccess.ReaderAndWriterMaker` makes the field accessible while 
building the mapping
     model, before Hibernate builds its property accessors; on 
`grails-data-hibernate7` the default
     access type is `PROPERTY`, so the strategy is not selected by default. The 
strategy still needs
     to be correct in isolation.
   - Affected versions:
     - `grails-data-hibernate5`: all maintained lines (`7.0.x`, `7.1.x`, 
`7.2.x`, `8.0.x`, `8.1.x`,
       `9.0.x`).
     - `grails-data-hibernate7`: `8.0.x` and later (`8.1.x`, `9.0.x`); the 
module does not exist on 7.x.
   - Proposed fix: call `ReflectionUtils.makeAccessible(field)` on the resolved 
field in
     `TraitPropertyAccessStrategy#buildPropertyAccess` (both modules).
   - I can submit the Hibernate 5 fix against `7.0.x` and the Hibernate 7 fix 
against `8.0.x` as two
     focused PRs.
   


-- 
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