Avoid serializing object variable right at the beginning of a process

Hi, I am starting a process with message and a variable of a type that cannot be serialized. It keeps a not read inputstream that has to be processed in the next service tasks.

As I didn’t need any variable change history or anything of that kind, I was hoping that the engine wouldn’t attempt to serialize the object before it reached a wait state, when it needed to persist the state in the db or cache; before that the engine should store it in memory a normal object, and by the transaction end I would get rid of it.

In my setup (embedded Camunda engine built with Maven) it turned out not to be the case, the engine tries to serialize the object right ahead. Is there any way to hint the system not to do it?

A quick search of the forum shows that in 2016 it worked as I would expect

Here’s the trace:

Exception in thread "Thread-8" org.camunda.bpm.engine.ProcessEngineException: Cannot serialize object in variable 'streamHolder': .......
at org.camunda.bpm.engine.impl.variable.serializer.AbstractSerializableValueSerializer.writeValue(AbstractSerializableValueSerializer.java:53)
at org.camunda.bpm.engine.impl.variable.serializer.AbstractSerializableValueSerializer.writeValue(AbstractSerializableValueSerializer.java:27)
at org.camunda.bpm.engine.impl.persistence.entity.util.TypedValueField.writeValue(TypedValueField.java:160)
at org.camunda.bpm.engine.impl.persistence.entity.util.TypedValueField.setValue(TypedValueField.java:120)
at org.camunda.bpm.engine.impl.persistence.entity.VariableInstanceEntity.<init>(VariableInstanceEntity.java:118)
at org.camunda.bpm.engine.impl.persistence.entity.VariableInstanceEntity.create(VariableInstanceEntity.java:136)
at org.camunda.bpm.engine.impl.persistence.entity.VariableInstanceEntityFactory.build(VariableInstanceEntityFactory.java:27)
at org.camunda.bpm.engine.impl.persistence.entity.VariableInstanceEntityFactory.build(VariableInstanceEntityFactory.java:21)
at org.camunda.bpm.engine.impl.core.variable.scope.AbstractVariableScope.setVariableLocal(AbstractVariableScope.java:330)
at org.camunda.bpm.engine.impl.core.variable.scope.AbstractVariableScope.setVariable(AbstractVariableScope.java:307)
at org.camunda.bpm.engine.impl.core.variable.scope.AbstractVariableScope.setVariable(AbstractVariableScope.java:289)
at org.camunda.bpm.engine.impl.core.variable.scope.AbstractVariableScope.setVariables(AbstractVariableScope.java:236)
at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl.start(PvmExecutionImpl.java:232)
at org.camunda.bpm.engine.impl.persistence.entity.ExecutionEntity.start(ExecutionEntity.java:431)
at org.camunda.bpm.engine.impl.cmd.AbstractCorrelateMessageCmd.instantiateProcess(AbstractCorrelateMessageCmd.java:62)
at org.camunda.bpm.engine.impl.cmd.CorrelateStartMessageCmd.execute(CorrelateStartMessageCmd.java:63)
at org.camunda.bpm.engine.impl.cmd.CorrelateStartMessageCmd.execute(CorrelateStartMessageCmd.java:32)
at org.camunda.bpm.engine.impl.interceptor.CommandExecutorImpl.execute(CommandExecutorImpl.java:24)
at org.camunda.bpm.engine.impl.interceptor.CommandContextInterceptor.execute(CommandContextInterceptor.java:104)
at org.camunda.bpm.engine.spring.SpringTransactionInterceptor$1.doInTransaction(SpringTransactionInterceptor.java:42)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140)
at org.camunda.bpm.engine.spring.SpringTransactionInterceptor.execute(SpringTransactionInterceptor.java:40)
at org.camunda.bpm.engine.impl.interceptor.ProcessApplicationContextInterceptor.execute(ProcessApplicationContextInterceptor.java:66)
at org.camunda.bpm.engine.impl.interceptor.LogInterceptor.execute(LogInterceptor.java:30)
at org.camunda.bpm.engine.impl.MessageCorrelationBuilderImpl.execute(MessageCorrelationBuilderImpl.java:240)
at org.camunda.bpm.engine.impl.MessageCorrelationBuilderImpl.correlateStartMessage(MessageCorrelationBuilderImpl.java:211)
at org.camunda.bpm.engine.impl.RuntimeServiceImpl.startProcessInstanceByMessage(RuntimeServiceImpl.java:516)
at crm.MessageSystem$ConsumerService$1.run(MessageSystem.java:302)

You can’t avoid that as of 7.8. In 7.9, you can declare transient variables that won’t be serialized, see https://app.camunda.com/jira/browse/CAM-8086.

Hi @thorben, it’ll be great to have the transient variables, but the link doesn’t say anything that they won’t be serialized…

Today, the variables are serialized before the wait state is reached and the variable might need to be persisted. Do you happen to know why the developers decided to design it like that?

I’m joking, but without understanding I may doubt they won’t decide to serialize that transient variables as well :slight_smile:

Since transient variables are already released part of 7.9.0-alpha1, I recommend you try out that version and see if it works the way you want. Btw there are good reasons for immediately serializing the value, e.g. a delegate may access the serialized value of a not yet persisted variable, in case of failure an exception is thrown at the point where the variable is set which is much easier to understand and debug, etc.

1 Like