1: Sure, no problem... just model it that way

2: leaving the node but keeping the task and 'just' notify? Via Email? That is 
possible with a timer. Via a new task, leaving the node where to? A new 
tasknode? And what if the user finishes the task before someone else can react 
on this task? Do you want to cancel it then? 

Remember that jBPM van have tasks that are not in the flow... you can create 
and start them when a timer goes off. And e.g. cancel them when a transition is 
taken on the original node.

Just to show you (and this is a one time effort by me ;-)) I've made an example 
of this which is even somewhat configurable. 


These are all possible with jBPM *now* just think out of the box and model 
these things into your process. Or write some code (actionhandlers etc..) The 
thing is, escalation, or the way people want it, is so dependant on the case, 
it cannot to the fullest extend be part of the processlanguage. 

The solution for the initial problem 'reported' is to give both the timer and 
the duedate (which is just for informing the original owner) the same date. but 
what need is a date for a reminder if when the duedate is reached 


  | package net.vankuijk.jbpm;
  | 
  | import java.util.ArrayList;
  | import java.util.Collection;
  | import java.util.List;
  | import java.util.Map;
  | 
  | import org.apache.commons.logging.Log;
  | import org.apache.commons.logging.LogFactory;
  | import org.jbpm.db.AbstractDbTestCase;
  | import org.jbpm.graph.def.ActionHandler;
  | import org.jbpm.graph.def.Node;
  | import org.jbpm.graph.def.ProcessDefinition;
  | import org.jbpm.graph.exe.ExecutionContext;
  | import org.jbpm.graph.exe.ProcessInstance;
  | import org.jbpm.graph.exe.Token;
  | import org.jbpm.graph.node.TaskNode;
  | import org.jbpm.taskmgmt.def.Task;
  | import org.jbpm.taskmgmt.exe.TaskInstance;
  | import org.jbpm.taskmgmt.exe.TaskMgmtInstance;
  | 
  | public class EscalationExampleTest extends AbstractDbTestCase {
  | 
  |     ArrayList ownerIDs;
  |     ArrayList escalatorIDs;
  | 
  |     List ownerTasks;
  |     List escalatorTasks;
  | 
  |     public void setUp() throws Exception {
  |             super.setUp();
  | 
  |             ownerIDs = new ArrayList();
  |             ownerIDs.add("owner");
  | 
  |             escalatorIDs = new ArrayList();
  |             escalatorIDs.add("escalator");
  | 
  |     }
  | 
  |     static String processDefinition = "<process-definition 
name='testEscalation'>"
  |                     + "  <swimlane name='ownerSwimlane'>"
  |                     + "    <assignment pooled-actors='owner' />"
  |                     + "  </swimlane>"
  | 
  |                     + "  <event type='node-leave'>"
  |                     + "    <action 
class='net.vankuijk.jbpm.EscalationExampleTest$CancelEscalationTask' />"
  |                     + "  </event>"
  | 
  |                     + "  <action name='createEscalationTask' 
class='net.vankuijk.jbpm.EscalationExampleTest$CreateEscalationTask'>"
  |                     + "    <escalationTaskNodeName>task 
escalated</escalationTaskNodeName>"
  |                     + "  </action>"
  | 
  |                     + "  <swimlane name='escalationSwimlane'>"
  |                     + "    <assignment pooled-actors='escalator' />"
  |                     + "  </swimlane>"
  | 
  |                     + "  <start-state>"
  |                     + "    <transition name='to_task' to='task' />"
  |                     + "  </start-state>"
  | 
  |                     + "  <task-node name='task'>"
  |                     + "    <task name='task 0' swimlane='ownerSwimlane'>"
  |                     + "      <timer duedate='5 seconds'>"
  |                     + "        <action ref-name='createEscalationTask' />"
  |                     + "      </timer>"
  |                     + "    </task>"
  |                     + "    <transition name='to_end' to='end' />"
  |                     + "  </task-node>"
  | 
  |                     + "  <task-node name='task escalated'>"
  |                     + "    <task name='escalated task 0' 
swimlane='escalationSwimlane' signalling='false'/>"
  |                     + "  </task-node>"
  | 
  |                     + "  <end-state name='end' />"
  | 
  |                     + "</process-definition>";
  | 
  |     void deployProcessDefinition(String xml) {
  |             ProcessDefinition processDefinition = ProcessDefinition
  |                             .parseXmlString(xml);
  |             jbpmContext.deployProcessDefinition(processDefinition);
  |             newTransaction();
  |     }
  | 
  |     public void testNormalFlow() {
  | 
  |             deployProcessDefinition(processDefinition);
  | 
  |             ProcessInstance processInstance = jbpmContext
  |                             .newProcessInstanceForUpdate("testEscalation");
  |             processInstance.signal();
  | 
  |             processInstance = saveAndReload(processInstance);
  | 
  |             ownerTasks = jbpmContext.getGroupTaskList(ownerIDs);
  |             TaskInstance ownerTask = (TaskInstance) ownerTasks.get(0);
  |             ownerTask.end();
  | 
  |             assertEquals(0, processInstance.getTaskMgmtInstance()
  |                             
.getUnfinishedTasks(processInstance.getRootToken()).size());
  | 
  |             assertEquals(true, processInstance.hasEnded());
  | 
  |     }
  | 
  |     public void testEndingNormalTaskAfterEscalationCancelsEscalation() {
  |             deployProcessDefinition(processDefinition);
  | 
  |             ProcessInstance processInstance = jbpmContext
  |                             .newProcessInstanceForUpdate("testEscalation");
  |             long piId = processInstance.getId();
  |             processInstance.signal();
  | 
  |             assertEquals(1, processInstance.getTaskMgmtInstance()
  |                             .getTaskInstances().size());
  | 
  |             processInstance = saveAndReload(processInstance);
  | 
  |             ownerTasks = jbpmContext.getGroupTaskList(ownerIDs);
  |             assertEquals(1, ownerTasks.size());
  | 
  |             escalatorTasks = jbpmContext.getGroupTaskList(escalatorIDs);
  |             assertEquals(0, escalatorTasks.size());
  | 
  |             processJobs(10000);
  | 
  |             processInstance = jbpmContext.getProcessInstance(piId);
  | 
  |             assertEquals(2, processInstance.getTaskMgmtInstance()
  |                             .getTaskInstances().size());
  | 
  |             escalatorTasks = jbpmContext.getGroupTaskList(escalatorIDs);
  |             assertEquals(1, escalatorTasks.size());
  | 
  |             ownerTasks = jbpmContext.getGroupTaskList(ownerIDs);
  |             TaskInstance ownerTask = (TaskInstance) 
ownerTasks.iterator().next();
  |             ownerTask.end();
  | 
  |             // processInstance = saveAndReload(processInstance);
  | 
  |             // Escalation task should be cancelled
  |             escalatorTasks = jbpmContext.getGroupTaskList(escalatorIDs);
  |             assertEquals(0, escalatorTasks.size());
  | 
  |     }
  | 
  |     public void testEscalationEnded_NormalTaskStays() {
  |             deployProcessDefinition(processDefinition);
  | 
  |             ProcessInstance processInstance = jbpmContext
  |                             .newProcessInstanceForUpdate("testEscalation");
  |             long piId = processInstance.getId();
  |             processInstance.signal();
  | 
  |             assertEquals(1, processInstance.getTaskMgmtInstance()
  |                             .getTaskInstances().size());
  | 
  |             processInstance = saveAndReload(processInstance);
  | 
  |             ownerTasks = jbpmContext.getGroupTaskList(ownerIDs);
  |             assertEquals(1, ownerTasks.size());
  | 
  |             escalatorTasks = jbpmContext.getGroupTaskList(escalatorIDs);
  |             assertEquals(0, escalatorTasks.size());
  | 
  |             processJobs(10000);
  | 
  |             processInstance = jbpmContext.getProcessInstance(piId);
  | 
  |             assertEquals(2, processInstance.getTaskMgmtInstance()
  |                             .getTaskInstances().size());
  | 
  |             escalatorTasks = jbpmContext.getGroupTaskList(escalatorIDs);
  |             assertEquals(1, escalatorTasks.size());
  | 
  |             TaskInstance escalatorTask = (TaskInstance) 
escalatorTasks.iterator()
  |                             .next();
  |             assertEquals("escalated task 0", escalatorTask.getName());
  |             escalatorTask.end();
  | 
  |             processInstance = saveAndReload(processInstance);
  | 
  |             // owner task should still be there... is it?
  |             ownerTasks = jbpmContext.getGroupTaskList(ownerIDs);
  |             assertEquals(1, ownerTasks.size());
  | 
  |             escalatorTasks = jbpmContext.getGroupTaskList(escalatorIDs);
  |             assertEquals(0, escalatorTasks.size());
  | 
  |     }
  | 
  |     public static class CreateEscalationTask implements ActionHandler {
  |             private static final long serialVersionUID = 1L;
  | 
  |             public String escalationTaskNodeName;
  | 
  |             public void execute(ExecutionContext executionContext) throws 
Exception {
  | 
  |                     
  |                     if ("".equals(escalationTaskNodeName) || 
escalationTaskNodeName == null) {
  |                             log.warn("escalationTaskNodeName not 
specified");
  |                             return;
  |                     }
  | 
  |                     Token token = executionContext.getToken();
  |                     TaskMgmtInstance tmi = 
executionContext.getTaskMgmtInstance();
  |                     
  |                     Node node = 
executionContext.getProcessDefinition().getNode(
  |                                     escalationTaskNodeName);
  |                     if (node != null) {
  |                             TaskNode escalatedTaskNode = (TaskNode) node;
  | 
  |                             // assuming 1 task in node... otherwise also 
use e.g. a param
  |                             // like escalationTaskNodeName. Errorhandling 
for this not done yet
  |                             Task escalateTask = (Task) 
escalatedTaskNode.getTasksMap()
  |                                             .values().iterator().next();
  | 
  |                             Token childToken = new Token(token, 
token.getFullName()
  |                                             + "_child_" + 
token.getChildren().size());
  | 
  |                             childToken.setNode(escalatedTaskNode);
  | 
  |                             tmi.createTaskInstance(escalateTask, 
childToken);
  |                     } else {
  |                             log.warn("escalationTaskNode with name " + 
escalationTaskNodeName + " not found.");
  |                     }
  | 
  |             }
  |     }
  | 
  |     public static class CancelEscalationTask implements ActionHandler {
  |             private static final long serialVersionUID = 1L;
  | 
  |             public void execute(ExecutionContext executionContext) throws 
Exception {
  | 
  |                     // Assuming max one active childToken and max one 
unfinished task in
  |                     // this childtoken
  |                     Map activeChildren = executionContext.getToken()
  |                                     .getActiveChildren();
  |                     if (!activeChildren.isEmpty()) {
  |                             Token childToken = (Token) 
activeChildren.values().iterator()
  |                                             .next();
  |                             Collection unfinishedTasks = executionContext
  |                                             
.getTaskMgmtInstance().getUnfinishedTasks(childToken);
  |                             if (!unfinishedTasks.isEmpty()) {
  |                                     ((TaskInstance) 
unfinishedTasks.iterator().next()).cancel();
  |                             }
  |                     }
  | 
  |             }
  |     }
  | 
  |     private static final Log log = 
LogFactory.getLog(EscalationExampleTest.class);
  | 
  | }
  | 
  | 

Maybe someone wants to make a wiki page out of this....

View the original post : 
http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4176232#4176232

Reply to the post : 
http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4176232
_______________________________________________
jboss-user mailing list
jboss-user@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/jboss-user

Reply via email to