A mediation flow can run multiple branches in parallel but in a single thread. Basically, it uses the request with deferred response pattern. We will use an example to understand how things exactly work. But, before we get to that, let’s look at what we need to do to enable parallel processing. You will need to do two things:
1. For the Service Invoke primitives in the aggregation block, set the Invocation Style property to Async.
2. For the Fan Out primitive, choose Check for asynchronous responses after all messages have been fired. The Fan Out has to be in iteration mode for you to be able to choose that option.
Now, let’s examine an example.
Here, for all Service Invoke primitives, Invocation Style has been set to Async. For the Fan Out, Check for asynchronous responses after all messages have been fired has been selected.
The flow will perform as follows. First ServiceInvoke1 will be called immediately followed by ServiceInvoke3 (actually, the exact order of their invocation can not be determined and does not really matter). System will not wait for response from ServiceInvoke1 before ServiceInvoke3 is executed.
Since there are primitives left to be executed in both branches, the flow will then go to wait for responses to come back from the two already executed operations. This wait in the middle of the paths can not be avoided since the subsequent primitives may depend upon the output of the executed operations. After ServiceInvoke1 and ServiceInvoke3 return output back, system will then execute XSL4 and ServiceInvoke4. Without waiting for response from ServiceInvoke4, system will execute XSL2 and ServiceInvoke2. System will then wait for the responses to come back from these two Service Invoke primitives.
WID actually give you an error message if you setup parallel processing but do not configure the transaction boundary correctly.
1. For the Service Invoke primitives in the aggregation block, set the Invocation Style property to Async.
2. For the Fan Out primitive, choose Check for asynchronous responses after all messages have been fired. The Fan Out has to be in iteration mode for you to be able to choose that option.
Now, let’s examine an example.
Here, for all Service Invoke primitives, Invocation Style has been set to Async. For the Fan Out, Check for asynchronous responses after all messages have been fired has been selected.
The flow will perform as follows. First ServiceInvoke1 will be called immediately followed by ServiceInvoke3 (actually, the exact order of their invocation can not be determined and does not really matter). System will not wait for response from ServiceInvoke1 before ServiceInvoke3 is executed.
Since there are primitives left to be executed in both branches, the flow will then go to wait for responses to come back from the two already executed operations. This wait in the middle of the paths can not be avoided since the subsequent primitives may depend upon the output of the executed operations. After ServiceInvoke1 and ServiceInvoke3 return output back, system will then execute XSL4 and ServiceInvoke4. Without waiting for response from ServiceInvoke4, system will execute XSL2 and ServiceInvoke2. System will then wait for the responses to come back from these two Service Invoke primitives.
A Note About Deadlock
In the example above, request is sent but the system does not wait for a response. You need to be careful about the transaction boundary. Let us say that a request is sent by posting a message in a JMS queue. By default, the message will be actually posted if the transaction of the mediation flow commits. If the flow waits for a response, that will never come since the transaction is still active and the request message never went out in the first place. Long story short, you will have to post the request message in a separate transaction from the main transaction of the message flow. To do that, select the service reference of the mediation flow in the assembly diagram. Then set the Asynchronous invocation qualifier to Call.WID actually give you an error message if you setup parallel processing but do not configure the transaction boundary correctly.