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

SOAP请求元素名称与WSDL不一致问题排查

问题:SOAP请求XML元素名称与WSDL定义不符

通过IntelliJ导入第三方WSDL生成Java类后,发送SOAP请求时输出的XML元素名称和WSDL定义不一致。用SoapUI导入则能得到符合预期的元素名称,推测是编组过程忽略了@XmlElementRef注解,直接使用了变量类型。

预期输出XML:

<rxh2:Documents>
   <rxh2:Document>
      <rxh2:Base64String>JVBERi0xLjQN</rxh2:Base64String>
      <rxh2:DocumentType>Pdf</rxh2:DocumentType>
   </rxh2:Document>
</rxh2:Documents>

实际输出XML:

<ns2:ArrayOfDocument>
   <ns2:Document>
       <ns2:Base64String>JVBERi0xLjYKJbiakp0KMS</ns2:Base64String>
       <ns2:DocumentType>Pdf</ns2:DocumentType>
   </ns2:Document>
</ns2:ArrayOfDocument>

疑问:为何输出的元素名为ArrayOfDocument而非Documents?

pom.xml中wsimport插件配置

<plugin>
  <groupId>com.sun.xml.ws</groupId>
  <artifactId>jaxws-maven-plugin</artifactId>
  <version>4.0.2</version>
  <configuration>
    <wsdlUrls>
      <wsdlUrl>
        https://thewebsite/Integration/Service.OrderService.svc?wsdl
      </wsdlUrl>
    </wsdlUrls>
    <extension>true</extension>
    <verbose>true</verbose>
    <vmArgs>
      <vmArg>-Djavax.xml.accessExternalSchema=all</vmArg>
    </vmArgs>
  </configuration>
  <executions>
    <execution>
      <id>endpoint.hpc</id>
      <phase>generate-sources</phase>
      <goals>
        <goal>wsimport</goal>
      </goals>
      <configuration>
        <packageName>com.cgm.ms.script</packageName>
        <args>
          <arg>-B-XautoNameResolution</arg>
        </args>
      </configuration>
    </execution>
  </executions>
</plugin>

生成的关键Java代码

对应属性定义:

@XmlElementRef(name = "Documents", namespace = "http://schemas.datacontract.org/2010/12/Service.Models.RFM", type = JAXBElement.class, required = false)
protected JAXBElement<ArrayOfDocument> documents;

ArrayOfDocument类定义:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "ArrayOfDocument", propOrder = {
    "document"
})
public class ArrayOfDocument {

    @XmlElement(name = "Document", nillable = true)
    protected List<Document> document;
...
}

问题原因与解决办法

原因分析

核心问题是对象编组时未正确使用JAXBElement包装实例。生成的代码中documents属性是JAXBElement<ArrayOfDocument>类型,这个类型的作用就是携带@XmlElementRef中指定的XML元素名称(即Documents)。如果直接把ArrayOfDocument实例赋值给documents,或编组时跳过JAXBElement包装,JAXB会忽略注解配置,直接根据ArrayOfDocument类的@XmlType注解生成ArrayOfDocument元素名。

解决办法

构建请求对象时,必须用JAXBElement包装ArrayOfDocument实例,步骤如下:

  1. 创建并填充ArrayOfDocument实例:
ArrayOfDocument arrayOfDoc = new ArrayOfDocument();
Document doc = new Document();
doc.setBase64String("JVBERi0xLjQN");
doc.setDocumentType("Pdf");
arrayOfDoc.getDocument().add(doc);
  1. 使用自动生成的ObjectFactory创建JAXBElement(wsimport会自动生成该类):
ObjectFactory factory = new ObjectFactory();
JAXBElement<ArrayOfDocument> documentsElement = factory.createDocuments(arrayOfDoc);
request.setDocuments(documentsElement);

若找不到自动生成的createDocuments方法,可手动构建JAXBElement:

QName qName = new QName("http://schemas.datacontract.org/2010/12/Service.Models.RFM", "Documents");
JAXBElement<ArrayOfDocument> documentsElement = new JAXBElement<>(qName, ArrayOfDocument.class, arrayOfDoc);
request.setDocuments(documentsElement);

这样编组时JAXB会读取JAXBElement中的元素名称,输出预期的<rxh2:Documents>节点,而非ArrayOfDocument对应的元素名。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 14:44:55