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

为何maven-jaxb2-plugin不生成wsdl:message的Java类?如何解决?

问题:maven-jaxb2-plugin不生成wsdl:message对应Java类的原因及解决办法

按照Spring官方指南《Consuming a SOAP web service》创建SOAP服务客户端时,遇到一个问题:maven-jaxb2-plugin没有从WSDL文件生成wsdl:message对应的Java类,只生成了schema相关的简单类型。导致调用getWebServiceTemplate().marshalSendAndReceive()时必须手动构造请求对象。

使用的WSDL文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
                  xmlns:tns="http://www.test.com/soap/jacky/client"
                  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                  xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"
                  targetNamespace="http://www.test.com/soap/jacky/client">
    <wsdl:types/>

    <wsdl:message name="retrieveResponse">
        <wsdl:part name="retValue" type="xsd:string"/>
    </wsdl:message>

    <wsdl:message name="retrieveRequest">
        <wsdl:part name="name" type="xsd:string"/>
        <wsdl:part name="flag" type="xsd:boolean"/>
    </wsdl:message>

    <wsdl:portType name="DemoSoap">
        <wsdl:operation name="retrieve" parameterOrder="name flag">
            <wsdl:input message="tns:retrieveRequest" name="retrieveRequest"/>
            <wsdl:output message="tns:retrieveResponse" name="retrieveResponse"/>
        </wsdl:operation>
    </wsdl:portType>

    <wsdl:binding name="DemoBinding" type="tns:DemoSoap">
        <wsdlsoap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
        <wsdl:operation name="retrieve">
            <wsdlsoap:operation soapAction=""/>
            <wsdl:input name="retrieveRequest">
                <wsdlsoap:body  use="literal"/>
            </wsdl:input>
            <wsdl:output name="retrieveResponse">
                <wsdlsoap:body  use="literal"/>
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>

    <wsdl:service name="DemoClient">
        <wsdl:port binding="tns:DemoBinding" name="Demo">
            <wsdlsoap:address location="http://www.test.com/soap/jacky/client"/>
        </wsdl:port>
    </wsdl:service>

</wsdl:definitions>

原因分析

  • 你的WSDL采用了RPC/literal风格:在<wsdl:binding>里明确指定了style="rpc",这种风格下,JAXB默认不会为wsdl:message生成专门的封装类,而是直接使用message part对应的简单类型(比如String、Boolean)作为方法参数和返回值。
  • JAXB的核心是处理XML Schema定义的类型,而RPC风格的message parts直接引用了XSD内置的简单类型,没有在<wsdl:types>里定义对应的复杂类型,所以maven-jaxb2-plugin不会生成请求/响应的封装类。

解决办法

方法1:修改WSDL为Document/literal风格(推荐)

Document风格是当前SOAP服务的主流规范,它基于XML Schema定义请求和响应的结构,JAXB能自动生成对应的封装类。修改后的WSDL示例如下:

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
                  xmlns:tns="http://www.test.com/soap/jacky/client"
                  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                  xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"
                  targetNamespace="http://www.test.com/soap/jacky/client">
    <wsdl:types>
        <xsd:schema targetNamespace="http://www.test.com/soap/jacky/client">
            <xsd:element name="retrieveRequest">
                <xsd:complexType>
                    <xsd:sequence>
                        <xsd:element name="name" type="xsd:string"/>
                        <xsd:element name="flag" type="xsd:boolean"/>
                    </xsd:sequence>
                </xsd:complexType>
            </xsd:element>
            <xsd:element name="retrieveResponse">
                <xsd:complexType>
                    <xsd:sequence>
                        <xsd:element name="retValue" type="xsd:string"/>
                    </xsd:sequence>
                </xsd:complexType>
            </xsd:element>
        </xsd:schema>
    </wsdl:types>

    <wsdl:message name="retrieveResponse">
        <wsdl:part name="parameters" element="tns:retrieveResponse"/>
    </wsdl:message>

    <wsdl:message name="retrieveRequest">
        <wsdl:part name="parameters" element="tns:retrieveRequest"/>
    </wsdl:message>

    <wsdl:portType name="DemoSoap">
        <wsdl:operation name="retrieve">
            <wsdl:input message="tns:retrieveRequest" name="retrieveRequest"/>
            <wsdl:output message="tns:retrieveResponse" name="retrieveResponse"/>
        </wsdl:operation>
    </wsdl:portType>

    <wsdl:binding name="DemoBinding" type="tns:DemoSoap">
        <wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
        <wsdl:operation name="retrieve">
            <wsdlsoap:operation soapAction=""/>
            <wsdl:input name="retrieveRequest">
                <wsdlsoap:body use="literal"/>
            </wsdl:input>
            <wsdl:output name="retrieveResponse">
                <wsdlsoap:body use="literal"/>
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>

    <wsdl:service name="DemoClient">
        <wsdl:port binding="tns:DemoBinding" name="Demo">
            <wsdlsoap:address location="http://www.test.com/soap/jacky/client"/>
        </wsdl:port>
    </wsdl:service>

</wsdl:definitions>

修改后重新执行maven生成命令,插件会自动生成RetrieveRequest和RetrieveResponse类,直接用于marshalSendAndReceive调用即可。

方法2:改用jaxws-maven-plugin(适配RPC风格)

如果无法修改WSDL,可以换用jaxws-maven-plugin,它对RPC风格的WSDL支持更好,会自动生成包含请求/响应封装类的客户端代码。在pom.xml中添加如下配置:

<plugin>
    <groupId>org.jvnet.jax-ws-commons</groupId>
    <artifactId>jaxws-maven-plugin</artifactId>
    <version>2.3</version>
    <executions>
        <execution>
            <goals>
                <goal>wsimport</goal>
            </goals>
            <configuration>
                <wsdlFiles>
                    <wsdlFile>src/main/resources/your.wsdl</wsdlFile>
                </wsdlFiles>
                <packageName>com.test.soap.jacky.client</packageName>
                <keep>true</keep>
            </configuration>
        </execution>
    </executions>
</plugin>

执行mvn jaxws:wsimport命令后,会生成包含Retrieve、RetrieveRequest、RetrieveResponse等类的客户端代码,直接调用即可。

方法3:添加JAXB绑定文件(不推荐)

如果必须使用maven-jaxb2-plugin,可以创建一个JAXB绑定文件强制生成封装类,但这种方式兼容性较差。

创建bindings.xjb文件:

<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
               xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
               version="2.1">
    <jaxb:bindings wsdlLocation="your.wsdl" node="/wsdl:definitions/wsdl:portType/wsdl:operation[@name='retrieve']">
        <jaxb:enableWrapperStyle>true</jaxb:enableWrapperStyle>
    </jaxb:bindings>
</jaxb:bindings>

然后在maven-jaxb2-plugin配置中引用该文件:

<plugin>
    <groupId>org.jvnet.jaxb2.maven2</groupId>
    <artifactId>maven-jaxb2-plugin</artifactId>
    <version>0.14.0</version>
    <executions>
        <execution>
            <goals>
                <goal>generate</goal>
            </goals>
            <configuration>
                <wsdl>src/main/resources/your.wsdl</wsdl>
                <bindingDirectory>src/main/resources</bindingDirectory>
                <bindingFiles>
                    <bindingFile>bindings.xjb</bindingFile>
                </bindingFiles>
            </configuration>
        </execution>
    </executions>
</plugin>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 19:45:51