Search code examples
javagrailsasynchronousgroovygrails-orm

GORM Object Relation is not loaded in an async block


I use Grails GPaars to create an async block.

In BuildConfig:

compile 'org.codehaus.gpars:gpars:1.2.1'
compile 'org.codehaus.jsr166-mirror:jsr166y:1.7.0'

I defined a helper Class:

class TaskService {

  private ForkJoinPool pool = new ForkJoinPool()

  /**
   * Executes the given closure in a new thread.
   * @param args is a map of arguments to be used in the async closure.
   * @return
   */
  def executeAsync(args, closure = null) {
    if(!closure) {
      closure = args
      args = null
    }

    GParsPool.withExistingPool(pool) { closure.callAsync(args) }
  }
}

Now in a controller I do:

TrackingEmail tEmail = TrackingEmail.get(trackingEmailId)
Device targetDevice = tEmail.device

The former works the deviceis retrieved from the TrackingEmail object.

Now I try to do the same in an async block:

taskService.executeAsync(trackingEmailId: trackingEmailId) { data ->
   TrackingEmail tEmail = TrackingEmail.get(data.trackingEmailId)
   Device targetDevice = tEmail.device
}

In this async block only tEmailis retrieved from the database. The second line is not executed.

How do I get relational objects in an async block?


Solution

  • I don't think you should use GPars for GORMing directly. In this case you would have to take care of transactions/sessions yourself:

     taskService.executeAsync(trackingEmailId: trackingEmailId) { data ->
       Device.withTransaction{ tx ->
         TrackingEmail tEmail = TrackingEmail.get(data.trackingEmailId)
         Device targetDevice = tEmail.device
       }
    }
    

    and that would give you bad performace in case of frequent parallel calls.

    I'd recommend to take a look at Asynchronous Programming in Grails, which uses the extended GPars