cancel
Showing results for 
Search instead for 
Did you mean: 

How to execute two stateful cron jobs(java classes) simultaneously?

Sanjana_17
Champ on-the-rise
Champ on-the-rise

I have created two timer jobs with job classes implementing org.quartz.StatefulJob. The entry of their respective cron expressions has been done in the alfresco-global.properties file.

The issue is only one job runs despite the execution time given in properties file as different for both the jobs.I am new to alfresco, will be grateful if someone can help to solve this. I have followed the link mentioned below to create the jobs:

http://javaworld-abhinav.blogspot.com/2015/08/creating-scheduled-job-in-alfresco.html 

1 ACCEPTED ANSWER

I noticed that you have defined same cron bean id (customJobTrigger) for both jobs which is not correct.  And looking at your bean definitions, it seems you have two different job-context.xml files. 

<bean id="customJobTrigger" class="org.alfresco.util.CronTriggerBean"> 

I would suggest to change it like:

Job1 cronTrigger: 

<bean id="customJobTriggerABC" class="org.alfresco.util.CronTriggerBean">
<property name="jobDetail">
<ref bean="abcJob" />
</property>
<property name="scheduler">
<ref bean="schedulerFactory" />
</property>
<property name="cronExpression">
<value>${abcJob.cron.expression}</value>
</property>
<property name="startDelay">
<value>${delayabc.cron.expression}</value>
</property>
</bean>

Job2 cronTrigger: 

<bean id="customJobTriggerPQR" class="org.alfresco.util.CronTriggerBean">
<property name="jobDetail">
<ref bean="pqrJob" />
</property>
<property name="scheduler">
<ref bean="schedulerFactory" />
</property>
<property name="cronExpression">

<value>${pqrJob.cron.expression}</value>
</property>
<property name="startDelay">
<value>${delaypqrJob.cron.expression}</value>
</property>
</bean>

Can you explain the requirement as well?

~Abhinav
(ACSCE, AWS SAA, Azure Admin)

View answer in original post

4 REPLIES 4

abhinavmishra14
World-Class Innovator
World-Class Innovator

If you have configured the crons appropriately then it should execute all the jobs unless there is any error which is preventing the job to start.  

However, i would suggest to implement your jobs using: https://dev.alfresco.com/resource/docs/java/org/alfresco/schedule/AbstractScheduledLockedJob.html 

This implementation is cluster aware, so if your application is running in cluster, you won't face conflicts. 

The link you shared is talking about this Abstract class as well. Check this section : "AbstractScheduledLockedJob (Cluster Aware Job Scheduler Implementation)"

Your job processor would look something like this: 

package com.abhinav.jobs;
import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.schedule.AbstractScheduledLockedJob; import org.alfresco.service.transaction.TransactionService; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class CustomClusterAwareJobProcessor extends AbstractScheduledLockedJob { private static final Log LOG = LogFactory.getLog(CustomClusterAwareJobProcessor.class); private TransactionService transactionService; @Override public void executeJob(final JobExecutionContext jobCtx) throws JobExecutionException {
LOG.info("CustomClusterAwareJobProcessor started..."); try { // Run as system user since this job is user independent hence // permission is required on repository AuthenticationUtil.setRunAsUserSystem(); final RetryingTransactionCallback<Object> txnWork = new RetryingTransactionCallback<Object>() { public Object execute() throws Exception { //TODO:: YOUR CUSTOM CODE } }; transactionService.getRetryingTransactionHelper().doInTransaction(txnWork);
LOG.info("CustomClusterAwareJobProcessor finished."); } catch (Exception excp) { LOG.error("Exception occurred while processing job", excp); } } public void setTransactionService(final TransactionService transactionService) { this.transactionService = transactionService; } }

Update the context something like:

 <bean id="customClusterAwareJobDetail" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass">
<value>com.abhinav.jobs.CustomClusterAwareJobProcessor</value>
</property>
<!--In the map, you can pass all the services you would need during the job processing-->
<property name="jobDataAsMap">
<map>
<entry key="transactionService">
 <ref bean="transactionService"/>
</entry>
<!-- JobLockService used to aquire the lock on jobs while they are 
     being processed to avoid other thread to modify the jobs state-->
<entry key="jobLockService">
<ref bean="jobLockService"/>
</entry>
</map>
</property>
</bean>
                       
 <bean id="customClusterAwareJobTrigger" class="org.alfresco.util.CronTriggerBean">
<property name="jobDetail">
<ref bean="customClusterAwareJobDetail" />
</property>
<property name="scheduler">
<ref bean="schedulerFactory" />
</property>
<property name="cronExpression">
 <!-- Provided the cron expession in alfresco-global.propeties file -->
<value>${customjob.cron.expression}</value>
</property>
</bean>
 
In alfresco-global.properties: 
#This expression will execute the job every 1 minute
customjob.cron.expression=0 0/1 * 1/1 * ? *
 
You can configure the cron as per your requirement.
 
 
~Abhinav
(ACSCE, AWS SAA, Azure Admin)

Thanks Abhinav for your reply.

This time I have extended the java(job) classes with AbstractScheduledLockedJob, the timer job are executing but the problem still prevailsThe jobs are not running simultaneously, when I comment the entry of one of the job's context file in module-context.xml the other job runs and vice versa.

I am sharing the context files of both the jobs below along with the cron expressions that I have used to trigger the jobs.

Job1:

<bean id="abcJob" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass">
<value>com.vil.jobs.ABCJob</value>
</property>
<property name="jobDataAsMap">
<map>
<entry key="serviceRegistry">
<ref bean="ServiceRegistry" />
</entry>

<entry key="searchService">
<ref bean="SearchService" />
</entry>

<entry key="nodeService">
<ref bean="NodeService" />
</entry>

<entry key="actionService">
<ref bean="ActionService" />
</entry>

<entry key="transactionService">
<ref bean="TransactionService" />
</entry>

<entry key="namespaceService">
<ref bean="NamespaceService" />
</entry>

<entry key="globalProperties">
<ref bean="global-properties" />
</entry>

<entry key="jobLockService">
<ref bean="jobLockService" />
</entry>

<entry key="TransactionService">
<ref bean="transactionService" />
</entry>

</map>
</property>
</bean>

<bean id="customJobTrigger" class="org.alfresco.util.CronTriggerBean">
<property name="jobDetail">
<ref bean="abcJob" />
</property>
<property name="scheduler">
<ref bean="schedulerFactory" />
</property>
<property name="cronExpression">

<value>${abcJob.cron.expression}</value>
</property>
<property name="startDelay">
<value>${delayabc.cron.expression}</value>
</property>
</bean>

</beans>

Job2:

<bean id="pqrJob" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass">
<value>com.vil.jobs.PQRJob</value>
</property>
<property name="jobDataAsMap">
<map>
<entry key="serviceRegistry">
<ref bean="ServiceRegistry" />
</entry>

<entry key="searchService">
<ref bean="SearchService" />
</entry>

<entry key="nodeService">
<ref bean="NodeService" />
</entry>

<entry key="actionService">
<ref bean="ActionService" />
</entry>

<entry key="transactionService">
<ref bean="TransactionService" />
</entry>

<entry key="namespaceService">
<ref bean="NamespaceService" />
</entry>

<entry key="globalProperties">
<ref bean="global-properties" />
</entry>

<entry key="jobLockService">
<ref bean="jobLockService" />
</entry>
</map>
</property>
</bean>

<bean id="customJobTrigger" class="org.alfresco.util.CronTriggerBean">
<property name="jobDetail">
<ref bean="pqrJob" />
</property>
<property name="scheduler">
<ref bean="schedulerFactory" />
</property>
<property name="cronExpression">

<value>${pqrJob.cron.expression}</value>
</property>
<property name="startDelay">
<value>${delaypqrJob.cron.expression}</value>
</property>
</bean>

</beans>

CronExpressions in properties File -

delaypqrJob.cron.expression=180000
delayabcJob.cron.expression=300000
pqrJob.cron.expression=0 0/5 * 1/1 * ? * (5 minutes)
abcJob.cron.expression=0 0/2 * 1/1 * ? * (2 minutes)

I noticed that you have defined same cron bean id (customJobTrigger) for both jobs which is not correct.  And looking at your bean definitions, it seems you have two different job-context.xml files. 

<bean id="customJobTrigger" class="org.alfresco.util.CronTriggerBean"> 

I would suggest to change it like:

Job1 cronTrigger: 

<bean id="customJobTriggerABC" class="org.alfresco.util.CronTriggerBean">
<property name="jobDetail">
<ref bean="abcJob" />
</property>
<property name="scheduler">
<ref bean="schedulerFactory" />
</property>
<property name="cronExpression">
<value>${abcJob.cron.expression}</value>
</property>
<property name="startDelay">
<value>${delayabc.cron.expression}</value>
</property>
</bean>

Job2 cronTrigger: 

<bean id="customJobTriggerPQR" class="org.alfresco.util.CronTriggerBean">
<property name="jobDetail">
<ref bean="pqrJob" />
</property>
<property name="scheduler">
<ref bean="schedulerFactory" />
</property>
<property name="cronExpression">

<value>${pqrJob.cron.expression}</value>
</property>
<property name="startDelay">
<value>${delaypqrJob.cron.expression}</value>
</property>
</bean>

Can you explain the requirement as well?

~Abhinav
(ACSCE, AWS SAA, Azure Admin)

Thank you for the revert.

I have updated the job-context.xml files with the proper bean ids as suggested by you and it worked for all my cron jobs. 

Thanks! again Smiley Very Happy