Suppose you want submit job to ExecutorService.
The Baroque version
You could create a class that implements Callable:
class MyJob implements Callable<Integer>{ @Override Integer call() throws Exception { return 42 } }
and give it to the executor service:
def 'submit callable as MyJob object'() { expect: executorService.submit(new MyJob()).get() == 42 }
The response is, as expected, 42.
Map as Callable version
You want to use this job only in one place so why not inline this class:
def 'submit callable as map'() { expect: executorService.submit([call: { 42 }] as Callable).get() == 42 }
The response is again 42.
Groovy closure version
Why not use closure instead of map?
def 'submit callable as closure'(){ expect: executorService.submit { 42 }.get() == 42 }
The response is … null.
Condition not satisfied: executorService.submit { 42 }.get() == 42 | | | | | | | false | | null | java.util.concurrent.FutureTask@21de60b4 java.util.concurrent.Executors$FinalizableDelegatedExecutorService@1700915
Why? It is because Groovy treats this closure as Runnable, not Callable and Future#get returns null when task is complete.
Groovy closure version with cast
We have to cast our closure before submiting to executor service:
def 'submit callable as closure with cast'() { when: int result = executorService.submit({ return 42 } as Callable<Integer>).get() then: result == 42 }
The response is, as expected, again 42.
What interesting, the same test with inlined result variable fails… Strange… It could be Spock framework error.
Source code is available here.
Thanks for the article. I had the same issue in the past and I had to find solution on my own (thanks to you other people will safe their time). However. I propose to extend your blog post by one thing.
`{ 42 } as Callable` works fine if used inline. When it is extracted to a reference (even declared as `Callable`) it is still treated as `Runnable`. In that situation only the approach with map coerced to Callable works as expected. See my PR:
https://github.com/alien11689/CallableInGroovy/pull/1
Just passing by to tell that this article helped me to understand a problem of mine. Thanks!
Thanks for your post!!
Thanks, you saved my day!
Hello World