Reputation: 1021
Here's roughly what I'm doing in a service:
runAsync
{
<some work here>
myDomainObject.merge()
}
I get an error saying "No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here". I know for sure that the code is being run asynchronously, so it would seem that the Executor Plugin is setup correctly.
So I tried this next, thinking the domain object "myDomainObject" must not be bound in this thread although the thread has a hibernate session thanks to the executor plugin:
runAsync
{
<work>
def instance2= MyDomainObject.get(myDomainObject.id) // works
instance2.field1=123
instance2.save() // fails
}
I get the same error here and interestingly, the get() succeeds in bringing the correct data and setting it to instance2. It's only the "save()" that fails. I know this because I've stepped through the code in a debugger.
Finally, if I do the following, everything works:
runAsync
{
<some work here>
MyDomainObject.withTransaction {
myDomainObject.field1=123
myDomainObject.merge()
}
}
I don't understand why this transaction is required since I haven't set the service I'm writing the above code in to be transactional. I know there must be something fundamental that I don't know here, but I can't find out what it is.
Upvotes: 0
Views: 2041
Reputation: 50265
Looks like you answered your own question :)
I don't understand why this transaction is required since I haven't set the service I'm writing the above code in to be transactional.
Have a look at the NOTE ON TRANSACTIONS. You need your service to be transactional.
NOTE ON TRANSACTIONS: keep in mind that this is spinning off a new thread and that any call will be outside of the transaction you are in. Use .withTransaction inside your closure, runnable or callable to make your process run in a transaction that is not calling a transactional service method (such as when using this in a controller).
UPDATE
Try the service class like below:
class MyService{
def someMethod(){
runAsync {
anotherMethod()
}
}
def anotherMethod(){
<work>
def instance2= MyDomainObject.get(myDomainObject.id) // works
instance2.field1=123
instance2.save() // should work as well
}
}
Upvotes: 2