I am trying to work around a problem I have somehow introduced by moving some code from a controller to a service, to do with asynchronous processing in a Grails 2.2.5 application (using 'runAsync' from the Executor plugin). It's not possible to reproduce the code here in any meaningful way, so I am just after some better understanding of why my problem might be occurring.
Basically, I am saving a Policy object (it's an insurance system), and then doing some post-processing to create and mail the necessary documents to the customer, among other things. To avoid their having to wait for a response, I run the most time-cnsuming part of the post-processing in a separate thread, with runAsync. Until yesterday, the initial post-processing occurred in the controller and then a service method was called which included the runAsync block. Yesterday, because I needed to use the same processing from another place, I moved the initial processing code into the service as well. This has changed the behaviour in one way I cannot understand (the only difference being the move from controller to service). The initial processing set a Date field, 'issued', to the current date and saved the Policy record, with flush:true. Then within the runAsync block, this 'issued' value is used. To get around possible Hibernate issues, the first line within the runAsync block was policy=Policy.get(id). As of yesterday, this causes an error because the reloaded policy has an 'issued' of null, despite my having saved the policy record successfully immediately prior to calling the runAsync block. And, as I said, this change of behaviour was simply the result of moving the code from the controller to the service.
So, I thought I would try without the failsafe reload of the Policy (i.e.,just use the existing Policy object), and this time the issued value is available within runAsync. But when I try and do something else with the policy record within this block I get this:
Caused by: org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session:
So, what I really need to know is how best I can a) do some manipulation of a domain object in the main thread, and save those changes, and then b) do some further work on that domain object in a separate thread (with runAsync), ensuring that all changes from stage a are present and that there are no Hibernate issues. Can I explicitly unload the object somehow in the main thread before running the async block, so as to avoid the 'different object with the same identifier value was already associated with the session' issue? Or do I need to start a new Hibernate session in the async block? Or a transaction?