jdaugherty opened a new pull request, #16468:
URL: https://github.com/apache/grails-core/pull/16468

   ### Problem
   
   A domain class whose identifier is mapped to a generator that is not one of 
the built-in `ValueGenerator` constants, such as a Hibernate generator class 
name:
   
   ```groovy
   static mapping = {
       id generator: 'com.example.CustomIdGenerator'
   }
   ```
   
   cannot be mocked in a unit test on 8.0.x. Any `DataTest`, `DomainUnitTest`, 
or controller unit test that mocks the class fails during setup with:
   
   ```
   java.lang.IllegalArgumentException: No enum constant 
org.grails.datastore.mapping.model.ValueGenerator.COM.EXAMPLE.CUSTOMIDGENERATOR
   ```
   
   The application itself starts and runs correctly, because the Hibernate 5 
and Hibernate 7 mapping factories resolve the generator name themselves. Only 
datastores that use the default identity mapping in `MappingFactory` are 
affected: the simple map datastore that backs `DataTest`, and MongoDB.
   
   ### Cause
   
   c74f868890 replaced the lazily evaluated identity mapping with 
`DefaultIdentityMapping`, and resolved the generator name through 
`ValueGenerator.valueOf` while the mapping is built. On Grails 7 the lookup 
only ran when something read `IdentityMapping.getGenerator()`, which nothing on 
the simple map or Mongo path does, so these domain classes mocked without 
error. On 8.0.x the lookup runs during entity registration and throws.
   
   Neo4j had already worked around this with its own override of 
`createDefaultIdentityMapping`.
   
   ### Fix
   
   `MappingFactory.createDefaultIdentityMapping` resolves a built-in name 
case-insensitively as before, and resolves any other name to 
`ValueGenerator.CUSTOM`, leaving the name on the mapped form for the datastore 
to interpret. That is what the Hibernate and Neo4j factories already did for 
themselves. The Neo4j override is removed because the base behaviour now 
matches it.
   
   The unit-testing guide notes that a mocked domain class never runs such a 
generator, so its behaviour must be verified against the real datastore.
   
   ### Tests
   
   - `IdentityGeneratorMappingSpec` (grails-datastore-core): built-in names in 
lower and mixed case, a generator class name, a datastore-specific strategy 
name, and no generator, through the key-value and document mapping contexts.
   - `SimpleMapIdentifierSpec`: a custom generator class name and `assigned` 
persist and are retrieved through real sessions.
   - `MongoMappingContextSpec`: a generator class name is retained without a 
server.
   - Without the fallback, these specs and the Neo4j `SnowflakeIdGeneratorSpec` 
fail with the error above; the Hibernate 5 `HibernateMappingContextSpec` still 
passes, confirming the Hibernate path was never affected.
   


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