Вопрос

I've been spending this afternoon trying to understand Camel & it's webservices components. I'm trying to set up the simplest Camel endpoint for the simplest case I can think of: I've defined a timer that will trigger every 5 seconds. When it triggers, I want to hit a remote RESTful URL, retrieve some JSON, and use it to initialize a new data object.

My Camel route is as follows:

    <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>

The bitcoinPriceSvc is defined in my Spring config as:

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

The ItemRetriever class is as follows:

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);
    }
}

It seems like the ws call is actually being made, but it's being made as a POST rather than a GET, so it fails with a 405 error.

    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=[*/*]}

What am I missing? Thanks!

Это было полезно?

Решение

Turns out you can (and do need to) specify the HttpMethod, although the documentation is pretty opaque.

    <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>

The key here is the "magic" setHeader invocation. Also, I unfairly blamed CXF when the configuration had to be done on Camel's http call...

Better yet:

    <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>

Now the bean has access to a Map of data.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top