Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
danielleiszen opened this issue Jun 8, 2023 · 1 comment

Comments

@danielleiszen
Copy link

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
Copy link
Author

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant