Repeat processing for multiple users in state machine
Document review workflow with one to many reviewers. Each reviewer can approve, reject, skip, submit comments, etc. (i.e. several possible events). I am looking for recommendations on how best to implement this facet of the state machine.
OK, interesting.I had actually defined the CorrelationParameter to be the base-class InstanceId.You’re saying I don’t even need that.(I assume because it is implicit feature of ExternalDataEventArgs).
The next thing I am working on is waiting for completion of the child (individual reviewer) workflows.
First, for each child, I was planning on having a Listener to receive either a completion event (external event from the web UI) or continually send an email reminder (to the reviewer) via a Delay activity. (The Listener would be contained in a While loop).Eventually, after enough time, the wait for the reviewer’s feedback can be timed out.
Secondly, I need to "join" on the overall completion of ALL of the child workflows.Again, I was planning on having a Listener (outside the Replicator) to capture each child workflow completion (perhaps using the same event as above ) then using CallExternalMethod to communicate completion back up to the parent workflow.(I know the WorkflowCompleted event is available via the Runtime, but I wasn’t sure this would be a viable mechanism because in a multiple user/multiple document environment, how would I identify the source of the completed review )
I am really struggling with parent/child workflow communication. I can start a subworkflow and pass it the parent workflow instanceId. However, I can't figure out how to raise an event back to the parent workflow once the subworkflow is completed.
I can't seem to find any method that would handle me the workflow runtime from within an Activity. So when you say "call a service to raise an event back to the parent", I'm really not sure what kind of service to call...
If you have a state machine for the reviewer, then you should only need to use the workflow instance ID on the event arguments when you submit them, that will route the message to the correct workflow instance. You only need correlation when you have multiple activities waiting for the same input. With the state machine, this is more easily modeled (often) with a super state that handles the event.
I am very new to WWF and really struggling with the implementation details of how to get this all working.I have been all over the web trying to find answers.I have tried and failed with different approaches.I am learning a lot but can’t seem to address these specific issues.
Here is the design (again) in a nutshell:
Document review system with multiple reviewers.All user interaction is via a web site.Each reviewer will ultimately approve or reject the document.(Before this happens, there can also be a series of comments back and forth with the submitter and/or an adjudicator.This seems to lend itself well to a separate state machine – i.e. a child workflow).So we have a Replicator that launches a child workflow for each reviewer.Then of course we need to wait on each reviewers response.No problem conceptually, but it evokes a whole slew of implementation questions.
First, how does the child workflow know which reviewer it is handling The only place I seem to be able to get a reference to the reviewer (InstanceData) is in the ChildInitialized event handler for the Replicator.Am I supposed to invoke the child workflow manually (in code) from the ChildInitialized handler, or is there a way to get it all working using the InvokeWorkflow activity in the designer Or should I be using the child workflow’s Invoking event to set up the parameters (How) (In short, what specific mechanism(s) should I be using to pass the reviewer down to the child workflow )
Second, there is the issue of event handling.Conceptually, I understand how correlation works.But again, the devil is in the details.In my case, I have a number of different user initiated events that can come from the host into the reviewer’s child workflow (e.g. Reject, Approve, Comment, RequestAdjudication, etc.), causing various state transitions.The reviewer’s name is the obvious correlation parameter.But if I have several possible events, can/should each event declare the same correlation alias (i.e. reviewer), or will this cause problems Also, from all the examples I have seen, it seems that in order for correlation to work, there needs to be a “handshake” between the host and the workflow.(That is, an external method call to the host coupled with an event back to the workflow).Must the external method call be initiated within the child workflow, or can/should it be done within the Replicator logic (What are the different implications )Or should I ditch the external data service approach altogether in favor of some sort of custom queuing logic instead
I am a stranger in a strange land, indeed.Please help!
In the replicator, when you create your custom composite, have it include the starting of the workflow for each user as well as the listen shape which has the delay and the receiving of the response/completion.
Here you will want to setup correlation such that the event on the listen is correlated based on the user name or something unique to the workflow instance (you could even use the child workflow instance ID which might be easiest. (Note that you might need to create a dummy call method to initiate the correlation token).
In the child workflow, as the last activity, call a service to raise an event back to the parent. This assumes that one of the parameters for your chlid workflow is the ID of the parent since you will need this to raise the event correctly. Send any other parameters needed for the correlation.
In this way, the replicator won't complete until all reviews are complete or timed out.
public class MyService : IMyService, INotifyComplete
{
public event EventHandler<ExternalDataEventArgs> Completed;
public void SetupCorrelation(Guid parentInstanceId)
{
return;
}
public void NotifyComplete(Guid parentInstanceId)
{
if (Completed != null)
Completed(this, new ExternalDataEventArgs (parentInstanceId));
}
}
In Parent Workflow:
CallExternalMethod (IMyService.SetupCorrelation) which establishes the parent’s message queue.
InvokeWorkflow – passing in parentInstanceId
HandleExternalEvent (Completed) – from the child
In Child Workflow (upon conclusion):
CallExternalMethod (INotifyComplete.NotifyComplete) which will send the Completed event to the parent workflow’s message queue.
Note:All of this is implicitly handled as part of the ExternalDataExchange framework. All you need to do is add MyService to the ExternalDataExchangeService when the host app is initialized:
ExternalDataExchangeService dataExchangeService = new ExternalDataExchangeService();
One idea would be to have a starting workflow (sequential or state machine) with a replicator that is driven on the list of users. Then for each repitition, start a state machine for each of the users to do their part.
OK, I think I found the answer to my first question. My replicator creates a sequence whose first activity is InvokeWorkflow. Given dependency property ReviewerAccount on the child workflow, in the replicator's ChildInitialized event handler I have:
SequenceActivity seq = e.Activity.GetActivityByName("MySequenceActivity", true) as SequenceActivity;
InvokeWorkflowActivity wkf = seq.GetActivityByName("InvokeReviewerWorkflow", true) as InvokeWorkflowActivity;
Am I forced to invoke the child workflow(s) explicitly IN CODE (e.g. within the Replicator’s ChildInitialized event handler), or can I include the InvokeWorkflow in DESIGN mode and set its input parameters at runtime The Invoking event doesn’t seem to allow access to the input parameters.Is there an execution context of some sort (accessible in the Invoking handler) that would allow me to determine which of the Replicator’s children is being processed Or am I missing something obvious (I am only a few weeks into WWF at this point and still groping my way through it).
Repeat processing for multiple users in state machine
Repeat processing for multiple users in state machine
Dudets
OK, interesting. I had actually defined the CorrelationParameter to be the base-class InstanceId. You’re saying I don’t even need that. (I assume because it is implicit feature of ExternalDataEventArgs).
The next thing I am working on is waiting for completion of the child (individual reviewer) workflows.
First, for each child, I was planning on having a Listener to receive either a completion event (external event from the web UI) or continually send an email reminder (to the reviewer) via a Delay activity. (The Listener would be contained in a While loop). Eventually, after enough time, the wait for the reviewer’s feedback can be timed out.
Secondly, I need to "join" on the overall completion of ALL of the child workflows. Again, I was planning on having a Listener (outside the Replicator) to capture each child workflow completion (perhaps using the same event as above ) then using CallExternalMethod to communicate completion back up to the parent workflow. (I know the WorkflowCompleted event is available via the Runtime, but I wasn’t sure this would be a viable mechanism because in a multiple user/multiple document environment, how would I identify the source of the completed review )
Am I on the right track Thank you so much.
UK_2006
I can start a subworkflow and pass it the parent workflow instanceId.
However, I can't figure out how to raise an event back to the parent workflow once the subworkflow is completed.
I can't seem to find any method that would handle me the workflow runtime from within an Activity. So when you say "call a service to raise an event back to the parent", I'm really not sure what kind of service to call...
Thx
Blaise
JNG
Paul Monaghan
If you have a state machine for the reviewer, then you should only need to use the workflow instance ID on the event arguments when you submit them, that will route the message to the correct workflow instance. You only need correlation when you have multiple activities waiting for the same input. With the state machine, this is more easily modeled (often) with a super state that handles the event.
Matt
brottmayer
I am very new to WWF and really struggling with the implementation details of how to get this all working. I have been all over the web trying to find answers. I have tried and failed with different approaches. I am learning a lot but can’t seem to address these specific issues.
Here is the design (again) in a nutshell:
Document review system with multiple reviewers. All user interaction is via a web site. Each reviewer will ultimately approve or reject the document. (Before this happens, there can also be a series of comments back and forth with the submitter and/or an adjudicator. This seems to lend itself well to a separate state machine – i.e. a child workflow). So we have a Replicator that launches a child workflow for each reviewer. Then of course we need to wait on each reviewers response. No problem conceptually, but it evokes a whole slew of implementation questions.
First, how does the child workflow know which reviewer it is handling The only place I seem to be able to get a reference to the reviewer (InstanceData) is in the ChildInitialized event handler for the Replicator. Am I supposed to invoke the child workflow manually (in code) from the ChildInitialized handler, or is there a way to get it all working using the InvokeWorkflow activity in the designer Or should I be using the child workflow’s Invoking event to set up the parameters (How) (In short, what specific mechanism(s) should I be using to pass the reviewer down to the child workflow )
Second, there is the issue of event handling. Conceptually, I understand how correlation works. But again, the devil is in the details. In my case, I have a number of different user initiated events that can come from the host into the reviewer’s child workflow (e.g. Reject, Approve, Comment, RequestAdjudication, etc.), causing various state transitions. The reviewer’s name is the obvious correlation parameter. But if I have several possible events, can/should each event declare the same correlation alias (i.e. reviewer), or will this cause problems Also, from all the examples I have seen, it seems that in order for correlation to work, there needs to be a “handshake” between the host and the workflow. (That is, an external method call to the host coupled with an event back to the workflow). Must the external method call be initiated within the child workflow, or can/should it be done within the Replicator logic (What are the different implications ) Or should I ditch the external data service approach altogether in favor of some sort of custom queuing logic instead
I am a stranger in a strange land, indeed. Please help!
douner001
In this case, you might want do the following:
In the replicator, when you create your custom composite, have it include the starting of the workflow for each user as well as the listen shape which has the delay and the receiving of the response/completion.
Here you will want to setup correlation such that the event on the listen is correlated based on the user name or something unique to the workflow instance (you could even use the child workflow instance ID which might be easiest. (Note that you might need to create a dummy call method to initiate the correlation token).
In the child workflow, as the last activity, call a service to raise an event back to the parent. This assumes that one of the parameters for your chlid workflow is the ID of the parent since you will need this to raise the event correctly. Send any other parameters needed for the correlation.
In this way, the replicator won't complete until all reviews are complete or timed out.
Matt
Chronusus
[ExternalDataExchange]
[CorrelationParameter("instanceId")]
public interface IMyService
{
[CorrelationInitializer]
void SetupCorrelation(Guid parentInstanceId);
[CorrelationAlias("instanceId", "e.InstanceId")]
event EventHandler<CompletionEventArgs> Completed;
}
[ExternalDataExchange]
public interface INotifyComplete
{
void NotifyComplete(Guid parentInstanceId);
}
[Serializable]
public class MyService : IMyService, INotifyComplete
{
public event EventHandler<ExternalDataEventArgs> Completed;
public void SetupCorrelation(Guid parentInstanceId)
{
return;
}
public void NotifyComplete(Guid parentInstanceId)
{
if (Completed != null)
Completed(this, new ExternalDataEventArgs (parentInstanceId));
}
}
In Parent Workflow:
CallExternalMethod (IMyService.SetupCorrelation) which establishes the parent’s message queue.
InvokeWorkflow – passing in parentInstanceId
HandleExternalEvent (Completed) – from the child
In Child Workflow (upon conclusion):
CallExternalMethod (INotifyComplete.NotifyComplete) which will send the Completed event to the parent workflow’s message queue.
Note: All of this is implicitly handled as part of the ExternalDataExchange framework. All you need to do is add MyService to the ExternalDataExchangeService when the host app is initialized:
ExternalDataExchangeService dataExchangeService = new ExternalDataExchangeService();
workflowRuntime.AddService(dataExchangeService);
dataExchangeService.AddService(new MyService());
Joudoki
One idea would be to have a starting workflow (sequential or state machine) with a replicator that is driven on the list of users. Then for each repitition, start a state machine for each of the users to do their part.
Matt
RAGOpoR
OK, I think I found the answer to my first question. My replicator creates a sequence whose first activity is InvokeWorkflow. Given dependency property ReviewerAccount on the child workflow, in the replicator's ChildInitialized event handler I have:
SequenceActivity seq = e.Activity.GetActivityByName("MySequenceActivity", true) as SequenceActivity;
InvokeWorkflowActivity wkf = seq.GetActivityByName("InvokeReviewerWorkflow", true) as InvokeWorkflowActivity;
wkf.ParameterBindings["ReviewerAccount"].Value = e.InstanceData;
That seems to work.
ShawnE
Define a property on the child workflow that can take in the user. Then when you use the InvokeWorkflowActivity, you can set / bind that parameter.
Matt
gatekeeper6838
Am I forced to invoke the child workflow(s) explicitly IN CODE (e.g. within the Replicator’s ChildInitialized event handler), or can I include the InvokeWorkflow in DESIGN mode and set its input parameters at runtime The Invoking event doesn’t seem to allow access to the input parameters. Is there an execution context of some sort (accessible in the Invoking handler) that would allow me to determine which of the Replicator’s children is being processed Or am I missing something obvious (I am only a few weeks into WWF at this point and still groping my way through it).