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?
The problem is that
onCompletedoes not block. The request/action does finish before your tasks andlistgoes out of scope.You need to use
waitAll()to wait for all tasks to finish before the action returns. Easiest is to replace theonCompletewithlist.get()is implemented by callingwaitAll().