In a Grails service, I create/update domain entities based on an external list. Updates take place in a loop. If the line in the input file is valid, entities are updated. Otherwise, I store the faulty line number and process the next one.
Problem: when I call validate() on an entity, if the result is false
, any work done in the service in rolled back, even if does not pertain to the validation, and although no exception is visible. For instance:
assert contact.firstName = 'Bruce'
contact.firstName = 'John'
assert contact.save()
...
company.vat = 'bogus'
if (!company.validate()) {
log.error "bogus"
company.discard()
} else {
assert company.save()
}
log.debug "done"
If company does not validate, my log will show "bogus" and "done". Contact first name will be 'Bruce'
in the database, not 'John'
.
Alternate version: if I do not call company.validate()
, the contact first name is updated.
At this stage, I suspect Grails attaches my company instance upon the validate() call, dooming the transaction when it realizes validations do not pass, and despite the discard() effort.
From the validate() semantic and its javadoc ("Validates an instance"), I didn't expect any side effect, whether the validation fails or not, or whether I even invoke validate() or not.
What do you think? Is this a "normal" bahavior, or a bug? How can I work around this?
I have a simple reproduction case with two entities if needed.