I have been using Spock instead of JUnit for a few months now. Today, I’m trying something around thread safety and I found something about Groovy that annoyed me. In my unit test, I need to submit a Callable task to ExecutorService.
The Problem
In Java, normally we will normally do this:
1
2
3
4
ExecutorService executor = Executors.newSingleThreadExecutor();
Callable<Integer> c = () -> 1 + 2;
Future<Integer> future = executor.submit(c);
System.out.println("Result: " + future.get());
Output:
1
Result: 3
In Groovy(Spock),
1
2
3
4
ExecutorService executor = Executors.newSingleThreadExecutor()
Callable<Integer> c = { -> return 1 + 2 }
Future<Integer> future = executor.submit(c)
System.out.println("Result: " + future.get())
Output:
1
Result: null
Why??!?
Root Cause
In Groovy, the closure is always default as Runnable instead of Callable. (See more in ticket GROOVY-3295) Thus, when we execute submit method Groovy will auto convert it to submit(Runnable) instead of submit(Callable).
This happen even I assigned it to a variable c with type Callable<Integer>.
The Solution
Use as Callable.
1
2
3
4
ExecutorService executor = Executors.newSingleThreadExecutor()
Callable<Integer> c = { -> return 1 + 2 }
Future<Integer> future = executor.submit(c as Callable<Integer>)
System.out.println("Result: " + future.get())
Output:
1
Result: 3