Spring + Quartz + Clustering
En Javi’s Java podemos encontrar un estupendo post a cerca de Quartz, sobre qué es y cómo se configura dentro de nuestra aplicación Web por lo que no es necesario hablar mucho más del tema. En este post sólo me gustaría resaltar la sencillez y elegancia resultante de la integración de Quartz con Spring, como el mismo Javi comentaba en uno de los comentarios, que nos permite configurar una tarea en apenas un par de minutos.
Tampoco es necesario escribir ninguna línea de código como ejemplo para la integración con Spring ya que la documentación de Spring sobre el tema (cronExpression) es clara y sencilla.
¿Quién necesita ahora los crones de Linux o las tareas de Windows para programar tareas relacionas con nuestra aplicación Web?
Si además necesitamos ejecutar la aplicación en distintas instancias y no queremos que haya problemas, como que el proceso se ejecute simultáneamente en todas ellas, podemos configurar Quartz para que se ejecute en Clustering añadiendo sólo unas cuántas líneas extras en la configuración. Ejemplo de configuración en Spring para la ejecución de Quartz en clustering:
<bean name="job"
class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass" value="whatabout.Job" />
<property name="jobDataAsMap">
<map>
<!-- properties
<entry key="timeout" value="" />
-->
</map>
</property>
</bean>
<bean id="cronTrigger"
class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail" ref="job" />
<property name="cronExpression" value="0 0 6 * * ?" />
</bean>
<bean
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="cronTrigger" />
</list>
</property>
<property name="applicationContextSchedulerContextKey">
<value>applicationContext</value>
</property>
<property name="startupDelay" value="0" />
<property name="waitForJobsToCompleteOnShutdown" value="true" />
<property name="dataSource" ref="myDataSource" />
<property name="quartzProperties">
<props>
<!-- ThreadPool -->
<prop key="org.quartz.threadPool.class">org.quartz.simpl.SimpleThreadPool</prop>
<prop key="org.quartz.threadPool.threadCount">5</prop>
<prop key="org.quartz.threadPool.threadPriority">5</prop>
<!-- Job store -->
<prop key="org.quartz.jobStore.misfireThreshold">60000</prop>
<prop key="org.quartz.jobStore.class">org.quartz.impl.jdbcjobstore.JobStoreTX</prop>
<prop key="org.quartz.jobStore.driverDelegateClass">org.quartz.impl.jdbcjobstore.StdJDBCDelegate</prop>
<prop key="org.quartz.jobStore.useProperties">false</prop>
<!-- Clustering -->
<prop key="org.quartz.jobStore.isClustered">true</prop>
<prop key="org.quartz.scheduler.instanceId">AUTO</prop>
<prop key="org.quartz.jobStore.clusterCheckinInterval">30000</prop>
</props>
</property>
</bean>
Evidéntemente es necesario configurar un Datasource (myDataSource en el ejemplo) y crear las tablas de Quartz oportunas. He de añadir que en uno de los últimos proyectos en los que he trabajado hemos montado Quartz en Clustering con cinco máquinas con éxito y después de varios meses en producción ningún proceso se ha ejecutado más de una vez o ninguna.
Referencia: