Reputation: 1944
According to Spring's documentation the way to use the TaskExecutor is as follows:
import org.springframework.core.task.TaskExecutor;
public class TaskExecutorExample {
private class MessagePrinterTask implements Runnable {
private String message;
public MessagePrinterTask(String message) {
this.message = message;
}
public void run() {
System.out.println(message);
}
}
private TaskExecutor taskExecutor;
public TaskExecutorExample(TaskExecutor taskExecutor) {
this.taskExecutor = taskExecutor;
}
public void printMessages() {
for(int i = 0; i < 25; i++) {
taskExecutor.execute(new MessagePrinterTask("Message" + i));
}
}
}
However, if MessagePrinterTask has autowired dependencies they will not be configured by Spring because we are instantiating our bean outside of Spring's context (at least that's how I understand it) even though Spring will provide the actual thread creation. If MessagePrinterTask were to have autowired dependencies how do we get Spring to recognize them? I tried the following modified example to no avail (and yes, autowiring is enabled properly):
import org.springframework.core.task.TaskExecutor;
public class TaskExecutorExample {
@Component
private class MessagePrinterTask implements Runnable {
@Autowired
private autoWiredDependency;
public void run() {
autoWiredDependency.doNotThrowNullPointerExceptionPlease();
}
}
private TaskExecutor taskExecutor;
public TaskExecutorExample(TaskExecutor taskExecutor) {
this.taskExecutor = taskExecutor;
}
public void printMessages() {
for(int i = 0; i < 25; i++) {
taskExecutor.execute(new MessagePrinterTask());
}
}
}
Upvotes: 13
Views: 27215
Reputation: 51
Try this method.
@Service
@Scope("prototype")
public invokeClass {
@Autowired
private ApplicationContext applicationContext;
public void methodName(TestRequest input){
TaskExecutor taskExecutor = new SimpleAsyncTaskExecutor();
taskExecutor.execute(new Runnable() {
public void run() {
applicationContext.getBean("testService", TestService.class).execute(input);
}
});
}
}
Upvotes: 0
Reputation: 250
You can also use the @Async annotation.
public class TaskExecutorExample {
@Autowired
private MessagePrinterTask task;
public void printMessages() {
for(int i = 0; i < 25; i++) {
task.printMessage();
}
}
}
@Component
public class MessagePrinterTask implements Runnable {
@Autowired
private String message;
@Async
public void printMessage() {
System.out.println(message);
}
}
Any call to printMessage() will be executed asynchronously using a default executor, which you can configure using the following in your Spring xml config.
<task:annotation-driven executor="myExecutor"/>
<task:executor id="myExecutor" pool-size="5" />
Upvotes: 4
Reputation: 49915
There are two ways I think that you can go about this:
a. Provide the dependencies to the Task - this way:
class MessagePrinterTask implements Runnable {
public MessagePrinterTask(ADependency aDependency){
this.aDependency = aDependency;
}
private ADependency aDependency;
public void run() {
aDependency.doNotThrowNullPointerExceptionPlease();
}
}
And in your TaskExectorExample which can be the singleton:
import org.springframework.core.task.TaskExecutor;
public class TaskExecutorExample {
@Autowired private ADependency aDependency;
@Autowired
public TaskExecutorExample(TaskExecutor taskExecutor) {
this.taskExecutor = taskExecutor;
}
public void printMessages() {
for(int i = 0; i < 25; i++) {
taskExecutor.execute(new MessagePrinterTask(this.aDependency));
}
}
}
b. Using @Configurable annotation on your MesasgePrinterTask, this will inject in dependencies into MessagePrinterTask even though it is instantiated outside of a Spring Container - there are some catches in using @Configurable though(requires AspectJ):
@Configurable
class MessagePrinterTask implements Runnable {
Upvotes: 16