web-servicessoapcxfwsdl2java

Apache CXF is unable to handle duplicate localnames


I'm trying to generate Java stubs for the new 3rd party service. It worked before with no problem but recently they have added a new method verifyDataExistence and wsdl2java got failed with the following error (real names were changed):

Loading FrontEnd jaxws ...
Loading DataBinding jaxb ...
wsdl2java -verbose -b jaxb-bindings.xml -client -d src https://othercompany.com/SOAP/TheirService/Services?wsdl
wsdl2java - Apache CXF 3.5.5
Jan 06, 2024 1:22:55 PM org.apache.cxf.wsdl11.WSDLServiceBuilder checkForWrapped
INFO: Operation {urn:PegaRULES:SOAP:TheirService:Services}GetList cannot be unwrapped, input message must reference global element declaration with same localname as operation
Jan 06, 2024 1:22:55 PM org.apache.cxf.wsdl11.WSDLServiceBuilder checkForWrapped
INFO: Operation {urn:PegaRULES:SOAP:TheirService:Services}HandleInfo cannot be unwrapped, input message must reference global element declaration with same localname as operation
WSDLToJava Error: Parameter: theirData already exists for method verifyDataExistence but of type com.othercompany.soap.myservice.services.VerifyDataExistenceType.TheirData instead of com.mycompany.soap.theirservice.services.VerifyDataExistenceResponseType.TheirData.  Use a JAXWS/JAXB binding customization to rename the parameter.
org.apache.cxf.tools.common.ToolException: Parameter: theirData already exists for method verifyDataExistence but of type com.othercompany.soap.myservice.services.VerifyDataExistenceType.TheirData instead of com.othercompany.soap.myservice.services.VerifyDataExistenceResponseType.TheirData.  Use a JAXWS/JAXB binding customization to rename the parameter.
    at org.apache.cxf.tools.common.model.JavaMethod.addParameter(JavaMethod.java:178)
    at org.apache.cxf.tools.wsdlto.frontend.jaxws.processor.internal.ParameterProcessor.addParameter(ParameterProcessor.java:130)
    at org.apache.cxf.tools.wsdlto.frontend.jaxws.processor.internal.ParameterProcessor.processWrappedAbstractOutput(ParameterProcessor.java:482)
    at org.apache.cxf.tools.wsdlto.frontend.jaxws.processor.internal.ParameterProcessor.processWrappedOutput(ParameterProcessor.java:360)
    at org.apache.cxf.tools.wsdlto.frontend.jaxws.processor.internal.ParameterProcessor.buildParamModelsWithoutOrdering(ParameterProcessor.java:651)
    at org.apache.cxf.tools.wsdlto.frontend.jaxws.processor.internal.ParameterProcessor.process(ParameterProcessor.java:88)
    at org.apache.cxf.tools.wsdlto.frontend.jaxws.processor.internal.OperationProcessor.processMethod(OperationProcessor.java:141)
    at org.apache.cxf.tools.wsdlto.frontend.jaxws.processor.internal.OperationProcessor.process(OperationProcessor.java:62)
    at org.apache.cxf.tools.wsdlto.frontend.jaxws.processor.internal.PortTypeProcessor.process(PortTypeProcessor.java:156)
    at org.apache.cxf.tools.wsdlto.frontend.jaxws.processor.WSDLToJavaProcessor.wsdlDefinitionToJavaModel(WSDLToJavaProcessor.java:83)
    at org.apache.cxf.tools.wsdlto.frontend.jaxws.processor.WSDLToJavaProcessor.process(WSDLToJavaProcessor.java:60)
    at org.apache.cxf.tools.wsdlto.WSDLToJavaContainer.processWsdl(WSDLToJavaContainer.java:274)
    at org.apache.cxf.tools.wsdlto.WSDLToJavaContainer.execute(WSDLToJavaContainer.java:156)
    at org.apache.cxf.tools.wsdlto.WSDLToJavaContainer.execute(WSDLToJavaContainer.java:402)
    at org.apache.cxf.tools.common.toolspec.ToolRunner.runTool(ToolRunner.java:105)
    at org.apache.cxf.tools.wsdlto.WSDLToJava.run(WSDLToJava.java:113)
    at org.apache.cxf.tools.wsdlto.WSDLToJava.run(WSDLToJava.java:86)
    at org.apache.cxf.tools.wsdlto.WSDLToJava.main(WSDLToJava.java:184)

Here is wsdl:


<wsdl:definitions
    targetNamespace="urn:PegaRULES:SOAP:TheirService:Services">
    <wsdl:types>
        <xsd:schema>
            <xsd:import schemaLocation="Services.xsd1.xsd"
                namespace="urn:PegaRULES:SOAP:TheirService:Services" />
        </xsd:schema>
    </wsdl:types>
    <wsdl:message name="GetList">
        <wsdl:part name="GetListRequest"
            element="xsns:GetListRequest" />
    </wsdl:message>
    <wsdl:message name="GetListResponse">
        <wsdl:part name="GetListResponse"
            element="xsns:GetListResponse" />
    </wsdl:message>
    <wsdl:message name="HandleInfo">
        <wsdl:part name="HandleInfoRequest"
            element="xsns:HandleInfoRequest" />
    </wsdl:message>
    <wsdl:message name="HandleInfoResponse">
        <wsdl:part name="HandleInfoResponse"
            element="xsns:HandleInfoResponse" />
    </wsdl:message>
    <wsdl:message name="VerifyDataExistence">
        <wsdl:part name="VerifyDataExistence"
            element="xsns:VerifyDataExistence" />
    </wsdl:message>
    <wsdl:message name="VerifyDataExistenceResponse">
        <wsdl:part name="VerifyDataExistenceResponse"
            element="xsns:VerifyDataExistenceResponse" />
    </wsdl:message>
    <wsdl:portType name="ServicesType">
        <wsdl:operation name="GetList">
            <wsdl:input name="GetListRequest"
                message="ns0:GetList" />
            <wsdl:output name="GetListResponse"
                message="ns0:GetListResponse" />
        </wsdl:operation>
        <wsdl:operation name="HandleInfo">
            <wsdl:input name="HandleInfoRequest"
                message="ns0:HandleInfo" />
            <wsdl:output name="HandleInfoResponse"
                message="ns0:HandleInfoResponse" />
        </wsdl:operation>
        <wsdl:operation name="VerifyDataExistence">
            <wsdl:input name="VerifyDataExistenceRequest"
                message="ns0:VerifyDataExistence" />
            <wsdl:output name="VerifyDataExistenceResponse"
                message="ns0:VerifyDataExistenceResponse" />
        </wsdl:operation>
    </wsdl:portType>
    <wsdl:binding name="ServicesBindingSOAP"
        type="ns0:ServicesType">
        <soap11:binding
            transport="http://schemas.xmlsoap.org/soap/http" style="document" />
        <wsdl:operation name="GetList">
            <soap11:operation
                soapAction="urn:PegaRULES:SOAP:TheirService:Services#GetList"
                style="document" />
            <wsdl:input name="GetListRequest">
                <soap11:body use="literal" />
            </wsdl:input>
            <wsdl:output name="GetListResponse">
                <soap11:body use="literal" />
            </wsdl:output>
        </wsdl:operation>
        <wsdl:operation name="HandleInfo">
            <soap11:operation
                soapAction="urn:PegaRULES:SOAP:TheirService:Services#HandleInfo"
                style="document" />
            <wsdl:input name="HandleInfoRequest">
                <soap11:body use="literal" />
            </wsdl:input>
            <wsdl:output name="HandleInfoResponse">
                <soap11:body use="literal" />
            </wsdl:output>
        </wsdl:operation>
        <wsdl:operation name="VerifyDataExistence">
            <soap11:operation
                soapAction="urn:PegaRULES:SOAP:TheirService:Services#VerifyDataExistence"
                style="document" />
            <wsdl:input name="VerifyDataExistenceRequest">
                <soap11:body use="literal" />
            </wsdl:input>
            <wsdl:output name="VerifyDataExistenceResponse">
                <soap11:body use="literal" />
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>
    <wsdl:binding name="ServicesBindingSOAP12"
        type="ns0:ServicesType">
        <soap12:binding
            transport="http://schemas.xmlsoap.org/soap/http" style="document" />
        <wsdl:operation name="GetList">
            <soap12:operation
                soapAction="urn:PegaRULES:SOAP:TheirService:Services#GetList"
                soapActionRequired="false" style="document" />
            <wsdl:input name="GetRequest">
                <soap12:body use="literal" />
            </wsdl:input>
            <wsdl:output name="GetListResponse">
                <soap12:body use="literal" />
            </wsdl:output>
        </wsdl:operation>
        <wsdl:operation name="HandleInfo">
            <soap12:operation
                soapAction="urn:PegaRULES:SOAP:TheirService:Services#HandleInfo"
                soapActionRequired="false" style="document" />
            <wsdl:input name="HandleInfoRequest">
                <soap12:body use="literal" />
            </wsdl:input>
            <wsdl:output name="HandleInfoResponse">
                <soap12:body use="literal" />
            </wsdl:output>
        </wsdl:operation>
        <wsdl:operation name="VerifyDataExistence">
            <soap12:operation
                soapAction="urn:PegaRULES:SOAP:TheirService:Services#VerifyDataExistence"
                soapActionRequired="false" style="document" />
            <wsdl:input name="VerifyDataExistenceRequest">
                <soap12:body use="literal" />
            </wsdl:input>
            <wsdl:output name="VerifyDataExistenceResponse">
                <soap12:body use="literal" />
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>
    <wsdl:service name="ServicesService">
        <wsdl:port name="ServicesPortSOAP"
            binding="ns0:ServicesBindingSOAP">
            <soap11:address
                location="https://192.168.1.2:1234/one/SomeServlet/SOAP/TheirService/Services" />
        </wsdl:port>
        <wsdl:port name="ServicesPortSOAP12"
            binding="ns0:ServicesBindingSOAP12">
            <soap12:address
                location="https://192.168.1.2:1234/one/SomeServlet/SOAP/TheirService/Services" />
        </wsdl:port>
    </wsdl:service>
</wsdl:definitions>

and the separate schema file:

<schema elementFormDefault="unqualified"
    targetNamespace="urn:PegaRULES:SOAP:TheirService:Services">
    <complexType name="GetListRequestType">
        <sequence>
            <element name="AppId" type="xsd:string" />
            <element minOccurs="0" name="DataCode" type="xsd:string" />
            <element minOccurs="0" name="DepId" type="xsd:string" />
        </sequence>
    </complexType>
    <element name="GetListRequest"
        type="tns:GetListRequestType" />
    <complexType name="GetListResponseType">
        <sequence>
            <element name="Count" type="xsd:string" />
            <element name="List">
                <complexType>
                    <sequence>
                        <element maxOccurs="unbounded" name="Data">
                            <complexType>
                                <sequence>
                                    <element name="ItemNo" type="xsd:string" />
                                    <element name="DataCode" type="xsd:string" />
                                    <element name="Prefix" type="xsd:string" />
                                    <element name="Year" type="xsd:string" />
                                </sequence>
                            </complexType>
                        </element>
                    </sequence>
                </complexType>
            </element>
            <element name="ErrorList">
                <complexType>
                    <sequence>
                        <element maxOccurs="unbounded" name="Error">
                            <complexType>
                                <sequence>
                                    <element name="Code" type="xsd:string" />
                                    <element name="Desc" type="xsd:string" />
                                </sequence>
                            </complexType>
                        </element>
                    </sequence>
                </complexType>
            </element>
        </sequence>
    </complexType>
    <element name="GetListResponse"
        type="nslt1:GetListResponseType" />
    
    <element name="HandleInfoRequest"
        type="tns:HandleInfoRequestType" />
    <complexType name="HandleInfoResponseType">
        <sequence>
            <element name="TheirData">
                <complexType>
                    <sequence>
                        <element name="DataCode" type="xsd:string" />
                        <element name="Prefix" type="xsd:string" />
                        <element name="Year" type="xsd:string" />
                        <element name="ItemNo" type="xsd:string" />
                        <element name="HandlingStatus" type="xsd:string" />
                    </sequence>
                </complexType>
            </element>
            <element minOccurs="0" name="ErrorsList">
                <complexType>
                    <sequence>
                        <element maxOccurs="unbounded" name="Error">
                            <complexType>
                                <sequence>
                                    <element name="Code" type="xsd:string" />
                                    <element name="Desc" type="xsd:string" />
                                </sequence>
                            </complexType>
                        </element>
                    </sequence>
                </complexType>
            </element>
        </sequence>
    </complexType>
    <element name="HandleInfoResponse"
        type="nslt1:HandleInfoResponseType" />
    <complexType name="VerifyDataExistenceType">
        <sequence>
            <element name="AppId" type="xsd:string" />
            <element name="TheirData">
                <complexType>
                    <sequence>
                        <element name="DataCode" type="xsd:string" />
                        <element name="Prefix" type="xsd:string" />
                        <element minOccurs="0" name="Year" type="xsd:string" />
                        <element name="ItemNo" type="xsd:string" />
                    </sequence>
                </complexType>
            </element>
        </sequence>
    </complexType>
    <element name="VerifyDataExistence"
        type="tns:VerifyDataExistenceType" />
    <complexType name="VerifyDataExistenceResponseType">
        <sequence>
            <element name="TheirData">
                <complexType>
                    <sequence>
                        <element name="ItemNo" type="xsd:string" />
                        <element name="DataCode" type="xsd:string" />
                        <element name="Prefix" type="xsd:string" />
                        <element minOccurs="0" name="Year" type="xsd:string" />
                        <element name="DataExists" type="xsd:string" />
                        <element name="ProcessingCompleted" type="xsd:string" />
                    </sequence>
                </complexType>
            </element>
            <element minOccurs="0" name="ErrorList">
                <complexType>
                    <sequence>
                        <element maxOccurs="unbounded" name="Error">
                            <complexType>
                                <sequence>
                                    <element name="Code" type="xsd:string" />
                                    <element name="Desc" type="xsd:string" />
                                </sequence>
                            </complexType>
                        </element>
                    </sequence>
                </complexType>
            </element>
        </sequence>
    </complexType>
    <element name="VerifyDataExistenceResponse"
        type="nslt1:VerifyDataExistenceResponseType" />
</schema>

To customize the generation I already have jaxb-bindings.xml

<jaxb:bindings version="2.0" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb">
    <jaxb:bindings>
        <jaxb:globalBindings generateElementProperty="false"/>
    </jaxb:bindings>
</jaxb:bindings>

According to suggestion from the error I tried to use a JAXWS/JAXB binding customization to rename the parameter like

    <jaxb:bindings node="//wsdl:message[@name='verifyDataExistenceRequest']/wsdl:part[@name='theirData']">
        <jaxb:property name="verifyExistenceRequestTheirData" />
    </jaxb:bindings>

    <jaxb:bindings node="//wsdl:message[@name='verifyDataExistenceResponse']/wsdl:part[@name='theirData']">
        <jaxb:property name="verifyExistenceResponseTheirData" />
    </jaxb:bindings>

But it does not work since the definition of verifyDataExistenceRequest and verifyDataExistenceResponse types are in the separate xml scheme file https://othercompany.com/SOAP/TheirService/Services.xsd1.xsd

Also I tried to play with schemaLocation attribute but it all fails.

Will appreciate any ideas how to make it work. Thanks


Solution

  • No need for the customization in jaxb-bindings.xml

    It would be sufficient just to add additional parameter -autoNameResolution to WSDLTOJava

    E.g. gradle task could be like:

    task generateFromWsdl(type: JavaExec) {
        main = 'org.apache.cxf.tools.wsdlto.WSDLToJava'
        classpath = configurations.jaxb
        args '-verbose', '-client', '-d', 'src/main/java', '-b', "$projectDir/src/jaxb/resources/jaxb-bindings.xml", "-suppress-generated-date", "-autoNameResolution", "$projectDir/src/jaxb/resources/${myWsdl}"
    }
    

    More details at: https://cxf.apache.org/docs/wsdl-to-java.html