Object Type changed when updated via TaskList

I have Spring Boot application having embedded BPM Engine and below dependencies in my POM:

Parent POM describes BOMs as below in dependency management:

            <dependency>
				<groupId>org.camunda.bpm</groupId>
				<artifactId>camunda-bom</artifactId>
				<version>7.15.0</version>
				<scope>import</scope>
				<type>pom</type>
			</dependency>
			<dependency>
				<groupId>org.camunda.spin</groupId>
				<artifactId>camunda-spin-bom</artifactId>
				<version>1.10.1</version>
				<scope>import</scope>
				<type>pom</type>
			</dependency>

and child pom defines dependencies below:

        <dependency>
			<groupId>org.camunda.bpm.springboot</groupId>
			<artifactId>camunda-bpm-spring-boot-starter-webapp</artifactId>
		</dependency>
		<dependency>
			<groupId>org.camunda.bpm.springboot</groupId>
			<artifactId>camunda-bpm-spring-boot-starter-rest</artifactId>
		</dependency>
		<dependency>
			<groupId>org.camunda.bpm</groupId>
			<artifactId>camunda-engine-plugin-spin</artifactId>
		</dependency>
		<dependency>
			<groupId>org.camunda.spin</groupId>
			<artifactId>camunda-spin-core</artifactId>
		</dependency>
		<dependency>
			<groupId>org.camunda.spin</groupId>
			<artifactId>camunda-spin-dataformat-json-jackson</artifactId>
		</dependency>

I kick-off a process with below code:

    VariableMap variables = Variables.createVariables()
        .putValueTyped("input",
            Variables.objectValue(myDto).create())
        .putValueTyped("inputArray",
            Variables.objectValue(myDto.getArray()).create()));

    ProcessInstance instance = runtimeService.startProcessInstanceByKey(
        "processName", "processBusinessKey", variables);

In my delegate, I get the variables like below (inputArray is a List of concrete type ArrayList):

ObjectValue myArrayObj = execution.getVariableTyped("inputArray");

@SuppressWarnings("unchecked")
List<MyDto> myArray = (List<MyDto>) orderArrayObj.getValue();

Everything works fine unless I change the value of this variable from TaskList application. My scenario is to show user some values from these variables and in case of certain conditions, allow them to change these values and complete the tasks. Below is the exception I get when this object is changed (change any smallest of the property from TaskList by claiming the task, loading the variables and then without changing the type or anything else, add some text in any existing property of this variable):

Caused by: spinjar.com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type `java.util.ArrayList<MyDto>` from String value (token `JsonToken.VALUE_STRING`)
 at [Source: UNKNOWN; line: -1, column: -1]
	at spinjar.com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:59) ~[camunda-spin-dataformat-all-1.10.1.jar:1.10.1]
	at spinjar.com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1601) ~[camunda-spin-dataformat-all-1.10.1.jar:1.10.1]
	at spinjar.com.fasterxml.jackson.databind.DeserializationContext.handleUnexpectedToken(DeserializationContext.java:1375) ~[camunda-spin-dataformat-all-1.10.1.jar:1.10.1]
	at spinjar.com.fasterxml.jackson.databind.DeserializationContext.handleUnexpectedToken(DeserializationContext.java:1322) ~[camunda-spin-dataformat-all-1.10.1.jar:1.10.1]
	at spinjar.com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.handleNonArray(CollectionDeserializer.java:384) ~[camunda-spin-dataformat-all-1.10.1.jar:1.10.1]
	at spinjar.com.fasterxml.jackson.databind.deser.std.CollectionDeserializer._deserializeFromString(CollectionDeserializer.java:318) ~[camunda-spin-dataformat-all-1.10.1.jar:1.10.1]
	at spinjar.com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:250) ~[camunda-spin-dataformat-all-1.10.1.jar:1.10.1]
	at spinjar.com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:28) ~[camunda-spin-dataformat-all-1.10.1.jar:1.10.1]
	at spinjar.com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:322) ~[camunda-spin-dataformat-all-1.10.1.jar:1.10.1]
	at spinjar.com.fasterxml.jackson.databind.ObjectMapper._readValue(ObjectMapper.java:4569) ~[camunda-spin-dataformat-all-1.10.1.jar:1.10.1]
	at spinjar.com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2867) ~[camunda-spin-dataformat-all-1.10.1.jar:1.10.1]
	at org.camunda.spin.impl.json.jackson.format.JacksonJsonDataFormatMapper.mapInternalToJava(JacksonJsonDataFormatMapper.java:98) ~[camunda-spin-dataformat-all-1.10.1.jar:1.10.1]
	... 110 common frames omitted

Any help would be much appreciated.

Thanks

Addition:

From the TaskList application, claiming a task and then clicking on “load variables” which are saved already and only hitting “Complete” button without any change raises this issue as well. I am not sure whether its a platform issue or something is missing at my end.

Edit#2: When any Variable of type object is loaded in TaskList, it is changing it into string. JacksonJsonDataFormatReader is returning TextNode instead of the actual type. This is the reason once these objects are loaded in TaskList after pressing “Claim” button, custom object types are changed and Deserialization error is thrown by Jackson.

Is this an issue in Camunda 7.15.0 or I am missing something here?

Awaiting anxiously, dear community.

Thanks.

@Ingo_Richtsmeier and @StephenOTT need your help and advice please if you possibly can?

Once i click the “Load Variables” in the task, it loads the variables and data is obviously, which is json, contains escaped characters and then once this data goes to server, it overwrites the data in the database and is treated as String rather than object.

My use case is simplest of the one, created a process and added variables into it, created a User Task and then in that task, loaded the variables and without changing anything, pressed “Complete”. I see in the database as well that Byte Array gets updated for that variable and then deserialization in any subsequent service task fails.

Repeat the steps (simplest version) that causes the issue and use the Browser’s network inspect to look at the Request and Response urls and objects being sent/received. Validate if a variable update is being sent and/or on complete it is submitting your json variable as a String. Share your findings.

Thank you for your reply, yes I did that. This is the URL which is being used:

/api/engine/engine/default/task/–task-id–>/submit-form:

Debugged the process and it is updating the variables. When the form is loaded in the browser, escapes the json and that is probably causing the change. The type is properly loaded in the task list default form but somehow its not being handled properly on the server may be due to some missing piece.

Here are the values being submitted as part of the above form submission:

“orderArray”: {
“type”: “Object”,
“value”: “”[{\“id\”:null,\“updateRegistry\”:true,\“reference\”:\“580276337\”,\“payload\”:null,\“serviceType\”:null,\“callRequestJson\”:null,\“status\”:null,\“type\”:\"\",\“msg\”:null,\“remedyTicket\”:false,\“loginTransId\”:\“464769244\”,\“isChangePlan\”:true,\“originator\”:null,\“originTransactionId\”:null,\“serviceRequestId\”:null,\“friendlyName\”:null,\“accountId\”:null,\“orderStatusDate\”:\“11-11-2020 12:33:22\”,\“reqContent\”:\"[Etisalat UAE] Order Submitted\",\“destRefNum\”:\“580276337\”,\“destRespCode\”:\“200\”,\“destName\”:\“TIBCO\”,\“servDesc\”:\“SaaS service\”,\“transStatus\”:\“0\”,\“subChannelName\”:\“NA\”,\“categoryCode\”:\“Notification\”,\“destRespDesc\”:\"\",\“errorCode\”:null,\“errorDescription\”:null,\“addOn\”:null,\“channel\”:\“BCRM\”,\“tenantId\”:null,\“backendIsvName\”:\“esd\”,\“freeTrial\”:false,\“freeTrialPeriod\”:0,\“registrationType\”:null,\“expiryDate\”:null,\“otc\”:\“0\”,\“rentalCost\”:\“300\”,\“isDiscountApplied\”:false,\“discountObj\”:[],\“callBackReceivedAlready\”:\“FAILED\”,\“assignedSupportGroup\”:\"\",\“customJson\”:{\“email\”:\“dummy@dggd.com\”,\“mobileNumber\”:\“971563546675\”,\“firstName\”:\“DummyFirst\”,\“lastName\”:\“DL\”,\“domain\”:null,\“customerUniqueId\”:null,\“companyName\”:\“RA1\”,\“contactName\”:null},\“remedyTicketDomain\”:null,\“samlUserInfo\”:{\“userName\”:\“Dummy\”,\“userEmail\”:\“dummy@gmail.com\”},\“isv_name\”:\“ESD\”,\“id_customer\”:104,\“company_id\”:104,\“company_name\”:\“RA1\”,\“id_order\”:2005,\“portal_product_id\”:1390,\“idp_account_id\”:\“780031130\”,\“product_id\”:null,\“product_name\”:\“Light\”,\“channelPartnerOrderID\”:\“ORD-771753-S2T0B1_029\”,\“updatedFromETL\”:\“1\”,\“transactionID\”:\“580276337\”,\“idp_account_no\”:\“026320768\”,\“templateID\”:\“17\”,\“agentUserID\”:\“NA\”,\“usage_type\”:\“recurring\”,\“offer_id\”:\“PC000102\”,\“offer_type\”:\“R\”,\“offer_code\”:\“RPSAAS001\”,\“party_id\”:\“21418875\”,\“product_quantity\”:1,\“portal_product_name\”:\“Light\”,\“subscription_id\”:13,\“cfx_subscription_id\”:1347,\“license_quantity\”:null,\“id_order_detail\”:2213,\“id_cart_rule\”:null,\“UpdateLicenceFlag\”:\“YES\”,\“glcode_otc\”:\“A000.15209.500101\”,\“glcode_mrc\”:\“A000.15209.500101\”,\“glcode_usage\”:\“A000.15209.500101\”,\“glcode_discount\”:\“A000.15209.500101\”,\“idp_customer_id\”:\“B2128334\”,\“contact_email\”:\“dummy@gmail.com\”,\“contact_phone\”:\“022222222\”,\“domain_prefix\”:\"\"}]"",
“valueInfo”: {
“objectTypeName”: “java.util.ArrayList<my.dto.AbcDto>”,
“serializationDataFormat”: “application/json”
}
}

Following these steps: I am unable to reproduce your bug:

var myJson = S(’{“someKey”:“someValue”,“someOtherKey”:“someOtherValue”}’)

Running on 7.15.

The JSON variables do not load without a pre-defined form.

and the submission does not contain any re-written json:

and we can see in cockpit that everything is still working:

Let me create a small project for you to see in GitHub.

@StephenOTT please see if you could clone: GitHub - hammad-k-dar/camunda-poc: POCs related to Camunda

Cockpit user/pass: demo/demo
URL to start process: http://localhost:8080/start

It has embedded H2 database so nothing else should be required. Please do check application.properties as i have some properties added for Camunda, which should not be problematic as well.

Once you start the process, it will print dto values and move the process to User Task. Just open the task in TaskList and:

  1. Add new variable named as “review” of type String and give value “retry”.
  2. Press Load Variables button but do not do anything with the json value.
  3. Complete

See the console as our delegate tries to get the value pulled up and crashes.

Thank you once again for your time, really appreciated.

Thanks

class MyTest implements JavaDelegate{

    @Override
    void execute(DelegateExecution execution) throws Exception {

        def myMap = new HashMap()
        myMap.put("someKey", "SomeValue")

        def myVar = Variables.objectValue(myMap).serializationDataFormat(Variables.SerializationDataFormats.JSON).create()
        execution.setVariable("myJson", myVar)
    }
}

Looks fine.

What behaviour is unexpected for you based on my images above?

@StephenOTT did you check the project i created? May be accessing the variable again from the Java Delegate is the problem, what do you think? You need to create a service task and then get the variable from the DelegateExecution. Probably it works fine in your case but it crashes straight-forwardly in the project i shared.