我今天下午一直在努力了解Camel&它的webservices组件。我试图为我能想到的最简单的情况设置最简单的Camel端点:我已经定义了一个每5秒触发一次的计时器。当它触发时,我想点击一个远程RESTful URL,检索一些JSON,并用它来初始化一个新的数据对象。
我的骆驼路线如下:
<route>
<from uri="timer:aTimer?fixedRate=true&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=[*/*]}
我错过了什么?谢谢!
答案 0 :(得分:2)
事实证明你可以(并且确实需要)指定HttpMethod,尽管文档非常不透明。
<route>
<from uri="timer:aTimer?fixedRate=true&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&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。