João Ricardo Pereira

Hi,

For example I have this activities in the workflow:

Start
CodeActivity1
HandleExternalActivity1
CodeActivity2
HandleExternalActivity2
CodeActivity3
End

What I want is to handle possible exceptions that may occur in the code activity's...

For example, I start the workflow and it will wait for a event. When the event HandleExternalActivity1 arrives, it will execute the CodeActivity2.
If any error occurs inside CodeActivity2, I want to suspend the execution, and return to the previous state, that is wait for event HandleExternalActivity1 to arrive again...
Is this possible and how can I do it

And what if the error occurs in the CodeActivity1 Can I handle the exception and run the same workflow again with other input values or objects, or it's better to just dump this instance and start a new one

Thanks in advance



Re: Windows Workflow Foundation About Exception Handlers and RollBacks

SonaliC

If an exception occurs in codeactivity, only way you can handle it is using try-catch block. However you will not be able to influence execution of the workflow from code activity. One option is to add codeactivity to a sequence and handle the exception in the faulthandlersactivty of the sequence

So your workflow could be like this

Declare a variable bool repeat = true in codebeside file
Start
CodeActivity1
While ( repeat == true)
HandleExternalActivity1
Sequence1
CodeActivity2 (Set repeat = false at the end of your code)
FaultHandlersActivity
FaultHandlerActivity (Handle System.Exception or whatever is your exception. Add activities to do any other processing)
CodeActivity4 (Set repeat = true, to continue the while loop in case of exception)
IfElseActivity( If repeat == false ) //Go here only if codeactivity1 completed successfully
HandleExternalActivity2
Sequence2
CodeActivity3
FaultHandlersActivity
FaultHandlerActivity (Handle System.Exception or whatever is your exception. Add activities to do any other processing)
CodeActivity5 (Set repeat = true, to continue the while loop)

End


CodeActivity4 and 5 can point to the same codehandler.

WF provides activities like TransactionScope, CompensatableTransactionScope and CompensatableSequence to handle the rollbacks and compensation of a completed task. You might find these activities useful for your scenario

http://msdn2.microsoft.com/en-us/library/ms733615.aspx






Re: Windows Workflow Foundation About Exception Handlers and RollBacks

Joao Ricardo Pereira

Hi SonaliC,

Thank you for helping me out.

Ok. I managed to set up the workflow as you mentioned above.
The only difference is that I use a TransactionScopeActivity instead of a SequenceActivity.
I force a error to occur in the CodeActivity and throw one of our custom exception.
I catch it in the FaultHandlersActivity and do what I want in a CodeActivity.

The problem now is that when it finishes executing the CodeActivity of the FaultHandlerActivity it persists the workflow and then COMPLETES the workflow (I subscribed to all events just for debugging).
I set the UnloadOnIdle to false for convenience and use ManualWorkflowSchedulerService because this is an ASP.NET app.
I understand why it persists before completion, but why it completes I can't figured it out.

Am I supposed to do anything more


Here are the samples of the code I use:
where the exception is raised inside a CodeActivity:

if (StockItemDeliveryFactory.Insert(item, Au.UserName))
{
throw new SIADBAccessException("Distribution", "OrderDistribution", "StockItemDelivery", "", "StockItemDeliveryFactory.Insert");
}

(StockItemDeliveryFactory.Insert returns true if it succeeds, and I omitted the NOT! just for testing)

and the code of the FaultHandlers CodeActivity:

void FaultHandler_ExeCode(object sender, EventArgs e)
{
repeat = true;
............
}



I have a few more questions:

- For state machine workflows, the schema is the same but I don't need the while activity's, it works if in the FaultHandlers I use a SetState to point the path to where I want it, right

- In the schema you mentioned above, if the error occurs in CodeActivity1, the best solution is to handle the exception in the FaultHandlers and terminate the workflow, and start a new one on a new submission. Do you have a better or "cleaner" solution

Thanks in advance again, and I appreciate your support.





Re: Windows Workflow Foundation About Exception Handlers and RollBacks

SonaliC

If there are no more activities in the workflow, it will complete. Do you mean there are some activities in the execution path and workflow is completing without executing them

About your other question, Statemachine is better suited for your scenario. So your solution with statemachine should work fine.






Re: Windows Workflow Foundation About Exception Handlers and RollBacks

Joao Ricardo Pereira

I have other workflows in the solution that are statemachine... But this ones, because of it simplicity, i'd like to keep them sequential...

SonaliC wrote:

Do you mean there are some activities in the execution path and workflow is completing without executing them



Yes! What I mean is exactly that!
I even forced an exception in the first CodeActivity and the workflow still completes without executing the rest of the activities!





Re: Windows Workflow Foundation About Exception Handlers and RollBacks

Pedro Pita

Viva ;-)

I don't know the cause for your specific problem but one advice I can give you is to turn on logging on the app/web config. It can be very helpful (i once lost about 5 hours because of some lost exception in the runtime...)

<system.diagnostics>
<switches>
<add name="System.Workflow LogToTraceListeners" value="1" />

<add name="System.Workflow.Runtime" value="Error" />
<add name="System.Workflow.Runtime.Hosting" value="Error" />
<add name="System.Workflow.Runtime.Tracking" value="Error" />
<add name="System.Workflow.Activities" value="Error" />
<add name="System.Workflow.Activities.Rules" value="Error" />

</switches>
<trace autoflush="true" indentsize="4">
<listeners>
<add name="customListener" type="System.Diagnostics.TextWriterTraceListener" initializeData="X:\somewhere\WFTrace.log" />
</listeners>
</trace>
</system.diagnostics>


There are more levels of logging for the sources, you can check them here:

http://msdn2.microsoft.com/en-us/library/ms732240.aspx (Enabling Workflow Logging)

Sorry if you already knew about this, but since it helped me a lot thought it would be relevant.

Cumprimentos,
Pedro Pita




Re: Windows Workflow Foundation About Exception Handlers and RollBacks

Joao Ricardo Pereira

Boas! ;P

I've already read about this, but I never actually used it!

I used it now, but the only logging that was made is this:

System.Workflow.Runtime Error: 1 : Execute of Activity OrderDistribution threw SIA.BusinessExceptions.SIADBAccessException: Error in the application.
at SIA.BusinessWorkflows.Distribution.OrderDistribution_ExeCode(Object sender, EventArgs e) in E:\Projectos\SIA\Solution_12_07_2007_v2\BusinessWorkflows\Distribution.designer.cs:line 313
at System.Workflow.ComponentModel.Activity.RaiseEvent(DependencyProperty dependencyEvent, Object sender, EventArgs e)
at System.Workflow.Activities.CodeActivity.Execute(ActivityExecutionContext executionContext)
at System.Workflow.ComponentModel.ActivityExecutor`1.Execute(T activity, ActivityExecutionContext executionContext)
at System.Workflow.ComponentModel.ActivityExecutor`1.Execute(Activity activity, ActivityExecutionContext executionContext)
at System.Workflow.ComponentModel.ActivityExecutorOperation.Run(IWorkflowCoreRuntime workflowCoreRuntime)



When I set the log to All, I get lots of info, but what I can get from here, is that it handles the exception I raised, it returns the execution, and then the activity Distribution (workflow itself) seems to fault also... Indifferent

My workflow now looks like this
Start
TransactionScope3
OrderDistribution(CodeActivity)
ProcessOutgoingActivity(HandleExternalActivity)
TransactionScope2
UpdateOutgoingStock(CodeActivity)
ProcessIncomingActivity(HandleExternalActivity)
TransactionScope3
UpdateIncomingStock(CodeActivity)
End

DistributionFaultHandlers
FaultHandlerDBAccess
FaultHandlerDBAccessCodeActivity(CodeActivity)


I'm raising an exception in the OrderDistribution(CodeActivity). Indifferent





Re: Windows Workflow Foundation About Exception Handlers and RollBacks

Joao Ricardo Pereira

Ok... That was I just beeing dumb! Sorry!

It works fine now. I didn't understand why you used a SequenceActivity, I thought that it was because of the WhileActivity, because I can't put a HandleExternalActivity and a CodeActivity inside a WhileActivity, without grouping them with a SequenceActivity or a TransactionalScopeActivity...
The problem is that the TransactionalScope doesn't support fault handlers, so I thought that I was supposed to used the global FaultHandler...

If we treat the exception in the global FaultHandlers it finishes the execution of the workflow without executing any more activities, in a "cleaner" way (Completed).

One last question now...

My workflow now is like this:

Start
SequenceActivity1
TransactionScope1
CodeActivity1
FaultHandlersActivity1
FaultHandlerActivity1
CodeActivity4
WhileActivity1 (repeat == true)
TransactionScope2
HandleExternalActivity1
CodeActivity2
FaultHandlersActivity2 (from WhileActivity1)
FaultHandlerActivity2
CodeActivity5
WhileActivity2 (repeat2 == true)
TransactionScope3
HandleExternalActivity2
CodeActivity3
FaultHandlersActivity3 (from WhileActivity2)
FaultHandlerActivity3
CodeActivity6
End

Is it correct to have a Activity's inside a TransactionScopeActivity, that is inside a SequenceActivity

It sounds a little messy... but I think it's the best thing to do... Do you agree





Re: Windows Workflow Foundation About Exception Handlers and RollBacks

SonaliC

While activity can have only single child, so we typically add a sequence to it and then add other activities to the sequence. It is absolutely fine to nest activities they way you want. If it is not our compiler will give a sematic error.

Why do you need to add codeactivity to TransactionScope TransactionScope should be typically used if you want to execute multiple tasks within the same transaction. One thing to keep in mind is transaction associated with the TransactionScope might timeout if your event does not arrive within the timeout of the TransactionScope and throw an exception.