Reusing workflows in a State machine

I have a state machine with states A and B. Both of them have an EventDrivenActivity which has the same sequential workflow. What is the best way to create just one copy of this workflow instead of repeating under both EventDrivenActivities? Note that there are other EventDrivenActivities on each state which make them truely different, so combining the two states into one is not an option.
[398 byte] By [NareshBhatia] at [2007-12-18]
# 1

Hi Naresh,

You can nest both the child state activities into a parent state activity which will have the event driven that invokes another workflow. i.e.

State Machine Workflow

State 1 (Parent State)

|__ EventDriven1 that Invokes Sequential Workflow

|__ State 2 (with event driven activity)

|__ State 3 (with event driven activity)

This way the common functionality for invoking the sequential workflow can be bubbled up to the parent and need not be duplicated

Hope this helps.

- Vihang

vihang at 2007-9-8 > top of Msdn Tech,Software Development for Windows Vista,Windows Workflow Foundation...
# 2
Good idea except that one of the states is the initial state of the workflow. If I move it inside a parent state I can no longer mark it as an initial state.
NareshBhatia at 2007-9-8 > top of Msdn Tech,Software Development for Windows Vista,Windows Workflow Foundation...
# 3
You can mark a state as initial state as long as it does not contain any other states. Initial state can have a parent state and it should work fine.
vihang at 2007-9-8 > top of Msdn Tech,Software Development for Windows Vista,Windows Workflow Foundation...
# 4
Ok, I have resturctured the workflow as you suggested, but now I am getting an exception that the event cannot be delivered to the outer state:

System.Workflow.Activities.EventDeliveryFailedException:
Event "CommodityQuoteRequestedEvent" on interface type "HighEnergy.WorkflowUtils.IWorkflowDataExchangeService"
for instance id "ac642cd7-7842-4fae-a7da-2d1171a35785" cannot be delivered. >
System.InvalidOperationException: Queue 'Message Properties
Interface Type:HighEnergy.WorkflowUtils.IWorkflowDataExchangeService
Method Name:CommodityQuoteRequestedEvent
CorrelationValues:
' is not enabled.
at System.Workflow.Runtime.WorkflowQueuingService.EnqueueEvent(IComparable queueName, Object item)
at System.Workflow.Runtime.WorkflowExecutor.EnqueueItem(IComparable queueName, Object item, IPendingWork pendingWork, Object workItem)
at System.Workflow.Runtime.WorkflowInstance.EnqueueItem(IComparable queueName, Object item, IPendingWork pendingWork, Object workItem)
at System.Workflow.Activities.WorkflowMessageEventHandler.EventHandler(Object sender, ExternalDataEventArgs eventArgs)
End of inner exception stack trace
at System.Workflow.Activities.WorkflowMessageEventHandler.EventHandler(Object sender, ExternalDataEventArgs eventArgs)
at HighEnergy.WorkflowUtils.WorkflowDataExchangeService.FireCommodityQuoteRequestedEvent(CommodityQuoteRequestedEventArgs eventArgs) in C:\HighEnergy\high_energy\Development\Code\Microsoft\HighEnergy\HighEnergyWorkflowUtils\WorkflowDataExchangeService.cs:line 28
at HighEnergy.Services.TradeService.CreateTrade(TradeVO tradeVO, Int64 contactId) in C:\HighEnergy\high_energy\Development\Code\Microsoft\HighEnergy\HighEnergyServices\TradeService.cs:line 78
at HighEnergy.Services.TradeService.SaveTrade(TradeVO tradeVO, Int64 contactId) in C:\HighEnergy\high_energy\Development\Code\Microsoft\HighEnergy\HighEnergyServices\TradeService.cs:line 47
at TradeService.SaveTrade(TradeVO tradeVO, Int64 contactId) in c:\HighEnergy\high_energy\Development\Code\Microsoft\HighEnergy\HighEnergyWebServices\App_Code\TradeService.cs:line 49
End of inner exception stack trace

Here's the structure of my workflow:

??<StateMachineWorkflowActivity x:Class="HighEnergy.Services.ProcessCommodityQuoteWorkflow"
InitialStateName="ProcessCommodityQuoteWorkflowInitialState"
x:Name="ProcessCommodityQuoteWorkflow"
DynamicUpdateCondition="{x:Null}"
CompletedStateName="ProcessEnd" ...>
<StateActivity x:Name="ProcessingQuoteRequest">
<StateActivity x:Name="ProcessCommodityQuoteWorkflowInitialState" />
<StateActivity x:Name="WaitingForPrice">
<EventDrivenActivity x:Name="ProcessTradePricedEvent">
...
</EventDrivenActivity>
</StateActivity>
<StateActivity x:Name="WaitingForSalesApproval">
<EventDrivenActivity x:Name="ProcessSalesApprovedEvent">
...
</EventDrivenActivity>
</StateActivity>
<EventDrivenActivity x:Name="ProcessCommodityQuoteRequestedEvent">
<HandleExternalEventActivity
Invoked="ValidateAndSaveTrade_Invoked"
x:Name="ValidateAndSaveTrade"
EventName="CommodityQuoteRequestedEvent"
InterfaceType="{x:Type HighEnergy.WorkflowUtils.IWorkflowDataExchangeService}" />
...
</EventDrivenActivity>
</StateActivity>
<StateActivity x:Name="ProcessEnd" />
</StateMachineWorkflowActivity>

Note that the initial state (ProcessCommodityQuoteWorkflowInitialState) is now empty. Its event driven activity is moved up to its parent state.

NareshBhatia at 2007-9-8 > top of Msdn Tech,Software Development for Windows Vista,Windows Workflow Foundation...
# 5

Naresh,

This is because when raising an event on the initial state, the sink must be contained inside the initial state. You'll need to move or copy the event driven back to the initial state.

Arjun

ArjunBanker at 2007-9-8 > top of Msdn Tech,Software Development for Windows Vista,Windows Workflow Foundation...
# 6
Well then that defeats the purpose of why I was trying to do this in the first place. The event driven is applicable to the intial state as well as other states inside the parent state. And hence I wanted it at the parent level. My understanding is that any event driven in a parent state is as if it was copied to all child states.
NareshBhatia at 2007-9-8 > top of Msdn Tech,Software Development for Windows Vista,Windows Workflow Foundation...
# 7

What about factoring out a state C that is a SetState target of the common event activity of A and B that contains the workflow and whose eventdriven event is a delay of 0? Where does A and B go after the event? State C could determine where to return to based on something else in the workflow.

This is a great example of why WF needs a synchronous 'Call Workflow' activity -- workflow refactoring.

JTDSpoons at 2007-9-8 > top of Msdn Tech,Software Development for Windows Vista,Windows Workflow Foundation...
# 8

Very creative! I think this would work. Whether in state A or B, the response to the event is the same including what the next state is. So the next state for state C will remain the same.

I think your suggestion for calling workflows synchronously makes sense. Either that or the state machine implementation should be changed to allow nested states without any activities and have them pick up activities from the parent state.

NareshBhatia at 2007-9-8 > top of Msdn Tech,Software Development for Windows Vista,Windows Workflow Foundation...
# 9

This is exactly what I need as well. I just posted a new thread today on the need to have Hierarchical State Machine support exactly as outlined in the book "Practical Statecharts in C/C++" by Miro Samek. This would get what you want. The parent event handlers and behavior should be inherited by the child states. WF doesn't seem to work that way. You leave child state when receiving a parent state event. This should not happen.

WillSmith at 2007-9-8 > top of Msdn Tech,Software Development for Windows Vista,Windows Workflow Foundation...

Software Development for Windows Vista

Site Classified