I\'m trying to create an async task that will not block the request. The user make the request, the task will start, and the controller will render \"Job is running...\", this i
I was able to get rid of this exception in a controller by removing the onComplete
and onError
calls. I guess the exception happens because the parent thread ended when you called render
.
So your:
Promise p = task {
complexAsyncMethodCall(); // (1) do stuff
}
.onComplete { result -> println result } // (2) on success
.onError { Throwable t -> System.err.println("Error: " + t) } // (3) on error
Becomes:
Promise p = task {
try {
def result = complexAsyncMethodCall(); // (1) do stuff
println result // (2) on success
} catch(Throwable t) {
System.err.println("Error: " + t) // (3) on error
}
}
This adds coupling between your work (1) and the result processing (2 and 3) but you could overcome this by writing your own Closure
wrapper that takes extra Closures as arguments. Something like this:
// may not work! written off the top of my head
class ProcessableClosure extends Closure {
Closure work;
Closure> onError;
Closure> onComplete;
@Override
public V call(Object... args) {
try {
def result = work.call(args); // (1) do stuff
onComplete.call(result); // (2) on complete
} catch(Exception e) {
onError.call(result); // (3) on error
}
}
}
That makes your code more readable:
Closure doWork = { complexAsyncMethodCall(); } // (1) do stuff
Closure printResult = { println it } // (2) on complete
Closure logError = { Throwable t -> log.error t } // (3) on error
Closure runEverythingNicely = new ProcessableClosure(work: doWork, onComplete: printResult, onError: logError)
Promise p = task { runEverythingNicely }