Tuesday, July 21, 2009

Workflow persistence and FaultHandler


I´m currently working an a quite big project, atm all alone. The purpose of the system im developing is to safely transfer/fetch/push data from business to business (B2B) with web services according to a securityspecification used by many well known insurencebusinesses in Sweden.

The problem I´ve stumbled into generates no matches on google search. My setup is as follows:
I got a workflow runtime running workflows that each represent a transaction of message between companies. Each workflow has a bunch of SendActivity/ReceiveActivities used to communicate to the other company but also to local so interests (the system takes no interest in what it send/receive).

Of of the many bugs I´ve found is when using a SendActivity or a CodeActivity which throws an MessageSecurityException (the bug is not likely to be restricted to that exception though) and having a FaultHandlerActivity catching the FaultException from the WCF call.



The first problem is that the Fault property of the FaultHandler is null making it totaly useless (mind FaultType is not null).. the second problem is when trying to presist the workflow after received exception. The latter generates the following exception:



Inner exception: System.Workflow.Runtime.Hosting.PersistenceException: Type 'System.ServiceModel.Channels.ReceivedFault' in Assembly 'System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' is not marked as serializable. ---> System.Runtime.Serialization.SerializationException: Type 'System.ServiceModel.Channels.ReceivedFault' in Assembly 'System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' is not marked as serializable.
at System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers(RuntimeType type)
at System.Runtime.Serialization.FormatterServices.GetSerializableMembers(Type type, StreamingContext context)
at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberInfo()
at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter)
at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.Serialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter)
at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Write(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo)
at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph)
at System.Workflow.ComponentModel.Activity.Save(Stream stream, IFormatter formatter)
at System.Workflow.ComponentModel.Activity.Save(Stream stream)
at System.Workflow.Runtime.Hosting.WorkflowPersistenceService.GetDefaultSerializedForm(Activity activity)
at System.Workflow.Runtime.Hosting.SqlWorkflowPersistenceService.SaveWorkflowInstanceState(Activity rootActivity, Boolean unlock)
at System.Workflow.Runtime.WorkflowExecutor.Persist(Activity dynamicActivity, Boolean unlock, Boolean needsCompensation)
--- End of inner exception stack trace ---
at System.Workflow.Runtime.WorkflowExecutor.Persist(Activity dynamicActivity, Boolean unlock, Boolean needsCompensation)
at System.Workflow.Runtime.WorkflowExecutor.ProtectedPersist(Boolean unlock)


The reason for this problem is according to the exception that serialization is unpossible but why in the world is the SqlPersistenceService trying to save the FaultHandlerActivity? And how can I avoid it?

  • the easiest workaround is not to idle (atm I have a DelayActivity and PersistOnIdle="true").
  • or just dont use FaultHandlerActivity for catching WCF faults - but then I cannot use the SendActivity and has to do all proxymanagement in "workflow behind"
I´ve also tried to get feedback from WCF Forum in this thread.

Updated!

Ok, I´ve now given up finding a solution to this problem. I now manually create proxys from each workflow and handle the exception in code - making it much much much slower than the proxymanagement available through the ChannelManagerService. Unfortunately one cannot fetch the opened channels from the manager because it only contains internal classes...

No comments: