java - 通过 Spring XML 使用 CXF-RS 客户端配置 Camel Producer

标签 java spring cxf apache-camel

我今天下午一直在努力了解 Camel 及其网络服务组件。我正在尝试为我能想到的最简单的情况设置最简单的 Camel 端点:我定义了一个每 5 秒触发一次的计时器。当它触发时,我想访问一个远程 RESTful URL,检索一些 JSON,并使用它来初始化一个新的数据对象。

我的 Camel 路线如下:

    <route>
        <from uri="timer:aTimer?fixedRate=true&amp;period=5s"/>
        <to uri="log:com.foocorp.demonstrations?level=WARN"/>
        <to uri="cxfrs://bean://bitcoinPriceSvc"/>
        <process ref="itemRetriever"/>
        <log message="{$body}"/>
    </route>

bitcoinPriceSvc 在我的 Spring 配置中定义为:

    <cxf:rsClient id="bitcoinPriceSvc" address="http://api.coindesk.com/v1/bpi/currentprice.json"
              serviceClass="com.foocorp.demonstrations.ws.service.RemoteService"
              loggingFeatureEnabled="true" skipFaultLogging="true"
        />

ItemRetriever类如下:

public class ItemRetriever implements Processor
{
    private static final Log log = LogFactory.getLog(ItemRetriever.class);

    @Override
    public void process(Exchange exchange) throws Exception
    {
        exchange.setPattern(ExchangePattern.InOut);
        Message message = exchange.getIn();
        message.setHeader(Exchange.HTTP_METHOD, "GET");
        message.setHeader(Exchange.HTTP_PATH, "/currentprice.json");
        message.setHeader(CxfConstants.CAMEL_CXF_RS_RESPONSE_CLASS, BitcoinPrice.class);
        message.getBody();

        BitcoinPrice price = (BitcoinPrice)exchange.getOut().getBody();
        log.error("Got price: " + price);
    }
}

似乎实际上正在执行 ws 调用,但它是作为 POST 而不是 GET 进行的,因此它失败并显示 405 错误。

    2014-03-23 17:06:47,317 [Camel (camel-1) thread #0 - timer://aTimer] ERROR org.apache.camel.processor.DefaultErrorHandler - Failed delivery for (MessageId: ID-ibc-win-52811-1395608519935-0-115 on ExchangeId: ID-ibc-win-52811-1395608519935-0-116). Exhausted after delivery attempt: 1 caught: org.apache.camel.component.cxf.CxfOperationException: JAXRS operation failed invoking timer://aTimer?fixedRate=true&period=5s with statusCode: 405

Message History
---------------------------------------------------------------------------------------------------------------------------------------
RouteId              ProcessorId          Processor                                                                        Elapsed (ms)
[route1            ] [route1            ] [timer://aTimer?fixedRate=true&period=5s                                       ] [       235]
[route1            ] [to1               ] [log:com.foocorp.demonstrations?level=WARN                                ] [         0]
[route1            ] [to2               ] [cxfrs://bean://bitcoinPriceSvc                                                ] [       234]

Exchange
---------------------------------------------------------------------------------------------------------------------------------------
Exchange[
        Id                  ID-ibc-win-52811-1395608519935-0-116
        ExchangePattern     InOnly
        Headers             {breadcrumbId=ID-ibc-win-52811-1395608519935-0-115, CamelRedelivered=false, CamelRedeliveryCounter=0, firedTime=Sun Mar 23 17:06:47 EDT 2014}
        BodyType            null
        Body                [Body is null]
]

Stacktrace
---------------------------------------------------------------------------------------------------------------------------------------
org.apache.camel.component.cxf.CxfOperationException: JAXRS operation failed invoking timer://aTimer?fixedRate=true&period=5s with statusCode: 405
        at org.apache.camel.component.cxf.jaxrs.CxfRsProducer.populateCxfRsProducerException(CxfRsProducer.java:317)
        at org.apache.camel.component.cxf.jaxrs.CxfRsProducer.invokeHttpClient(CxfRsProducer.java:177)
        at org.apache.camel.component.cxf.jaxrs.CxfRsProducer.process(CxfRsProducer.java:87)
        at org.apache.camel.util.AsyncProcessorConverterHelper$ProcessorToAsyncProcessorBridge.process(AsyncProcessorConverterHelper.java:61)
        at org.apache.camel.processor.SendProcessor$2.doInAsyncProducer(SendProcessor.java:132)
        at org.apache.camel.impl.ProducerCache.doInAsyncProducer(ProducerCache.java:307)
        at org.apache.camel.processor.SendProcessor.process(SendProcessor.java:127)
        at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:72)
        at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:398)
        at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:191)
        at org.apache.camel.processor.Pipeline.process(Pipeline.java:118)
        at org.apache.camel.processor.Pipeline.process(Pipeline.java:80)
        at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:191)
        at org.apache.camel.component.timer.TimerConsumer.sendTimerExchange(TimerConsumer.java:139)
        at org.apache.camel.component.timer.TimerConsumer$1.run(TimerConsumer.java:64)
        at java.util.TimerThread.mainLoop(Timer.java:555)
        at java.util.TimerThread.run(Timer.java:505)

2014-03-23 17:12:12,082 [Camel (camel-1) thread #0 - timer://aTimer] WARN  com.foocorp.demonstrations - Exchange[ExchangePattern: InOnly, BodyType: null, Body: [Body is null]]
2014-03-23 17:12:12,086 [Camel (camel-1) thread #0 - timer://aTimer] INFO  org.apache.cxf.interceptor.LoggingOutInterceptor - Outbound Message
---------------------------
ID: 123
Address: http://api.coindesk.com/v1/bpi/currentprice.json
Http-Method: POST
Content-Type: */*
Headers: {firedTime=[Sun Mar 23 17:12:12 EDT 2014], breadcrumbId=[ID-ibc-win-52811-1395608519935-0-245], Content-Type=[*/*], Accept=[*/*]}

我错过了什么?谢谢!

最佳答案

事实证明,您可以(并且确实需要)指定 HttpMethod,尽管文档非常不透明。

    <route>
        <from uri="timer:aTimer?fixedRate=true&amp;period=60s"/>
        <setHeader headerName="CamelHttpMethod">
            <constant>GET</constant>
        </setHeader>
        <to uri="cxfrs://bean://bitcoinPriceSvc"/>
        <process ref="itemRetriever"/>
        <to uri="log:com.foocorps.demonstrations?level=INFO"/>
        <log message="{$body}"/>
    </route>

这里的关键是“神奇的”setHeader 调用。此外,当配置必须在 Camel 的 http 调用上完成时,我不公平地指责 CXF...

更好的是:

    <route>
        <from uri="timer:aTimer?fixedRate=true&amp;period=60s"/>
        <setHeader headerName="CamelHttpMethod">
            <constant>GET</constant>
        </setHeader>
        <to uri="http4://foo.com/api/dosomething"/>
        <unmarshall ref="json"/>
        <to uri="bean:aDomainPojo"/>
        <to uri="log:com.foocorps.demonstrations?level=INFO"/>
        <log message="{$body}"/>
    </route>

    <dataFormats>
        <json id="json" library="Jackson"/>
    </dataFormats>

现在 bean 可以访问数据的 Map。

关于java - 通过 Spring XML 使用 CXF-RS 客户端配置 Camel Producer,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22597123/

相关文章:

java - 解码 soap 类转换异常

java - 记录生成的 CXF 客户端的原始 XML

java - 关于servlet的正确使用方法的问题

java - 通用方法语法 <Type>method()

java - 从@ElementCollection 中搜索一个对象

java - tx :advice? 的实现在哪里

java - 什么注释/属性定义了 wsdl :definitions section of a wsdl in Jaxb?

java - 用 Java 关闭远程计算机 - 无法启动关闭但没有错误

java - 如何使用 okHttpClient 执行 graphql 查询?

java - 如何配置监听器来处理来自rabbitmq spring中同一队列的多个交换器的消息