jlucansky / Camunda.Api.Client

Camunda REST API Client for .NET platform
MIT License
141 stars 77 forks source link

JsonSerializationException when dealing with Json objects in external tasks #5

Closed SamuelMeza closed 6 years ago

SamuelMeza commented 7 years ago

When working with embedded javascript in camunda, it seems that the best way to deal with strings that represent json objects is to convert them with the spin method "S()" and storing them in the format returned by this method, in the camunda rest api this types of objects are returned with a type of "Json" like in the example:

 "Item":
                {
                    "type": "Json",
                    "value": "{"ItemType":0,"Format":"","SourceFormat":9,"SourcePath":"\\\\LOCALHOST\\pathtofile\file.txt","Sample":1,"number":2,"allow":true},"SampleDetails":null}",
                    "valueInfo":
                    {
                    }
                }

This representation will result in an exception when trying to pull an external task using the library as it cannot find a type of Json, I believe this is a bug as the library should be able to figure out that the Json type served by camunda is basically a string.

Exception bellow.


System.AggregateException occurred
  HResult=-2146233088
  Message=One or more errors occurred.
  Source=mscorlib
  StackTrace:
       at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
       at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
       at System.Threading.Tasks.Task`1.get_Result()
       at IN.Infrastructure.Workflow.Impl.CamundaWorkflowConsumer.Acquire() in e:\IN\IN.Infrastructure\IN.Infrastructure.Workflow\Impl\CamundaWorkflowConsumer.cs:line 97
  InnerException: 
       HResult=-2146233088
       Message=Error converting value "Json" to type 'Camunda.Api.Client.VariableType'. Path '[0].variables.DistributionItem.type', line 1, position 773.
       Source=Newtonsoft.Json
       StackTrace:
            at Newtonsoft.Json.Converters.StringEnumConverter.ReadJson(JsonReader reader, Type objectType, Object existingValue, JsonSerializer serializer)
            at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.DeserializeConvertable(JsonConverter converter, JsonReader reader, Type objectType, Object existingValue)
            at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
            at Newtonsoft.Json.Serialization.JsonSerializerProxy.DeserializeInternal(JsonReader reader, Type objectType)
            at Camunda.Api.Client.VariableValue.VariableValueJsonConverter.PopulateMember(String memberName, JsonReader reader, JsonSerializer serializer, Object target)
            at Camunda.Api.Client.VariableValue.VariableValueJsonConverter.ReadJson(JsonReader reader, Type objectType, Object existingValue, JsonSerializer serializer)
            at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.DeserializeConvertable(JsonConverter converter, JsonReader reader, Type objectType, Object existingValue)
            at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateDictionary(IDictionary dictionary, JsonReader reader, JsonDictionaryContract contract, JsonProperty containerProperty, String id)
            at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
            at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
            at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target)
            at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)
            at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
            at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
            at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateList(IList list, JsonReader reader, JsonArrayContract contract, JsonProperty containerProperty, String id)
            at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateList(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue, String id)
            at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
            at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
            at Newtonsoft.Json.JsonSerializer.DeserializeInternal(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 Refit.RequestBuilderImplementation.<>c__DisplayClass12_0`1.<<buildCancellableTaskFuncForMethod>b__0>d.MoveNext()
         --- End of stack trace from previous location where exception was thrown ---
            at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
            at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
            at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
            at IN.Infrastructure.Workflow.Impl.CamundaClientContainer.<FetchAndLock>d__d.MoveNext() in e:\IN\IN.Infrastructure\IN.Infrastructure.Workflow\Impl\CamundaClientContainer.cs:line 60
         --- End of stack trace from previous location where exception was thrown ---
            at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
            at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
            at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
            at IN.Infrastructure.Workflow.Impl.CamundaWorkflowConsumer.<AcquireAsync>d__2.MoveNext() in e:\IN\IN.Infrastructure\IN.Infrastructure.Workflow\Impl\CamundaWorkflowConsumer.cs:line 149
       InnerException: 
            HResult=-2147024809
            Message=Requested value 'Json' was not found.
            Source=mscorlib
            StackTrace:
                 at System.Enum.EnumResult.SetFailure(ParseFailureKind failure, String failureMessageID, Object failureMessageFormatArgument)
                 at System.Enum.TryParseEnum(Type enumType, String value, Boolean ignoreCase, EnumResult& parseResult)
                 at System.Enum.Parse(Type enumType, String value, Boolean ignoreCase)
                 at Newtonsoft.Json.Utilities.EnumUtils.ParseEnumName(String enumText, Boolean isNullable, Type t)
                 at Newtonsoft.Json.Converters.StringEnumConverter.ReadJson(JsonReader reader, Type objectType, Object existingValue, JsonSerializer serializer)
            InnerException: 
jlucansky commented 7 years ago

Hello,

if you looked at implementation of type resolver there is no Json type defined. Maybe all undefined values should be approached like Object? Will that be convenient for you?

SamuelMeza commented 7 years ago

Hey,

I am actually converting the json object to a string and limiting the variables returned by the rest api to get around this situation, but I do wonder if this should be supported somehow as the usage of json objects when saving data seems to be a thing on camunda, I will take a look later and see if I can suggest something :)

joelhess commented 6 years ago

I'm seeing the same thing, and would think that if you can't do anything else to it then returning an object would be preferable to the exception that is returned today. Otherwise, if you can see that it's JSON, returning it as a string would be nice too.

flyingpie commented 6 years ago

@jlucansky The "Json" type comes from the Spin plugin: https://github.com/camunda/camunda-bpm-platform/blob/master/engine-plugins/spin-plugin/src/main/java/org/camunda/spin/plugin/variable/type/JsonValueType.java

We encountered this very issue before, I've fixed it here: https://github.com/flyingpie/Camunda.Api.Client/pull/2/files

Want a PR?

jlucansky commented 6 years ago

Thank you PR will be awesome

flyingpie commented 6 years ago

@jlucansky Here you go https://github.com/jlucansky/Camunda.Api.Client/pull/25

No pressure, take a look whenever you have the time :)

jlucansky commented 6 years ago

Merged. You have now option to specify deserializeValue = false when reading variables.