简体   繁体   中英

Spring autowire a class on server startup

I have a spring application. I am autowiring classes and they are working fine. For eg

@Controller
public class SearchController {
    @Autowired
    private EnvironmentControl envControl;
    @Autowired
    private SearchControl searchControl;
...

But now i have on server startup class called ScheduleServlet which uses init method to schedule something...

public class SchedulerServlet extends HttpServlet {
    @Override
    public void init(ServletConfig config) throws ServletException {

    super.init(config);
    this.LOGGER.info("timer servlet is initialized  ");
    try {
        InitialContext ic = new InitialContext();
        TimerManager tm = (TimerManager) ic.lookup("java:comp/env/tm/TimerManager");
        Timer timer = tm.schedule(new GlobalTemplateScheduler(), 0, 3600000);// one hour interval
        System.out.println("Timer..... " + timer);
    }
...

In this my GlobalTemplateScheduler class has timerExpired method which is scheduled to execute after every one hour interval.

public class GlobalTemplateScheduler implements TimerListener {

    @Autowired
    private TemplateControl templateControl;

    @Override
    public void timerExpired(Timer timer) {
        try {
            templateControl.updateMappings(names);
        } catch (Exception e) {
            this.LOGGER.error(e.getMessage());
            e.printStackTrace();
        }
...

So i have to autowire templateControl which i am getting null. This should happen on server startup.

Further inside updateMappings there's a datasource object which is also autowired as constructor-arg(This is working fine on browser request but need to do it on server startup).

Note: I cannot use the ApplicationListener interface.

Any suggestions would really help.

Thankyou.

On application startup beans initialization would not be completed, beans can be used after the application context refresh or after the intialization of the bean, it will make no sense to execute a logic which requires the bean on the startup unless you detect whether the bean is ready or not.

You can execute some logic using @PostConstruct in the bean which will be executed after the initialization of the bean so you can manipulate your logic in a way to do so after the intialization of the bean or you could detect and execute logic after the ContextRefreshedEvent by impelementing applicationListener and put your logic in onAppplicationEvent method.

One solution would be to use Spring's Container within your servlet. There are many implementations for this purpose, for instance the AnnotationConfigApplicationContext. Spring's documentation describes how to use the ClassPathXmlApplicationContext

Suppose GlobalTemplateScheduler is also a bean, then the key point is this:

ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

GlobalTemplateScheduler sheduler = context.getBean("sheduler", GlobalTemplateScheduler.class);

sheduler.someMethod();

The content of the XML, which is used by the ClassPathXmlApplicationContext is small. But you need to enable component scan:

<context:component-scan base-package="foo.bar.baz" />

Another approach, I could suggest, is to use Spring's DispatcherServlet to wire all the beans together. It can use the same XML, it is just a matter of loading it. The benefit is that is you don't need to load the application context by yourself and launch a bean as an entry point

There are plenty of tutorials how to use this servlet.

If you dont't like to write XML, you could use the WebApplicationInitializer

As i said the beans which i was autowiring were working fine. I just needed those beans in my Scheduler Servlet.

Here's the solution which worked...

In my scheduler servlet i got the application context xml and used the beans which were required...

ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());
GlobalTemplateControl globalTemplateControlObject = context.getBean("globalTemplateControl", GlobalTemplateControl.class);

Thanks @duffymo @Amer Qarabsa @Spindizzy for your suggestions :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM