Reputation: 914
I'm trying to use a service in my domain class for custom validation. In other domain classes this works out pretty well but here I'm receiving a Hibernate assertion error.
domain class custom validation:
end validator: { val, obj ->
if (obj.userWorkingTimeRegulationService.validateit() == false){
return ["error.workingregulation"]
}
I injected the service using:
def userWorkingTimeRegulationService
The service just returns true for testing purposes:
package usermanagement
import grails.transaction.Transactional
@Transactional
class UserWorkingTimeRegulationService {
def serviceMethod() {
}
def validateit(){
return true
}
}
Stacktrace:
| Error 2015-05-27 15:07:54,909 [localhost-startStop-1] ERROR hibernate.AssertionFailure - HHH000099: an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session): org.hibernate.AssertionFailure: null id in usermanagement.UserWorkingTimeRegulation entry (don't flush the Session after an exception occurs)
| Error 2015-05-27 15:07:54,927 [localhost-startStop-1] ERROR context.GrailsContextLoaderListener - Error initializing the application: null id in usermanagement.UserWorkingTimeRegulation entry (don't flush the Session after an exception occurs)
Message: null id in usermanagement.UserWorkingTimeRegulation entry (don't flush the Session after an exception occurs)
Line | Method
->> 24 | doCall in usermanagement.UserWorkingTimeRegulation$__clinit__closure4$_closure8
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 47 | onApplicationEvent in org.grails.datastore.mapping.engine.event.AbstractPersistenceEventListener
| 52 | create . . . . . . . . . . . . . in usermanagement.UserWorkingTimeRegulation
| 47 | doCall in BootStrap$_closure1
| 327 | evaluateEnvironmentSpecificBlock in grails.util.Environment
| 320 | executeForEnvironment in ''
| 296 | executeForCurrentEnvironment . . in ''
| 266 | run in java.util.concurrent.FutureTask
| 1142 | runWorker . . . . . . . . . . . in java.util.concurrent.ThreadPoolExecutor
| 617 | run in java.util.concurrent.ThreadPoolExecutor$Worker
^ 745 | run . . . . . . . . . . . . . . in java.lang.Thread
Error |
Forked Grails VM exited with error
If I use a method declared in the domain class all works, there must be a problem with the service. In another domain class I used services without problems in my custom validation, I don't know what's so special about this one.
EDIT:
I create a UserWorkingTimeRegulation in my Bootstrap.groovy
which is saved correctly if I comment the custom validation in my domain class which shouldn't do anything since the service is returning true
and the validation kicks in with false
.
Bootstrap:
UserWorkingTimeRegulation.create adminUser, workingTimeRegulation, new LocalDate(), new LocalDate().plusMonths(1)
Upvotes: 0
Views: 406
Reputation: 75681
Services are transactional by default - the only way to make a service non-transactional is to add static transactional = false
and remove all @Transactional
annotations. The Spring/Hibernate transaction manager always flushes the Hibernate session at the end of a successful transaction, so what you're seeing is that after calling the service method (even one like yours which does no persistence), all modified persistent objects are flushed from the Hibernate cache to the database, but there's a problem with one of them.
The error message is fairly cryptic, but it's saying that a usermanagement.UserWorkingTimeRegulation
doesn't have an id. This implies that you called save()
but it didn't validate, so you need to check what values are missing or invalid by calling hasErrors
and/or getErrors
. The reason that not having an id is a problem is that this instance is a property of another domain object, and the id is used as the foreign key to link them together.
p.s. feel free to delete the unused autogenerated serviceMethod
method.
Upvotes: 1