Notice: This Wiki is now read only and edits are no longer possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.
Stardust/Knowledge Base/Java API/Dynamic Event Binding
Contents
Requirements
A process, let say, Main Process has to trigger a sub-process called Escalation Process, but it doesn't know when to trigger it (not known during design). It only knows that when certain data or indicator will be available at proces execution it would like to trigger the sub-process.
Approach
We will be modelling the Main Process by defining an Process level Event Handling, Timer, and will not bind it Automatically. We will use a process data that will be set somewhere during process execution and this data will be used to indicate the time when we would like the Timer event to get fired and trigger the Escalation Process.
Complete Process
We will use IPP WorkflowService's API bindProcessEventHandler to bind the event after a value is available to the data to which Timer is bound.
Code:
package com.sungard.cm.invo.ipp.training; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.Properties; import org.eclipse.stardust.common.config.Parameters; import org.eclipse.stardust.engine.api.query.ActivityInstanceQuery; import org.eclipse.stardust.engine.api.query.ActivityInstances; import org.eclipse.stardust.engine.api.query.ActivityStateFilter; import org.eclipse.stardust.engine.api.runtime.ActivityInstance; import org.eclipse.stardust.engine.api.runtime.ActivityInstanceState; import org.eclipse.stardust.engine.api.runtime.AdministrationService; import org.eclipse.stardust.engine.api.runtime.DocumentManagementService; import org.eclipse.stardust.engine.api.runtime.QueryService; import org.eclipse.stardust.engine.api.runtime.ServiceFactory; import org.eclipse.stardust.engine.api.runtime.ServiceFactoryLocator; import org.eclipse.stardust.engine.api.runtime.UserService; import org.eclipse.stardust.engine.api.runtime.WorkflowService; import org.eclipse.stardust.engine.core.runtime.beans.removethis.SecurityProperties; public class PrioritySettler { private static ServiceFactory serviceFactory; private static QueryService queryService; private static WorkflowService workflowService; private static UserService userService; private static AdministrationService adminService; private static DocumentManagementService documentService; public PrioritySettler() { } @SuppressWarnings("deprecation") public void evaluateAndUpdatePriority(long pOID) { System.out.println("Process OID to change the priority: "+ pOID); try{ init("motu", "motu"); workflowService.bindProcessEventHandler(pOID, "SLA"); }catch(Exception e){ //Default thresholdMins to 10 minutes e.printStackTrace(); thresholdValue = 1; } finally { uninit(); } } static void init(String backdoorAccount, String backdoorKey) throws IOException { // Get the factory and provide login credentials Map <String, String> prop = new HashMap(); serviceFactory = ServiceFactoryLocator .get("motu", "motu"); // Get the service instances queryService = serviceFactory.getQueryService(); workflowService = serviceFactory.getWorkflowService(); userService = serviceFactory.getUserService(); documentService = serviceFactory.getDocumentManagementService(); adminService = serviceFactory.getAdministrationService(); } static void uninit() { //System.out.println("In Uninit#############"); if (serviceFactory != null) { // Release all resources serviceFactory.close(); } } }
Another approach can be taken to define the class and instead of hard coding motu/motu, we can declare a bean referring to this class and can inject the required service objects as properties, like:
<bean id="prioritySettler" class="com.sungard.cm.invo.ipp.training.PrioritySettler"> <property name="userService" ref="carnotUserService" /> <property name="queryService" ref="carnotQueryService" /> <property name="adminService" ref="carnotAdministrationService" /> <property name="workflowService" ref="carnotWorkflowService" /> <property name="documentService" ref="carnotDocumentManagementService" /> </bean>
public class PrioritySettler { private static QueryService queryService; private static WorkflowService workflowService; private static UserService userService; private static AdministrationService adminService; private static DocumentManagementService documentService; public static QueryService getQueryService() { return queryService; } public static void setQueryService(QueryService queryService) { PrioritySettler.queryService = queryService; } public static WorkflowService getWorkflowService() { return workflowService; } public static void setWorkflowService(WorkflowService workflowService) { PrioritySettler.workflowService = workflowService; } public static UserService getUserService() { return userService; } public static void setUserService(UserService userService) { PrioritySettler.userService = userService; } public static AdministrationService getAdminService() { return adminService; } public static void setAdminService(AdministrationService adminService) { PrioritySettler.adminService = adminService; } public static DocumentManagementService getDocumentService() { return documentService; } public static void setDocumentService(DocumentManagementService documentService) { PrioritySettler.documentService = documentService; } public PrioritySettler() { } @SuppressWarnings("deprecation") public void evaluateAndUpdatePriority(long pOID) { System.out.println("Process OID to change the priority: "+ pOID); try{ workflowService.bindProcessEventHandler(pOID, "SLA"); }catch(Exception e){ //Default thresholdMins to 10 minutes e.printStackTrace(); thresholdValue = 1; } finally { } } }
With this approach please ensure to edit the model so that activity Bind Timer is now uses Spring Bean application instead of POJO and uses the bean 'prioritySettler'.
Results
In this example case, when Main Process is started:
- User will input data (time in milliseconds since Jan 1, 1970) on first activity UI.
- User will see the entered time value on next screen, after completing this activity.
- The application activity "Bind Timer", will call the POJO method and bind the Timer Event named "SLA" and the process Escalation Process witll be triggered at the time the user entered on first activity.
For example, you started Main Process at 16:45 hours and input the value (in milliseconds since Jan1, 1970) of 16:50, the Escalation Process will be triggered at 16:50.
Artifacts
Please get the required artifacts from here