-
1. Re: Possible bug in fork-joins
jits_1998 Sep 5, 2006 3:04 PM (in response to gmournos)Hi,
The fork and join work in tandem, the join expects exact number of incoming transitions as the fork sent out.
In the code above you have fork 1 giving out 2 and fork 2 splitting one into 2 and all three then meeting into the single join.
To get this to work it will need another join to be added after fork2 and the output from it will go into join1.
something like:public static ProcessDefinition createForkJoinProcessDefinition() { ProcessDefinition pd = new ProcessDefinition( new String[]{"start-state start", "fork f1", "state s1", "fork f2", "state s2", "join j1", "join j2", "state s3", "end-state end"}, new String[]{"start --> f1", "f1 --to_s1--> s1", "f1 --to_j1_1--> j1", "s1 --> f2", "f2 --to_j2_1--> j2", "f2 --to_s2--> s2", "s2 --to_j2_2--> j2","j2 --to_j1_2-->j1", "j1 --> s3", "s3 --> end"}); return pd; }
-
2. Re: Possible bug in fork-joins
gmournos Sep 6, 2006 5:54 AM (in response to gmournos)Thx for the fast reply.
Well, this coupling of forks and joins puts me off a bit.
I would rather that jbpm would be smart enough to figure out that the join is "joining" both parent forks, instead of introducing structural constraints that cannot be automatically validated at design time.
Is there an AUTOMATIC way to decouple joins from forks by setting any of the flags (e.g. discriminator and NoutofM)? Or an AUTOMATIC way to achieve behavior similar to introducing a second join. -
3. Re: Possible bug in fork-joins
jits_1998 Sep 6, 2006 7:49 AM (in response to gmournos)I do not think its possible to decouple them completely. But will get some ideas on partial de-coupling, by reading the execute method of the Join.
It comes with some options like activating/executing the join on:
1) first token arrival, i.e. discriminator
2) n count token arrival, i.e. nOutOfM
3) it allows for a script to be placed in the join tag of process definition xml.
4) can specify exact names of the tokens to expect for activation.
5) simple plain vanilla complete coupling.
thats all for AUTOMATIC decoupling.. or you can write a spl join that will check for all active child tokens to be arriving for a join to be executed/activated.
hope it helps... -
4. Re: Possible bug in fork-joins
jerwah Sep 6, 2006 12:42 PM (in response to gmournos)I recently battled this very issue. Attached is the code for a custom join node that seems to work in all scenarios. (I edited out some of our specific code so as posted may not exactly work but you should get the gist.)
public class join implements ActionHandler { private static final long serialVersionUID = 1L; private static final Log log = LogFactory.getLog(Join.class); public void execute(ExecutionContext executionContext) { Node ThisNode = executionContext.getNode(); int tokenCount = 0; try { tokenCount = (Integer) executionContext.getVariable(ThisNode.getName() + "tokenCount"); } catch (Exception e) { log.debug(e); } Token token = executionContext.getToken(); if(token.isAbleToReactivateParent()) { log.debug("Set token: " + token.getFullName()+ " now unable to reactivate parent."); token.setAbleToReactivateParent(false); } if(!token.hasEnded()) { token.end(); log.debug("Set token:" + token.getFullName()+ " now set to ended."); } //Sanity Check log.debug("Inbound token ended status=" + token.hasEnded()); tokenCount++; int transitionCount = ThisNode.getArrivingTransitions().size(); // If we have all of our tokens, then we can proceed. //But we need to see if our parent has all it needs done or not. // Decide if the parent fork is ready to go or not. ExecutionContext exitContext = CalculateCurrentExitContext(token); if(tokenCount >= transitionCount) { log.debug("All tokens are here..keep going..."); ThisNode.leave(exitContext); } else { log.debug("We received: " + token.getFullName()+ " and it is able to reactivate parent = " + token.isAbleToReactivateParent()); log.debug("Received: " + tokenCount + " tokens out of: " + transitionCount + " paths. Waiting for remaining"); } executionContext.setVariable(ThisNode.getName() + "tokenCount", tokenCount); executionContext.getJbpmContext().save(executionContext.getProcessInstance()); } // Returns the current Execution Context to leave the current node with public ExecutionContext CalculateCurrentExitContext(Token Token) { // We need to work our way up the tree to find the lowest fork that all // paths are complete and use this to set our context. ExecutionContext exitContext = null; Token parentToken = Token.getParent(); ExecutionContext currentContext = new ExecutionContext(Token); // See if we have a parent token if ( parentToken != null ) { log.debug("Parent Token = "+parentToken.toString()); // See if that parent has any active children if (!parentToken.hasActiveChildren()) { // NO: // Recursively call ourselves to see if the parent of // the parent has active children log.debug("No Active Children - Making Recursive Call"); exitContext = CalculateCurrentExitContext(parentToken); }else{ // YES: // Our parent has active children then // our current context is this token, not the parent log.debug("Active Children: "+parentToken.getActiveChildren().toString()); log.debug("Children - Setting to currentContext"); exitContext = currentContext; } }else{ // If parentToken = null then we have no parent exitContext = currentContext; } log.debug("Calculated Highest Possible execution context:" + exitContext.toString()); return exitContext; } }
-
5. Re: Possible bug in fork-joins
gmournos Sep 7, 2006 4:54 AM (in response to gmournos)Hi Jerwah,
Good work. I cannot understand what the class is doing cos I am new to this project, but it is passing my testcase and joining all parents, and this is great.
One comment, the line:executionContext.getJbpmContext().save(executionContext.getProcessInstance());
was throwing a null pointer exception in my test cases, so I commented it out.
In the test cases I am not using persistency, just testing the navigation.
But shouldn't the persistency be out of the code for the join? -
6. Re: Possible bug in fork-joins
jerwah Sep 7, 2006 9:22 AM (in response to gmournos)Glad I could help. We too are very new to bpm.
As for the persistence, in our situation we have a very slow process (Months) which is externally moved forward via a custom webapp, so obviously we need to persist the token counter. It seemed most logical to us to persist it in the join at update time to ensure we always had the accurate count but if you are persisting the process elsewhere, I would suspect it would work fine too. -
7. Re: Possible bug in fork-joins
pedrosacosta Oct 4, 2006 7:14 AM (in response to gmournos)I've saw the code of Jerwah, but i don't understand one thing. How we can call join class. Is it defined in the process definition?
Can you give me an example?
Thanks,
Pedro -
8. Re: Possible bug in fork-joins
gmournos Oct 4, 2006 7:44 AM (in response to gmournos)Hi Pedro,
The easiest way would be to override the corresponding class from jbpm...
I am not using this code. I switched back to the default jpbm implementations