Introduction
This is the last of five articles about Host - Workflow communication.
This series of articles tries to show the different possibilities to implement communication between workflow and the host application, from the simplest case to more complex. I am not planning to be exhaustive, but I try to give a general panoramic in order to get us a good idea about the thematic.
Because I also don’t like large articles, I have divided them in the followings parts:
Part V: Intercommunications with a Workflow Instance using Correlation Parameter
Background
Until now, we have studied communication examples in which the events are called one time in the same workflow instance. The last situation that we want to see in this article is the situation in which you use the same external event in different parts of your workflow.
The workflow runtime can find a particular instance of the workflow, but when you try to bind the event, it finds two or more instances of the same events in the workflow, and only one needs to receive the data (for our purpose, of course). How to avoid that the workflow confused our data? Normally, the runtime processes the information from left to right, that is the activities that are situated in the right branch are executed first, but you are not guaranteed that there is always success in this form.
The solution is the correlation parameter.
Correlation mining is when you “correlate” two or more activities in the workflow. The process begins when you call an external activity to request a information from host. This request should initialize the correlation parameter. When you return the information to workflow, you send it with the same value in the correlation parameter. In the workflow, the received information goes to the Handle external Event activity that is “marked” with the same correlation token as the call external activity.
That can be confused. The correlation parameter (used in the host to correlate a method with the event is not the same as the correlation token used in the workflow to correlate two (or more) activities but working together.
The correlation parameter uses the value to identify to correlated action in host and the correlation token works in the workflow and only uses its name and the value is irrelevant.
We can illustrate the concept in the following application:
Code Hand-on
Companion Code Usage
Use ExampleWithOutCorrelation
solution to see the code without Correlation. You can also add in it the necessary modifications that are explained in this text to convert the workflow in a correlate workflow. Use ExampleWithCorrelation
solution if you want to see how the correlate workflow should be.
Imagine that you have a workflow that receives a customer name and checks if he/she has a order, if it has a order, the workflow asks in parallel the host for the e-mail address of the order provider and the customer e-mail address. When the workflow gets the emails address, it sends a notification email for each address and informs the host that the emails were sent.
The following figure illustrates the workflow:
Normally that work, and the runtime assigns the correct values in each branch of the parallel activity, but not always, if the host application for any reason delays the response information from the first branch, and the second branch response goes first, then the program does not work OK. We have forced this situation in our example by introducing a delay. In this case, the response is as you can see in the following figure:
As you see, the first send response from Host was taken by the workflow and used in the two branches of the workflow.
It is clear that the runtime cannot know what getEmailAddress
has requested the information and also and more important has no idea what sendEmailToWorkflow
HandlerExternalEvent
receiver gets the returned email address. You can see this program in the attachment.
Normally the workflow processes the information from left to right, but you cannot be sure that the response can also send left to right, that it is the situation exposed in this example. A normal cause of this behaviour can be the access to a database or a web service previous to return the information to workflow.
What can we do in this situation? “Correlation”: We need to inform the runtime that the activity getEmailAddress1
is “correlated” with the sendEmailToWorkflow1
activity and the activity getEmailAddress2
is “correlated” with the sendEmailToWorkflow2
activity.
A second point, we don’t need to correlate all external actions in our workflow, if you create an interface that uses correlation, all that is in the interface is correlated. When you don’t give a correlate parameter, the NET framework throws an error when the program is running.
Solution: Create a second communication interface and use both to create your Communication
manager class. In the second interface, place the external methods and events that you don’t want to correlate. In our example, the only external method is SendMailNotification
.
Before continuing, open the ExampleWithoutCorrelation
solution, build it and observe how it works. We will use this application as a base to create our correlated application. In the attached code: Open the solution ExampleWithoutCorrelation
, open the project CommunicationManager
and open the file IMailConfiguration
, modify the file as you can see:
[ExternalDataExchange]
[CorrelationParameter("typo")]
public interface IMailCommunication
{
#region Workflow To Host
[CorrelationInitializer]
void GetEmailAddress(Guid wfId, string typo, string orderNumber);
#endregion
#region Host To Workflow
[CorrelationAlias("typo", "e.Typo")]
event EventHandler<MailEventArgs> SendEmailToWorkflow;
#endregion
}
Observe that you must delete the method SendEmailNotification
, this external method must be translated to an additional interface. In IMailCommunication
, you need only add the [CorrelationParameter]
header that tells runtime that you declare typo as a correlation parameter. Then in the external method, the header [CorrelationInitializer]
begins the process of correlation when the method is called, then all methods or events in the interface take place under this correlation process. All methods or events that do not have a correlation parameter raise an exception when called in this context.
Because we don’t need that SendEmailNotification
has the correlation parameter, we can declare it in another communication interface.
Create a new interface file in the open project and name it as IMailConfiguration2
, enter the following code:
[ExternalDataExchange]
public interface IMailCommunication2
{
void SendEmailNotification(Guid wfId, string Notification);
}
You can see that it is a normal ExternalDataExchange
interface.
Now we need to modify the IMailCommunication
implementation to be compatible with the two interfaces: You need to add in the class declaration the name of the second interface. See code:
public class MailCommunication:IMailCommunication, IMailCommunication2
{
..........
}
You don’t need to do another modification.
That is all in our communication interface. Now we need to generate with wca.exe (or WWCA.EXE) the custom activities (See part 4 of this article. You can download WWCA here). Call wwca.exe and give the CommunicationManager.dll as input and send the output to CorrelationDemoWF directory.
Generate the activities and open the project CorrelationDemoWF
, you can see now that the generated activities from IMailCommunication
have a red point. See diagram:
The activities generated that come from IMailCommunication2
are not red marked. That is because we are applied correlation parameter only in the first interface.
The red point indicates that you must enter the correlation token for this activities, which is a new property that appears when you applied correlation in the communication interface.
The correlation token is arbitrary, only you must select the same token for the correlated activities; in our situation, you select a1 for getEmailAddress1
and sendEmailToWorkflow1
. When you select a token, a new dependency property is created and you should enter the scope of this token, in our example it is seqProviderEmail
, the container activity.
Select for the left branch the correlation token b2 and assign as owner seqCustomerEmail
for both activities.
You can see that the activities SendEmailNotification1
and 2
do not have the correlation token. That is because they were declared in the second interface without the correlation headers.
That is all, compile the application and execute. Now you can see that the result is as is shown in the following screen:
Correlation makes sure that the data comes and goes to the source to the correct receptor under all program conditions.
Correlation helps you to avoid those strange and erratic errors in the workflow application when the factor delay in a busy server enters in the play.
Well, it is the end of this series. I think that now we have a better idea about how to get and send data to a workflow instance or multiple instances. We have also showed how to work to create custom entities and a method to create the communication interface.
History
- First version: 04.10.2008