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
onComplete
does not block. The request/action does finish before your tasks andlist
goes out of scope.You need to use
waitAll()
to wait for all tasks to finish before the action returns. Easiest is to replace theonComplete
withlist.get()
is implemented by callingwaitAll()
.