I have several container managed callable tasks that are invoked with invokeAll
. I need to pass arguments to each of these tasks, and since I'm getting instances instead of creating objects manually (this is a requirement) I cannot pass arguments in a constructor.
I'm using setters in the task to set values, but for some reason when I have multiple tasks the last value overrides the previous one.
Given this task:
@Stateless
@LocalBean
public class MyTask implements Callable<String> {
private String value;
@Override
public String call() throws Exception {
System.out.println("MyTask called with value = " + value);
return "MyTask called";
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
Called with this Test
class:
public class Test {
@Inject
Instance<MyTask> myTaskInstance;
@Resource
private ManagedExecutorService executor;
public void test() throws InterruptedException, ExecutionException {
List<Callable<String>> tasks = new ArrayList<>();
MyTask task1 = myTaskInstance.get();
task1.setValue("VAL1");
tasks.add(task1);
MyTask task2 = myTaskInstance.get();
task2.setValue("VAL2");
tasks.add(task2);
List<Future<String>> taskResults = null;
taskResults = executor.invokeAll(tasks);
List<String> results = new ArrayList<>();
for(Future<String> taskResult : taskResults) {
results.add(taskResult.get());
}
}
}
The result is (note VAL2
twice):
13:04:49,044 INFO [stdout] (EE-ManagedExecutorService-default-Thread-3) MyTask called with value = VAL2
13:04:49,045 INFO [stdout] (EE-ManagedExecutorService-default-Thread-4) MyTask called with value = VAL2
What is wrong with this code? How to fix this?
UPDATE
After changing the bean to @Stateful
these are the task instances right before invokeAll
This is perfectly normal.
A @Stateless
bean is created in multiple instances, depending on your server pool configuration.
So the same instance is re-used from the pool.
Per definition a @Stateless
bean cannot maintain a state.
Use a @Stateful
bean instead.