Presentation is loading. Please wait.

Presentation is loading. Please wait.

#SummitNow Using Scheduler with Long Running Activiti Workflow Tasks 6 November 2013 (Barcelona) 14 November 2013 (Boston) Bill Young, Flatirons Solutions.

Similar presentations


Presentation on theme: "#SummitNow Using Scheduler with Long Running Activiti Workflow Tasks 6 November 2013 (Barcelona) 14 November 2013 (Boston) Bill Young, Flatirons Solutions."— Presentation transcript:

1 #SummitNow Using Scheduler with Long Running Activiti Workflow Tasks 6 November 2013 (Barcelona) 14 November 2013 (Boston) Bill Young, Flatirons Solutions

2 #SummitNow Overview Justification Problem Analysis Solution

3 #SummitNow Justification Manage Long Running (Batch-like) Processes in Workflow Queue Processes Limited Resources Throttle Running Jobs - Configuration

4 #SummitNow Sample Workflow

5 #SummitNow Problem Analysis Quartz Scheduler Available Activiti Doesn’t Provide Scheduling Activiti Does Provide Receive Tasks

6 #SummitNow Technologies Quartz Open Source Job Scheduling Library Already Integrated with Alfresco Java API http://quartz-scheduler.org/

7 #SummitNow Technologies Activiti Open Source BPMN 2 Process Engine Heart of Alfresco Workflows (since 4.0) http://activiti.org/

8 #SummitNow Solution Split Tasks in Workflow Design Custom Scheduler Custom Jobs Custom Delegate Spring Configuration JDBC Job Store

9 #SummitNow Revised Workflow Diagram

10 #SummitNow Custom Delegate UML Diagram and Code

11 #SummitNow Custom Java Delegate

12 #SummitNow Abstract Java Delegate public abstract class AbstractCustomJavaDelegate extends BaseJavaDelegate { /** bean holding workflow settings */ private WorkflowServiceBean workflowSettings; /** * @return the workflowSettings */ public WorkflowServiceBean getWorkflowSettings() { return workflowSettings; } /** * @param value the workflowSettings to set */ public void setWorkflowSettings(final WorkflowServiceBean value) { this.workflowSettings = value; }

13 #SummitNow Abstract Scheduled Job Delegate public abstract class AbstractScheduledJobDelegate extends AbstractCustomJavaDelegate { /** Quartz Scheduler */ private Scheduler scheduler; /** Default Priority level */ private int defaultPriority; /** @return the scheduler */ public Scheduler getScheduler() { return scheduler; } /** @param value the scheduler to set */ public void setScheduler(final Scheduler value) { this.scheduler = value; } /** @return the defaultPriority */ public int getDefaultPriority() { return defaultPriority; } /** @param value the defaultPriority to set */ public void setDefaultPriority(final int value) { this.defaultPriority = value; }

14 #SummitNow Abstract Scheduled Job Delegate public Map getVariablesMap(final DelegateExecution execution) { Map variablesMap = new HashMap (); variablesMap.put(WORK_PACKAGE_ID_VAR, execution.getVariable(WORK_PACKAGE_ID_VAR)); variablesMap.put(WORKFLOW_DESC_VAR, execution.getVariable(WORKFLOW_DESC_VAR)); variablesMap.put(CONTENT_PACKAGE_VAR, execution.getVariable(CONTENT_PACKAGE_VAR)); variablesMap.put(WORKFLOW_DUE_DATE_VAR, execution.getVariable(WORKFLOW_DUE_DATE_VAR)); variablesMap.put(WORKFLOW_INSTANCE_ID, execution.getVariable(WORKFLOW_INSTANCE_ID)); variablesMap.put(TASK_OWNER, execution.getVariable(TASK_OWNER)); variablesMap.put(JOB_PRIORITY_VAR, Integer.valueOf(defaultPriority)); return variablesMap; }

15 #SummitNow Abstract Scheduled Job Delegate public void execute(final DelegateExecution execution) throws Exception { Map variablesMap = getVariablesMap(execution); String jobTraqId = (String) variablesMap.get(WORK_PACKAGE_ID_VAR); WorkflowInstance wkfInstance = getWorkflowSettings().getServiceRegistry().getWorkflowService().getWorkflowById( (String) variablesMap.get(WORKFLOW_INSTANCE_ID)); JobDetail jobDetail = new JobDetail(getJobPrefix() + jobTraqId, getJobsGroup(), getJobClass()); JobDataMap jobDataMap = new JobDataMap(); jobDataMap.put(JOB_TRAQ_ID, jobTraqId); jobDataMap.put(EXEC_VARIABLES, variablesMap); jobDataMap.put(WORKFLOW_INSTANCE, wkfInstance); jobDetail.setJobDataMap(jobDataMap); Trigger trigger = new SimpleTrigger(getTriggerPrefix() + jobTraqId, getTriggersGroup()); trigger.setPriority(((Integer) variablesMap.get(JOB_PRIORITY_VAR)).intValue()); getScheduler().scheduleJob(jobDetail, trigger); }

16 #SummitNow Concrete Scheduled Job Delegate public class IngestDelegate extends AbstractScheduledJobDelegate { public String getJobPrefix() { return INGESTION_JOB_PREFIX; } public String getJobsGroup() { return INGESTION_JOBS_GROUP; } public String getTriggerPrefix() { return INGESTION_TRIGGER_PREFIX; } public String getTriggersGroup() { return INGESTION_TRIGGERS_GROUP; } public Class getJobClass() { return ContentIngestionJob.class; } }

17 #SummitNow Bean Initialization

18 #SummitNow Workflow Settings Bean <bean id="CustomWorkflowSettings" class="com.flatirons.workflow.WorkflowServiceBean"> ${audit. alfresco.enabled}...

19 #SummitNow Java Delegate Beans <bean id="abstractJavaDelegate" parent="baseJavaDelegate" class="com.flatirons.workflow.AbstractCustomJavaDelegate" abstract="true"> <bean id="abstractScheduledJobDelegate" parent="abstractJavaDelegate" class="com.flatirons.workflow.AbstractScheduledJobDelegate“ abstract="true"> ${quartz.priority.default} <bean id="IngestDelegate" parent="abstractScheduledJobDelegate" class="com.flatirons.workflow.ingest.IngestDelegate">

20 #SummitNow Custom Scheduler UML diagram and code

21 #SummitNow Scheduler UML

22 #SummitNow Custom Std Scheduler public class FlatironsStdScheduler extends StdScheduler { /** bean holding workflow settings */ private WorkflowServiceBean workflowSettings; public FlatironsStdScheduler(final QuartzScheduler scheduler, final SchedulingContext schedulingContext) { super(scheduler, schedulingContext); } public WorkflowServiceBean getWorkflowSettings() { return workflowSettings; } public void setWorkflowSettings(final WorkflowServiceBean value) { workflowSettings = value; }

23 #SummitNow Scheduler Factory public class FlatironsSchedulerFactory extends StdSchedulerFactory { public FlatironsSchedulerFactory() { } protected Scheduler instantiate(final QuartzSchedulerResources resources, final QuartzScheduler scheduler) { SchedulingContext schedulingContext = new SchedulingContext(); schedulingContext.setInstanceId(resources.getInstanceId()); return new FlatironsStdScheduler(scheduler, schedulingContext); }

24 #SummitNow Scheduler Factory Bean public class FlatironsSchedulerFactoryBean extends SchedulerFactoryBean { private WorkflowServiceBean workflowSettings; public FlatironsSchedulerFactoryBean() { setSchedulerFactoryClass(FlatironsSchedulerFactory.class); } protected Scheduler createScheduler(final SchedulerFactory schedulerFactory, final String schedulerName) throws SchedulerException { FlatironsStdScheduler newScheduler = (FlatironsStdScheduler) super.createScheduler(schedulerFactory, schedulerName); newScheduler.setWorkflowSettings(this.workflowSettings); return newScheduler; }

25 #SummitNow Custom Jobs UML diagram and code

26 #SummitNow Jobs UML

27 #SummitNow Abstract Custom Job public abstract class FlatironsJob implements org.quartz.Job { public void execute(final JobExecutionContext context) throws JobExecutionException { try { JobDataMap jobDataMap = context.getMergedJobDataMap(); execute((WorkflowInstance) jobDataMap.get(WORKFLOW_INSTANCE), (FlatironsStdScheduler) context.getScheduler(), (Map ) jobDataMap.get(EXEC_VARIABLES)); } catch (Exception e) { throw new JobExecutionException(e); } finally { signalCompletion(null); } protected abstract void execute(WorkflowInstance workflowInstance, FlatironsStdScheduler scheduler, Map variablesMap) throws JobExecutionException; }

28 #SummitNow Concrete Custom Job public class ContentIngestionJob extends FlatironsJob { protected void execute(final WorkflowInstance workflowInstance, final FlatironsStdScheduler scheduler, final Map variablesMap) { ContentIngester contentIngester = new ContentIngester( scheduler.getWorkflowSettings(), variablesMap, workflowInstance); contentIngester.execute(); }

29 #SummitNow Spring Configuration <bean id="quartzIngestionSchedulerProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean"> 10 QRTZ_ING_ <bean id="ingestionScheduler" class="com.flatirons.workflow.scheduler.quartz.FlatironsSchedulerFactoryBean">

30 #SummitNow Quartz Properties org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool org.quartz.threadPool.makeThreadsDaemons=false org.quartz.scheduler.makeSchedulerThreadDaemon=true org.quartz.scheduler.instanceId=AUTO org.quartz.scheduler.jmx.export=true org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate org.quartz.jobStore.isClustered=false org.quartz.jobStore.clusterCheckinInterval=20000 org.quartz.jobStore.dataSource=myDS org.quartz.dataSource.myDS.driver=com.mysql.jdbc.Driver org.quartz.dataSource.myDS.URL=jdbc:mysql://localhost:3306/alfresco_quartz?useUnicode=yes&ch aracterEncoding=UTF-8 org.quartz.dataSource.myDS.user=quartz_usr org.quartz.dataSource.myDS.password=quartz...

31 #SummitNow JDBC Job Store create database if not exists alfresco_quartz; use alfresco_quartz; grant all on alfresco_quartz.* to quartz_usr@'localhost' identified by 'quartz'; grant all on alfresco_quartz.* to quartz_usr@'127.0.0.1' identified by 'quartz'; DROP TABLE IF EXISTS QRTZ_ING_JOB_DETAILS;... CREATE TABLE QRTZ_ING_JOB_DETAILS(... )... DROP TABLE IF EXISTS QRTZ_CON_JOB_DETAILS;... CREATE TABLE QRTZ_CON_JOB_DETAILS(... )...

32 #SummitNow Quartz Job Store mysql> show tables; +------------------------------+ | Tables_in_alfresco_quartz | +------------------------------+ |... | | QRTZ_CON_TRIGGERS | | QRTZ_CON_TRIGGER_LISTENERS | | QRTZ_ING_BLOB_TRIGGERS | | QRTZ_ING_CALENDARS | | QRTZ_ING_CRON_TRIGGERS | | QRTZ_ING_FIRED_TRIGGERS | | QRTZ_ING_JOB_DETAILS | | QRTZ_ING_JOB_LISTENERS | | QRTZ_ING_LOCKS | | QRTZ_ING_PAUSED_TRIGGER_GRPS | | QRTZ_ING_SCHEDULER_STATE | | QRTZ_ING_SIMPLE_TRIGGERS | | QRTZ_ING_TRIGGERS | | QRTZ_ING_TRIGGER_LISTENERS | |... | +------------------------------+

33 #SummitNow Quartz Job Store mysql> desc QRTZ_ING_TRIGGERS; +----------------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +----------------+--------------+------+-----+---------+-------+ | TRIGGER_NAME | varchar(200) | NO | PRI | NULL | | | TRIGGER_GROUP | varchar(200) | NO | PRI | NULL | | | JOB_NAME | varchar(200) | NO | MUL | NULL | | | JOB_GROUP | varchar(200) | NO | | NULL | | | IS_VOLATILE | varchar(1) | NO | | NULL | | | DESCRIPTION | varchar(250) | YES | | NULL | | | NEXT_FIRE_TIME | bigint(13) | YES | | NULL | | | PREV_FIRE_TIME | bigint(13) | YES | | NULL | | | PRIORITY | int(11) | YES | | NULL | | | TRIGGER_STATE | varchar(16) | NO | | NULL | | | TRIGGER_TYPE | varchar(8) | NO | | NULL | | | START_TIME | bigint(13) | NO | | NULL | | | END_TIME | bigint(13) | YES | | NULL | | | CALENDAR_NAME | varchar(200) | YES | | NULL | | | MISFIRE_INSTR | smallint(2) | YES | | NULL | | | JOB_DATA | blob | YES | | NULL | | +----------------+--------------+------+-----+---------+-------+ 16 rows in set (0.02 sec)

34 #SummitNow Quartz Job Store mysql> select TRIGGER_NAME, JOB_NAME, PRIORITY, TRIGGER_STATE from QRTZ_ING_TRIGGERS; +---------------------------+-----------------------+----------+---------------+ | TRIGGER_NAME | JOB_NAME | PRIORITY | TRIGGER_STATE | +---------------------------+-----------------------+----------+---------------+ | IngestionTrigger_Summit E | IngestionJob_Summit E | 3 | COMPLETE | | IngestionTrigger_Summit F | IngestionJob_Summit F | 3 | WAITING | +---------------------------+-----------------------+----------+---------------+ 2 rows in set (0.00 sec)

35 #SummitNow Quartz Job Store mysql> desc QRTZ_ING_JOB_DETAILS; +-------------------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------------------+--------------+------+-----+---------+-------+ | JOB_NAME | varchar(200) | NO | PRI | NULL | | | JOB_GROUP | varchar(200) | NO | PRI | NULL | | | DESCRIPTION | varchar(250) | YES | | NULL | | | JOB_CLASS_NAME | varchar(250) | NO | | NULL | | | IS_DURABLE | varchar(1) | NO | | NULL | | | IS_VOLATILE | varchar(1) | NO | | NULL | | | IS_STATEFUL | varchar(1) | NO | | NULL | | | REQUESTS_RECOVERY | varchar(1) | NO | | NULL | | | JOB_DATA | blob | YES | | NULL | | +-------------------+--------------+------+-----+---------+-------+ 9 rows in set (0.01 sec)

36 #SummitNow Quartz Job Store mysql> select JOB_NAME, JOB_CLASS_NAME from QRTZ_ING_JOB_DETAILS; +-----------------------+------------------------------------------------------+ | JOB_NAME | JOB_CLASS_NAME | +-----------------------+------------------------------------------------------+ | IngestionJob_Summit E | com.flatirons.workflow.scheduler.ContentIngestionJob | | IngestionJob_Summit F | com.flatirons.workflow.scheduler.ContentIngestionJob | +-----------------------+------------------------------------------------------+ 2 rows in set (0.00 sec)

37 #SummitNow Additional Features Custom Page for Job Priority Clustering Remove Jobs from Queue

38 #SummitNow Contributors Sri Patil, Senior Developer, Flatirons

39 #SummitNow Questions

40 #SummitNow


Download ppt "#SummitNow Using Scheduler with Long Running Activiti Workflow Tasks 6 November 2013 (Barcelona) 14 November 2013 (Boston) Bill Young, Flatirons Solutions."

Similar presentations


Ads by Google