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

使用JAXB反序列化BPMN XML为Java对象时遇命名空间错误

解决Camunda BPMN XML JAXB反序列化命名空间不匹配错误

问题场景

从Camunda引擎获取BPMN XML响应,使用JAXB Unmarshaller将XML字符串转换为Java对象时,触发命名空间不匹配错误。

错误日志

Exception in thread "main" jakarta.xml.bind.UnmarshalException: unexpected element (uri:"http://www.omg.org/spec/BPMN/20100524/MODEL", local:"definitions"). Expected elements are <{}bpmn:definitions>
    at org.glassfish.jaxb.runtime.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:701)
    at org.glassfish.jaxb.runtime.v2.runtime.unmarshaller.Loader.reportError(Loader.java:230)
    at org.glassfish.jaxb.runtime.v2.runtime.unmarshaller.Loader.reportError(Loader.java:225)
    at org.glassfish.jaxb.runtime.v2.runtime.unmarshaller.Loader.reportUnexpectedChildElement(Loader.java:92)
    at org.glassfish.jaxb.runtime.v2.runtime.unmarshaller.UnmarshallingContext$DefaultRootLoader.childElement(UnmarshallingContext.java:1106)
    at org.glassfish.jaxb.runtime.v2.runtime.unmarshaller.UnmarshallingContext._startElement(UnmarshallingContext.java:531)
    at org.glassfish.jaxb.runtime.v2.runtime.unmarshaller.UnmarshallingContext.startElement(UnmarshallingContext.java:513)
    at org.glassfish.jaxb.runtime.v2.runtime.unmarshaller.SAXConnector.startElement(SAXConnector.java:137)
    at java.xml/com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:518)
    at java.xml/com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(XMLNSDocumentScannerImpl.java:374)
    at java.xml/com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl$NSContentDriver.scanRootElementHook(XMLNSDocumentScannerImpl.java:613)
    at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:3079)

待解析的XML示例

<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:modeler="http://camunda.org/schema/modeler/1.0" id="Definitions_1xqdoqa" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.13.0" modeler:executionPlatform="Camunda Platform" modeler:executionPlatformVersion="7.19.0">
  <bpmn:process id="Process2" isExecutable="true" camunda:historyTimeToLive="1">
    <bpmn:userTask id="Activity_0r63cqs">
      <bpmn:incoming>Flow02</bpmn:incoming>
      <bpmn:outgoing>Flow_0xsmp8q</bpmn:outgoing>
    </bpmn:userTask>
    <bpmn:userTask id="Activity_0e7h96z">
      <bpmn:extensionElements>
        <camunda:taskListener class="ir.edmp.camunda.listeners.EDMPTaskCreateListener" event="create">
          <camunda:field name="assigneeType">
            <camunda:string>Static</camunda:string>
          </camunda:field>
          <camunda:field name="assigneeApproach">
            <camunda:string>admin_platform</camunda:string>
          </camunda:field>
        </camunda:taskListener>
....
</bpmn:definitions>

原Java实体类(BPMNDefinitions)

@XmlRootElement(name = "bpmn:definitions")
public class BPMNDefinitions {
    private String bPMN;
    private String xPMNDI;
    private String dC;
    private String camunda;
    private String xSI;
    private String dI;
    private String modeler;
    private String id;
    private String targetNameSpace;
    private String exporter;
    private String exporterVersion;
    private String executionPlatform;
    private String executionPlatformVersion;

    public String getbPMN() {
        return bPMN;
    }

    @XmlAttribute
    public void setbPMN(String bPMN) {
        this.bPMN = bPMN;
    }

    public String getxPMNDI() {
        return xPMNDI;
    }
    @XmlAttribute
    public void setxPMNDI(String xPMNDI) {
        this.xPMNDI = xPMNDI;
    }

    public String getdC() {
        return dC;
    }
    @XmlAttribute
    public void setdC(String dC) {
        this.dC = dC;
    }

    public String getCamunda() {
        return camunda;
    }
    @XmlAttribute
    public void setCamunda(String camunda) {
        this.camunda = camunda;
    }

    public String getxSI() {
        return xSI;
    }
    @XmlAttribute
    public void setxSI(String xSI) {
        this.xSI = xSI;
    }

    public String getdI() {
        return dI;
    }
    @XmlAttribute
    public void setdI(String dI) {
        this.dI = dI;
    }

    public String getModeler() {
        return modeler;
    }
    @XmlAttribute
    public void setModeler(String modeler) {
        this.modeler = modeler;
    }

    public String getId() {
        return id;
    }
    @XmlAttribute
    public void setId(String id) {
        this.id = id;
    }

    public String getTargetNameSpace() {
        return targetNameSpace;
    }
    @XmlAttribute
    public void setTargetNameSpace(String targetNameSpace) {
        this.targetNameSpace = targetNameSpace;
    }

    public String getExporter() {
        return exporter;
    }
    @XmlAttribute
    public void setExporter(String exporter) {
        this.exporter = exporter;
    }

    public String getExporterVersion() {
        return exporterVersion;
    }
    @XmlAttribute
    public void setExporterVersion(String exporterVersion) {
        this.exporterVersion = exporterVersion;
    }

    public String getExecutionPlatform() {
        return executionPlatform;
    }
    @XmlAttribute
    public void setExecutionPlatform(String executionPlatform) {
        this.executionPlatform = executionPlatform;
    }

    public String getExecutionPlatformVersion() {
        return executionPlatformVersion;
    }
    @XmlAttribute
    public void setExecutionPlatformVersion(String executionPlatformVersion) {
        this.executionPlatformVersion = executionPlatformVersion;
    }
}

反序列化代码

public static void main(String[] args) throws IOException, ParseException, JAXBException {
    HttpGet getRequest = new HttpGet("http://localhost:8081/engine-rest/process-definition/key/Process2/xml");
    CloseableHttpClient client = HttpClientBuilder.create().build();
    CloseableHttpResponse response = client.execute(getRequest);
    JSONObject firstTaskFlows = new JSONObject(EntityUtils.toString(response.getEntity()));
    String xmlString = firstTaskFlows.get("bpmn20Xml").toString();
    JAXBContext jaxbContext = JAXBContext.newInstance(BPMNDefinitions.class);
    StringReader reader = new StringReader(xmlString);
    Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
    BPMNDefinitions customer = (BPMNDefinitions) jaxbUnmarshaller.unmarshal(reader);
}

解决方案

错误原因

XML中的<bpmn:definitions>属于命名空间http://www.omg.org/spec/BPMN/20100524/MODEL,前缀bpmn只是该命名空间的别名。原代码用@XmlRootElement(name = "bpmn:definitions")绑定带前缀的标签名,而非实际命名空间,导致JAXB无法匹配XML元素。

修正步骤

  1. 修正根元素的命名空间绑定
    将@XmlRootElement改为指定实际命名空间URI和本地名称,而非带前缀的名称:

    @XmlRootElement(name = "definitions", namespace = "http://www.omg.org/spec/BPMN/20100524/MODEL")
    public class BPMNDefinitions {
        // ... 其他代码
    }
    
  2. 添加包级命名空间映射
    在实体类所在的包下创建package-info.java文件,声明命名空间前缀与URI的映射,确保JAXB能识别XML中的前缀:

    @XmlSchema(
        namespace = "http://www.omg.org/spec/BPMN/20100524/MODEL",
        elementFormDefault = XmlNsForm.QUALIFIED,
        xmlns = {
            @XmlNs(prefix = "bpmn", namespaceURI = "http://www.omg.org/spec/BPMN/20100524/MODEL"),
            @XmlNs(prefix = "modeler", namespaceURI = "http://camunda.org/schema/modeler/1.0"),
            @XmlNs(prefix = "camunda", namespaceURI = "http://camunda.org/schema/1.0/bpmn")
        }
    )
    package com.your.package; // 替换为实体类实际所在包名
    
    import jakarta.xml.bind.annotation.XmlNs;
    import jakarta.xml.bind.annotation.XmlNsForm;
    import jakarta.xml.bind.annotation.XmlSchema;
    
  3. 修正带命名空间前缀的属性绑定
    XML中modeler:executionPlatform这类带前缀的属性,需要通过@XmlAttribute的namespace指定对应的URI:

    public String getExecutionPlatform() {
        return executionPlatform;
    }
    
    @XmlAttribute(namespace = "http://camunda.org/schema/modeler/1.0")
    public void setExecutionPlatform(String executionPlatform) {
        this.executionPlatform = executionPlatform;
    }
    
    public String getExecutionPlatformVersion() {
        return executionPlatformVersion;
    }
    
    @XmlAttribute(namespace = "http://camunda.org/schema/modeler/1.0")
    public void setExecutionPlatformVersion(String executionPlatformVersion) {
        this.executionPlatformVersion = executionPlatformVersion;
    }
    
  4. 删除无效的命名空间声明属性
    XML中的xmlns:bpmn、xmlns:modeler等是命名空间声明,属于XML语法的一部分,不需要手动绑定到Java属性。删除原实体类中bPMN、xPMNDI、dC、camunda、xSI、dI、modeler这些对应命名空间声明的属性及getter/setter方法。

最终修正后的BPMNDefinitions类示例

@XmlRootElement(name = "definitions", namespace = "http://www.omg.org/spec/BPMN/20100524/MODEL")
public class BPMNDefinitions {
    private String id;
    private String targetNamespace;
    private String exporter;
    private String exporterVersion;
    private String executionPlatform;
    private String executionPlatformVersion;

    public String getId() {
        return id;
    }

    @XmlAttribute
    public void setId(String id) {
        this.id = id;
    }

    public String getTargetNamespace() {
        return targetNamespace;
    }

    @XmlAttribute
    public void setTargetNamespace(String targetNamespace) {
        this.targetNamespace = targetNamespace;
    }

    public String getExporter() {
        return exporter;
    }

    @XmlAttribute
    public void setExporter(String exporter) {
        this.exporter = exporter;
    }

    public String getExporterVersion() {
        return exporterVersion;
    }

    @XmlAttribute
    public void setExporterVersion(String exporterVersion) {
        this.exporterVersion = exporterVersion;
    }

    public String getExecutionPlatform() {
        return executionPlatform;
    }

    @XmlAttribute(namespace = "http://camunda.org/schema/modeler/1.0")
    public void setExecutionPlatform(String executionPlatform) {
        this.executionPlatform = executionPlatform;
    }

    public String getExecutionPlatformVersion() {
        return executionPlatformVersion;
    }

    @XmlAttribute(namespace = "http://camunda.org/schema/modeler/1.0")
    public void setExecutionPlatformVersion(String executionPlatformVersion) {
        this.executionPlatformVersion = executionPlatformVersion;
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 04:58:10