0
votes

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

2
Can you try getting the branch from DB again inside onComplete rather than using the copy created at start of method e.g. def branch = Branch.get( newBranch.id ) then set active & saveMike W

2 Answers

0
votes

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()
  }
}    
0
votes

Thanks, with the changes mentioned this works:

Promise<Branch> p = gitService.asyncPull(newBranch)     
p.onComplete { b ->
  Branch.withTransaction { session ->               
    Branch br = Branch.findByName(b.name);
    br.setActive(true);
    br.save(flush:true);
  }
}