Search code examples
javaspringosgiquartz-schedulerapplicationcontext

How to get Quartz jobs running in a multi-ApplicationContext environment?


I have a Spring Web application with an applicationContext.xml loaded through a ContextLoaderListener in an XmlWebApplicationContext. The application context has a Quartz scheduler (defined with a SchedulerFactoryBean like here) but has no trigger nor job details.

During loading of this main application context, I load some "plug-in" JARs containing their own pluginApplicationContext.xml file. Each pluginApplicationContext.xml is loaded in a GenericXmlApplicationContext as a child of the main XmlWebApplicationContext.

Those plug-ins may contain Quartz jobs (QuartzJobBean) which are scheduled within the scheduler discussed above. Scheduling have to be done programmatically through the Quartz API but this is fine for me. When the job is triggered, it is well instanciated by Quartz and, because it extends the QuartzJobBean, I'm able to get the current ApplicationContext through setApplicationContext. The problem here is that I get the XmlWebApplicationContext instead of the GenericXmlApplicationContext from which the job have been scheduled. Thus, I cannot call getBean to retrieve the beans defined within the plugin.

I well understand why all of this happen. But I cannot find a clean and reusable solution to handle it. I've already had a look at OSGi but we're implementing this plug-in system on an existing application, not creating a new one from scratch and migrating the whole application to OSGi would be too much work to do. Do you know how OSGi and other plug-in frameworks deal with this kind of situation?

Thanks a lot for your help


Solution

  • I am not sure I get all those spring problems but I've done these things with OSGi.

    What people often do not realize is that you can embed OSGi in your existing application without making any changes to the existing code. Richard Hall describes it here http://felix.apache.org/site/apache-felix-framework-launching-and-embedding.html (the API is 100% standardized).

    Having a framework, you can then run your plugins in the framework. You will have to make sure the framework exports all the application packages (see the org.osgi.framework.system.packages.extra launch property). Plugins and application can then communicate through services.

    I've never used Quartz but I've some experience with scheduling. I register a Runnable service with cron like properties:

       @Component(properties="cron=1 * * * *")
       public void SomeImpl implements Runnable {
         public void run() {
            ...
         }
       }
    

    You will then need to make a bundle that calls that service according to its cron specification).