所以我使用 mavensmaven-jaxb2-plugin
从一个大而复杂的 WSDL 文件生成类并遇到了这个问题。问题在于 WSDL 中的元素将complexType
定义引用为type
未生成的元素类,并且在尝试使用 complexType 类时会产生缺失的@XmlRootElement
错误。
在我看来,修改 WSDL 并不是一个真正可行的解决方案,唯一可行的方法似乎是设计一种在生成期间添加缺失注释的方法。它还在编组时导致序列化问题,因为请求发送了错误的元素名称,并且响应中也没有具有匹配元素名称的类。
我最终做的是使用第二个 maven 插件jaxb2-basics-annotate
,它允许您通过使用 jaxb 绑定文件将缺少的注释添加到所需的类中。这使您不必在不添加不必要的代码的情况下解决这个问题,并且还意味着如果您将来需要使用更新的 WSDL 文件,您可以轻松地重新生成。
pom.xml(注意配置中有一个插件部分用于执行 - WSDL 文件位置是 /src/main/resources/wsdl/EstimatingService.wsdl)
<project>
...
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<jaxb2.version>0.14.0</jaxb2.version>
<jaxb2.annotate.version>1.1.0</jaxb2.annotate.version>
</properties>
<dependencies>
<dependency>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>${jaxb2.version}</version>
</dependency>
<dependency>
<groupId>org.jvnet.jaxb2_commons</groupId>
<artifactId>jaxb2-basics-annotate</artifactId>
<version>${jaxb2.annotate.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>${jaxb2.version}</version>
<executions>
<execution>
<id>estimating</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<schemaLanguage>WSDL</schemaLanguage>
<generateDirectory>target/generated-sources/acme/src/gen/estimating-service</generateDirectory>
<generatePackage>com.acme.shipping.estimating.service</generatePackage>
<schemaDirectory>${project.basedir}/src/main/resources/wsdl</schemaDirectory>
<schemaIncludes>
<include>EstimatingService.wsdl</include>
</schemaIncludes>
<bindingDirectory>${project.basedir}/src/main/resources/bindings</bindingDirectory>
<bindingIncludes>estimateServiceBinding.xjb</bindingIncludes>
<extension>true</extension>
<args>
<arg>-Xannotate</arg>
<arg>-XremoveAnnotation</arg>
</args>
<plugins>
<plugin>
<groupId>org.jvnet.jaxb2_commons</groupId>
<artifactId>jaxb2-basics-annotate</artifactId>
</plugin>
</plugins>
</configuration>
</execution>
...
// More executions here if you have multiple WSDL files (Dont forget to give it a different package name and id)
</executions>
</plugin>
</plugins>
</build>
...
</project>
estimateServiceBinding.xjb(本示例中使用的 jaxb 绑定文件 - /src/main/resources/bindings/estimateServiceBinding.xjb)
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jaxb:bindings version="2.0" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:annox="http://annox.dev.java.net" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
<jaxb:globalBindings generateElementProperty="false">
<xjc:simple />
</jaxb:globalBindings>
<!-- Target the schema section in the WSDL file using the given target namespace which contains the complexType definitions we want to annotate -->
<jaxb:bindings schemaLocation="../wsdl/EstimatingService.wsdl" node="//xs:schema[@targetNamespace='http://acme.com/schema/datatypes/v2']">
<jaxb:bindings node="xs:complexType[@name='GetQuickEstimateRequestContainer']">
<!-- Add the @XmlRootElement annotation to the generated class and then tell it use the correct element name required when marshalling. e.g GetQuickEstimateRequestContainer element is renamed to the element name that referenced it in the WSDL (GetQuickEstimateRequest) -->
<annox:annotateClass>@javax.xml.bind.annotation.XmlRootElement(name="GetQuickEstimateRequest")</annox:annotateClass>
</jaxb:bindings>
<jaxb:bindings node="xs:complexType[@name='GetQuickEstimateResponseContainer']">
<annox:annotateClass>@javax.xml.bind.annotation.XmlRootElement(name="GetQuickEstimateResponse")</annox:annotateClass>
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
生成的类(GetQuickEstimateRequestContainer.java) 带有 @XmlRootElement 注释和正确的元素名称
@XmlRootElement(name = "GetQuickEstimateRequest")
public class GetQuickEstimateRequestContainer {
...
// class member fields & setters and getters
...
}