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.

Hello @StephenOTT - Did you get a chance to run the project I shared? Please could you advise whether a ticket should be opened up for this issue?

@Hammad_Dar I was able to reproduce the issue stated when we set review=retry

great @aravindhrs , so please advise the way forward here?

@Hammad_Dar in the future it would be much better if you did some trial and error based on the working examples I provided. It feels like you dropped this problem without any basic trial and error testing and working from the known example that was working (the screenshots i shared) and then working step by step to identify your problem…

You problem is you are using an incorrect configuration on your service task. I don’t know why off the top of my head, but when you have Async and it runs as a job, the expression evaluator is acting “differently”.

You can see the behaviour occur if you try and create any variable (such as a basic string) within your Delegate.

.

A common complaint and unresolved UX issue: Impacts of not using Delegate Expression for SpringBoot Java Delegate Resolution needs to be highlighted more clearly in docs!?

Hello @StephenOTT - I have been trying different options but probably in the wrong area. Please note that I am very new to the platform.

Secondly, I cannot say anything but it starts before our Service Task is hit second time. Once the form ins loaded in Task List application and user loads the variables and presses “Complete”, that is where the bytearray is changed and its version is updated from 1 to 2. That is where I was suspicious.

I simply was not expecting this kind of issue which is the basic scenario as far as I see this in the platform. If you could see the title of the issue, you would understand where my energies were targeted towards.

Initially, I thought the change is causing the issue, looked for the JacksonJsonDataFormat and implemented that to see if my object structure is of the issue, then I tried a custom deserializer and once the issue was there after that, then i did a small POC to check the platform in a small application. It has been quite a while since I am trying to wrap my head around it, all the help available over the internet points towards wrong object structure for the error I posted earlier. Lastly I created a working example for you guys to check and I was expecting an issue to be opened up for this if this is the issue. I am definitely missing something if hit and trial was due at my end.

Thank you for your time.

Did changing to “delegateExpression” resolve the problem?

@StephenOTT No it did not, I tried it with DelegateExpression as well, pushed the code as well which I tried. Tried with different Async Before and Async After combinations as well, same result.