You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Camunda REST API创建List<Inventory>类型表单字段

解决Camunda FormField自定义List类型解析异常的方案

刚遇到这个问题的时候我也踩过坑——Camunda的内置表单字段类型确实不支持直接写List<org.example.Inventory>这种泛型自定义类,这就是你看到ENGINE-09005错误的核心原因。结合你偏好纯HTML表单、只用Camunda REST API的需求,给你两个可行的方案:

方案1:用String类型中转JSON(简单易上手)

因为Camunda能直接处理字符串变量,我们可以把Inventory列表转成JSON字符串提交,再在流程里解析成对象:

  1. 修改BPMN的formField配置:
    把type设为string,给字段起个明确的ID,比如inventoriesJson:
    <userTask id="inventoryTask" name="Inventory Task">
      <camunda:formFields>
        <camunda:formField id="inventoriesJson" label="Inventory Data" type="string" />
      </camunda:formFields>
    </userTask>
    
  2. HTML表单处理:
    在你的HTML表单里,用JavaScript把要提交的Inventory数组转成JSON字符串,赋值给隐藏的表单字段(这种场景用隐藏域更合适,避免用户误编辑):
    <form id="inventoryForm">
      <!-- 其他表单元素 -->
      <input type="hidden" name="inventoriesJson" id="inventoriesJson">
      <button type="submit">Submit</button>
    </form>
    
    <script>
      // 假设你已经有了要提交的inventory数组
      const inventories = [{"name": "banana","count": 3},{"name":"orange","count": 4}];
      // 转成JSON字符串赋值给隐藏域
      document.getElementById('inventoriesJson').value = JSON.stringify(inventories);
    
      // 提交表单到Camunda的submit-form接口
      document.getElementById('inventoryForm').addEventListener('submit', async (e) => {
        e.preventDefault();
        const formData = new FormData(e.target);
        const variables = Object.fromEntries(formData.entries());
        const taskId = '你的任务ID'; // 替换成实际的任务ID
        await fetch(`/task/${taskId}/submit-form`, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ variables })
        });
      });
    </script>
    
  3. 流程内解析JSON:
    在流程的后续步骤(比如用ExecutionListener或者JavaDelegate)里,把字符串解析成List<Inventory>:
    import com.fasterxml.jackson.core.type.TypeReference;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import org.camunda.bpm.engine.delegate.DelegateExecution;
    import org.camunda.bpm.engine.delegate.JavaDelegate;
    import java.util.List;
    
    public class ParseInventoryDelegate implements JavaDelegate {
      @Override
      public void execute(DelegateExecution execution) throws Exception {
        String json = (String) execution.getVariable("inventoriesJson");
        ObjectMapper mapper = new ObjectMapper();
        // 注意这里要和你的JSON字段对应,或者给Inventory类加@JsonProperty注解
        List<Inventory> inventories = mapper.readValue(json, new TypeReference<List<Inventory>>(){});
        execution.setVariable("inventories", inventories);
      }
    }
    

方案2:用generic类型直接映射(更优雅)

Camunda的generic类型支持自定义复杂对象,只要配置正确的类型信息,就能直接把提交的JSON数组映射成List<Inventory>:

  1. 修改BPMN的formField配置:
    把type设为generic,并通过property指定valueType为你的泛型类型(注意XML里要转义<为&lt;):
    <userTask id="inventoryTask" name="Inventory Task">
      <camunda:formFields>
        <camunda:formField id="inventories" label="Inventory List" type="generic">
          <camunda:properties>
            <camunda:property name="valueType" value="java.util.List&lt;org.example.Inventory&gt;" />
          </camunda:properties>
        </camunda:formField>
      </camunda:formFields>
    </userTask>
    
  2. 调整JSON字段名匹配:
    你提交的JSON里用的是name和count,但你的Inventory类字段是objectName和objectCount,这会导致映射失败。解决方法二选一:
    • 把提交的JSON改成{"objectName": "banana","objectCount": 3};
    • 给Inventory类的字段加Jackson的@JsonProperty注解,对应JSON的键:
      import com.fasterxml.jackson.annotation.JsonProperty;
      
      public class Inventory {
        @JsonProperty("name")
        private String objectName;
        @JsonProperty("count")
        private int objectCount;
        // getters and setters
      }
      
  3. HTML表单提交:
    直接按照你原来的格式提交JSON到/task/{id}/submit-form接口即可,Camunda的REST API会自动帮你把JSON数组转成List<Inventory>变量:
    <form id="inventoryForm">
      <button type="submit">Submit</button>
    </form>
    
    <script>
      document.getElementById('inventoryForm').addEventListener('submit', async (e) => {
        e.preventDefault();
        const taskId = '你的任务ID';
        const payload = {
          "inventories" : [{"name": "banana","count": 3},{"name":"orange","count": 4}]
        };
        await fetch(`/task/${taskId}/submit-form`, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(payload)
        });
      });
    </script>
    

关键注意点

  • 确保Inventory类在Camunda的类路径下:如果是把Camunda Engine嵌入你的REST应用,只要你的Inventory类在应用的classpath里就没问题;如果是独立的Camunda服务器,需要把包含Inventory类的JAR包放到Camunda的lib目录下。
  • 序列化兼容性:Inventory类需要有默认无参构造器,并且getter/setter方法完整,这样Camunda的ObjectMapper才能正确序列化/反序列化。

内容的提问来源于stack exchange,提问作者niceman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:08:59