Camunda Java外部任务报错:无法反序列化变量中的自定义对象
问题描述
实现Java ExternalTaskHandler处理Camunda外部任务时,返回自定义对象列表作为结果,出现Camunda无法反序列化对象的错误。将MyObject列表替换为String列表时,代码可正常运行。
代码实现
ExternalTaskHandler实现类:
public class MyClass implements ExternalTaskHandler { public void execute(ExternalTask externalTask, ExternalTaskService externalTaskService) { // 构建返回对象 List<MyObject> myObjects = new ArrayList<MyObject>(); myObjects.add(new MyObject()); // 放入响应中 Map<String,Object> returnedObjects = new HashMap<String,Object>(); returnedObjects.put("myObjects", myObjects); // 完成任务——错误发生在此处 externalTaskService.setVariables(externalTask, returnedObjects); } }
自定义对象MyObject:
public class MyObject { private String name; private List<String> values; public String getName() { return name; } public void setName(String name) { this.name = name; } public List<String> getValues() { return values; } public void setValues(List<String> values) { this.values = values; } }
错误信息
TASK/CLIENT-01009 Exception while completing the external task:
The corresponding process instance could not be resumed. Reason: status code: 500, reason phrase:
{"type":"ProcessEngineException","message":"Cannot deserialize object in variable 'returnedObjects': SPIN/JACKSON-JSON-01007 Cannot construct java type from string 'java.util.ArrayList<my.test.MyObject>'","code":0}
解决方案
1. 为自定义对象添加Jackson序列化注解
Camunda默认使用Jackson做JSON序列化,需为MyObject添加类型识别注解,让序列化时记录类型信息:
import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonTypeName; @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "@type") @JsonTypeName("MyObject") public class MyObject { private String name; private List<String> values; // 原有getter/setter保持不变 public String getName() { return name; } public void setName(String name) { this.name = name; } public List<String> getValues() { return values; } public void setValues(List<String> values) { this.values = values; } }
2. 配置Camunda识别自定义类型
方式一:配置文件映射
- XML配置(
camunda.cfg.xml):
<bean id="processEngineConfiguration" class="org.camunda.bpm.engine.impl.cfg.StandaloneProcessEngineConfiguration"> <!-- 其他配置项 --> <property name="spinJsonDataFormatConfigurator"> <bean class="org.camunda.spin.plugin.impl.json.jackson.format.JacksonJsonDataFormatConfigurator"> <property name="typeMappings"> <map> <entry key="MyObject" value="my.test.MyObject"/> </map> </property> </bean> </property> </bean>
- Spring Boot YAML配置(
application.yml):
camunda: bpm: generic-properties: properties: spin.json.type.mapping.MyObject: my.test.MyObject
方式二:代码注册类型映射
在ProcessEngine初始化时注册自定义类型:
import org.camunda.spin.plugin.impl.json.jackson.format.JacksonJsonDataFormat; import org.camunda.spin.spi.DataFormat; import com.fasterxml.jackson.databind.ObjectMapper; // 获取Spin的JSON数据格式实例 DataFormat<?> jsonDataFormat = org.camunda.spin.Spin.getDataFormats().getDataFormat("application/json"); if (jsonDataFormat instanceof JacksonJsonDataFormat) { JacksonJsonDataFormat jacksonFormat = (JacksonJsonDataFormat) jsonDataFormat; ObjectMapper objectMapper = jacksonFormat.getObjectMapper(); // 注册自定义类型 objectMapper.registerSubtypes(MyObject.class); }
3. 确保自定义对象在引擎类路径中
如果MyObject在外部任务客户端项目中,需将该类打包为jar放入Camunda引擎的lib目录,或使用JSON序列化格式(而非Java序列化),避免引擎直接依赖该类。
4. 显式指定变量序列化格式
设置变量时,明确指定使用JSON序列化:
import org.camunda.bpm.engine.variable.Variables; import org.camunda.bpm.engine.variable.value.ObjectValue; // 构建带序列化格式的对象值 ObjectValue objectValue = Variables.objectValue(myObjects) .serializationDataFormat("application/json") .create(); Map<String, Object> returnedObjects = new HashMap<>(); returnedObjects.put("myObjects", objectValue); externalTaskService.setVariables(externalTask, returnedObjects);
内容的提问来源于stack exchange,提问作者87dsf897w6543d54fsdf

