grails 2.3.x async and sleep

1.3k views Asked by At

I got some strange behaviour using grails 2.3.x and async. I'm doing some test with this code:

def test1() {
    def list = new PromiseList()
    list << {
        Thread.sleep(1000)
        println "1"
        return "1"
    }
    list << {
        Thread.sleep(2000)
        println "2"
        return "2"
    }
    list << {
        Thread.sleep(3000)
        println "3"
        return  "3"
    }
    list.onComplete { List results ->
        println 'finished: '+results
    }
    list.onError { error ->
        error.printStackTrace()
    }
    render 'finish'
}

but in my log i got:

1
| Error java.lang.NullPointerException
| Error     at org.apache.catalina.connector.Request.notifyAttributeAssigned(Request.java:1565)
| Error     at org.apache.catalina.connector.Request.setAttribute(Request.java:1556)
| Error     at org.apache.catalina.connector.RequestFacade.setAttribute(RequestFacade.java:543) 
| Error     at org.apache.catalina.core.ApplicationHttpRequest.setAttribute(ApplicationHttpRequest.java:281)
| Error     at org.codehaus.groovy.grails.web.util.WebUtils.storeGrailsWebRequest(WebUtils.java:682)
| Error     at org.codehaus.groovy.grails.plugins.web.async.WebRequestPromsiseDecorator$_decorate_closure1.doCall(WebRequestPromiseDecoratorLookupStrategy.groovy:61)
| Error     at sun.reflect.GeneratedMethodAccessor283.invoke(Unknown Source)
| Error     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
| Error     at java.lang.reflect.Method.invoke(Method.java:606)
| Error     at org.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1260)
| Error     at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
| Error     at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
| Error     at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1086)
| Error     at groovy.lang.ExpandoMetaClass.invokeMethod(ExpandoMetaClass.java:1110)
| Error     at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:910)
| Error     at groovy.lang.Closure.call(Closure.java:411)
| Error     at groovy.lang.Closure.call(Closure.java:405)
| Error     at groovyx.gpars.group.PGroup$3.call(PGroup.java:287)
| Error     at groovyx.gpars.group.PGroup$4.run(PGroup.java:311)
| Error     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
| Error     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
| Error     at java.lang.Thread.run(Thread.java:724)
2
3

In fact the tasks (and onError closure) are executed, but onComplete is not (off course)!!

what am i doing wrong?

except for the Thread.sleep() is pratically code taken from doc: http://grails.org/doc/latest/guide/async.html

Is Thread.sleep() not compatible with GPars for some reason?

1

There are 1 answers

0
Martin Hauner On

The problem is that onComplete does not block. The request/action does finish before your tasks and list goes out of scope.

You need to use waitAll() to wait for all tasks to finish before the action returns. Easiest is to replace the onComplete with

    def result = list.get ()
    println 'finished: ' + result

list.get() is implemented by calling waitAll().