UiPath / CoreWF

WF runtime ported to work on .NET 6
MIT License
1.14k stars 218 forks source link

Custom deserializer fails whenever CompiledLocation class is serialized with workflow since it is internal #267

Open danielleiszen opened 1 year ago

danielleiszen commented 1 year ago

We have a workflow that we use in our business logic. We run that workflow using the CoreWF runtime. We have certain custom activities and one of them creates a bookmark and makes the workflow wait for input. In that case the workflow is being serialized. We are using a JSON custom serializer based on your JsonFileInstanceStore example.

Whenever the workflow is persisted, it cannot be loaded back again due to a JSON deserialization error:

Newtonsoft.Json.JsonSerializationException
  HResult=0x80131500
  Message=Unable to find a constructor to use for type System.Activities.XamlIntegration.CompiledLocation`1[Camino.Approval.QuoteArrival]. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute. Path '['{urn:schemas-microsoft-com:System.Activities/4.0/properties}Workflow'].Value.bookmarkMgr.bookmarks.Quote.ActivityInstance.SerializedEnvironment.locations[1].innerLocation.CompiledRootActivityQualifiedId', line 34, position 56.
  Source=Newtonsoft.Json
  StackTrace:
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateNewObject(JsonReader reader, JsonObjectContract objectContract, JsonProperty containerMember, JsonProperty containerProperty, String id, Boolean& createdFromNonDefaultCreator)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   _.... [truncated for the sake of brevity]_
   at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
   at Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader, Type objectType)
   at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings)
   at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings)
   at Camino.Persistency.InMemory.InMemoryInstanceData.Load(InstancePersistenceContext context) in C:\Projects\camino\camino-automation\automation-backend\3_Workflow\Camino.Workflow.Infrastructure\Persistency\InMemory\InMemoryInstanceData.cs:line 101

  This exception was originally thrown at this call stack:
    Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateNewObject(Newtonsoft.Json.JsonReader, Newtonsoft.Json.Serialization.JsonObjectContract, Newtonsoft.Json.Serialization.JsonProperty, Newtonsoft.Json.Serialization.JsonProperty, string, out bool)

The exception occures, since CompiledLocation<> class is internal and there is no default constructor for it. Nonetheless, the serialized workflow contains that type and hence the deserializer mechanism is trying to create an instance of that class.

It would be possible to create a custom serializer if any of our logic could create an instance of the class.

Proposal to elminate the issue:

  1. Please create a default constructor for it, OR
  2. Please make it public, OR
  3. Please create a factory that helps instatiation of the class

The important section of the serialized workflow follows:

{
  "$id": "10",
  "$type": "System.Activities.Location`1+ReferenceLocation[[Camino.Approval.QuoteArrival, Camino.TestClasses]], System.Activities",
  "innerLocation": {
    "$id": "11",
    "$type": "System.Activities.XamlIntegration.CompiledLocation`1[[Camino.Approval.QuoteArrival, Camino.TestClasses]], System.Activities",
...
   }
}

Thank you in advance...

danielleiszen commented 1 year ago

As it turned out for me, checking the codebase - that the default constructor has been added to the class at Oct 12, 2022, however your latest NuGet package is published at 4/1/2022...

So the solution is even more easier than I thought.

Please, update the NuGet package!

Thank you