-
1. Re: JBPM Nested Fork/Joins Doesn't seem to work
kukeltje Jun 7, 2009 11:49 AM (in response to philsegal)Should work. Can you make a unittest that demonstrates the problem? Please make the unittest like: http://fisheye.jboss.com/browse/~raw,r=4398/JbpmSvn/jbpm3/trunk/modules/core/src/test/java/org/jbpm/job/executor/JobExecutorDbTest.java
-
2. Re: JBPM Nested Fork/Joins Doesn't seem to work
philsegal Jun 7, 2009 11:55 AM (in response to philsegal)Hi,
Thanks for the feedback, I will build the junit and get back to you, tho i may have spotted something. Do the internal fork/joins have to be totally self contained? At the moment I have transitions from within the internal f/j that goes to the outer one. Would this cause the issue? Is there anywhere to find a definitive do's/dont's list? -
3. Re: JBPM Nested Fork/Joins Doesn't seem to work
kukeltje Jun 7, 2009 2:56 PM (in response to philsegal)yes, that is what fully contained/nested means....
Regarding do's/dont's, this is the most important one, together with 'do not loop for polling the existence of a file' kind of things. -
4. Re: JBPM Nested Fork/Joins Doesn't seem to work
philsegal Jun 7, 2009 3:04 PM (in response to philsegal)It seems that within my Junit test i can have non-fully contained fork/joins, and that provided i get the correct child token (and childs-child etc) to signal, then it works succesfully.
Is there any documentation on how taskInstance signalling works? Since I think maybe the problem is more to do with the taskInstance signal, than the token signal. -
5. Re: JBPM Nested Fork/Joins Doesn't seem to work
kukeltje Jun 7, 2009 3:54 PM (in response to philsegal)If you manually signal tokens, a non fully nested fork/join might work, but that behaviour is not guaranteed to stay/be the same over versions.
What do you mean by 'how task signalling works'? You end a task and the token continues if the other attributes on the task node allow it to. By default, ending the task makes it take the specified transition. So nothing special to it. -
6. Re: JBPM Nested Fork/Joins Doesn't seem to work
philsegal Jun 7, 2009 4:17 PM (in response to philsegal)Im not sure whether the signalling of tasks ie task.signal has the save behaviour as the direct signalling on the token object. Also, is the token object uniquely identified by something other than its name? ie its path parent/child? I am trying to work out thru junits what the constraints are, but it doesnt seem to be limited to fully nested f/j's.
It is all rather bizarre. Since, I have managed to see that all child tokens of a parent token are at the join, yet the parent is still at the fork. I didnt think that this should happed.
Finally, I have seen instances where the child tokens go past the join, yet the parent token is still at the fork... -
7. Re: JBPM Nested Fork/Joins Doesn't seem to work
kukeltje Jun 7, 2009 9:30 PM (in response to philsegal)if you have the unittest, please post it. Then I can see what you do instead of guessing or reading text ;-)
-
8. Re: JBPM Nested Fork/Joins Doesn't seem to work
philsegal Jun 8, 2009 8:59 AM (in response to philsegal)Thanks, Junit and jbpm xml file are below.
package com.jpmorgan.orion.workflow.ny;
import org.jbpm.graph.def.ProcessDefinition;
import org.jbpm.graph.exe.ProcessInstance;
import org.junit.Test;
import com.jpmorgan.orion.workflow.service.BaseManagerTestCase;
/**
* Phil Segal
* @date @14 May 2009
*/
public class JoinsTest extends BaseManagerTestCase {
@Test
public void testNoAdjustments() throws Exception {
ProcessDefinition def = ProcessDefinition.parseXmlResource("workflow/ny-workflow-2/processdefinition.xml");
assertNotNull("Definition should not be null", def);
ProcessInstance instance = new ProcessInstance(def);
assertEquals("Def should be at start",
"start-daily-pnl",
instance.getRootToken().getNode().getName());
instance.signal("default");
instance.getRootToken().getChild("signoff").signal("signoff pnl");
instance.getRootToken().getChild("propose").signal("cancel fork1");
assertEquals("Def should be at auto approve",
"auto-signoff-adj",
instance.getRootToken().getNode().getName()
);
instance.signal("leave-asa");
assertEquals("Def should be at ds feeds",
"downstream-feeds",
instance.getRootToken().getNode().getName());
instance.signal("leave-dsf");
assertEquals("Def should be at fork 3",
"fork3",
instance.getRootToken().getNode().getName());
instance.getRootToken().getChild("reviewed").signal("review");
instance.getRootToken().getChild("unsignoff").signal("cancel");
// instance.signal();
assertTrue("Instance has ended", instance.hasEnded());
}
@Test
public void testWithAdjustmentsProcessNoApprove() throws Exception
{
ProcessDefinition def = ProcessDefinition.parseXmlResource("workflow/ny-workflow-2/processdefinition.xml");
assertNotNull("Definition should not be null", def);
ProcessInstance instance = new ProcessInstance(def);
assertEquals("Def should be at start",
"start-daily-pnl",
instance.getRootToken().getNode().getName());
instance.signal("default");
instance.getRootToken().getChild("propose").signal("propose an adjustment");
assertEquals("Def should be at fork2",
"fork2",
instance.getRootToken().getChild("propose").getNode().getName());
instance.getRootToken().getChild("propose").getChild("propose").signal("cancel");
instance.getRootToken().getChild("propose").getChild("approve").signal("cancel");
assertEquals("child should be at join1",
"join1",
instance.getRootToken().getChild("propose").getNode().getName());
assertEquals("parent should be at fork1",
"fork1",
instance.getRootToken().getNode().getName());
instance.getRootToken().getChild("signoff").signal("signoff pnl");
assertEquals("Def should be at auto approve",
"auto-signoff-adj",
instance.getRootToken().getNode().getName()
);
}
@Test
public void testWithMultipleAdjustmentsProcessNoApprove() throws Exception
{
ProcessDefinition def = ProcessDefinition.parseXmlResource("workflow/ny-workflow-2/processdefinition.xml");
assertNotNull("Definition should not be null", def);
ProcessInstance instance = new ProcessInstance(def);
assertEquals("Def should be at start",
"start-daily-pnl",
instance.getRootToken().getNode().getName());
instance.signal("default");
instance.getRootToken().getChild("propose").signal("propose an adjustment");
assertEquals("Def should be at fork2",
"fork2",
instance.getRootToken().getChild("propose").getNode().getName());
instance.getRootToken().getChild("propose").getChild("propose").signal("propose an adjustment");
// Use either just cancel, or both approve and default signals for approve signalling...
// instance.getRootToken().getChild("propose").getChild("approve").signal("cancel");
instance.getRootToken().getChild("propose").getChild("approve").signal("approve");
instance.getRootToken().getChild("propose").getChild("approve").signal("default");
instance.getRootToken().getChild("propose").getChild("propose").getChild("propose").signal("cancel");
instance.getRootToken().getChild("propose").getChild("propose").getChild("approve").signal("cancel");
assertEquals("propose/propose should be at join1",
"join1",
instance.getRootToken().getChild("propose").getChild("propose").getNode().getName());
assertEquals("propose/approve should be at join2",
"join2",
instance.getRootToken().getChild("propose").getChild("approve").getNode().getName());
assertEquals("parent should be at fork1",
"fork1",
instance.getRootToken().getNode().getName());
assertEquals("propose should be at join1",
"join1",
instance.getRootToken().getChild("propose").getNode().getName());
instance.getRootToken().getChild("signoff").signal("signoff pnl");
assertEquals("signoff should be at join1",
"join1",
instance.getRootToken().getChild("signoff").getNode().getName());
// instance.getRootToken().getChild("propose").getChild("propose").getChild("propose").signal("cancel");
// instance.getRootToken().getChild("propose").getChild("propose").getChild("propose").signal("propose an adjustment");
// instance.getRootToken().getChild("propose").getChild("propose").getChild("propose").getChild("propose").signal("cancel fork1");
// instance.getRootToken().getChild("propose").getChild("propose").getChild("approve").signal("cancel fork1");
// instance.getRootToken().getChild("propose").getChild("propose").getChild("propose").getChild("approve").signal("cancel fork1");
assertEquals("Def should be at auto approve",
"auto-signoff-adj",
instance.getRootToken().getNode().getName()
);
}
}
____________________________________________________
processdefinition
<?xml version="1.0" encoding="UTF-8"?>
<process-definition xmlns="" name="ny-workflow-2">
<start-state name="start-daily-pnl">
</start-state>
<task-node name="signoff-pnl">
<!-- timer name="signoff-timer" duedate="1 minute" repeat="true">
<action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
signOffTimerAction
jbpmConfiguration
</timer-->
<assignment config-type="bean" class="org.springmodules.workflow.jbpm31.JbpmHandler">
pnlSignOffMOAssignmentHandler
jbpmConfiguration
<action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
signOffMultiAction
jbpmConfiguration
<!-- cancel-timer name="signoff-timer"/-->
</task-node>
<task-node name="propose-adjustments">
<assignment config-type="bean" class="org.springmodules.workflow.jbpm31.JbpmHandler">
proposeAdjustmentAssignmentHandler
jbpmConfiguration
<action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
proposeAdjustmentsAction
jbpmConfiguration
</task-node>
<task-node name="approve-reject-adj">
<assignment config-type="bean" class="org.springmodules.workflow.jbpm31.JbpmHandler">
approveRejectAdjustmentAssignmentHandler
jbpmConfiguration
</task-node>
<!-- Reject select adjustment(s) -->
<action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
rejectAdjustmentsAction
jbpmConfiguration
<task-node name="review">
<assignment config-type="bean" class="org.springmodules.workflow.jbpm31.JbpmHandler">
reviewPnlAssignmentHandler
jbpmConfiguration
<action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
reviewPnlAction
jbpmConfiguration
</task-node>
<action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
autoApproveAdjustmentsAction
jbpmConfiguration
<action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
approveAdjustmentsAction
jbpmConfiguration
<action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
downstreamFeedsAction
jbpmConfiguration
<task-node name="unsignoff-pnl">
<assignment config-type="bean" class="org.springmodules.workflow.jbpm31.JbpmHandler">
pnlSignOffMOAssignmentHandler
jbpmConfiguration
<action config-type="bean" class="org.springmodules.workflow.jbpm31.JbpmHandler">
unsignoffAction
jbpmConfiguration
<!-- timer name="unsignoff-timer" duedate="1 business second" repeat="true">
<action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
unsignOffTimerAction
jbpmConfiguration
</timer-->
<!--cancel-timer name="unsignoff-timer"/-->
<!--cancel-timer name="unsignoff-timer"/-->
</task-node>
<end-state name="end-daily-pnl"></end-state>
</process-definition> -
9. Re: JBPM Nested Fork/Joins Doesn't seem to work
philsegal Jun 8, 2009 9:04 AM (in response to philsegal)2nd time lucky...
<?xml version="1.0" encoding="UTF-8"?>
<process-definition xmlns="" name="ny-workflow-2">
<start-state name="start-daily-pnl">
</start-state>
<task-node name="signoff-pnl">
<!-- timer name="signoff-timer" duedate="1 minute" repeat="true">
<action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
signOffTimerAction
jbpmConfiguration
</timer-->
<assignment config-type="bean" class="org.springmodules.workflow.jbpm31.JbpmHandler">
pnlSignOffMOAssignmentHandler
jbpmConfiguration
<action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
signOffMultiAction
jbpmConfiguration
<!-- cancel-timer name="signoff-timer"/-->
</task-node>
<task-node name="propose-adjustments">
<assignment config-type="bean" class="org.springmodules.workflow.jbpm31.JbpmHandler">
proposeAdjustmentAssignmentHandler
jbpmConfiguration
<action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
proposeAdjustmentsAction
jbpmConfiguration
</task-node>
<task-node name="approve-reject-adj">
<assignment config-type="bean" class="org.springmodules.workflow.jbpm31.JbpmHandler">
approveRejectAdjustmentAssignmentHandler
jbpmConfiguration
</task-node>
<!-- Reject select adjustment(s) -->
<action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
rejectAdjustmentsAction
jbpmConfiguration
<task-node name="review">
<assignment config-type="bean" class="org.springmodules.workflow.jbpm31.JbpmHandler">
reviewPnlAssignmentHandler
jbpmConfiguration
<action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
reviewPnlAction
jbpmConfiguration
</task-node>
<action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
autoApproveAdjustmentsAction
jbpmConfiguration
<action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
approveAdjustmentsAction
jbpmConfiguration
<action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
downstreamFeedsAction
jbpmConfiguration
<task-node name="unsignoff-pnl">
<assignment config-type="bean" class="org.springmodules.workflow.jbpm31.JbpmHandler">
pnlSignOffMOAssignmentHandler
jbpmConfiguration
<action config-type="bean" class="org.springmodules.workflow.jbpm31.JbpmHandler">
unsignoffAction
jbpmConfiguration
<!-- timer name="unsignoff-timer" duedate="1 business second" repeat="true">
<action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
unsignOffTimerAction
jbpmConfiguration
</timer-->
<!--cancel-timer name="unsignoff-timer"/-->
<!--cancel-timer name="unsignoff-timer"/-->
</task-node>
<end-state name="end-daily-pnl"></end-state>
</process-definition> -
10. Re: JBPM Nested Fork/Joins Doesn't seem to work
philsegal Jun 8, 2009 9:05 AM (in response to philsegal)sorry, im new to all this :)
<?xml version="1.0" encoding="UTF-8"?> <process-definition xmlns="" name="ny-workflow-2"> <start-state name="start-daily-pnl"> <transition to="fork1" name="default"></transition> </start-state> <task-node name="signoff-pnl"> <task name="Sign Off Daily PNL" description="signoff"> <!-- timer name="signoff-timer" duedate="1 minute" repeat="true"> <action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean"> <beanName>signOffTimerAction</beanName> <factoryKey>jbpmConfiguration</factoryKey> </action> </timer--> <assignment config-type="bean" class="org.springmodules.workflow.jbpm31.JbpmHandler"> <beanName>pnlSignOffMOAssignmentHandler</beanName> <factoryKey>jbpmConfiguration</factoryKey> </assignment> <event type="task-end"> <action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean"> <beanName>signOffMultiAction</beanName> <factoryKey>jbpmConfiguration</factoryKey> </action> </event> </task> <transition to="join1" name="signoff pnl"> <!-- cancel-timer name="signoff-timer"/--> </transition> </task-node> <task-node name="propose-adjustments"> <task name="Propose Adjustments" description="proposeAdjustment"> <assignment config-type="bean" class="org.springmodules.workflow.jbpm31.JbpmHandler"> <beanName>proposeAdjustmentAssignmentHandler</beanName> <factoryKey>jbpmConfiguration</factoryKey> </assignment> <event type="task-end"> <action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean"> <beanName>proposeAdjustmentsAction</beanName> <factoryKey>jbpmConfiguration</factoryKey> </action> </event> </task> <transition name="propose an adjustment" to="fork2"></transition> <transition name="cancel fork1" to="join1"></transition> <transition name="cancel" to="join2"></transition> </task-node> <task-node name="approve-reject-adj"> <task name="Approve Adjustments" description="adjustmentDecision"> <assignment config-type="bean" class="org.springmodules.workflow.jbpm31.JbpmHandler"> <beanName>approveRejectAdjustmentAssignmentHandler</beanName> <factoryKey>jbpmConfiguration</factoryKey> </assignment> </task> <transition to="reject-adjustment" name="reject"></transition> <transition to="approve-adjustment" name="approve"></transition> <transition to="join1" name="cancel fork1"></transition> <transition to="join2" name="cancel"></transition> </task-node> <!-- Reject select adjustment(s) --> <node name="reject-adjustment"> <action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean"> <beanName>rejectAdjustmentsAction</beanName> <factoryKey>jbpmConfiguration</factoryKey> </action> <transition name="default" to="join2"></transition> </node> <task-node name="review"> <task name="Review Daily PnL" description="reviewPNL"> <assignment config-type="bean" class="org.springmodules.workflow.jbpm31.JbpmHandler"> <beanName>reviewPnlAssignmentHandler</beanName> <factoryKey>jbpmConfiguration</factoryKey> </assignment> <event type="task-end"> <action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean"> <beanName>reviewPnlAction</beanName> <factoryKey>jbpmConfiguration</factoryKey> </action> </event> </task> <transition name="review" to="join3"></transition> </task-node> <node name="auto-signoff-adj"> <action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean"> <beanName>autoApproveAdjustmentsAction</beanName> <factoryKey>jbpmConfiguration</factoryKey> </action> <transition name="leave-asa" to="downstream-feeds"></transition> </node> <fork name="fork1"> <transition name="propose" to="propose-adjustments"></transition> <transition name="signoff" to="signoff-pnl"></transition> </fork> <fork name="fork2"> <transition name="propose" to="propose-adjustments"></transition> <transition name="approve" to="approve-reject-adj"></transition> </fork> <node name="approve-adjustment"> <action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean"> <beanName>approveAdjustmentsAction</beanName> <factoryKey>jbpmConfiguration</factoryKey> </action> <transition name="default" to="join2"></transition> </node> <join name="join1"> <transition name="default" to="auto-signoff-adj"></transition> </join> <node name="downstream-feeds"> <action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean"> <beanName>downstreamFeedsAction</beanName> <factoryKey>jbpmConfiguration</factoryKey> </action> <transition name="leave-dsf" to="fork3"></transition> </node> <task-node name="unsignoff-pnl"> <task name="Unsignoff PNL" description="signoff"> <assignment config-type="bean" class="org.springmodules.workflow.jbpm31.JbpmHandler"> <beanName>pnlSignOffMOAssignmentHandler</beanName> <factoryKey>jbpmConfiguration</factoryKey> </assignment> <event type="task-end"> <action config-type="bean" class="org.springmodules.workflow.jbpm31.JbpmHandler"> <beanName>unsignoffAction</beanName> <factoryKey>jbpmConfiguration</factoryKey> </action> </event> <!-- timer name="unsignoff-timer" duedate="1 business second" repeat="true"> <action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean"> <beanName>unsignOffTimerAction</beanName> <factoryKey>jbpmConfiguration</factoryKey> </action> </timer--> </task> <transition to="join3" name="cancel"> <!--cancel-timer name="unsignoff-timer"/--> </transition> <transition to="fork1" name="unsignoff"> <!--cancel-timer name="unsignoff-timer"/--> </transition> </task-node> <fork name="fork3"> <transition to="unsignoff-pnl" name="unsignoff"></transition> <transition to="review" name="reviewed"></transition> </fork> <join name="join3"> <transition to="end-daily-pnl" name="default"></transition> </join> <join name="join2"> <transition to="join1" name="default"></transition> </join> <end-state name="end-daily-pnl"></end-state> </process-definition>
-
11. Re: JBPM Nested Fork/Joins Doesn't seem to work
kukeltje Jun 8, 2009 9:30 AM (in response to philsegal)nope, not even the second time : -)
Use [ c o d e ] [ / c o d e ] tags around it, without the spaces.
Ont small thing though. If it is not to much trouble, the example I referred to had everyting in one file. The processdefinition as a string and the actionhandlers as inner classes. That way I only have to create one file, not multiple, with possible typos etc. -
12. Re: JBPM Nested Fork/Joins Doesn't seem to work
kukeltje Jun 8, 2009 9:34 AM (in response to philsegal)ah, sorry, I missed the thrid time :-)
-
13. Re: JBPM Nested Fork/Joins Doesn't seem to work
kukeltje Jun 8, 2009 9:37 AM (in response to philsegal)oh, and one more thing, it would be nice if you could reduce the test to a minimal one. Just showing this one issue.
-
14. Re: JBPM Nested Fork/Joins Doesn't seem to work
philsegal Jun 8, 2009 9:40 AM (in response to philsegal)Here is the 1 failing test, the other 2 work.
@Test public void testWithMultipleAdjustmentsProcessNoApprove() throws Exception { ProcessDefinition def = ProcessDefinition.parseXmlResource("workflow/ny-workflow-2/processdefinition.xml"); assertNotNull("Definition should not be null", def); ProcessInstance instance = new ProcessInstance(def); assertEquals("Def should be at start", "start-daily-pnl", instance.getRootToken().getNode().getName()); instance.signal("default"); instance.getRootToken().getChild("propose").signal("propose an adjustment"); assertEquals("Def should be at fork2", "fork2", instance.getRootToken().getChild("propose").getNode().getName()); instance.getRootToken().getChild("propose").getChild("propose").signal("propose an adjustment"); instance.getRootToken().getChild("propose").getChild("approve").signal("cancel"); instance.getRootToken().getChild("propose").getChild("propose").getChild("propose").signal("cancel"); instance.getRootToken().getChild("propose").getChild("propose").getChild("approve").signal("cancel"); assertEquals("propose/propose should be at join1", "join1", instance.getRootToken().getChild("propose").getChild("propose").getNode().getName()); assertEquals("propose/approve should be at join2", "join2", instance.getRootToken().getChild("propose").getChild("approve").getNode().getName()); assertEquals("parent should be at fork1", "fork1", instance.getRootToken().getNode().getName()); assertEquals("propose should be at join1", "join1", instance.getRootToken().getChild("propose").getNode().getName()); instance.getRootToken().getChild("signoff").signal("signoff pnl"); assertEquals("signoff should be at join1", "join1", instance.getRootToken().getChild("signoff").getNode().getName()); assertEquals("Def should be at auto approve", "auto-signoff-adj", instance.getRootToken().getNode().getName() ); }