Reputation: 1429
I have a Spring web application in which I have multiple Service and DAO classes. In normal crud operations everything is working fine. But I am facing issue while injecting dependency in thread.
In my application I need to create a thread and execute it on demand. For this in a controller class I am creating thread like below.
TestThread testThread = new TestThread();
Thread thread = new Thread(testThread);
thread.start();
In my thread I am trying to get a dependency like below.
WebApplicationContext context = ContextLoader.getCurrentWebApplicationContext();
TestService testService = (TestService) context.getBean("myService");
My service class looks below.
@Service("myService")
public class TestServiceImpl implements TestService {
some methods...
}
But every time I am getting below exception.
Exception in thread "Thread-21" org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'myService' available
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:685)
at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1199)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:284)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1081)
Upvotes: 1
Views: 2110
Reputation: 3125
As the other stated, if you instantiate a new thread on your own, it will be out of Spring business.
There are 2 things that you can do within the Spring context. First of all is to declare a prototype component thread and demand it to spring whenever you need it:
@Component
@Scope("prototype")
public class CustomThread extends Thread{
@Override
public void run() {
System.out.println(“Thread is running");
}
}
As it is scoped prototype, each time you demand it to the spring context, it will be created a new instance each time.
If you don't like this approach, you can define a taskExecutor as a spring bean and then submit your custom CustomTask
that implements the Runnable
interface:
public class CustomTask implements Runnable {
@Override
public void run() {
System.out.println("CustomTask is running");
}
}
This can be the configuration for the task executor:
@Bean
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(25);
return executor;
}
If you want, you can give a look at the post Spring and Java Thread example that cover these cases.
Upvotes: 0
Reputation: 1386
Instead implementing your own Thread
I'd suggest you to implement a Runnable
interface.
class MyTask implements Runnable {
@Override
public void run() {
//your logic is here
}
}
This class you can even make a prototype bean (using @Scope("prototype")
for example). In this case spring will create a new instance of MyTask
every time asked for the bean injecting all the dependencies. Any additional intialization that varies from request to request you can do via setter methods.
Once the task instance is fully initialized, you can run it in many different ways.The most simple of them is instantiating dedicated Thread
manually.
MyTask task = context.getBean("myTask");
//additional initialization
Thread taskRunner = new Thread(task);
taskRunner.start();
But it does not stand up to your requirement to
execute them one by one after success return of previous threads
For that you can use Executor
service. You can inject it with spring or instantiate one inside of your controller:
Executor executor = Executors.newFixedThreadPool(1);
Then executing your task will look somewhat like following:
MyTask task = context.getBean("myTask");
//additional initialization
executor.execute(task); //enqueues the task for future execution
If you are running it on Java 8, you can use a lambda in order to avoid implementing MyTask
:
executor.execute(() -> {
// here you have access to all the injected beans of the controller
// as well as to arguments of the handler method
});
Upvotes: 1