当前位置: 首页 > 知识库问答 >
问题:

Apache Camel和web服务

史鸿运
2023-03-14

我试图理解如何将Apache Camel与任何web服务集成,这些web服务提供WSDL来生成类,然后调用his方法返回一些请求。

我对camel-spring-ws和camel-cxf包进行了一些研究。正如我所看到的,Spring Web Services组件不支持使用WSDL,但CXF支持,不过它只支持与托管在CXF中的JAX-WS服务的连接。

如果我从客户那里收到WSDL,我可以使用CXF吗?或者我需要创建一个自定义组件来使用他的方法?

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:camel="http://camel.apache.org/schema/spring"
       xmlns:cxf="http://camel.apache.org/schema/cxf"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd 
       http://camel.apache.org/schema/cxf http://camel.apache.org/schema/cxf/camel-cxf.xsd">

    <import resource="classpath:META-INF/cxf/cxf.xml"/> 

    <cxf:cxfEndpoint 
        id="osvEndpoint" 
        address="http://10.193.1.90:8767/" 
        serviceClass="siemens_hiq8000.SiemensHiq8000PortType"/> 

    <bean id="osvWebServiceProcessor" class="br.com.willianantunes.processor.OsvWebServiceProcessor" />

</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:camel="http://camel.apache.org/schema/spring"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">

    <routeContext id="osvWebServiceInvoke" xmlns="http://camel.apache.org/schema/spring">
        <route>
            <from uri="quartz2://test?cron=0/10+*+*+*+*+?"/>
            <process ref="osvWebServiceProcessor" />
            <to uri="cxf:bean:osvEndpoint"/>
            <to uri="log:live?level=INFO" />
        </route>
    </routeContext>

</beans>

和我的处理器:

public class OsvWebServiceProcessor implements Processor
{
    @Override
    public void process(Exchange exchange) throws Exception
    {
        Message inMessage = exchange.getIn();

        // The method to be called
        inMessage.setHeader(CxfConstants.OPERATION_NAME, "getVersion");

        // Parameters to be passed into the web service
        List<Object> params = new ArrayList<Object>();
        ResultCodeStructHolder resultCodeStructHolder = new ResultCodeStructHolder();
        VersionDataHolder versionDataHolder = new VersionDataHolder();
        params.add(resultCodeStructHolder);
        params.add(versionDataHolder);
        inMessage.setBody(params);
    }
}

方法getVersion需要一些参数,如下所示:

public void getVersion(siemens_hiq8000.holders.ResultCodeStructHolder result, 
siemens_hiq8000.holders.VersionDataHolder versionData) throws java.rmi.RemoteException;

我怎么才能通过他们?这些持有者必须用web服务的响应填充。当我运行我的项目时,我得到以下错误:

[main] INFO org.apache.cxf.service.factory.ReflectionServiceFactoryBean - Creating Service {http://siemens_hiq8000/}SiemensHiq8000PortType from class siemens_hiq8000.SiemensHiq8000PortType
Exception in thread "main" java.lang.NoSuchMethodError: org.apache.cxf.wsdl11.WSDLEndpointFactory.createEndpointInfo(Lorg/apache/cxf/service/model/ServiceInfo;Lorg/apache/cxf/service/model/BindingInfo;Ljava/util/List;)Lorg/apache/cxf/service/model/EndpointInfo;
    at org.apache.cxf.frontend.AbstractWSDLBasedEndpointFactory.createEndpointInfo(AbstractWSDLBasedEndpointFactory.java:287)
    at org.apache.cxf.frontend.AbstractWSDLBasedEndpointFactory.createEndpoint(AbstractWSDLBasedEndpointFactory.java:144)
    at org.apache.cxf.frontend.ClientFactoryBean.create(ClientFactoryBean.java:91)
    at org.apache.camel.component.cxf.CxfSpringEndpoint.createClient(CxfSpringEndpoint.java:116)
    at org.apache.camel.component.cxf.CxfProducer.doStart(CxfProducer.java:76)
    at org.apache.camel.support.ServiceSupport.start(ServiceSupport.java:61)
    at org.apache.camel.impl.DefaultCamelContext.startService(DefaultCamelContext.java:2869)
    at org.apache.camel.impl.DefaultCamelContext.doAddService(DefaultCamelContext.java:1097)
    at org.apache.camel.impl.DefaultCamelContext.addService(DefaultCamelContext.java:1058)
    at org.apache.camel.impl.ProducerCache.doGetProducer(ProducerCache.java:405)
    at org.apache.camel.impl.ProducerCache.acquireProducer(ProducerCache.java:123)
    at org.apache.camel.processor.SendProcessor.doStart(SendProcessor.java:219)
    at org.apache.camel.support.ServiceSupport.start(ServiceSupport.java:61)
    at org.apache.camel.util.ServiceHelper.startService(ServiceHelper.java:74)
    at org.apache.camel.util.ServiceHelper.startService(ServiceHelper.java:59)
    at org.apache.camel.util.ServiceHelper.startServices(ServiceHelper.java:103)
    at org.apache.camel.util.ServiceHelper.startServices(ServiceHelper.java:89)
    at org.apache.camel.processor.DelegateAsyncProcessor.doStart(DelegateAsyncProcessor.java:79)
    at org.apache.camel.support.ServiceSupport.start(ServiceSupport.java:61)
    at org.apache.camel.util.ServiceHelper.startService(ServiceHelper.java:74)
    at org.apache.camel.util.ServiceHelper.startService(ServiceHelper.java:59)
    at org.apache.camel.util.ServiceHelper.startServices(ServiceHelper.java:103)
    at org.apache.camel.util.ServiceHelper.startServices(ServiceHelper.java:89)
    at org.apache.camel.processor.RedeliveryErrorHandler.doStart(RedeliveryErrorHandler.java:1272)
    at org.apache.camel.support.ChildServiceSupport.start(ChildServiceSupport.java:44)
    at org.apache.camel.support.ChildServiceSupport.start(ChildServiceSupport.java:31)
    at org.apache.camel.util.ServiceHelper.startService(ServiceHelper.java:74)
    at org.apache.camel.util.ServiceHelper.startService(ServiceHelper.java:59)
    at org.apache.camel.util.ServiceHelper.startServices(ServiceHelper.java:103)
    at org.apache.camel.util.ServiceHelper.startServices(ServiceHelper.java:89)
    at org.apache.camel.processor.interceptor.DefaultChannel.doStart(DefaultChannel.java:153)
    at org.apache.camel.support.ServiceSupport.start(ServiceSupport.java:61)
    at org.apache.camel.util.ServiceHelper.startService(ServiceHelper.java:74)
    at org.apache.camel.util.ServiceHelper.startService(ServiceHelper.java:59)
    at org.apache.camel.util.ServiceHelper.startServices(ServiceHelper.java:103)
    at org.apache.camel.util.ServiceHelper.startService(ServiceHelper.java:61)
    at org.apache.camel.util.ServiceHelper.startServices(ServiceHelper.java:103)
    at org.apache.camel.util.ServiceHelper.startServices(ServiceHelper.java:89)
    at org.apache.camel.processor.MulticastProcessor.doStart(MulticastProcessor.java:1060)
    at org.apache.camel.support.ServiceSupport.start(ServiceSupport.java:61)
    at org.apache.camel.util.ServiceHelper.startService(ServiceHelper.java:74)
    at org.apache.camel.util.ServiceHelper.startService(ServiceHelper.java:59)
    at org.apache.camel.util.ServiceHelper.startServices(ServiceHelper.java:103)
    at org.apache.camel.util.ServiceHelper.startServices(ServiceHelper.java:89)
    at org.apache.camel.processor.DelegateAsyncProcessor.doStart(DelegateAsyncProcessor.java:79)
    at org.apache.camel.support.ServiceSupport.start(ServiceSupport.java:61)
    at org.apache.camel.util.ServiceHelper.startService(ServiceHelper.java:74)
    at org.apache.camel.impl.RouteService.startChildService(RouteService.java:340)
    at org.apache.camel.impl.RouteService.warmUp(RouteService.java:182)
    at org.apache.camel.impl.DefaultCamelContext.doWarmUpRoutes(DefaultCamelContext.java:3090)
    at org.apache.camel.impl.DefaultCamelContext.safelyStartRouteServices(DefaultCamelContext.java:3020)
    at org.apache.camel.impl.DefaultCamelContext.doStartOrResumeRoutes(DefaultCamelContext.java:2797)
    at org.apache.camel.impl.DefaultCamelContext.doStartCamel(DefaultCamelContext.java:2653)
    at org.apache.camel.impl.DefaultCamelContext.access$000(DefaultCamelContext.java:167)
    at org.apache.camel.impl.DefaultCamelContext$2.call(DefaultCamelContext.java:2467)
    at org.apache.camel.impl.DefaultCamelContext$2.call(DefaultCamelContext.java:2463)
    at org.apache.camel.impl.DefaultCamelContext.doWithDefinedClassLoader(DefaultCamelContext.java:2486)
    at org.apache.camel.impl.DefaultCamelContext.doStart(DefaultCamelContext.java:2463)
    at org.apache.camel.support.ServiceSupport.start(ServiceSupport.java:61)
    at org.apache.camel.impl.DefaultCamelContext.start(DefaultCamelContext.java:2432)
    at org.apache.camel.spring.SpringCamelContext.maybeStart(SpringCamelContext.java:255)
    at org.apache.camel.spring.SpringCamelContext.onApplicationEvent(SpringCamelContext.java:121)
    at org.apache.camel.spring.CamelContextFactoryBean.onApplicationEvent(CamelContextFactoryBean.java:332)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:151)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:128)
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:331)
    at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:773)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:483)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:93)
    at org.apache.camel.spring.Main.createDefaultApplicationContext(Main.java:216)
    at org.apache.camel.spring.Main.doStart(Main.java:156)
    at org.apache.camel.support.ServiceSupport.start(ServiceSupport.java:61)
    at org.apache.camel.main.MainSupport.run(MainSupport.java:150)
    at br.com.willianantunes.test.Program.main(Program.java:12)

对于那些想让camel-cxf像生产者一样工作的人,只需按照下面的步骤作为示例:

  1. 首先,我在此开发人员页面中下载了OpenScape Voice可用的最后一个WSDL文件。
  2. 客户端代码是在选项serviceClass中通知SEI(服务endpoint接口)所必需的。您可以发出以下命令来生成:

wsdl2java-client-d“targetfolderhere”-autonameresolution“openscape-voice_v8.00.28.01.wsdl”

<import resource="classpath:META-INF/cxf/cxf.xml" />    

<cxf:cxfEndpoint xmlns:urn="urn:openscape-voice"
    id="osvEndpoint" 
    address="http://10.193.1.90:8767/" 
    serviceClass="voice.openscape.OpenscapeVoicePortType"
    wsdlURL="OpenScape-Voice_V8.00.28.01.wsdl"
    serviceName="urn:openscape_voice">  
</cxf:cxfEndpoint>

<bean id="osvWebServiceProcessor" class="br.com.willianantunes.processor.OsvWebServiceProcessor" />
Message inMessage = exchange.getIn();

// The method to be called
inMessage.setHeader(CxfConstants.OPERATION_NAME, "GetVersion");

// Parameters to be passed into the web service
List<Object> params = new ArrayList<Object>();

Holder<ResultCodeStruct> result = new Holder<>();
Holder<VersionData> versionData = new Holder<>();

params.add(result);
params.add(versionData);
inMessage.setBody(params);
<routeContext id="osvWebServiceInvoke" xmlns="http://camel.apache.org/schema/spring">
    <route>
        <from uri="quartz2://test?cron=0/10+*+*+*+*+?"/>
        <process ref="osvWebServiceProcessor"/>
        <to uri="cxf:bean:osvEndpoint"/>
        <to uri="log:live?level=INFO"/>
    </route>
</routeContext>

并且日志打印以下内容:

- Quartz scheduler 'DefaultQuartzScheduler-main-application' initialized from an externally provided properties instance.
- Quartz scheduler version: 2.2.1
- Job Camel_main-application.test (triggerType=CronTriggerImpl, jobClass=CamelJob) is scheduled. Next fire date is Tue Mar 31 09:12:00 BRT 2015
- AllowUseOriginalMessage is enabled. If access to the original message is not needed, then its recommended to turn this option off as it may improve performance.
- StreamCaching is not in use. If using streams then its recommended to enable stream caching. See more details at http://camel.apache.org/stream-caching.html
- Creating Service {urn:openscape-voice}openscape_voice from WSDL: OpenScape-Voice_V8.00.28.01.wsdl
- Could not find endpoint/port for {urn:openscape-voice}openscape_voicePortTypePort in wsdl. Using {urn:openscape-voice}openscape_voice.
- Route: route1 started and consuming from: Endpoint[quartz2://test?cron=0%2F10+*+*+*+*+%3F]
- Starting scheduler.
- Scheduler DefaultQuartzScheduler-main-application_$_NON_CLUSTERED started.
- Total 1 routes, of which 1 is started.
- Apache Camel 2.15.0 (CamelContext: main-application) started in 10.759 seconds
- Exchange[ExchangePattern: InOnly, BodyType: org.apache.cxf.message.MessageContentsList, Body: [null, javax.xml.ws.Holder@508696f5, javax.xml.ws.Holder@333cf1ba]]

我在CXF依赖项方面遇到了一些问题,所以下面是我的pom.xml:

<dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-cxf</artifactId>
    <version>${camel-version}</version>
</dependency>
<!-- Apache CXF -->
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-frontend-jaxws</artifactId>
    <version>${cxf.version}</version>
</dependency>
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-frontend-jaxrs</artifactId>
    <version>${cxf.version}</version>
</dependency>   
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-transports-http</artifactId>
    <version>${cxf.version}</version>
</dependency>
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-transports-http-jetty</artifactId>
    <version>${cxf.version}</version>
</dependency>
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-bindings-soap</artifactId>
    <version>${cxf.version}</version>
</dependency>   
<dependency>
    <groupId>javax.ws.rs</groupId>
    <artifactId>jsr311-api</artifactId>
    <version>1.1.1</version>
</dependency>
<!-- End of Apache CXF -->

您可以设计一个新的处理器或bean来从web服务获得带有响应的主体消息(不是纯SOAP消息,而是以前使用的POJO)。

@Namphibian提供的答案是可以的,也符合我的目的。

共有1个答案

长孙弘盛
2023-03-14

您指的是契约优先或自顶向下的Web服务开发。在这种方法中,您可以从WSDL定义生成存根代码,并在开发中使用这些类等。我已经做了很多这方面的工作,并且使用了在。NET、Java、PHP甚至Delphi中创建的WSDL from service(尽管Delphi破坏了WSI的遵从性)。

CXF将从库所指向的任何WSDL生成类。首先,您需要在Maven POM文件中添加一个条目,告诉Maven从WSDL为您生成类。

将以下内容添加到POM文件中:

<plugin>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-codegen-plugin</artifactId>
    <version>get the latest version or the version you want</version>
    <executions>
        <execution>
        <id>generate-sources</id>
        <phase>generate-sources</phase>
        <configuration>

            <sourceRoot>
            ${basedir}/target/generated/src/main/java
            </sourceRoot>
            <wsdlOptions>
                <wsdlOption>
                <wsdl>
                URI/FILE PATH OF WSDL HERE
                </wsdl>
                <extraargs>
                <extraarg>-impl</extraarg> <-- use this if you want to implement the service i.e. create it
                <extraarg>-client</extraarg> <-- us this if you want to generate a client for the service.
                </extraargs>
                </wsdlOption>
            </wsdlOptions>
        </configuration>
        <goals>
        <goal>wsdl2java</goal>
        </goals>
        </execution>
    </executions>
</plugin>

因此,简而言之,您可以使用CXF为几乎生成存根类(Delphi伙计们,你们在听吗?)然后在处理器中使用这些生成的类来实现客户端和服务器。

更新:

根据你上面的例子,你是在正确的轨道上。首先,我想讨论CXF在camel中的一些内容,这是一个重要的概念。例如,当您看到以下代码时,CXF bean与其他bean略有不同:

<from uri="file://....."/>
<to uri="mock"/>

下面是一个Web服务使用者的示例:

<from uri="cxf:bean:someService" />

CXF bean使用Web服务调用,然后将消息发送到其他各个部分。这允许您公开一些非常复杂的事情,例如从FTP服务器下载文件,使用JDBC调用充实内容,然后在SAP系统中将充实的数据作为Web服务处理。您的路由将 中的cxf bean作为服务公开,路由的其余部分可以完成所有集成,但它作为Web服务公开。非常强大的概念。

在您的情况下,Web服务bean是生产者或客户机。我通常不为客户机使用cxf bean,因为我使用的te服务可能相当复杂,我需要Java的全部能力来处理这些情况。所以我将向你们展示如何这样做。

<routeContext id="osvWebServiceInvoke" xmlns="http://camel.apache.org/schema/spring">
    <route>
        <from uri="quartz2://test?cron=0/10+*+*+*+*+?"/>
        <process ref="osvWebServiceProcessor" />
        <to uri="log:live?level=INFO" />
    </route>
</routeContext>
public class OsvWebServiceProcessor implements Processor
{
    @Override
    public void process(Exchange exchange) throws Exception
    {
        Message inMessage = exchange.getIn();



       /*
              SInce i dont have access to the WSDL and XSD I cant say how the following code will look but essentially you would need to call the web-service here in Java code and get the result back.

       */
      outSOAPMsg=  siemens_hiq8000.SiemensHiq8000PortType.OperationName(inSOAPMsg)
      //set the reply into the inbody and send onto other components for processing.
      inMessage.setBody(outSOAPMsg);

  }
}
 类似资料:
  • 我正在尝试向异步路由发送消息,但它不起作用。我刚刚在github上创建了一个项目来模拟这个问题

  • 我正在使用apache camel cxf开发一个Web服务(肥皂),我遇到了这个错误。 Java . lang . illegalargumentexception:Part { http://blue print . camel . ngt . TN/}返回的类型应为[ltn . ngt . camel . blue print . WB _ subscriptions;,而不是org . A

  • 我有一个restendpoint示例。org,返回表单的json响应 我的路线是这样的 我读过关于轮询消费者的内容,但找不到如何继续轮询endpoint的示例,直到它返回“success”响应。 是否应该使用轮询消费者?如果是这样的话,可以举一个与我的案例相关的例子。用于轮询restendpoint的任何其他资源都非常有用。

  • 问题内容: 我是Java新手,我知道Web服务有两种类型 SOAP Web服务。 RESTful Web服务。 谁能告诉我两者的基本区别是什么?在什么情况下创建?在什么情况下创建? 谢谢, 问题答案: 正如第一个答案已经解释的那样,SOAP Webservices和REST Webservices在各个方面有所不同。 肥皂: 您可以在.wsdl文件中定义您的界面,该文件准确描述了预期的输入参数以及

  • 错误日志: 浏览器出错 org.springframework.web.util.NestedServletException:请求处理失败;嵌套异常为java.lang.IllegalArgumentException:无效的处理程序方法返回值:false org.springframework.web.servlet.frameworkServlet.processRequest(framew

  • 我需要将文件从文件夹同步到restendpoint。因此,如果文件被放置在特定文件夹中,我需要将该文件发送到接受多部分文件的RESTendpoint。我正在使用ApacheCamel来实现这一点。 RESTendpoint在Spring中编写,如下所示: 我是Camel的新手,并且已经弄清楚了如何通过构建路由并获取文件来轮询目录,但是我无法弄清楚如何使用此路由将此文件放入其余endpoint。这是