代码之家  ›  专栏  ›  技术社区  ›  Marc

@具有基元数据类型的端点-没有用于端点的适配器

  •  3
  • Marc  · 技术社区  · 7 年前

    我正在尝试使用gradle(WSDL2Java)从WSDL生成CXF Java类,以便在SpringBoot应用程序中使用它。

    应用程序提供了一个SOAP端点。我想要的响应只包含一个简单的布尔值:

    请求:

    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
       <soap:Header/>
       <soap:Body>
          <ns:isActiveRequest xmlns:ns=\"http://problem.com\"><id>1234</id></ns:isActiveRequest>
       </soap:Body>
    </soap:Envelope>
    

    答复:

    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
       <soap:Header/>
       <soap:Body>
          <ns:isActiveResponse xmlns:ns="http://problem.com">true</ns3:isActiveResponse>
       </soap:Body>
    </soap:Envelope>
    

    我无法在我的WSDL中定义此响应,因此它在我的SpringBoot应用程序中使用@Endpoint注释生成CXF之后工作。我总是会遇到这样的错误:“没有端点适配器……您的端点是用@endpoint注释的,还是实现了MessageHandler或PayloadEndpoint等受支持的接口?”

    通常我对CXF和具有复杂响应类型的端点没有问题,因为它生成了一个@XmlRootElement。但它不会在响应中使用原语类型,并且无法识别@Endpoint注释下的方法。

    [...]
    import org.springframework.ws.server.endpoint.annotation.Endpoint;
    import org.springframework.ws.server.endpoint.annotation.PayloadRoot;
    import org.springframework.ws.server.endpoint.annotation.RequestPayload;
    import org.springframework.ws.server.endpoint.annotation.ResponsePayload;
    
    @Endpoint
    public class SoapEndpoint implements Problem {
    private static final String TARGET_NAMESPACE = "http://problem.com";
    
    @PayloadRoot(namespace = TARGET_NAMESPACE, localPart = "isActiveRequest")
    @ResponsePayload
    @Secured(Roles.PERMISSION)
    public boolean isActive(@RequestPayload IsActiveRequest request) {
        return true;
    }
    

    我用于生成的WSDL如下所示:

    <wsdl:types>
        <xs:schema attributeFormDefault="unqualified"
                   elementFormDefault="unqualified" targetNamespace="http://problem.com"
                   xmlns:xs="http://www.w3.org/2001/XMLSchema">
    
            <xs:element name="isActiveRequest">
                <xs:complexType>
                    <xs:sequence>
                        <xs:element name="id" maxOccurs="1" minOccurs="1"
                                    nillable="false" type="xs:string"/>
                    </xs:sequence>
                </xs:complexType>
            </xs:element>
            <xs:element name="isActiveResponse" type="xs:boolean"/>
    
        </xs:schema>
    </wsdl:types>
    
    <wsdl:message name="isActiveRequest">
        <wsdl:part name="parameters" element="tns:isActiveRequest"></wsdl:part>
    </wsdl:message>
    <wsdl:message name="isActiveResponse">
        <wsdl:part name="parameters" element="tns:isActiveResponse"></wsdl:part>
    </wsdl:message>
    
    <wsdl:portType name="problem">
        <wsdl:operation name="isActive">
            <wsdl:input message="tns:isActiveRequest" name="isActiveRequest"/>
            <wsdl:output message="tns:isActiveResponse" name="isActiveResponse"/>
            <wsdl:fault message="tns:myException" name="fault"/>
        </wsdl:operation>
    </wsdl:portType>
    
    <wsdl:binding name="problem_SOAPBinding" type="tns:problem">
        <soap:binding style="document"
                      transport="http://schemas.xmlsoap.org/soap/http"/>
    
        <wsdl:operation name="isActive">
            <soap:operation soapAction="isActive"/>
            <wsdl:input name="isActiveRequest">
                <soap:body use="literal"/>
            </wsdl:input>
            <wsdl:output name="isActiveResponse">
                <soap:body use="literal"/>
            </wsdl:output>
            <wsdl:fault name="fault">
                <soap:fault use="literal" name="fault"/>
            </wsdl:fault>
        </wsdl:operation>
    </wsdl:binding>
    

    在我的构建中。gradle我正在使用CXF 3.2.1

    task wsdl2java(type: JavaExec) {
        ext {
            outputDir = file(cxfOutputDir)
            wsdlFiles = new FileNameByRegexFinder().getFileNames("${wsdlDir}", /.*\.wsdl/)
        }
    
        wsdlFiles.each { String wsdlFile ->
            outputs.upToDateWhen { false }
            outputs.dir outputDir
            main = 'org.apache.cxf.tools.wsdlto.WSDLToJava'
            classpath = configurations.cxfTool
            args '-d', outputDir
            args '-wsdlLocation', "/wsdl/" + new File(wsdlFile).name
            args '-verbose'
            args '-validate'
            args wsdlFile
        }
    }
    
    compile group: 'org.apache.cxf', name: 'cxf-core', version: "3.2.1"
    compile group: 'org.apache.cxf', name: 'cxf-rt-frontend-jaxws', version: "3.2.1"
    compile "org.apache.cxf:cxf-spring-boot-starter-jaxws:3.2.1"
    cxfTool "org.apache.cxf:cxf-tools-wsdlto-frontend-jaxws:3.2.1"
    cxfTool "org.apache.cxf:cxf-tools-wsdlto-databinding-jaxb:3.2.1"
    cxfTool "org.apache.cxf:cxf-tools-common:3.2.1"
    cxfTool "org.apache.cxf:cxf-tools-wsdlto-core:3.2.1"
    
    2 回复  |  直到 7 年前
        1
  •  0
  •   Bence    4 年前

    默认情况下,没有基元类型MethodArgumentResolver。 正如参考资料所示,您可以使用10多种不同的解析器。 我最终选择了JAXB:

    @PayloadRoot(namespace = NAMESPACE_URI, localPart = "RemoveObject")
    @ResponsePayload
    public RemoveObjectResponse removeObject(@RequestPayload JAXBElement<Integer> objectID, @RequestPayload JAXBElement<Boolean> useTrashbin, @RequestPayload JAXBElement<Boolean> ignoreReferences) {
    ...
    }
    

    或者您可以为基本类型编写自己的扩展,但很可能不值得这样做。

    https://docs.spring.io/spring-ws/site/reference/html/server.html#d5e1086

    如果为组织启用跟踪日志。springframework。xml记录器然后您可以看到潜在参数解析器的日志条目 Testing if argument resolver ... supports <your parameter>

        2
  •  0
  •   Marc    3 年前

    我已经用JAXBElement解决了这个问题<&燃气轮机;

    public JAXBElement<Boolean> isActive(@RequestPayload IsActiveRequest request) {
       ...
       ObjectFactory factory = new ObjectFactory();
       return factory.createIsActiveResponse(myBoolean);
    }
    
    推荐文章