Startup code after Spring context has been initialized in web application deployed to Tomcat

I have a web application that I am packaging as war and I am deploying to tomcat 7.

This is a Spring MVC application that I want to add the Quartz scheduler to it. I want to run code that will use different Spring beans and populate the scheduler with jobs that are dynamically configured, so I need access to different beans in the code like

 @Autowired
 private CronDAO cronDAO;     

 public void loadCronJobs(final Scheduler scheduler) {
    LOGGER.info("Vas[{}]: Loading Cron Schedule...", vasName);
    final List<Cron> crons = cronDAO.fetchAll();
    final Long cronSid = cron.getSid();
    final String directive = cron.getDirective();
    final String expression = cron.getCronExpression();
    ...
 }

      

Typically I would put the initialization code for the scheduler in the main application function and use Autwired beans for my application logic. Now that the app server initializes the app, I cannot do this.

I tried adding my code to the servlet start function, but the Spring context is not ready yet, so the autowired beans (DAO in this example) could not be loaded.

public class MyWebAppInitializer implements WebApplicationInitializer {

 @Override
 public void onStartup(ServletContext container) throws ServletException {
  CronManager cron = new CronManagerImpl();
  cron.loadCronJobs();
 }
}

      

Is there a way to run the code (not just quartz related) when the application is running in the container, but the Spring context needs to be terminated?

+3


source to share


2 answers


You can write a "ServletContextListener" and register it in the web.xml file. In your implementation, you can rely on the spring frameworks WebApplicationContextUtil to get the context handle of the spring application.

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.springframework.web.context.support.WebApplicationContextUtils;

public class QuartzInitiator implements ServletContextListener {

     public void contextInitialized(ServletContextEvent servletContextEvent) {
            WebApplicationContextUtils.getRequiredWebApplicationContext(servletContextEvent.getServletContext())
           .getAutowireCapableBeanFactory().autowireBean(this);
          //your logic
     }
}

      



Auto-updated fields will be properly initialized by Util.

+2


source


Spring does a great job of tackling low-level issues.

At a higher level, you have:

  • number of beans declared in the context of a Spring application
  • the initialization procedure to be performed
    • after beans initialization
    • before running the rest of the code


Well just declare a new bean where you will inject all the other beans and do your initialization in the init method of the last bean. Spring makes sure that this method is called when the context is initialized after all dependent beans have been initialized.

This way is completely independent of whether your application is a web application or not: it becomes a problem for the Spring framework and is no longer yours.

0


source







All Articles