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

如何让wsdl2java生成包装式响应类替代Holder封装的输出参数

问题:wsdl2java生成WebService客户端时返回值为void,无法生成LoginResponse作为返回类型

问题场景

使用wsdl2java生成WebService客户端类时,遇到如下问题:接口方法(如Auth#login)的返回值始终为void,所有响应参数都被封装在Holder中,无法生成对应的LoginResponse类作为返回实例。

自动生成的Auth.java客户端接口示例:

@WebService(targetNamespace = "http://xml.kamsoft.pl/ws/auth", name = "Auth")
@XmlSeeAlso({pl.kamsoft.xml.ws.common.ObjectFactory.class, pl.kamsoft.xml.ws.kaas.login_types.ObjectFactory.class})
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
public interface Auth {

    // [...] - `logout`, `changePassword`, `changePasswordLog` 方法

    @WebMethod(action = "login")
    public void login(

        @WebParam(partName = "request", name = "login", targetNamespace = "http://xml.kamsoft.pl/ws/kaas/login_types")
        pl.kamsoft.xml.ws.kaas.login_types.LoginRequest request,
        @WebParam(partName = "response", mode = WebParam.Mode.OUT, name = "loginReturn", targetNamespace = "http://xml.kamsoft.pl/ws/kaas/login_types")
        jakarta.xml.ws.Holder<java.lang.String> response,
        @WebParam(partName = "session", mode = WebParam.Mode.OUT, name = "session", targetNamespace = "http://xml.kamsoft.pl/ws/common", header = true)
        jakarta.xml.ws.Holder<pl.kamsoft.xml.ws.common.Session> session,
        @WebParam(partName = "token", mode = WebParam.Mode.OUT, name = "authToken", targetNamespace = "http://xml.kamsoft.pl/ws/common", header = true)
        jakarta.xml.ws.Holder<pl.kamsoft.xml.ws.common.AuthToken> token
    ) throws pl.kamsoft.wsdl.common.AuthenticationExceptionMsg, pl.kamsoft.wsdl.common.ServerExceptionMsg, PassExpiredExceptionMsg, pl.kamsoft.wsdl.common.AuthTokenExceptionMsg, pl.kamsoft.wsdl.common.InputExceptionMsg, pl.kamsoft.wsdl.common.AuthorizationExceptionMsg;
}

对应的Gradle配置(build.gradle.kts):

plugins {
    java
    id("com.yupzip.wsdl2java") version "3.0.0"
}

java {
    toolchain {
        languageVersion.set(JavaLanguageVersion.of(17))
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation("org.apache.cxf:cxf-rt-frontend-jaxws:4.0.0")
    implementation("org.apache.cxf:cxf-rt-transports-http-hc5:4.0.0")
    wsdl2java("com.sun.xml.bind:jaxb-impl:4.0.1")
    wsdl2java("org.apache.cxf.xjc-utils:cxf-xjc-runtime:4.0.0")
    wsdl2java("jakarta.xml.ws:jakarta.xml.ws-api:4.0.0")
    wsdl2java("com.sun.xml.ws:rt:4.0.0")
    wsdl2java("org.jvnet.jaxb2_commons:jaxb2-namespace-prefix:2.0")
    wsdl2java("codes.rafael.jaxb2_commons:jaxb2-basics-runtime:3.0.0")
    wsdl2java("codes.rafael.jaxb2_commons:jaxb2-basics:3.0.0")
}

wsdl2java {
    wsdlDir = file("$projectDir/src/main/resources/")
    includeJava8XmlDependencies = false
    cxfVersion = "4.0.0"
    cxfPluginVersion = "4.0.0"
    wsdlsToGenerate = listOf(
        listOf(
            "-wsdlLocation", "https://ewus.nfz.gov.pl/ws-broker-server-ewus-auth-test/services/Auth?wsdl",
            "-autoNameResolution",
            "https://ewus.nfz.gov.pl/ws-broker-server-ewus-auth-test/services/Auth?wsdl",
        )
    )
}

核心疑问

如何强制wsdl2java生成可作为Auth#login方法返回实例的LoginResponse类?

已尝试使用绑定文件bindings.xml,但无论将enableWrapperStyle设为true或false都没有效果:

<bindings
        wsdlLocation="https://ewus.nfz.gov.pl/ws-broker-server-ewus-auth-test/services/Auth?wsdl"
        xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
        xmlns="http://java.sun.com/xml/ns/jaxws">
    <enableWrapperStyle>false</enableWrapperStyle>
</bindings>

对应的Gradle配置修改后:

wsdl2java {
    wsdlDir = file("$projectDir/src/main/resources/")
    includeJava8XmlDependencies = false
    cxfVersion = "4.0.0"
    cxfPluginVersion = "4.0.0"
    wsdlsToGenerate = listOf(
        listOf(
            "-b", "$projectDir/src/main/resources/wsdl/bindings.xml",
            "-wsdlLocation", "https://ewus.nfz.gov.pl/ws-broker-server-ewus-auth-test/services/Auth?wsdl",
            "-autoNameResolution",
            "https://ewus.nfz.gov.pl/ws-broker-server-ewus-auth-test/services/Auth?wsdl",
        )
    )
}

另外,session和token被声明为wsdlsoap:header是否会影响生成的Java代码?


解决方案

1. 根本原因:BARE参数样式

当前生成的代码是因为WSDL采用了BARE参数样式(对应代码中的@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)),这种样式下JAX-WS不会自动将请求/响应包装为单个对象,而是拆分参数到Holder中。要生成带返回类型的方法,需要切换到WRAPPED样式。

2. 修正绑定文件配置

全局设置enableWrapperStyle无效,是因为WSDL本身的参数样式优先级更高,需要精准定位到portType或具体operation节点配置:

<bindings wsdlLocation="https://ewus.nfz.gov.pl/ws-broker-server-ewus-auth-test/services/Auth?wsdl"
          xmlns="http://java.sun.com/xml/ns/jaxws"
          xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">

    <!-- 针对整个Auth portType启用包装样式 -->
    <bindings node="wsdl:definitions/wsdl:portType[@name='Auth']">
        <enableWrapperStyle>true</enableWrapperStyle>
    </bindings>

    <!-- 如需单独针对login方法配置,可使用下面这段 -->
    <!--
    <bindings node="wsdl:definitions/wsdl:portType[@name='Auth']/wsdl:operation[@name='login']">
        <enableWrapperStyle>true</enableWrapperStyle>
    </bindings>
    -->
</bindings>

3. 添加CXF强制包装类参数

在wsdl2java的参数中加入-wrapperbean,强制生成响应包装类:

wsdl2java {
    wsdlDir = file("$projectDir/src/main/resources/")
    includeJava8XmlDependencies = false
    cxfVersion = "4.0.0"
    cxfPluginVersion = "4.0.0"
    wsdlsToGenerate = listOf(
        listOf(
            "-b", "$projectDir/src/main/resources/wsdl/bindings.xml",
            "-wsdlLocation", "https://ewus.nfz.gov.pl/ws-broker-server-ewus-auth-test/services/Auth?wsdl",
            "-autoNameResolution",
            "-wrapperbean", // 新增参数:强制生成包装类
            "https://ewus.nfz.gov.pl/ws-broker-server-ewus-auth-test/services/Auth?wsdl",
        )
    )
}

关于Header参数的影响

session和token作为wsdlsoap:header确实会影响代码生成:它们属于SOAP Header部分,不属于Body内容,因此即使启用包装样式,也会保持作为方法的Holder参数存在,不会被包含在LoginResponse类中。但Body部分的响应会被正常包装到LoginResponse作为方法返回值。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 03:41:31