I've got a singleton Spring bean that creates a couple of tasks (java.util.concurrent.Callable
's) at runtime to do its work in parallel. Right now, the Callable
's are defined as inner classes in the singleton bean, and the singleton bean creates them simply by instantiating them with new Task(in)
, where in
is a parameter known only at runtime.
Now I want to extract the inner Task class to a regular top-level class because I want to make the Task's call()
method transactional, so I need it to be a Spring bean.
I guess I need to give my singleton some kind of factory of Task
s, but the tasks have to be prototype Spring beans that take a runtime value as a constructor parameter. How can I accomplish this?
Spring's bean factory and new are mutually exclusive. You can't call new and expect that object to be under Spring's control.
My suggestion is to inject those Tasks into the Singleton. Make them Spring beans, too.
You should recognize that the Task itself isn't going to be transaction, but its dependencies can be. Inject those into the Tasks and let Spring manage the transactions.
Another approach might be to use Spring's @Configurable
annotation with load-time weaving, this way you can use new
(instead of a bean factory) to create wired Callable's at runtime:
@Configurable
public class WiredTask implements Callable<Result> {
@Autowired
private TaskExecutor executor;
public WiredTask(String in) {
this.in = in;
}
public Result call() {
return executor.run(in);
}
}
@Bean @Scope("prototype")
public class TaskExecutor() {
@Transactional
public Result run(String in) {
...
}
}
// Example of how you might then use it in your singleton...
ExecutorService pool = Executors.newFixedThreadPool(3);
WiredTask task = new WiredTask("payload");
Future<Result> result = pool.submit(task);
See this article for more info. Note, you cannot use @Configurable and @Transactional in the same bean, hence the need for two classes. For that reason, this might not be the ideal solution if you have lots of different implementations of Callable (since you will need 2 classes for each one).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With