Apache CXF和Apache Camel:给定的SOAPAction与操作不匹配

时间:2014-04-02 19:43:13

标签: maven cxf apache-camel wsdl2java

我正试图走过Camel Report Incident tutorial,并被困在part 5的末尾。当我尝试运行单元测试时,它失败并显示消息The given SOAPAction http://reportincident.example.camel.apache.org/ReportIncident does not match an operation.

我看到一个similar question问题是WSDL文件中声明的soapAction属性与实际SOAP请求的值不同。这似乎不是我的情况。什么是错误的想法?提前谢谢。

reportIncident.wsdl

<?xml version="1.0" encoding="ISO-8859-1"?>
<wsdl:definitions 
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    xmlns:tns="http://reportincident.example.camel.apache.org" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" 
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    targetNamespace="http://reportincident.example.camel.apache.org">

    <!-- Type definitions for input- and output parameters for webservice -->
    <wsdl:types>
        <xs:schema targetNamespace="http://reportincident.example.camel.apache.org">
            <xs:element name="inputReportIncident">
                <xs:complexType name="inputReportIncident">
                    <xs:sequence>
                        <xs:element type="xs:string" name="incidentId" />
                        <xs:element type="xs:string" name="incidentDate" />
                        <xs:element type="xs:string" name="givenName" />
                        <xs:element type="xs:string" name="familyName" />
                        <xs:element type="xs:string" name="summary" />
                        <xs:element type="xs:string" name="details" />
                        <xs:element type="xs:string" name="email" />
                        <xs:element type="xs:string" name="phone" />
                    </xs:sequence>
                </xs:complexType>
            </xs:element>
            <xs:element name="outputReportIncident">
                <xs:complexType name="outputReportIncident">
                    <xs:sequence>
                        <xs:element type="xs:string" name="code" />
                    </xs:sequence>
                </xs:complexType>
            </xs:element>
        </xs:schema>
    </wsdl:types>

    <!-- Message definitions for input and output -->
    <wsdl:message name="inputReportIncident">
        <wsdl:part name="parameters" element="tns:inputReportIncident" />
    </wsdl:message>
    <wsdl:message name="outputReportIncident">
        <wsdl:part name="parameters" element="tns:outputReportIncident" />
    </wsdl:message>

    <!-- Port (interface) definitions -->
    <wsdl:portType name="ReportIncidentEndpoint">
        <wsdl:operation name="ReportIncident">
            <wsdl:input message="tns:inputReportIncident" />
            <wsdl:output message="tns:outputReportIncident" />
        </wsdl:operation>
    </wsdl:portType>

    <!-- Port bindings to transports and encoding - HTTP, document literal 
        encoding is used -->
    <wsdl:binding name="ReportIncidentBinding" type="tns:ReportIncidentEndpoint">
        <soap:binding transport="http://schemas.xmlsoap.org/soap/http" />
        <wsdl:operation name="ReportIncident">
            <soap:operation soapAction="http://reportincident.example.camel.apache.org/ReportIncident" style="document" />
            <wsdl:input>
                <soap:body parts="parameters" use="literal" />
            </wsdl:input>
            <wsdl:output>
                <soap:body parts="parameters" use="literal" />
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>

    <!-- Service definition -->
    <wsdl:service name="ReportIncidentService">
        <wsdl:port name="ReportIncidentPort" binding="tns:ReportIncidentBinding">
            <soap:address location="http://reportincident.example.camel.apache.org" />
        </wsdl:port>
    </wsdl:service>

</wsdl:definitions>

路由定义(在RouteBuilder子类中)

OutputReportIncident ok = new OutputReportIncident();
ok.setCode("0");

// endpoint to our CXF webservice
String cxfEndpoint = "cxf://http://localhost:8080/part-five/webservices/incident"
        + "?serviceClass=org.apache.camel.example.reportincident.ReportIncidentEndpoint"
        + "&wsdlURL=reportIncident.wsdl";

// first part from the webservice -> file backup
from(cxfEndpoint)
    // we need to convert the CXF payload to InputReportIncident that FilenameGenerator and velocity expects
    .convertBodyTo(InputReportIncident.class)
    // then set the file name using the FilenameGenerator bean
    .setHeader("CamelFileName", BeanLanguage.bean(FilenameGenerator.class, "generateFilename"))
    // transform the message using velocity to generate the mail message
    .to("velocity:mailBody.vm")
    // and store the file   
    .to("file://target/subfolder")
    // return OK as response
    // usando transformação!
    .transform(constant(ok));

pom.xml (wsdl2java用于从WSDL生成Java文件)

<plugin>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-codegen-plugin</artifactId>
    <version>2.13.0</version>
    <executions>
        <execution>
            <id>generate-sources</id>
            <phase>generate-sources</phase>
            <configuration>
                <sourceRoot>${project.build.directory}/generated/src/main/java</sourceRoot>
                <wsdlOptions>
                    <wsdlOption>
                        <wsdl>${basedir}/src/main/resources/reportIncident.wsdl</wsdl>
                    </wsdlOption>
                </wsdlOptions>
            </configuration>
            <goals>
                <goal>wsdl2java</goal>
            </goals>
        </execution>
    </executions>
</plugin>

测试代码

package org.apache.camel.example.reportincident;

import static org.junit.Assert.*;

import org.apache.camel.CamelContext;
import org.apache.camel.impl.DefaultCamelContext;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.junit.Test;
import org.jvnet.mock_javamail.Mailbox;

public class ReportIncidentRoutesTest {

    // should be the same address as we have in our route
    private static String ADDRESS = "http://localhost:8080/part-five/webservices/incident";

    private CamelContext context;

    @Test
    public void testRendportIncident() throws Exception {
        // start camel
        startCamel();

        // assert mailbox is empty before starting
        Mailbox inbox = Mailbox.get("incident@mycompany.com");
        assertEquals("Should not have mails", 0, inbox.size());

        // create input parameter
        InputReportIncident input = new InputReportIncident();
        input.setIncidentId("123");
        input.setIncidentDate("2008-08-18");
        input.setGivenName("Claus");
        input.setFamilyName("Ibsen");
        input.setSummary("Bla");
        input.setDetails("Bla bla");
        input.setEmail("davsclaus@apache.org");
        input.setPhone("0045 2962 7576");

        // create the webservice client and send the request
        ReportIncidentEndpoint client = createCXFClient();
        OutputReportIncident out = client.reportIncident(input);

        // assert we got a OK back
        assertEquals("0", out.getCode());

        // let some time pass to allow Camel to pickup the file and send it as an email
        Thread.sleep(3000);

        // assert mail box
        assertEquals("Should have got 1 mail", 1, inbox.size());

        // stop camel
        context.stop();
    }

    private void startCamel() throws Exception {
        context = new DefaultCamelContext();
        context.disableJMX();
        context.addRoutes(new ReportIncidentRoutes());
        context.start();
    }

    private ReportIncidentEndpoint createCXFClient() {
        // we use CXF to create a client for us as its easier than JAXWS and works
        JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
        factory.setServiceClass(ReportIncidentEndpoint.class);
        factory.setAddress(ADDRESS);
        return (ReportIncidentEndpoint) factory.create();
    }

}

1 个答案:

答案 0 :(得分:1)

我认为你只需要将WSDL url传递给JaxWsProxyFactoryBean,它就可以为你处理soap动作。

请像这样更改ReportIncidentRoutesTest.createCXFClient()

private ReportIncidentEndpoint createCXFClient() {
        // we use CXF to create a client for us as its easier than JAXWS and works
        JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
        factory.setServiceClass(ReportIncidentEndpoint.class);
        factory.setWsdlURL("reportIncident.wsdl");
        factory.setAddress(ADDRESS);
        return (ReportIncidentEndpoint) factory.create();
    }