codeconsole commented on issue #15680:
URL: https://github.com/apache/grails-core/issues/15680#issuecomment-4551849702
## Root Cause Investigation
Debugged the runtime state of the property mapping. After both `static
mapping` and `static constraints` are evaluated:
```
Category.name mapping: index=false, indexAttributes=null, unique=true,
class=MongoAttribute
```
The constraint evaluation (`name unique: true`) completely overwrites the
mapping (`name index: true, indexAttributes: [unique: true]`). A fresh
`MongoAttribute` is created with only `unique=true`; `index` reverts to its
default `false` and `indexAttributes` is `null`.
### Where it happens
`AbstractGormMappingFactory.createMappedForm()` evaluates both closures
through the same `DefaultMappingConfigurationBuilder`:
```java
// Line 94-103: evaluate mapping closure first
List<Object> values =
ClassPropertyFetcher.getStaticPropertyValuesFromInheritanceHierarchy(
entity.getJavaClass(), GormProperties.MAPPING, Object.class);
for (Object value : values) {
evaluateWithContext(builder, (Closure) value);
}
// Line 104-107: evaluate constraints closure AFTER mapping
List<Closure> constraintValues =
ClassPropertyFetcher.getStaticPropertyValuesFromInheritanceHierarchy(
entity.getJavaClass(), GormProperties.CONSTRAINTS, Closure.class);
for (Closure value : constraintValues) {
evaluateWithContext(builder, value);
}
```
The mapping closure stores a properly configured `MongoAttribute` (with
`index=true`, `indexAttributes={unique:true}`) in `builder.properties['name']`.
But when the constraints closure runs `name unique: true`, it creates a **new**
`MongoAttribute` (with only `unique=true`) that overwrites the mapping-set one.
The bug is in `DefaultMappingConfigurationBuilder.invokeMethod` — the
constraint call should reuse the existing property instance from the mapping,
but instead creates a fresh one. The interaction between `builder.properties`
and `Entity.propertyConfigs` (via `getProperties()` merging) likely causes the
loss.
### Workaround
Remove `unique: true` from `static constraints` when `indexAttributes:
[unique: true]` is declared in `static mapping`. The database-level unique
index provides the enforcement.
Alternatively, use `compoundIndex([name: 1, indexAttributes: [unique:
true]])` which is unaffected because compound indexes go through a different
code path (`Entity.getCompoundIndices()`).
--
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]