Hi,
We are migrating from java serialization to json serialization with spin & jackson.
I am having some issues figuring out how to serialize & deserialize Map / List variables that contain other Dto objects.
For example:
Map<String, TestDto> map = new HashMap<>();
map.put("testDto", testDto);
runtimeService.setVariable(process.getProcessInstanceId(), "map", map);
Map<String, TestDto> mapAgain = (Map<String, TestDto>) runtimeService.getVariableTyped(process.getProcessInstanceId(), "map").getValue();
This results in:
java.lang.ClassCastException: class java.util.LinkedHashMap cannot be cast to class com.someCompany.TestDto
This is because the type cannot be resolved. The serialized value looks like:
{"testDto": {"someField": "someValue"}}
So what happens is on deserialize the TestDto got deserialized into a LinkedHashMap because the TestDto type got lost. So you end up with a LinkedHashMap<String, LinkedHashMap> instead of Map<String, TestDto>. (LinkedHashMap is probably some jackson fallback default, if I remember correctly)
After lots of google searching, I came to the conclusion that I need to configure the jackson objectmapper used by camunda. (see the reply from thorben in this thread How to properly de-/serialize Collections to JSON - #5 by stefanzilske)
Thus I came up with this config, following the documentation:
public class CamundaJacksonConfiguration implements DataFormatConfigurator<JacksonJsonDataFormat> {
public void configure(JacksonJsonDataFormat dataFormat) {
dataFormat.getObjectMapper()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.activateDefaultTyping(
new LaissezFaireSubTypeValidator(),
ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE,
JsonTypeInfo.As.PROPERTY
);
}
public Class<JacksonJsonDataFormat> getDataFormatClass() {
return JacksonJsonDataFormat.class;
}
}
This makes my test work for both map and list. Though I had to add the jackson FAIL_ON_UNKNOWN_PROPERTIES, otherwise the list deserialization kept failing because it wants to map the type property ‘@class’ but it doesn’t exist on the dto. So it seems it is ignoring the jackson typing?
This is the only configuration that I found that makes the test pass. Changing the JsonTypeInfo.As.?, DefaultTyping.? setting to something else always ends up in serialization / deserialization errors on either the map or the list. (errors SPIN/JACKSON-JSON-01006 / SPIN/JACKSON-JSON-01009)
Also, this solution is still not usable for me because now it brakes things in other places, where we have a list variable that contains a simple map, e.g.: List<Map<String, String>
After deserializing we get the correct structure but the map contains an extra entry:
key: “@class”, value: “java.util.HashMap”
What are the options here?
Also, further info, we are using camunda with spring-boot and the following spin dependencies:
<dependency>
<groupId>org.camunda.spin</groupId>
<artifactId>camunda-spin-dataformat-json-jackson</artifactId>
<version>1.13.0</version>
</dependency>
<dependency>
<groupId>org.camunda.bpm</groupId>
<artifactId>camunda-engine-plugin-spin</artifactId>
</dependency>
So no xml or dataformat-all dependencies.