Reputation: 187
I have a class RunBackgroundServices which runs some background services at startup. I need a new object BackgroundServices in it. So I am using WebApplicationContext to get the bean. But it's not working.
RunBackgroundServices.java
@WebListener
public class RunBackgroundServices implements ServletContextListener {
private ExecutorService executor;
public void contextInitialized(ServletContextEvent event) {
final WebApplicationContext springContext = WebApplicationContextUtils.getWebApplicationContext(event.getServletContext());
BackgroundServices backgroundServices = springContext.getBean(BackgroundServices.class);
executor = Executors.newSingleThreadExecutor();
executor.submit(backgroundServices); // Task should implement Runnable.
}
public void contextDestroyed(ServletContextEvent event) {
executor.shutdown();
}
}
BackgroundServices.java
@Service
public class BackgroundServices extends Thread {
@Autowired
ServerListener serverListener;
@Autowired
ClientListener clientListener;
private static final Logger logger = LoggerFactory
.getLogger(BackgroundServices.class);
public void run() {
logger.debug("BackgroundServices :: run");
try {
serverListener.start();
} catch (InterruptedException e) {
logger.error(e.getStackTrace().toString());
}
try {
clientListener.start();
} catch (InterruptedException e) {
logger.error(e.getStackTrace().toString());
}
}
}
I am getting the following error -
Exception sending context initialized event to listener instance of class com.emc.hl7.common.RunBackgroundServices
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.emc.hl7.common.BackgroundServices] is defined
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:295)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1125)
at com.emc.hl7.common.RunBackgroundServices.contextInitialized(RunBackgroundServices.java:20)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4961)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5455)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:634)
at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:671)
at org.apache.catalina.startup.HostConfig$DeployDescriptor.run(HostConfig.java:1840)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Upvotes: 0
Views: 1371
Reputation: 64079
There is an easier way to perform bootstraping operations using Spring.
All you have to do is have Spring bean that implements ApplicationListener<ContextRefreshedEvent>
Your code would look like:
@Component
public class ContextStartupListener implements ApplicationListener<ContextRefreshedEvent> {
private final BackgroundServices backgroundServices;
private ExecutorService executor;
@Autowired
public ContextStartupListener(BackgroundServices backgroundServices) {
this.backgroundServices= backgroundServices;
}
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
if(!isRootApplicationContext(event)) {
return;
}
executor = Executors.newSingleThreadExecutor();
executor.submit(backgroundServices);
}
private boolean isRootApplicationContext(ContextRefreshedEvent event) {
return null == event.getApplicationContext().getParent();
}
}
Note the use of isRootApplicationContext
. It is needed if you have multiple application contexts and do no want to run the bootstrapping operation on each one.
Using the above code you are bootstrapping using Spring's events, not the Servlet container's events.
Upvotes: 5