Implementing Advanced Workflow Patterns in WebSphere Integration Developer and WebSphere Process Server, Part 3: Advanced branching and synchronization patterns

The Workflow Patterns Initiative is widely used or referenced when enterprises want to model their workflow. Its latest 43 workflow patterns post a big challenge to all kinds of BPEL engines.

WebSphere Process Server (WPS) is a powerful business process automation engine with high performance. Customers can implement their workflow patterns easily with WPS and WebSphere Integrated Developer (WID). Comparing with other BPEL engine products, the latest WID v7.0 and WPS v7.0 can not only implement those 43 patterns all, but also implement them easily and graciously.

Share:

Yu Jie Gu (guyujie@cn.ibm.com), Staff Software Engineer, IBM

Yu Jie Gu currently works in WebSphere Process Server Level 3 support team.



Jing Wen Cui (cuijwen@cn.ibm.com), Software Engineer, IBM

Jing Wen Cui works on WebSphere Process Server testing for more than three years. She is also familiar with workflow, BPEL and related WebSphere products.



Ying Ji Sun (sunyj@cn.ibm.com), Staff Software Engineer, IBM

Ying Ji Sun is currently on the WebSphere Process Server SWAT team. Previously he helped develop the WebSphere Enterprise Service Bus function validation test and has written several developerWorks articles on web service and WebSphere Enterprise Service Bus.



28 October 2010

Also available in Japanese

Overview

As discusses in part 1, the Workflow Patterns Initiative (WPI) was established with the aim of delineating the fundamental requirements that arise during business process modeling on a recurring basis and describe them in an imperative way. It is widely used or referenced when enterprises want to model their workflow. In the first WPI version, 20 patterns were delivered in 2003. The number increased to 43 in the latest release. Those patterns post a big challenge to all kinds of BPEL engines. It is very difficult to support all of them. In another word, one BPEL engine which can support those patterns well should gain more customers as its power.

In part 3 we will introduce two categories patterns (Basic Control Flow Patterns and Cancellation and Force Completion Patterns) in detail.


Advanced branching and synchronization patterns

There are 14 patterns in this category, including:

  1. Multi-choice
  2. Multi-merge
  3. Thread split
  4. Thread merge
  5. Structured partial join
  6. Blocking partial join
  7. Cancelling partial join
  8. Structured discriminator
  9. Blocking discriminator
  10. Cancelling discriminator
  11. Generalized AND-Join
  12. Structured synchronizing merge
  13. Local synchronizing merge
  14. General synchronizing merge

These patterns are related with branching and merging concept and widely used in real business process. Some of them can be implemented in WID 7 BPC editor easily, and some involve WID 7 SCA assembly structures.


Multi-choice

This pattern requires after incoming branch is enabled, more than one outgoing branches can be selected according to choice condition.

For example, one factory want to enlarge the scale of production, after capital investment, then depending on the current status, staff recruiting, equipment purchasing, workshop extending, could be initiated at the same time.

Pattern detail description is here.

Analysis

The focus of this pattern is:

  1. The gateway has one incoming branch and more then one outgoing branches.
  2. The outgoing branches are chosen according to predefined choice condition.
  3. One or more then one outgoing branches can be passed.

Implementation

Figure 1. Multi-Choice Implementation - SCA Component
SCA Component
Figure 2. Multi-Choice Implementation - BPC implementation
SCA Component

The choice conditions is defined according to the input of Receive activity, and set on the gateway‘s outgoing links. Case1 and Case 2 are executed according to process input parameters. Case3 is executed without condition.

This interface of Receive activity:

Figure 3. Receive interface
Receive interface
Figure 4. ProcessDate BO definition
ProcessDate BO definition

The choice condition on the Case2 link is shown in the below listing.

java.lang.String condition = input1.getString("field1");
if(condition.indexOf("Case2")>=0)
{
	return true;
}
return false;

Run on WebSphere Process Server

  1. Start P06_MultiChoice_gateway process instance
Figure 5. P06_MultiChoice_gateway instance
P06_MultiChoice_gateway instance
  1. Input parameter like below. Case1 and Case2 will be enabled.
Figure 6. Input parameter
Input parameter
  1. View log to see Case1, Case2, and Case3 are all executed.
Listing 1. MultiChoice Log
[9/23/10 13:12:47:921 CST] 0000006d SystemOut     O [MultiChoice_gateway]Run into Case2
[9/23/10 13:12:47:921 CST] 0000006d SystemOut     O [MultiChoice_gateway]Run into Case1
[9/23/10 13:12:47:937 CST] 0000006d SystemOut     O [MultiChoice_gateway]Run into Case3, 
                                                      Case3 do not contain a condition.

Multi-merge

This pattern requires two or more incoming branches are merged to one gateway. The gateway has one outgoing branch. This outgoing branch passes after each active incoming branch reaching the gateway. If there are n incoming branches are enabled, the outgoing branch will be executed n times.

For example, one factory starts processes to purchase three equipments in parallel. Every time, when one equipment purchasing is completed and arrival, the subsequent putting into storage process for will be executed.

Pattern detail description is here.

Analysis

The focus of this pattern is:

  1. The process splits into two or more branches at a given point.
  2. Those split branches are executed concurrently.
  3. All branches converge to one gateway.
  4. Every time, when one active branch reaches the gateway, next action after gateway is enabled one time.

Implementation

Figure 7. Synchronization Implementation - SCA component
Synchronization Implementation - SCA component
Figure 8. Synchronization Implementation - BPEL implementation
Synchronization Implementation - BPEL implementation

There are two scopes: Incoming branches scope and Merge gateway scope. And EventHandler scope is defined on Merge gateway scope. The one outgoing branch is in Eventhandler scope.

An integer type variable counter is used to record the branches pass condition. The initial value of counter is 0. When one incoming branch is enabled, the counter is increased 1. When the outgoing branch is executed one time, the counter is decreased 1. When the counter is decreased to 0, the multi-merge process completes.

In the Incoming branches scope, at the last of each incoming branch, an invoke activity is used to invoke TestEventHandler interface, that will trigger the onEvent activity in EventHandler scope.

Exit Condition of invoke1 activity. The counter is increased 1.

// @bpe.readWriteVariables names="counter"
System.out.println("[MultiMergeWithHandler]run into invoke2");
counter++;
return false;

The transaction behavior of Invoke activities are set to "commit before" or "requires own". You can read further about the transaction behavior in this support document: http://www-01.ibm.com/support/docview.wss?uid=swg21293793.

In EventHandler Scope, Case3 is on outgoing branch. Every time when Case3 is run, the counter is decreased 1. Case3 Snippet code:

counter--;
System.out.println("[MultiMergeWithHandler]run into Case3, the counter is: " + counter);

Case1 and Case2 are started in parallel. When each of them is finished, Case3 is executed. So Case3 is executed two times.

Note: EventHandler is used, so the correlation set should be defined.

Run on WebSphere Process Server

  1. Start the P08_MultiMergeWithHandler process instance
Figure 9. P08_MultiMergeWithHandler instance
P08_MultiMergeWithHandler
  1. Input parameters like below. As a result, Case1 and Case2 will be enabled
Figure 10. Parameters
Parameters
  1. View the log to see:
    • Case1 and Case2 were started
    • Run into Merge Scope
    • Case3 was started two times
Listing 2. MultiChoice Log
[9/23/10 13:28:37:328 CST] 0000006d SystemOut     O [MultiMergeWithHandler]run into 
                                                            setCounter
[9/23/10 13:28:37:328 CST] 0000006d SystemOut     O [MultiMergeWithHandler]run into 
                                                            Case1
[9/23/10 13:28:37:328 CST] 0000006d SystemOut     O [MultiMergeWithHandler]run into 
                                                            Case2
[9/23/10 13:28:37:359 CST] 0000006d SystemOut     O [MultiMergeWithHandler]run into 
                                                            invoke1
[9/23/10 13:28:37:484 CST] 0000006d SystemOut     O [MultiMergeWithHandler]run into 
                                                            invoke2
[9/23/10 13:28:37:500 CST] 0000006d SystemOut     O [MultiMergeWithHandler]run into 
                                                            MergeScope
[9/23/10 13:28:38:062 CST] 0000006d SystemOut     O [MultiMergeWithHandler]run into 
                                                            Case3, 
                                                            the counter is: 1
[9/23/10 13:28:38:093 CST] 0000006d SystemOut     O [MultiMergeWithHandler]run into 
                                                            Case3, 
                                                            the counter is: 0

Thread split

The thread split point only has one outgoing branch, but a nominated number of execution threads can be started from this point to run the outgoing branch many times.

For example, teacher designs same homework to ten students, so ten homework execution instances are initiated for ten students.

Pattern detail description is here.

Analysis

The focus of this pattern is:

  1. The split point only has one incoming branch
  2. The split point only has one outgoing branch.
  3. The split point can create many threads to run the outgoing branch many times.

Implementation

Figure 11. Thread Split Implementation - SCA components
Thread Split Implementation - SCA components
Figure 12. Thread Split Implementation - BPC Implementation
Thread Split Implementation - BPC Implementation

The P42_SplitPoint process uses the ForEach structure to split thread according to the integer value of input1 parameter. StartThread activity prints log to show thread number.

Figure 13. P42_SplitPoint operation
P42_SplitPoint operation
Figure 14. P42_SplitPoint Branch
P42_SplitPoint branch

The P42_OutgoingBranch process is executed for all threads.

Run on WebSphere Process Server

  1. Start the P42_SplitPoint process instance in BPC Explorer. Set the input1 parameter to 3, then 3 threads will be created to run ongoing branch separately.
Figure 15. P42_SplitPoint process
P42_SplitPoint process
  1. View log to see the thread split.
Listing 3. MultiChoice Log
[9/23/10 21:33:35:671 CST] 00000084 SystemOut     O [P42_ThredSplit] Start Thread 1
[9/23/10 21:33:37:859 CST] 00000084 SystemOut     O [P42_ThredSplit] Ongoing branch run
[9/23/10 21:33:40:640 CST] 0000006d SystemOut     O [P42_ThredSplit] Start Thread 2
[9/23/10 21:33:43:390 CST] 0000006d SystemOut     O [P42_ThredSplit] Ongoing branch run
[9/23/10 21:33:44:250 CST] 00000130 SystemOut     O [P42_ThredSplit] Start Thread 3
[9/23/10 21:33:46:437 CST] 00000130 SystemOut     O [P42_ThredSplit] Ongoing branch run
[9/23/10 21:33:47:937 CST] 0000006d SystemOut     O [P42_ThredSplit] All threads completed

Thread merge

At a given point in a process, a nominated number of execution threads in a single branch of the same process instance should be merged together into a single thread of execution.

For example, a teacher designs the same homework to ten students, so ten homework instances are initiated for each of the ten students. When the homework is submitted, the teacher begins to check and correct them.

The full pattern detail description is here.

Analysis

The focus of this pattern is:

  1. Many instance of one branch can be created.
  2. All instances are merged to one point.

Implementation

Figure 16. Thread Merge Implementation - SCA Component
Thread Merge Implementation - SCA Component
Figure 17. Thread Merge Implementation - BPC Implementation
Thread Merge Implementation - BPC Implementation

The merge point is implemented with WhileLoop and Wait activity. The invoke activity accepts the out side invocation and generate threads.

Integer nMerge saved the nominated thread merge number. Integer count is used to record the number of current merged thread. When one thread is merged, the count is added 1. When count is equal to nMerge, the WhileLoop in merge point exists and NextAction on outgoing branch can be executed.

Run on WebSphere Process Server

Run the new P41_ThreadMerge instance. nMerge is the nominated thread merge number. processeId is correlation set parameter.

Figure 18. P41_ThreadMerge instance
P41_ThreadMerge instance
  1. Go to Process Instances > Started By Me
Figure 19. Process instance
Process instance
  1. Click and open the P41_ThreadMerge instance.
Figure 20. P41_ThreadMerge instance
P41_ThreadMerge instance
  1. Click Waiting Operations > operation2
Figure 21. Waiting Operations
Waiting Operations
  1. Input the processId, that should the same value as in Step 1.
Figure 22. Enter processId
Enter processId
  1. Submit the invocation, which will create one thread.
  2. Repeat step 3 to step 6 for creating another tow thread.
  3. View log to see the thread merge.
Listing 4. Thread merge log
[9/28/10 14:38:30:687 CST] 00000076 SystemOut     O [P41_ThreadMerge] 
                                                            Starts
[9/28/10 14:38:31:562 CST] 00000076 SystemOut     O [P41_ThreadMerge] 
                                                            Run into wait activity
[9/28/10 14:38:32:515 CST] 00000076 SystemOut     O [P41_ThreadMerge] 
                                                            Run into OnEvent
[9/28/10 14:38:32:515 CST] 00000076 SystemOut     O [P41_ThreadMerge] 
                                                            count = 0
[9/28/10 14:38:32:531 CST] 00000076 SystemOut     O [P41_ThreadMerge] 
                                                            nMerge = 3
[9/28/10 14:38:32:531 CST] 00000076 SystemOut     O [P41_ThreadMerge] 
                                                            count = 0
[9/28/10 14:44:40:750 CST] 00000076 SystemOut     O [P41_ThreadMerge] 
                                                            Run into OnEvent
[9/28/10 14:44:40:750 CST] 00000076 SystemOut     O [P41_ThreadMerge] 
                                                            count = 1
[9/28/10 14:44:40:750 CST] 00000076 SystemOut     O [P41_ThreadMerge] 
                                                            Merging one thread
[9/28/10 14:44:40:750 CST] 00000076 SystemOut     O [P41_ThreadMerge] 
                                                            nMerge = 3
[9/28/10 14:44:40:750 CST] 00000076 SystemOut     O [P41_ThreadMerge] 
                                                            count = 1
[9/28/10 14:45:02:171 CST] 00000076 SystemOut     O [P41_ThreadMerge] 
                                                            Run into OnEvent
[9/28/10 14:45:02:171 CST] 00000076 SystemOut     O [P41_ThreadMerge] 
                                                            count = 2
[9/28/10 14:45:02:171 CST] 00000076 SystemOut     O [P41_ThreadMerge] 
                                                            Merging one thread
[9/28/10 14:45:02:171 CST] 00000076 SystemOut     O [P41_ThreadMerge] 
                                                            nMerge = 3
[9/28/10 14:45:02:171 CST] 00000076 SystemOut     O [P41_ThreadMerge] 
                                                            count = 2
[9/28/10 14:45:12:281 CST] 00000076 SystemOut     O [P41_ThreadMerge] 
                                                            Run into OnEvent
[9/28/10 14:45:12:281 CST] 00000076 SystemOut     O [P41_ThreadMerge] 
                                                            count = 3
[9/28/10 14:45:12:281 CST] 00000076 SystemOut     O [P41_ThreadMerge] 
                                                            Merging one thread
[9/28/10 14:45:12:281 CST] 00000076 SystemOut     O [P41_ThreadMerge] 
                                                            count >= nMerge
[9/28/10 14:45:12:281 CST] 00000076 SystemOut     O [P41_ThreadMerge] 
                                                            Run into NextActivity
[9/28/10 14:45:13:953 CST] 0000004d SystemOut     O [P41_ThreadMerge] 
                                                            Wait over
[9/28/10 14:45:13:953 CST] 0000004d SystemOut     O [P41_ThreadMerge] 
                                                            Reply

Structured partial join

This pattern requires two or more incoming branches (say m) are merged to one join construct. All incoming branches are divergent from one parallel split construct. The join construct has only one outgoing branch. When n (n<m) of the incoming branches have been enabled, the outgoing branch is triggered. And then the other (m-n) enabled subsequent incoming branches reach the join construct, but do not trigger the outgoing branch again. The join construct resets when all active incoming branches have been enabled.

For example, a thesis review committee has three members. When a thesis is submitted to the review committee, review activity for each member is enabled. When two members finish their review, the thesis oral defense scheduling activity can begin. The last review activity will be finished but does not trigger the oral defense scheduling activity again. Until all review activities are completed, another oral defense scheduling activity can be enabled.

The full pattern detail description is here.

Analysis

The focus of this pattern is:

  1. M branches is enabled from one divergence point first.
  2. M branches come to one join construct.
  3. The join construct has only one outgoing branch.
  4. When n (n<m) out of m branches come in the join construct, the single outgoing branch will be triggered.
  5. When left m-n branches come in the join construct, the single outgoing branch will not be triggered again.
  6. The join construct resets when all branches come in.
  7. The join construct can work again after resetting.
  8. M and n are all specific number.

Implementation

Figure 23. Structured Partial Join Implementation - SCA components
Structured Partial Join Implementation - SCA components

The P30_StarBranches is used to create 3 incoming branches (m=3).

Figure 24. P30_StarBranches
P30_StarBranches

The P30_StructPartialJoin is the n out of m partial join construct (m=3, n=2). Only one instance is created.

Figure 25. P30_StructPartialJoin
P30_StructPartialJoin

A WhileLoop make this partial join construct can be re-used for different incoming branch structure. Only when the input parameter is string "last", the WhileLoop exits.

Figure 26. WhileLoop
WhileLoop

An integer counter is used to calculate the reached incoming branches number. The initial number is 0. When one incoming branch reaches, the counter is increased 1. The counter is reset at the start of a new round while loop. That means the join construct resets when all branches reach and then the join construct can work again after resetting.

ForEach loop is for accepting incoming branches in one structure. Because the m is 3, the ForEach iteration starts from 1, and ends at 3.

Figure 27. ForEach loop
ForEach loop

When the partial join construct receive one incoming branch, the counter is increased 1. If the counter comes to 2, the outgoing branch NextAction is triggered. Below is the code within the snippet1 activity.

counter = counter+1;
System.out.println("[P30_StructuredPartialJoin] One Branch Joining. counter=" + counter);

After the NextAction is triggered, the partial join construct will still wait for the subsequent one branch joining. After all is coming, the partial join construct start next round while loop (reset) and wait for new incoming branches in another structure.

Outgoing empty activity can be replaced by any outward invocation or sub-process.

Note: Since there is more then one receiving activity, the correlation set should be defined.

Run on WebSphere Process Server

  1. Start the P30_StructParrtialJoin instance. Input parameter id is the correlation parameter.
Figure 28. P30_StructParrtialJoin
P30_StructParrtialJoin
  1. Start P30_StartBranches to start one branch structure. The parameter id should be same with that in step 1.
Figure 29. P30_StartBranches
P30_StartBranches
  1. Open the log to view the partial join results
    • 3 branches started
    • 2 branches joined
    • The outgoing branch(NextAction) is triggered
    • The last one branch join
  2. Start another P30_StartBranches instance to create anther branch structure.
  3. If input parameter request is set to last, the partial join process will be finished.
Listing 5. Structured partial join log
[9/23/10 22:34:03:140 CST] 0000006d SystemOut     O [P30_StructuredPartialJoin] 
                                                        Branch1 Started
[9/23/10 22:34:03:140 CST] 0000006d SystemOut     O [P30_StructuredPartialJoin] 
                                                        Branch3 Started
[9/23/10 22:34:03:187 CST] 0000006d SystemOut     O [P30_StructuredPartialJoin] 
                                                        Branch2 Started
[9/23/10 22:34:04:859 CST] 0000007b SystemOut     O [P30_StructuredPartialJoin] 
                                                        One Branch Joining. counter=1
[9/23/10 22:34:05:109 CST] 00000090 SystemOut     O [P30_StructuredPartialJoin] 
                                                        Branch3 Finished
[9/23/10 22:34:05:234 CST] 00000084 SystemOut     O [P30_StructuredPartialJoin] 
                                                        One Branch Joining. counter=2
[9/23/10 22:34:05:250 CST] 00000084 SystemOut     O [P30_StructuredPartialJoin] 
                                                        Run to NextAction
[9/23/10 22:34:05:609 CST] 00000078 SystemOut     O [P30_StructuredPartialJoin] 
                                                        Branch1 Finished
[9/23/10 22:34:05:640 CST] 00000084 SystemOut     O [P30_StructuredPartialJoin] 
                                                        One Branch Joining. counter=3
[9/23/10 22:34:05:843 CST] 00000090 SystemOut     O [P30_StructuredPartialJoin] 
                                                        Branch2 Finished

Blocking partial join

This pattern is a variant of the pattern Structured Partial Join. The only difference is that if it is not all incoming branches of one structure join, the incoming branches of another structure are blocked until the join construct reset. Join construct resets when all active incoming branches of one structure have been enabled.

For example, the thesis review committee in Structured Partial Join example only can work on one thesis at one time. Until all three review activities for current thesis are completed, new review tasks for another thesis can be started.

Read the full pattern detail description is here.

Analysis

The focus of this pattern is:

  1. This is a variant of the Structured Partial Join.
  2. The differences are:
    • The join construct resets when all branches in one structure are enabled for one process instance.
    • New branches will not be created until the join construct is reset.

Implementation

Figure 30. Blocking Partial Join Implementation - SCA component
Blocking Partial Join Implementation - SCA component

Within the P31_StartBranches instance, when a new trigger is coming, check the block flag first. If the isBlocked flag is false, create branches. If that is true, wait until the flag is reset to false.

Figure 31. Blocking Partial Join Implementation - BPC Implementation
Blocking Partial Join Implementation - BPC Implementation

There is a big while loop for receive new trigger continuously, until the input request parameter is last.

Figure 32. While Loop
While Loop

In the Block Scope, there is a while loop, that include a wait activity. If the isBlocked is true, the while loops cannot exit and check the value again after 1 second. Until the isBlocked changes to false, the Block Scope is passed.

Figure 33. isBlocked condition
isBlocked condition

One EventHandler is defined to wait the isBlocked resetting. When this value is reset to false, the blocked new trigger will pass the Block Scope and new branches will be created.

If the block is passed, before creating branches:

  1. Set the isBlocked flag to be true. Then if other event trigger is coming, no branch can be created.
  2. Start a P31_BlockingPartialJoin instance for current branches structure.

The incoming branch P31_StartBranches creates three P31_Branch instance every time. The Wait1 activity can be replaced by any activity, sub-process, human task.

Figure 34. P31_Branch
P31_Branch

The P31_BlockingPartialJoin(M=3, N=2) instance is created for each branch group in P30_StarBranches.

Figure 35. P31_BlockingPartialJoin
P31_BlockingPartialJoin

Next, the ForEach loop is used to accept 3 incoming branches.

Figure 36. ForEach loop
ForEach loop

When the second branch join, the outgoing branch NextAction is triggered. So this is a 2 out of 3 partial join. When the third branch joins, the block is reset to allow new branches creation. The resetBlock invoke activity will trigger the EventHandler in P31_StartBranches to reset isBlocked flag.

Run on WebSphere Process Server

  1. Begin a New P31_StartBranches instance. Id is correlation set parameter.
Figure 37. New P31_StartBranches instance
New P31_StartBranches instance
  1. Go to Process Instances > Started By Me
  2. Click and open the P31_StartBranches instance.
Figure 38. P31_StartBranches instance
P31_StartBranches instance
  1. Click Waiting Operations > join
  2. The input parameter request is used to mark the branch group.
Figure 39. Waiting operations
Waiting operations
Figure 40. Parameter request
Parameter request
  1. Submit the invocation, which will trigger P31_StartBranches new branch structure creation.
  2. Repeat steps 3 to 5 to create another trigger.
Figure 41. Second Parameter request
SecondParameter request
  1. Open the log to view the blocking partial join.
    • For request1 (black part)
      • A trigger came for request1
      • The default isBlocked flag is false, change it to true
      • Create 3 branches for request1
      • 2 branches joined
      • NextAction is invoked
      • The last branch joined
      • Partial join finished, and reset the isBlocked to false
    • For request2 (blue part)
      • A trigger came for request2
      • Because the request1 partial join was not reset, the isBlocked flag was true, request2 was waiting...
      • Request1 partial join finished and reset the iBlocked flag to false
      • Request2 passed the block and change isBlocked flag to true
      • Create 3 branches for request2
      • 2 branch in request2 joined
      • NextAction is invoked
      • The last branch in Request2 joined
      • Request2 partial join finished, and reset the isBlocked to false
Listing 6. Blocking partial join
[9/24/10 21:51:22:312 CST] 0000006b SystemOut     O [P31_BlockingPartialJoin] 
                                                    New trigger for request1
[9/24/10 21:51:22:406 CST] 0000006b SystemOut     O [P31_BlockingPartialJoin] 
                                                    Set block flag to true in request1
[9/24/10 21:51:23:109 CST] 000001f9 SystemOut     O [P31_BlockingPartialJoin] 
                                                    Branch1 started in request1
[9/24/10 21:51:23:328 CST] 000001f9 SystemOut     O [P31_BlockingPartialJoin] 
                                                    Branch3 started in request1
[9/24/10 21:51:23:796 CST] 000001f9 SystemOut     O [P31_BlockingPartialJoin] 
                                                    Branch2 started in request1
[9/24/10 21:51:38:031 CST] 00000066 SystemOut     O [P31_BlockingPartialJoin] 
                                                    New trigger for request2
[9/24/10 21:51:38:125 CST] 00000066 SystemOut     O [P31_BlockingPartialJoin] 
                                                    Block flag is true. Waiting.. 
                                                            in   request2
[9/24/10 21:51:39:796 CST] 0000006b SystemOut     O [P31_BlockingPartialJoin] 
                                                    One Branch Joined in request1
[9/24/10 21:51:40:750 CST] 0000006a SystemOut     O [P31_BlockingPartialJoin] 
                                                    One Branch Joined in request1
[9/24/10 21:51:41:578 CST] 00000045 SystemOut     O [P31_BlockingPartialJoin] 
                                                    Block flag is true. Waiting.. 
                                                            in   request2
[9/24/10 21:51:42:302 CST] 00000070 SystemOut     O [P31_BlockingPartialJoin] 
                                                    Next Action Started 
[9/24/10 21:51:42:328 CST] 00000236 SystemOut     O [P31_BlockingPartialJoin] 
                                                    One Branch Joined in request1
[9/24/10 21:51:42:343 CST] 00000070 SystemOut     O [P31_BlockingPartialJoin] 
                                                    PartialJoin finished, reset Block 
                                                            in request1

[9/24/10 21:51:42:640 CST] 000001ff SystemOut     O [P31_BlockingPartialJoin] 
                                                    Set block flag to true in request2
[9/24/10 21:51:43:375 CST] 000002d0 SystemOut     O [P31_BlockingPartialJoin] 
                                                    Branch1 started in request2
[9/24/10 21:51:43:437 CST] 000002d0 SystemOut     O [P31_BlockingPartialJoin] 
                                                    Branch3 started in request2
[9/24/10 21:51:43:515 CST] 000002d0 SystemOut     O [P31_BlockingPartialJoin] 
                                                    Branch2 started in request2
[9/24/10 21:51:58:937 CST] 0000006a SystemOut     O [P31_BlockingPartialJoin] 
                                                    One Branch Joined in request2
[9/24/10 21:51:59:046 CST] 00000235 SystemOut     O [P31_BlockingPartialJoin] 
                                                    One Branch Joined in request2
[9/24/10 21:51:59:140 CST] 00000236 SystemOut     O [P31_BlockingPartialJoin] 
                                                    Next Action Started
[9/24/10 21:51:59:250 CST] 00000069 SystemOut     O [P31_BlockingPartialJoin] 
                                                    One Branch Joined in request2 
[9/24/10 21:51:59:359 CST] 00000235 SystemOut     O [P31_BlockingPartialJoin] 
                                                    PartialJoin finished, reset Block 
                                                             in request2

Cancelling partial join

This pattern is a variant of the pattern Structured Partial Join. The only difference is when n out of m incoming branches reach the join construct, the execution of other m-n incoming branches will be cancelled and the join construct will be reset at the same time.

For example, in a thesis review committee example of Structured Partial Join pattern, when two members finish their review activities, the thesis oral defense scheduling activity can be started and the other review activity can be cancelled.

Read further about the pattern detail description is here.

Analysis

The focus of this pattern is:

  1. This is a variant of the Structured Partial Join
  2. The left m-n branches should be cancelled, not completed.
Figure 42. Cancelling Partial Join Implementation
Cancelling Partial Join Implementation

The P32_StarBranch is used to create branches (M=3). When the partial join is finished, the EventHandler will get notification, and then throw a CancelFault to cancel the left branches.

Figure 43. P32_StarBranch
P32_StarBranch

After two branches join in:

  1. A notification will be send out to notify the P32_StartBranch process, then the left branches will be cancelled
  2. The outgoing branch NextAction will be triggered. The Outgoing empty activity can be replaced by any other outward invocation or sub-proccess.
Figure 44. Outgoing branch
Outgoing branch

Run on WebSphere Process Server

  1. Start the P32_CancelPartialJoin instance. Input parameter id is the correlation parameter.
Figure 45. P32_CancelPartialJoin
P32_CancelPartialJoin
  1. Start the P32_StartBranch. The value of id should be same as discussed in step 1.
Figure 46. P32_StartBranch
P32_StartBranch
  1. Open the log to see the partial join result:
    • 3 branches are started
    • The branch2 join
    • Branch2 finished
    • The branch1 join
    • Branch1 finished
    • The P32_StartBranch got partial join finish notification
    • Outgoing branch(NextAction) is triggered
    • Left branch1 is cancelled
Listing 7. Cancelling partial join
[9/9/10 15:25:29:093 CST] 000000b9 SystemOut     O [P32_CancellingPartialJoin] 
                                                    Branch1 Started
[9/9/10 15:25:29:093 CST] 000000b9 SystemOut     O [P32_CancellingPartialJoin] 
                                                    Branch3 Started
[9/9/10 15:25:29:093 CST] 000000b9 SystemOut     O [P32_CancellingPartialJoin] 
                                                    Branch2 Started
[9/9/10 15:25:31:406 CST] 000000b9 SystemOut     O [P32_CancellingPartialJoin] 
                                                    One Branch Joined
[9/9/10 15:25:31:531 CST] 00000225 SystemOut     O [P32_CancellingPartialJoin] 
                                                    Branch2 Finished
[9/9/10 15:25:32:187 CST] 00000067 SystemOut     O [P32_CancellingPartialJoin] 
                                                    One Branch Joined
[9/9/10 15:25:32:234 CST] 00000287 SystemOut     O [P32_CancellingPartialJoin] 
                                                    Branch1 Finished
[9/9/10 15:25:32:312 CST] 00000225 SystemOut     O [P32_CancellingPartialJoin] 
                                                    Get Partial Join Completed Event
[9/9/10 15:25:32:687 CST] 00000064 SystemOut     O [P32_CancellingPartialJoin] 
                                                    Next Action Started
[9/9/10 15:25:33:671 CST] 00000225 SystemOut     O [P32_CancellingPartialJoin] 
                                                    Cancel left branches

Structured discriminator

This pattern is variation of pattern Structured Partial Join, the only one difference is when the first incoming branch joining, the outgoing branch is triggered.

The complete pattern detail description is here.

Implementation

Change the P30_StructPartialJoin outgoing branch trigger condition to counter==1.

Figure 47. Structured Discriminator Implementation
Structured Discriminator Implementation

Run on WebSphere Process Server

The similar is true with running Structured Partial Join:

  1. Start P9_StructDiscrim instance first.
  2. Start P9_StartBranches instance.
Listing 8. Structured discriminator log
[9/26/10 15:43:22:453 CST] 000000b5 SystemOut     O [P9_StructuredDiscriminator] 
                                                    Branch1 Started
[9/26/10 15:43:22:453 CST] 000000b5 SystemOut     O [P9_StructuredDiscriminator] 
                                                    Branch3 Started
[9/26/10 15:43:22:453 CST] 000000b5 SystemOut     O [P9_StructuredDiscriminator] 
                                                    Branch2 Started
[9/26/10 15:43:23:312 CST] 000000ab SystemOut     O [P9_StructuredDiscriminator] 
                                                    One Branch Joining. counter=1
[9/26/10 15:43:23:359 CST] 000000ab SystemOut     O [P9_StructuredDiscriminator] 
                                                    Run to NextAction
[9/26/10 15:43:23:593 CST] 000000ad SystemOut     O [P9_StructuredDiscriminator] 
                                                    Branch1 Finished
[9/26/10 15:43:24:687 CST] 000000b9 SystemOut     O [P9_StructuredDiscriminator] 
                                                    One Branch Joining. counter=2
[9/26/10 15:43:24:812 CST] 0000000b SystemOut     O [P9_StructuredDiscriminator] 
                                                    Branch2 Finished
[9/26/10 15:43:25:109 CST] 000000b1 SystemOut     O [P9_StructuredDiscriminator] 
                                                    One Branch Joining. counter=3

Blocking discriminator

This pattern is one variation of pattern Blocking Partial Join. The only difference is in this pattern, when first incoming branch join, the outgoing branch is triggered.

Full pattern detail description are located here.

Implementation

Change the P31_BlockPartialJoin a little. When the first branch reaches, release the outgoing branch.

Figure 48. Blocking Discriminator Implementation 1
Blocking Discriminator Implementation 1

Run on WebSphere Process Server

  1. New P28_StartBranches instance.
  2. Trigger the join operation 2 times.
Listing 9. Structured discriminator log
[9/26/10 16:55:02:187 CST] 00000210 SystemOut     O [P28_BlockingDiscriminator] 
                                                    New trigger for request1
[9/26/10 16:55:02:281 CST] 00000210 SystemOut     O [P28_BlockingDiscriminator] 
                                                    Set block flag to true in request1
[9/26/10 16:55:02:578 CST] 000000b1 SystemOut     O [P28_BlockingDiscriminator] 
                                                    Branch1 started in request1
[9/26/10 16:55:02:687 CST] 000000b1 SystemOut     O [P28_BlockingDiscriminator] 
                                                    Branch3 started in request1
[9/26/10 16:55:02:828 CST] 000000b1 SystemOut     O [P28_BlockingDiscriminator] 
                                                    Branch2 started in request1
[9/26/10 16:55:11:421 CST] 00000210 SystemOut     O [P28_BlockingDiscriminator] 
                                                    New trigger for request2
[9/26/10 16:55:11:468 CST] 00000210 SystemOut     O [P28_BlockingDiscriminator] 
                                                    Block flag is true. Waiting....  
                                                                in request2
[9/26/10 16:55:16:125 CST] 000000b3 SystemOut     O [P28_BlockingDiscriminator] 
                                                    Block flag is true. Waiting....  
                                                                in request2
[9/26/10 16:55:17:500 CST] 00000047 SystemOut     O [P28_BlockingDiscriminator] 
                                                    Block flag is true. Waiting....  
                                                                in request2
[9/26/10 16:55:19:234 CST] 0000000b SystemOut     O [P28_BlockingDiscriminator] 
                                                    One Branch Joined in request1
[9/26/10 16:55:19:953 CST] 000000b3 SystemOut     O [P28_BlockingDiscriminator] 
                                                    Block flag is true. Waiting....  
                                                                in request2
[9/26/10 16:55:20:437 CST] 000000b5 SystemOut     O [P28_BlockingDiscriminator] 
                                                    Next Action Started
[9/26/10 16:55:20:453 CST] 000000b4 SystemOut     O [P28_BlockingDiscriminator] 
                                                    One Branch Joined in request1
[9/26/10 16:55:21:250 CST] 000000b4 SystemOut     O [P28_BlockingDiscriminator] 
                                                    One Branch Joined in request1
[9/26/10 16:55:21:531 CST] 000000b4 SystemOut     O [P28_BlockingDiscriminator] 
                                                    PartialJoin finished, 
                                                    reset Block in request1
[9/26/10 16:55:22:921 CST] 00000046 SystemOut     O [P28_BlockingDiscriminator] 
                                                    Set block flag to true in request2
[9/26/10 16:55:23:359 CST] 00000241 SystemOut     O [P28_BlockingDiscriminator] 
                                                    Branch1 started in request2
[9/26/10 16:55:23:562 CST] 00000241 SystemOut     O [P28_BlockingDiscriminator] 
                                                    Branch3 started in request2
[9/26/10 16:55:23:718 CST] 00000241 SystemOut     O [P28_BlockingDiscriminator] 
                                                    Branch2 started in request2
[9/26/10 16:55:39:796 CST] 0000000b SystemOut     O [P28_BlockingDiscriminator] 
                                                    One Branch Joined in request2
[9/26/10 16:55:39:937 CST] 000000b5 SystemOut     O [P28_BlockingDiscriminator] 
                                                    Next Action Started
[9/26/10 16:55:40:062 CST] 000000b9 SystemOut     O [P28_BlockingDiscriminator]     
                                                    One Branch Joined in request2
[9/26/10 16:55:40:625 CST] 0000000b SystemOut     O [P28_BlockingDiscriminator] 
                                                    One Branch Joined in request2
[9/26/10 16:55:40:625 CST] 0000000b SystemOut     O [P28_BlockingDiscriminator] 
                                                    PartialJoin finished, 
                                                    reset Block in request2

Solution 2

Figure 49. Blocking Discriminator Implementation 2
Blocking Discriminator Implementation 2
Figure 50. BPEL Implementation
BPEL Implementation

If Task1 is completed first, invoke1 will be run, that will trigger the EventHandler, if not the Task1 branch will join CompleteAll and invoke2 in Task2 branch will trigger the EventHandler.

When the EventHandler is triggered, that means one branch is finished, and Task3 (outgoing branch) is started. The WhileLoop will wait the CompleteAll activity complement. When CompleteAll activity complement, that means all branches are finished and then one fault is thrown to reset the block.

In the below listing is the Reset Blocker snippet code:

System.out.println("[Blocking Discriminator] Reset Blocker");
Service sm = (Service)ServiceManager.INSTANCE.locateService("BusiBlockReqInfPartner");
Boolean block = (Boolean)((DataObject)(sm.invoke("getBlocking",""))).get(0);
System.out.println("[Blocking Discriminator] Block?" + block.booleanValue());
sm.invoke("setBlocking",!block.booleanValue());
block = (Boolean)((DataObject)(sm.invoke("getBlocking",""))).get(0);
System.out.println("[Blocking Discriminator] After reset Block?" + block.booleanValue());

The listing below is from SCA Implementation in Blocking POJO:

public void setBlocking(Boolean input) {
	blocking = input.booleanValue();
}
public Boolean getBlocking(String value) {
	return blocking;
}
public DataObject request(DataObject input) {
	System.out.println("[Blocking Discriminator] Run into Blocking, block?" 
                                                     + blocking);
	try {
		if (blocking) {
			do{
				System.out.println("[Blocking Discriminator] Waiting in 
                                                    Blocking as Blocked");
				Thread.sleep(5000);
			} while (blocking);
			System.out.println("[Blocking Discriminator] Continue as 
                                                    Unblocked Now");
		}
	} catch (Exception e) {
		System.out.println("[Blocking Discriminator] Run into Error");
		e.printStackTrace();
	} finally {
		System.out.println("[Blocking Discriminator] Start invoke");
		locateService_BusiReqInfPartner().invokeAsync("request", input);
		blocking = true;
	}
		return null;
}

Note: If there are many incoming branches, the solution 2 is not easy to be used, because the links will increased greatly with branch increasing.

Run on WebSphere Process Server

  1. In WID, right click P28_Blocking, select Test Component.
  2. New invoke to test the request operation with input parameter as below
Figure 51. Detailed properties
Detailed properties
  1. New another invoke to test the request operation with different id value. (This invoke will be blocked until all branch in first invocation are finished)
Figure 52. Invoke
Invoke
  1. Open BPC explorer to see My To-dos. Two human tasks that were created by first invocation have been here.
Figure 53. To-dos
To-dos
  1. Work on Task1 and finish that.
  2. Work on Task2 and finish that.
  3. The first invocation completes and the block is reset, so the second invocation will continue to run.
  4. See My To-dos in BPC Explorer. Two human tasks were created by the second invocation.
  5. Finish two tasks.
  6. View log to see the blocking discriminator.
    • The first invocation got block value false, so that can be run
    • The second invocation got block value true, so blocked
    • When Task1 completed, Task3 started (outgoing branch)
    • When Task2 completed, the block is reset to false
    • The second invocation went on.
Listing 10. Blocking discriminator log
[9/28/10 18:06:55:296 GMT+08:00] 00000388 SystemOut  O [Blocking Discriminator] 
                                                        Run into Blocking, 
                                                        block?false        
[9/28/10 18:06:55:296 GMT+08:00] 00000388 SystemOut  O [Blocking Discriminator] 
                                                        Start invoke
[9/28/10 18:07:01:656 GMT+08:00] 00000054 SystemOut  O [Blocking Discriminator] 
                                                        Run into Initiate  
[9/28/10 18:07:05:968 GMT+08:00] 00000050 SystemOut  O [Blocking Discriminator] 
                                                        Run into Blocking, 
                                                        block?true         
[9/28/10 18:07:05:968 GMT+08:00] 00000050 SystemOut  O [Blocking Discriminator] 
                                                        Waiting in Blocking 
                                                        as Blocked        
[9/28/10 18:07:35:968 GMT+08:00] 00000050 SystemOut  O [Blocking Discriminator] 
                                                        Waiting in Blocking 
                                                        as Blocked        
[9/28/10 18:07:38:687 GMT+08:00] 0000039b SystemOut  O [Blocking Discriminator] 
                                                        Task1 Completed       
[9/28/10 18:07:38:906 GMT+08:00] 000003ac SystemOut  O [Blocking Discriminator] 
                                                        Run into Task3    
[9/28/10 18:07:40:968 GMT+08:00] 00000050 SystemOut  O [Blocking Discriminator] 
                                                        Waiting in Blocking 
                                                        as Blocked        
[9/28/10 18:07:45:968 GMT+08:00] 00000050 SystemOut  O [Blocking Discriminator] 
                                                        Waiting in Blocking 
                                                        as Blocked        
[9/28/10 18:07:47:140 GMT+08:00] 0000039d SystemOut  O [Blocking Discriminator] 
                                                        Task2 Completed        
[9/28/10 18:07:47:140 GMT+08:00] 0000039d SystemOut  O [Blocking Discriminator] 
                                                        Completed ALL.     
[9/28/10 18:07:50:968 GMT+08:00] 00000050 SystemOut  O [Blocking Discriminator] 
                                                        Waiting in Blocking 
                                                        as Blocked       
[9/28/10 18:07:52:296 GMT+08:00] 000003ac SystemOut  O [Blocking Discriminator] 
                                                        Reset Blocker       
[9/28/10 18:07:55:968 GMT+08:00] 00000050 SystemOut  O [Blocking Discriminator] 
                                                        Continue as Unblocked Now
[9/28/10 18:07:55:968 GMT+08:00] 00000050 SystemOut  O [Blocking Discriminator] 
                                                        Start invoke     
[9/28/10 18:07:57:453 GMT+08:00] 00000051 SystemOut  O [Blocking Discriminator] 
                                                        Waiting in Blocking 
                                                        as Blocked        
[9/28/10 18:08:01:437 GMT+08:00] 00000054 SystemOut  O [Blocking Discriminator] 
                                                        Run into Initiate 
[9/28/10 18:08:01:968 GMT+08:00] 00000053 SystemOut  O [Blocking Discriminator] 
                                                        Waiting in Blocking 
                                                        as Blocked        
[9/28/10 18:08:27:015 GMT+08:00] 00000050 SystemOut  O [Blocking Discriminator] 
                                                        Task2 Completed   
[9/28/10 18:08:28:718 GMT+08:00] 000003ac SystemOut  O [Blocking Discriminator] 
                                                        Run into Task3 
[9/28/10 18:08:36:203 GMT+08:00] 0000039c SystemOut  O [Blocking Discriminator] 
                                                        Task1 Completed   
[9/28/10 18:08:36:203 GMT+08:00] 0000039c SystemOut  O [Blocking Discriminator] 
                                                        Completed ALL.   
[9/28/10 18:08:41:843 GMT+08:00] 00000054 SystemOut  O [Blocking Discriminator] 
                                                        Reset Blocker

Cancelling discriminator

This pattern is similar with pattern Cancelling Partial Join. The only difference is in this pattern, when first incoming branch join, the outgoing branch is triggered and remain branches are cancelled.

Full patten detail description is located here.

Implementation

Change P32_CancelPartialJoin slightly but only keeping one of the received scopes in P32_CancelPartialJoin.

Figure 54. Cancelling Discriminator Implementation 1
Cancelling Discriminator Implementation 1

Run on WebSphere Process Server

  1. Start the P29_CancelDiscrim instance
  2. Start the P29_StartBranch instance
Listing 11. Cancelling Discriminator 1
[9/26/10 17:30:37:968 CST] 000000a8 SystemOut     O [P29_CancellingDiscriminator] 
                                                        Branch1 Started
[9/26/10 17:30:37:968 CST] 000000a8 SystemOut     O [P29_CancellingDiscriminator] 
                                                        Branch3 Started
[9/26/10 17:30:37:968 CST] 000000a8 SystemOut     O [P29_CancellingDiscriminator] 
                                                        Branch2 Started
[9/26/10 17:30:40:593 CST] 000000b1 SystemOut     O [P29_CancellingDiscriminator] 
                                                        One Branch Joined
[9/26/10 17:30:40:718 CST] 000000b4 SystemOut     O [P29_CancellingDiscriminator] 
                                                        Next Action Started
[9/26/10 17:30:40:718 CST] 000000a8 SystemOut     O [P29_CancellingDiscriminator] 
                                                        Branch2 Finished
[9/26/10 17:30:40:781 CST] 000000a8 SystemOut     O [P29_CancellingDiscriminator] 
                                                        Get Partial Join Completed Event
[9/26/10 17:30:41:609 CST] 000000a8 SystemOut     O [P29_CancellingDiscriminator] 
                                                        Cancel left branches

Generalized AND-join

This pattern requires two or more incoming branches are merged to one join construct. The join construct has only one outgoing branches. The join construct fire outgoing branch, only when all incoming branches for same instance are reaching. Other branches can be received and retained for future firings.

For example, in a car factory, the engine, chassis and body components are accumulated from the various production lines. When one car's all component are received, using one of each component to assemble the car.

Complete pattern detail description are located here.

Analysis

The focus of this pattern is:

  1. Join construct has more then one incoming branches and one outgoing branch.
  2. Incoming branches from different instances reach join construct at any time with any order.
  3. The join point release outgoing branch only when all incoming branches of one instance are all joined.

Implementation

Figure 55. Generalized AND-Join Implementation - SCA component
Generalized AND-Join Implementation - SCA component

The P33_StartBranches instance is used to generate incoming branches. Each instance generates 3 incoming branches. Each branch simulate generate one part of product. One product has 3 parts. At the end of each branch, the Join_Invoke activity is used to join the P33_ANDJoin.

Figure 56. P33_StartBranches
P33_StartBranches

Wait activities are used to create delay. That can be replaced by any sub-process or human task. Here, wait time is set with random number.

Figure 57. Wait activity
Wait activity

The join interface definition for all Join_Invoke invocation:

  • Request is used to mark different instance.
  • Part is used to mark different branch.
  • Id is correlation set parameter.
Figure 58. Join_Invoke
Join_Invoke

P33_ANDJoin only has one instance to receive all incoming branches from all P33_StartBranches instances. When all three parts which are generated from one P33_StartBranches instance join in, the product will be assembled and next action can be triggered.

Figure 59. P33_ANDJoin branch
P33_ANDJoin branch

There are 3 lists to save all reached parts. Part1List, Part2List, Part3List, which are all RequestList type.

Figure 60. RequestList
RequestList

WhileLoop is used to receive all incoming branches continuously, that exits when request is last.

Figure 61. WhileLoop
WhileLoop

ClassifyChoice classifies all coming parts. Add different part to different list. When one part comes in, that will be added to the corresponding list according to the input part parameter.

Figure 62. Part1 choice condition
Part1 choice condition

AddPart1 snippet is used to add part1 request to part1List. Other AddPart activities are similar with it.

Figure 63. part1List request
part1List request

AssemblyChoice is used to check if all parts of one request are all reached. If yes, all parts will be assembled to product and the outgoing branch (NextAction) will be trigger.

AllPart choice condition (All part lists have one same request):

Figure 64. AllPart choice condition
AllPart choice condition

If all three part lists include this request, that means all parts of this request has reached. Then product can be assembled and the outgoing branch can be triggered. The remove snippet is used to clean part lists after one product is assembled.

Run on WebSphere Process Server

Execution Steps:

  1. Start the P33_ANDJoin process singleton instance. Id is correlation set parameter, so all join in branches should have some id value.
Figure 65. Starting P33_ANDJoin process
Starting P33_ANDJoin process
  1. Start one P33_StartBranches instance. The id value should be same with that in P33_ANDJoin instance.
Figure 66. P33_StartBranches
P33_StartBranches
  1. Start another two P33_StartBranches instance.
Figure 67. Two P33_StartBranches
Two P33_StartBranches
  1. Three P33_StartBranches instances have been created with different request input parameters. Now check the log file to see GeneralizedAndJoin.
    • Black part is the output log that was triggered by the first P33_StartBranches instance.
    • Blue part is the out put log that was triggered by the second P33_StartBranches instance.
    • Red part is the out put log that was triggered by the second P33_StartBranches instance.
    • The join construct get all incoming branches of request1 instance first and trigger the outgoing branch. Request3 branches were assembled second. And request2 branches were last.
Listing 12. Generalized AND-Join Log
[9/26/10 12:27:52:484 CST] 000000b5 SystemOut     O [P33_GeneralizedANDJoin] 
                                                    request1 part2 wait 17
[9/26/10 12:27:52:500 CST] 000000b5 SystemOut     O [P33_GeneralizedANDJoin] 
                                                    request1 part3 wait 13
[9/26/10 12:27:52:500 CST] 000000b5 SystemOut     O [P33_GeneralizedANDJoin] 
                                                    request1 part1 wait 2
[9/26/10 12:27:54:859 CST] 00000009 SystemOut     O [P33_GeneralizedANDJoin] 
                                                    Get part1 of request1
[9/26/10 12:28:00:203 CST] 000000a8 SystemOut     O [P33_GeneralizedANDJoin] 
                                                    request2 part2 wait 60
[9/26/10 12:28:00:203 CST] 000000a8 SystemOut     O [P33_GeneralizedANDJoin] 
                                                    request2 part3 wait 3
[9/26/10 12:28:00:218 CST] 000000a8 SystemOut     O [P33_GeneralizedANDJoin] 
                                                    request2 part1 wait 10
[9/26/10 12:28:03:609 CST] 000000ab SystemOut     O [P33_GeneralizedANDJoin] 
                                                    Get part3 of request2
[9/26/10 12:28:05:937 CST] 00000008 SystemOut     O [P33_GeneralizedANDJoin] 
                                                    Get part3 of request1
[9/26/10 12:28:08:796 CST] 000000b1 SystemOut     O [P33_GeneralizedANDJoin] 
                                                    request3 part2 wait 42
[9/26/10 12:28:08:812 CST] 000000b1 SystemOut     O [P33_GeneralizedANDJoin] 
                                                    request3 part3 wait 1
[9/26/10 12:28:08:812 CST] 000000b1 SystemOut     O [P33_GeneralizedANDJoin] 
                                                    request3 part1 wait 8
[9/26/10 12:28:09:656 CST] 00000009 SystemOut     O [P33_GeneralizedANDJoin] 
                                                    Get part2 of request1
[9/26/10 12:28:09:671 CST] 00000009 SystemOut     O [P33_GeneralizedANDJoin] 
                                                    NextAction - Assembly in request1
[9/26/10 12:28:10:500 CST] 00000008 SystemOut     O [P33_GeneralizedANDJoin] 
                                                    Get part3 of request3
[9/26/10 12:28:11:500 CST] 00000009 SystemOut     O [P33_GeneralizedANDJoin] 
                                                    Get part1 of request2
[9/26/10 12:28:17:718 CST] 0000000b SystemOut     O [P33_GeneralizedANDJoin] 
                                                    Get part1 of request3
[9/26/10 12:28:51:000 CST] 000000ad SystemOut     O [P33_GeneralizedANDJoin] 
                                                    Get part2 of request3
[9/26/10 12:28:51:000 CST] 000000ad SystemOut     O [P33_GeneralizedANDJoin] 
                                                    NextAction - Assembly in request3
[9/26/10 12:29:00:562 CST] 000000ab SystemOut     O [P33_GeneralizedANDJoin] 
                                                    Get part2 of request2
[9/26/10 12:29:00:562 CST] 000000ab SystemOut     O [P33_GeneralizedANDJoin] 
                                                    NextAction - Assembly in request2

Structured synchronizing merge

This pattern requires two or more incoming branches, which are split from one point in same structure, are merged to one merge point. The merge point can be passed, only when all active incoming branch arrival.

For example, depending on the factory status, the scale enlargement includes staff recruiting and equipment purchasing. These tasks are initiated at the same time. When all these two tasks are finished, the scale enlargement is completed and new production can be started.

Full pattern detail description is located here.

Analysis

The focus of this pattern is:

  1. The process splits into two or more branches at a given point.
  2. Those split branches are executed concurrently.
  3. All branches converge to one merge point.
  4. Only when all active branches reach the merge point, subsequent action can be enabled.

Implementation

Figure 68. Synchronizing Merge Implementation - SCA component
Synchronizing Merge Implementation - SCA component
Figure 69. Synchronizing Merge Implementation - BPC Implementation
Synchronizing Merge Implementation - BPC Implementation

If Wait4case1 and Wait4case2 are all enabled, SyncSnippet activity will starts after Case1 branch and Case2 branch are all finished.

Run on WebSphere Process Server

  1. Start the P07_StructuredSynchronizingMerge process instance
Figure 70. P07_StructuredSynchronizingMerge
P07_StructuredSynchronizingMerge
  1. Input parameters like below. Then Case1 and Case2 will be enabled. Case1 will wait 2 seconds and Case2 will wait 5 seconds.
Figure 71. Input parameters
Input parameters
  1. View log to see Case1 started. Three seconds later, Case2 started. SyncSnippet started after Case1 and Case2.
Listing 13. Synchronizing merge log
[9/23/10 13:18:44:390 CST] 00000046 SystemOut     O [Snippet4Case1]After wait: 
                                                    2, runinto the Snippet4Case1
[9/23/10 13:18:44:390 CST] 00000046 SystemOut     O [Snippet4Case1]The orginial 
                                                    string is: Case1Case2
[9/23/10 13:18:47:359 CST] 00000046 SystemOut     O [Snippet4Case2]After wait: 5, 
                                                    runinto the Snippet4Case2
[9/23/10 13:18:47:359 CST] 00000046 SystemOut     O [Snippet4Case2]The orginial string 
                                                    is: 
                                                    Case1Case2Case1Response
[9/23/10 13:18:47:421 CST] 00000046 SystemOut     O [SyncSnippet]runinto the SyncSnippet
[9/23/10 13:18:47:421 CST] 00000046 SystemOut     O [SyncSnippet]The synced string is: 
                                                    Case1Case2Case1ResponseCase2Response

Local synchronizing merge

This pattern requires two or more incoming branches which diverged earlier in the process are merged into a single outgoing branch. When each original activity incoming branch has been enabled, new branches still can be added according to local information. After all original and new incoming branches all come to the merge point, the outgoing branch can be triggered.

For example, project manger splits one project to three feature components and assigns to three developers. Developers start to work. But customer requests two new features, so project manager has to add two new feature components and assign to two new developers. Only when all features are completed, the project can be released.

Full pattern detail description is here.

Analysis

The focus of this pattern is:

  1. One branch diverges into two or more branches.
  2. Two or more branches merge into a single subsequent branch.
  3. When each active incoming branch has been enabled, the thread of control is passed to the subsequent outgoing branch.
  4. Can decide later how many branches need to be merged.

In WID, we can use Generalized Flow with conditioned links to implement this.

Implementation

Figure 72. Local Synchronizing Merge - SCA Component
Local Synchronizing Merge - SCA Component
Figure 73. Local Synchronizing Merge - BPC Implementation
Local Synchronizing Merge - BPC Implementation

Case1, Case2 and Case3 will be started concurrently. Then DeferCall is waiting for input to decide go Case4 or Case5, after all paths are enabled, all paths merged together.

Run on WebSphere Process Server

  1. Start the P37_LocalSyncMerge instance. Input Case1Case2Case3
Figure 74. P37_LocalSyncMerge
P37_LocalSyncMerge
  1. Click the instance
Figure 75. Instance options
Instance options
  1. Go to Waiting Operations to trigger the defer call
Figure 76. Waiting Operation
Waiting Operation
  1. Input 4 means the Case4 will be selected
Figure 77. Input value
Input value
  1. View the log to see the Local Synchronizing Merge result
Listing 14. Local Synchronizing Merge
[8/27/10 10:08:02:765 GMT+08:00] 00000061 SystemOut     O [Local Synchronizing Merge]
                                                            Run into Case1
[8/27/10 10:08:02:765 GMT+08:00] 00000061 SystemOut     O [Local Synchronizing Merge]
                                                            Run into Case2
[8/27/10 10:08:02:765 GMT+08:00] 00000061 SystemOut     O [Local Synchronizing Merge]
                                                            DeferDecide Case4 or Case5
[8/27/10 10:08:02:781 GMT+08:00] 00000061 SystemOut     O [Local Synchronizing Merge]
                                                            Run into Case3
[8/27/10 10:08:43:500 GMT+08:00] 00000052 SystemOut     O [Local Synchronizing Merge]
                                                            Run into Case4
[8/27/10 10:08:43:515 GMT+08:00] 00000052 SystemOut     O [Local Synchronizing Merge]
                                                            Run into Merge

General synchronizing merge

This pattern extends the Local Synchronizing Merge pattern. About this pattern, the enabled branch could not be finished. The outgoing branch can be release, only when (1) each active incoming branch has been enabled or (2) it is not possible that any branch that has not yet been enabled will be enabled at any future time.

For example, in the sample of Local Synchronizing Merge pattern, during development phrase, one feature is cancelled because customer requirement is changed. Then the project also can be released without this feature.

The complete pattern detail description is located here.

Analysis

The focus of this pattern is:

  1. One branch diverges into two or more branches.
  2. Two or more branches merge into a single subsequent branch.
  3. Can decide later how many branches need to be merged.
  4. When each active incoming branch has been enabled or it is not possible that any branch that has not yet been enabled will be enabled at any future time, the thread of control is passed to the subsequent branch.
  5. Can have loop structure.

Implementation

Figure 78. General Synchronizing Merge - SCA Component
General Synchronizing Merge - SCA Component
Figure 79. General Synchronizing Merge - BPC Implementation
General Synchronizing Merge - BPC Implementation

Case1, Case2 and Case3 will be started concurrently. Then DeferCall is waiting for input to decide go Case4 or Case5 or Case3 again. After all paths are enabled, all paths merged together. If Case5 is selected, the merge point will not waiting for Case5 merge.

Run on WebSphere Process Server

  1. Start the P37_LocalSyncMerge instance. Input Case1Case2Case3.
Figure 80. P37_LocalSyncMerge instance
P37_LocalSyncMerge instance
  1. Click the created instance
Figure 81. Created instance
created instance
  1. Go to Waiting Operations to trigger the defer call
Figure 82. Waiting Operations
Waiting Operations
  1. Input 3 means the Case3 will be run again.
Figure 83. Input 3
8. Input 3
  1. Rerun DeferCall and input 5, Case5 will be run, and P37_LocalSyncMerge instance will be finished.
  2. View log to see the Local Synchronizing Merge result.
Listing 15. General synchronizing merge
[8/30/10 15:43:59:453 GMT+08:00] 00000061 SystemOut     O [Local Synchronizing Merge]
                                                            Run into Case1
[8/30/10 15:43:59:453 GMT+08:00] 00000061 SystemOut     O [Local Synchronizing Merge]
                                                            Run into Case2
[8/30/10 15:43:59:468 GMT+08:00] 00000061 SystemOut     O [Local Synchronizing Merge]
                                                            Run into Case3
[8/30/10 15:45:01:437 GMT+08:00] 00000328 SystemOut     O [Local Synchronizing Merge]
                                                            Run into Case3
[8/30/10 15:45:21:937 GMT+08:00] 00000328 SystemOut     O [Local Synchronizing Merge]
                                                            Run into Merge
[8/30/10 15:45:22:218 GMT+08:00] 00000061 SystemOut     O [Local Synchronizing Merge]
                                                            Run into Case5

Conclusion

In this article, we introduce 12 advanced branching pattern and 3 synchronizing merge patterns with related WID implementation. With those workflow control patterns, we can construct complex business process graciously.


Download

DescriptionNameSize
PI files for this articlePart3PI.zip178KB

Resources

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into SOA and web services on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=SOA and web services
ArticleID=558550
ArticleTitle=Implementing Advanced Workflow Patterns in WebSphere Integration Developer and WebSphere Process Server, Part 3: Advanced branching and synchronization patterns
publish-date=10282010