/* vim: set ts=2 et sw=2 cindent fo=qroca: */ package com.globant.katari.quartz.domain; import org.apache.commons.lang.Validate; import org.quartz.JobDetail; import org.springframework.aop.framework.ProxyFactoryBean; import org.springframework.aop.target.LazyInitTargetSource; import org.springframework.beans.factory.BeanClassLoaderAware; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.scheduling.quartz.CronTriggerBean; import org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean; /** A lazy initializer cron trigger for quartz. * * This is a quartz trigger that lazily initializes the task to run. This is * used to guarantee that the task does not force premature initialization of * the application context. * * It uses the cron syntax to specify when the task should run. */ public class CronTrigger extends CronTriggerBean implements BeanFactoryAware, BeanClassLoaderAware { /** The serial version uid, used for serialization. */ private static final long serialVersionUID = 1L; /** The bean factory that contains this cron trigger. * * This is used to create the lazy scheduled command. It must be set by * spring to a non null value. */ private BeanFactory beanFactory; /** Classloader passed by spring through the implementation of * BeanClassLoaderAware. * * This is used by ProxyFactoryBean. It is set by spring to a non null * value. */ private ClassLoader classLoader; /** The bean name under which this object is registered in spring. * * This is used by MethodInvokingJobDetailFactoryBean. Set by spring to a non * null value. */ private String beanName; /** The cron expression that defines when the task is run, as defined by * quartz's CronTrigger. * * This is never null. */ private final String cronExpression; /** The spring bean name of the task to run. * * The bean must implement the ScheduledCommand interface. It is never null. */ private final String taskBeanName; /** Constructor. * * @param theCronExpression The cron expression that defines when the task is * run. See CronTrigger class in quartz for the syntax. It cannot be null. * * @param theTaskBeanName The name of the spring bean for the task. The bean * must implement the ScheduledCommand interface. It cannot be null. */ public CronTrigger(final String theCronExpression, final String theTaskBeanName) { Validate.notNull(theCronExpression, "The cron expression cannot be null."); Validate.notNull(theTaskBeanName, "The task bean name cannot be null."); cronExpression = theCronExpression; taskBeanName = theTaskBeanName; } /** Operation from interface BeanFactoryAware. * * {@inheritDoc} */ public void setBeanFactory(final BeanFactory theBeanFactory) { beanFactory = theBeanFactory; } /** Operation from interface BeanClassLoaderAware. * * {@inheritDoc} */ public void setBeanClassLoader(final ClassLoader theClassLoader) { classLoader = theClassLoader; } /** Operation from BeanNameAware. * * {@inheritDoc} */ @Override public void setBeanName(final String name) { beanName = name; super.setBeanName(name); } /** Operation from InitializingBean. * * All initilization work is done here. * * {@inheritDoc} * * @throws Exception if an error occured. */ @Override public void afterPropertiesSet() throws Exception { LazyInitTargetSource lazyInitScheduledCommand = new LazyInitTargetSource(); lazyInitScheduledCommand.setTargetBeanName(taskBeanName); lazyInitScheduledCommand.setBeanFactory(beanFactory); ProxyFactoryBean scheduledCommandProxy = new ProxyFactoryBean(); scheduledCommandProxy.setBeanClassLoader(classLoader); scheduledCommandProxy.setBeanFactory(beanFactory); scheduledCommandProxy.setTargetSource(lazyInitScheduledCommand); // This is just for convenience, we reuse springs wrapper for a job detail // through the MethodInvokingJobDetailFactoryBean. MethodInvokingJobDetailFactoryBean jobFactory; jobFactory = new MethodInvokingJobDetailFactoryBean(); jobFactory.setBeanClassLoader(classLoader); jobFactory.setBeanFactory(beanFactory); jobFactory.setBeanName(beanName); jobFactory.setConcurrent(false); jobFactory.setTargetObject(scheduledCommandProxy.getObject()); jobFactory.setTargetMethod("execute"); try { jobFactory.afterPropertiesSet(); } catch (ClassNotFoundException e) { throw new RuntimeException("Error in afterPropertiesSet of jobFactory", e); } catch (NoSuchMethodException e) { throw new RuntimeException("Error in afterPropertiesSet of jobFactory", e); } setCronExpression(cronExpression); setJobDetail((JobDetail) jobFactory.getObject()); super.afterPropertiesSet(); } }