gpt4 book ai didi

spring - Apache Camel 和 Web 服务

转载 作者:行者123 更新时间:2023-12-03 23:10:01 26 4
gpt4 key购买 nike

我试图了解如何将 Apache Camel 与任何提供 WSDL 以生成其类以随后调用他的方法以返回一些请求的 Web 服务集成。

我研究了一些关于 Camel Spring ws Camel cxf 包。正如我所看到的,Spring Web 服务组件不支持使用 WSDL,但 CXF 支持,但是它只支持与 CXF 中托管的 JAX-WS 服务的连接。

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

据我所知,实现它的最简单方法是创建一个 Process 或 Bean 来调用远程 Web 服务。

我试图实现一个生产者来调用远程 Web 服务。我的 beans.xml :

<?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 充当生产者的人,只需按照以下步骤作为示例:
  • 首先,我下载最后一个可用于 OpenScape Voice here 的 WSDL 文件在这个developer page .
  • 客户端代码需要在选项 serviceClass 中通知 SEI(服务端点接口(interface))。您可以发出以下命令来生成:

  • wsdl2java -client -d "TargetFolderHere"-autoNameResolution "OpenScape-Voice_V8.00.28.01.wsdl"
  • 在您的项目中插入生成的客户端类。这同样适用于 WSDL 文件。
  • 在您的 beans.xml 中通知 cxfEndpoint 配置。
    <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" />
  • 在 web 服务调用之前,配置一个处理器来通知参数和要执行的方法。
    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);
  • 现在您可以配置路线并作为引用插入到您的 camelContext 中以完成任务。
    <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 提供的答案还可以,也可以满足我的目的。

    最佳答案

    您指的是契约(Contract)优先或自上而下的Web服务开发。在这种方法中,您从 WSDL 定义生成 stub 代码并在您的开发中使用这些类等。我已经做了很多,我已经使用了 .Net、Java、PHP 甚至 Delphi 中创建的服务中的 WSDL(尽管 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>

    您现在可以运行他的 maven 目标 mvn generate-source生成所需的 stub 类以使用此文件。

    我通常会进入处理器/bean 来执行实际的实现,因为我生产和/或使用的大多数 Web 服务都具有相当复杂的数据结构。但是,这实际上取决于服务。

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

    更新:

    根据您上面的示例,您走在正确的轨道上。首先,我想讨论一下 Camel 中的 CXF,这是一个重要的概念。例如,当您看到以下代码时,CXF bean 与其他 bean 略有不同:
    <from uri="file://....."/>
    <to uri="mock"/>

    文件组件是一个生产者,它毕竟生成文件,而模拟组件是一个消费者,因为它获取文件组件生成的数据并使用它来完成其任务。

    Web 服务稍微扭曲了这个概念。当您有如下路线时:



    cxf bean 被称为生产者,因为它调用 Web 服务。当您将 cxf bean 用作消费者或在 <from> 中使用时,它会变得很有趣。你路线的一部分。

    以下是 Web 服务使用者的示例:
    <from uri="cxf:bean:someService" />

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

    在您的情况下,您的 Web 服务 bean 是生产者或客户端。我通常不会为客户端使用 cxf bean,因为我使用的服务可能相当复杂,我需要 Java 的全部功能来处理这些情况。所以我会告诉你如何做到这一点。

    所以在我的世界里,我会走以下 Camel 路线:
    <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>

    我的处理器 bean 将更改为:
    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);

    }
    }

    查看您的代码,我意识到您的 stub 类似乎没有正确生成。我强烈建议您将我帖子中描述的项目添加到您的 POM 文件中。如果您可以发布一些 WSDL 和 XSD 文件,我可以给您更多描述性的答案。

    关于spring - Apache Camel 和 Web 服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29276308/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com