Canigó - Servei de Planificació de Tasques 2.1
SERVEI DE PLANIFICACIÓ DE TASQUES
IntroduccióPropósitEl Servei de Planificació de Tasques de canigo permet configurar l'execució de tasques de forma diferida en els moments en els que es determini:
Context i Escenaris d'ÚsEl Servei de Planificació de Tasques es troba dins la Capa de Dades/Integració en el context dels serveis proporcionats per canigo.
Versions i DependènciesLes dependències descrites a la següent url son requerides per tal de compilar i fer funcionar el projecte: A qui va dirigitAquest document va dirigit als següents perfils:
Documents i Fonts de Referència
Descripció DetalladaArquitectura i ComponentsEl Servei de Planificació de Tasques de canigo ofereix interfícies d'ús que s'abstreuen de la implementació escollida per millor mantenibilitat en futures versions i futures implementacions alternatives. En l'actualitat, canigo proporciona una implementació basada en Quartz (projecte open source desenvolupat per PartNET). Els components podem classificar-los en:
JavaDoc: http://canigo.ctti.gencat.net/confluence/canigodocs/site/canigo2_0/canigo-services-scheduler/apidocs/index.html Instal- lació i ConfiguracióInstal- lacióLa instal- lació del servei requereix de la utilització de la llibreria 'canigo-services-scheduler' i les dependències indicades a l'apartat 'Introducció-Versions i Dependències'. ConfiguracióFitxer de configuració: canigo-services-scheduler.xml Ubicació proposada: <PROJECT_ROOT>/src/main/resources/spring ConfiguracióLa configuració del Servei de Planificació de tasques implica 3 pasos:
Definició de les tasques Per a definir una tasca cal definir 2 parts:
La tasca és simplement la referència a la classe que conté el mètode que volem executar de forma diferida. Exemple:
<!- TASKS DEFINITIONS -> <bean id="taskWriteLog" class="net.gencat.ctti.canigo.samples.jpetstore.scheduler.TaskWriteLog"/> La classe tasca és un POJO que no ha d'implementar cap interfície en concret ni extendre cap classe.
Per definir els detalls de la tasca per tal que pugui ser executada de forma diferida podem fer ús de 2 classes:
Exemple:
<bean id="taskWriteDetail" class="net.gencat.ctti.canigo.services.scheduler.impl.quartz. SpringQuartzMethodInvokingJobDetailFactoryBean"> <property name="targetObject" ref="taskWriteLog"/> <property name="targetMethod" value="writeLog"/> <property name="concurrent" value="false"/> </bean>
Exemple:
<bean name="exampleJob" class="net.gencat.ctti.canigo.services.scheduler.impl.quartz. SpringQuartzJobDetailBean"> <property name="jobClass" value="example.ExampleJob"/> <property name="jobDataAsMap"> <map> <entry key="timeout" value="5"/> </map> </property> </bean> En aquest cas, la tasca seria definida així: package example;
// import section ... public class ExampleJob extends SpringQuartzJobBean { private int timeout; /** * Setter called after the ExampleJob is instantiated * with the value from the JobDetailBean (5) */ public void setTimeout(int timeout) { this.timeout = timeout; } protected void executeInternal(JobExecutionContext ctx) throws SchedulerServiceException { // do the actual work } } Com veiem, la classe defineix el mètode 'executeInternal' on realitzarà el procediment de la tasca. Definició dels triggers Mitjançant els triggers configurarem en quin moment s'ha d'executar la tasca. canigo permet la utilització de 2 classes:
Exemple:
<!-- TRIGGERS DEFINITIONS --> <bean id="taskWriteTrigger" class="net.gencat.ctti.canigo.services.scheduler.impl.quartz. SpringQuartzSimpleTriggerBean"> <!-- see the example of method invoking job above --> <property name="jobDetail" ref="taskWriteDetail"/> <!-- 10 seconds --> <property name="startDelay" value="10000"/> <!-- repeat every 20 seconds --> <property name="repeatInterval" value="20000"/> <property name="concurrent" value="false"/> </bean>
Exemple:
<bean id="taskWriteTrigger2" class="net.gencat.ctti.canigo.services.scheduler.impl.quartz. SpringQuartzCronTriggerBean"> <!-- see the example of method invoking job above --> <property name="jobDetail" ref="taskWriteDetail"/> <!-- run every morning at 6 AM --> <property name="cronExpression" value="0 0 6 * * ?"/> <property name="concurrent" value="false"/> </bean> Definició de la factoria dels triggers Per últim, definirem un bean de la classe ' net.gencat.ctti.canigo.services.scheduler.impl.quartz.SpringQuartzSchedulerFactoryBean' on definirem les propietats:
Exemple:
<!-- SCHEDULER FACTORY BEAN DEFINITION --> <bean class="net.gencat.ctti.canigo.services.scheduler.impl.quartz.SpringQuartzSchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="taskWriteTrigger"/> <ref bean="taskWriteTrigger2"/> </list> </property> </bean> Utilització del ServeiLa instanciació, la preparació i la petició del servei es fa de manera transparent, de tal manera que el servei s'activa en el moment en que el "Scheduler Factory Bean" conté algun Trigger amb alguna tasca associada (tal i com he definit a la configuració). En el servei, es defineixen a la configuració les tasques (Jobs) i els disparadors (Triggers) que llençaran les tasques. Les tasques, en general no han d'extendre o implementar cap interfície, però sí serà necessari en cas de definir 'SpringQuartzJobDetailBean'. Per tant, la utilització del servei es realitzar pràcticament en la seva totalitat mitjançant la seva configuració. ExemplesCom exemple d'utilització del servei de Planificació de Tasques s'inclou un exemple en el que 2 Triggers invoquen un mètode d'una classe Java que genera un log (mitjançant el servei de traces): En el codi mostrat a baix, la tasca definida no implementa cap classe. Defineix únicament el mètode 'writeLog' on realitza la traça
package net.gencat.ctti.tutorial.web.temp; import org.apache.log4j.Logger; public class TaskWriteLog { public TaskWriteLog() { } public void writeLog(LoggingService logService) { if (logService!=null) { logService.getLog(this.getClass()).debug("Doing log at:" + System. currentTimeMillis()); } } } Un exemple de la configuració de la seva execució diferida és la següent: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/ spring-beans.dtd?"> <beans> <!-- SCHEDULER FACTORY BEAN DEFINITION --> <bean class="net.gencat.ctti.canigo.services.scheduler.impl.quartz. SpringQuartzSchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="taskWriteTrigger"/> </list> </property> </bean> <!-- TASKS DEFINITIONS --> <bean id="taskWriteLog" class="net.gencat.ctti.tutorial.web.temp.TaskWriteLog"/> <bean id="taskWriteDetail" class="net.gencat.ctti.canigo.services.scheduler.impl.quartz. SpringQuartzMethodInvokingJobDetailFactoryBean"> <property name="targetObject" ref="taskWriteLog"/> <property name="targetMethod" value="writeLog"/> <property name="arguments"> <list> <ref bean="logService"/> </list> </property> <property name="concurrent" value="false"/> </bean> <!-- TRIGGERS DEFINITIONS --> <bean id="taskWriteTrigger" class="net.gencat.ctti.canigo.services.scheduler.impl.quartz. SpringQuartzSimpleTriggerBean"> <!-- see the example of method invoking job above --> <property name="jobDetail" ref="taskWriteDetail"/> <!-- 10 seconds --> <property name="startDelay" value="10000"/> <!-- repeat every 20 seconds --> <property name="repeatInterval" value="20000"/> </bean> </beans> Nota En el cas que 2 Triggers utilitzin la mateixa tasca, es podria donar el cas de que abans de que el primer Trigger finalitzi, ja es comenci a executar el segon. Per evitar aquesta situació s'afegirà en la definició de la tasca la propietat _concurrent_ amb el valor "false" |