Issue
Grails 3.2.9
After executing a task, the onComplete method cannot get a hibernate session.
Controller:
def addBranch() {
Branch newBranch = new Branch(name: branchName, root: newBranchRoot, 'active':false).save();
Promise p = gitService.asyncPull(newBranch)
p.onComplete { b ->
println "finished adding branch " + branchName;
newBranch.setActive(true);
newBranch.save(); <<<=== EXCEEPTION THROWN HERE
}
p.onError { Throwable err ->
println "An error occurred ${err.message}"
}
respond(status:"ok", message:"success!");
}
Service:
public Promise<Branch> asyncPull(Branch branch) {
WebPromises.task {
initBranch(branch);
pull (branch.name);
branch;
}
}
Exception Stack Trace
2017-05-23 13:41:29.123 [ead 6]ERROR Async execution error: Could not obtain current Hibernate Session; nested exception is org.hibernate.HibernateException: No Session found for c urrent thread
org.springframework.dao.DataAccessResourceFailureException: Could not obtain current Hibernate Session; nested exception is org.hibernate.HibernateException: No Session found for c urrent thread at org.grails.orm.hibernate.GrailsHibernateTemplate.getSession(GrailsHibernateTemplate.java:317) at org.grails.orm.hibernate.GrailsHibernateTemplate.doExecute(GrailsHibernateTemplate.java:273) at org.grails.orm.hibernate.GrailsHibernateTemplate.execute(GrailsHibernateTemplate.java:230) at org.grails.orm.hibernate.GrailsHibernateTemplate.execute(GrailsHibernateTemplate.java:116) at org.grails.orm.hibernate.validation.UniqueConstraint.processValidate(UniqueConstraint.java:149) at grails.validation.AbstractConstraint.validate(AbstractConstraint.java:107) at grails.validation.ConstrainedProperty.validate(ConstrainedProperty.java:979) at org.grails.validation.GrailsDomainClassValidator.validatePropertyWithConstraint(GrailsDomainClassValidator.java:206) at org.grails.validation.GrailsDomainClassValidator.validate(GrailsDomainClassValidator.java:81) at org.grails.orm.hibernate.AbstractHibernateGormInstanceApi.save(AbstractHibernateGormInstanceApi.groovy:122) at org.grails.datastore.gorm.GormEntity$Trait$Helper.save(GormEntity.groovy:151) at org.grails.datastore.gorm.GormEntity$Trait$Helper$save$11.call(Unknown Source) at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:133) at com.care.incasa.Branch.save(Branch.groovy) at com.care.incasa.Branch.save(Branch.groovy) at org.grails.datastore.gorm.GormEntity$save$1.call(Unknown Source) at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125) at com.care.incasa.AdminController$_addBranch_closure1$$EQKTGeEk.doCall(AdminController.groovy:43) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springsource.loaded.ri.ReloadedTypeInvoker$2.invoke(ReloadedTypeInvoker.java:133) at org.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1461) at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93) at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325) at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:294) at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1027) at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:42) at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48) at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:57) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125) at org.grails.plugins.web.async.AsyncWebRequestPromiseDecorator.invokeClosure(AsyncWebRequestPromiseDecorator.groovy:91) at org.grails.plugins.web.async.AsyncWebRequestPromiseDecorator$_decorate_closure2.doCall(AsyncWebRequestPromiseDecorator.groovy:67) at org.grails.plugins.web.async.AsyncWebRequestPromiseDecorator$_decorate_closure2.call(AsyncWebRequestPromiseDecorator.groovy) at org.grails.async.factory.gpars.GparsPromise$_onComplete_closure1.doCall(GparsPromise.groovy:92) at org.grails.async.factory.gpars.GparsPromise$_onComplete_closure1.call(GparsPromise.groovy) at groovyx.gpars.dataflow.DataCallback$1.run(DataCallback.java:62) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745) Caused by: org.hibernate.HibernateException: No Session found for current thread at org.grails.orm.hibernate.GrailsSessionContext.currentSession(GrailsSessionContext.java:116) at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:688) at org.grails.orm.hibernate.GrailsHibernateTemplate.getSession(GrailsHibernateTemplate.java:315) ... 44 common frames omitted
Solution
For such cases you should be using withTransaction
or withSession
to handle the transactional context yourself:
p.onComplete { b ->
Branch.withTransaction{
println "finished adding branch $branchName"
newBranch.active = true
newBranch.save()
}
}
Answered By - injecteer