Apache CXF не может обрабатывать повторяющиеся локальные имена

Я пытаюсь создать заглушки Java для новой сторонней службы. Раньше это работало без проблем, но недавно они добавили новый метод verifyDataExistence и wsdl2java произошла ошибка со следующей ошибкой (настоящие имена были изменены):

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)

Вот 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>

и отдельный файл схемы:

<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>

Чтобы настроить генерацию, у меня уже есть 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>

Согласно предложению об ошибке, я попытался использовать настройку привязки JAXWS/JAXB, чтобы переименовать параметр, например

    <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>

Но это не работает, поскольку определение типовverifyDataExistenceRequest иverifyDataExistenceResponse находится в отдельном файле схемы xml https://othercompany.com/SOAP/TheirService/Services.xsd1.xsd

Также я пытался поиграть с атрибутом schemaLocation, но ничего не получилось.

Буду признателен за любые идеи, как заставить это работать. Спасибо


71
1

Ответ:

Решено

Нет необходимости в настройке jaxb-bindings.xml

Достаточно просто добавить дополнительный параметр -autoNameResolution к WSDLTOJava.

Например. Задача gradle может выглядеть так:

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}"
}

Более подробная информация: https://cxf.apache.org/docs/wsdl-to-java.html