You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@camel.apache.org by jelmer <jk...@gmail.com> on 2016/03/02 21:27:28 UTC

Polling http endpoints

Hi as part of a camel route i upload a file to a REST service, the service
will return status 202 and a Content-Location header that points to a json
resource with a status field
i want to wait for the status of this resource to change to completed, and
only then continue. so i need some sort of polling
But i don't see an obvious way to do this in camel
can anyone offer any suggestions?

Re: Polling http endpoints

Posted by Claus Ibsen <cl...@gmail.com>.
On Mon, Mar 7, 2016 at 4:23 PM, Quinn Stevenson
<qu...@pronoia-solutions.com> wrote:
> Sorry - I forgot that the loop DSL doesn’t take a predicate.
>

Yeah its been talked about from time to time about this need.

I have logged a ticket
https://issues.apache.org/jira/browse/CAMEL-9675

> How about this - configure redelivery handling on your main route, and then have the direct route throw an exception if the payload isn’t ready.
>
> Here’s a mocked example:
> public class MyRouteBuilder extends RouteBuilder {
>     Processor responseProcessor = new ResponseProcessor();
>
>     public void configure() {
>         onException(MyException.class)
>                 .logRetryAttempted(true)
>                 .retryAttemptedLogLevel(LoggingLevel.INFO)
>                 .redeliveryDelay(2000)
>                 .retryWhile(exchangeProperty(ResponseProcessor.RESPONSE_PROPERTY).isNotEqualTo(true))
>         ;
>
>         fromF("timer://%s?period=%d", "my-timer", 5000)
>                 .log("Waiting for processor")
>                 .to( "direct://wait-for-response")
>                 .to("mock://complete")
>         ;
>
>         from("direct://wait-for-response")
>                 .errorHandler(noErrorHandler())
>                 .log( "looking for response")
>                 .process(responseProcessor)
>                 .choice()
>                     .when( exchangeProperty(ResponseProcessor.RESPONSE_PROPERTY).isNotEqualTo( true ) )
>                         .throwException( MyException.class, "Not Ready" )
>                     .otherwise()
>                 .end()
>         ;
>     }
>
> }
> My simple processor just sets an exchange property - nothing fancy but hopefully it illustrates what I’m suggesting.
>
>> On Mar 6, 2016, at 6:18 AM, jelmer <jk...@gmail.com> wrote:
>>
>> It does not look like loop takes a predicate, it expects the expression to
>> be a number, which i think makes it unsuited for this sort of thing.
>>
>> I would this expect this to be a fairly common case, i am surprised its
>> this difficult to figure out how to do this
>>
>> On 4 March 2016 at 16:25, Quinn Stevenson <qu...@pronoia-solutions.com>
>> wrote:
>>
>>> The “direct:await-import-complete” calling itself makes me a little
>>> nervous - the call stack could get pretty deep if it has to wait very long.
>>>
>>> Could you use the loop DSL (http://camel.apache.org/loop.html <
>>> http://camel.apache.org/loop.html>)?
>>>
>>>
>>>> On Mar 3, 2016, at 11:44 AM, jelmer <jk...@gmail.com> wrote:
>>>>
>>>> Since no one answered I came up with this :
>>>>
>>>>   from("file:/Users/jkuperus/foo")
>>>>     .process(ToMultiPartRequestProcessor)
>>>>     .setHeader(Exchange.HTTP_METHOD, constant(HttpMethods.POST))
>>>>     .setHeader(Exchange.CONTENT_TYPE, constant("multipart/form-data"))
>>>>     .setHeader(Exchange.HTTP_PATH, constant("/api/tasks"))
>>>>     .to("http4://localhost:11380")
>>>>     .transform().header("Content-Location")
>>>>     .to("direct:await-import-complete")
>>>>
>>>>
>>>>   from("direct:await-import-complete")
>>>>     .setHeader(Exchange.HTTP_METHOD, constant(HttpMethods.GET))
>>>>     .setHeader(Exchange.HTTP_PATH, body().convertToString())
>>>>     .to("http4://localhost:11380")
>>>>     .transform(body().convertToString())
>>>>     .choice()
>>>>       .when().jsonpath("[?(@.state == 'completed')]")
>>>>         .transform().jsonpath("@.campaignId")
>>>>         .to("direct:do-stuff")
>>>>       .otherwise()
>>>>         .log("Task was not yet completed retrying in 2 seconds")
>>>>         .delay(2000)
>>>>         .transform().header(Exchange.HTTP_PATH)
>>>>         .to("direct:await-import-complete")
>>>>
>>>>
>>>> Does this make any sense ?
>>>>
>>>> On 2 March 2016 at 21:27, jelmer <jk...@gmail.com> wrote:
>>>>
>>>>> Hi as part of a camel route i upload a file to a REST service, the
>>> service
>>>>> will return status 202 and a Content-Location header that points to a
>>> json
>>>>> resource with a status field
>>>>> i want to wait for the status of this resource to change to completed,
>>> and
>>>>> only then continue. so i need some sort of polling
>>>>> But i don't see an obvious way to do this in camel
>>>>> can anyone offer any suggestions?
>>>>>
>>>
>>>
>



-- 
Claus Ibsen
-----------------
http://davsclaus.com @davsclaus
Camel in Action 2: https://www.manning.com/ibsen2

Re: Polling http endpoints

Posted by Quinn Stevenson <qu...@pronoia-solutions.com>.
Sorry - I forgot that the loop DSL doesn’t take a predicate.

How about this - configure redelivery handling on your main route, and then have the direct route throw an exception if the payload isn’t ready.

Here’s a mocked example:
public class MyRouteBuilder extends RouteBuilder {
    Processor responseProcessor = new ResponseProcessor();

    public void configure() {
        onException(MyException.class)
                .logRetryAttempted(true)
                .retryAttemptedLogLevel(LoggingLevel.INFO)
                .redeliveryDelay(2000)
                .retryWhile(exchangeProperty(ResponseProcessor.RESPONSE_PROPERTY).isNotEqualTo(true))
        ;

        fromF("timer://%s?period=%d", "my-timer", 5000)
                .log("Waiting for processor")
                .to( "direct://wait-for-response")
                .to("mock://complete")
        ;

        from("direct://wait-for-response")
                .errorHandler(noErrorHandler())
                .log( "looking for response")
                .process(responseProcessor)
                .choice()
                    .when( exchangeProperty(ResponseProcessor.RESPONSE_PROPERTY).isNotEqualTo( true ) )
                        .throwException( MyException.class, "Not Ready" )
                    .otherwise()
                .end()
        ;
    }

}
My simple processor just sets an exchange property - nothing fancy but hopefully it illustrates what I’m suggesting.

> On Mar 6, 2016, at 6:18 AM, jelmer <jk...@gmail.com> wrote:
> 
> It does not look like loop takes a predicate, it expects the expression to
> be a number, which i think makes it unsuited for this sort of thing.
> 
> I would this expect this to be a fairly common case, i am surprised its
> this difficult to figure out how to do this
> 
> On 4 March 2016 at 16:25, Quinn Stevenson <qu...@pronoia-solutions.com>
> wrote:
> 
>> The “direct:await-import-complete” calling itself makes me a little
>> nervous - the call stack could get pretty deep if it has to wait very long.
>> 
>> Could you use the loop DSL (http://camel.apache.org/loop.html <
>> http://camel.apache.org/loop.html>)?
>> 
>> 
>>> On Mar 3, 2016, at 11:44 AM, jelmer <jk...@gmail.com> wrote:
>>> 
>>> Since no one answered I came up with this :
>>> 
>>>   from("file:/Users/jkuperus/foo")
>>>     .process(ToMultiPartRequestProcessor)
>>>     .setHeader(Exchange.HTTP_METHOD, constant(HttpMethods.POST))
>>>     .setHeader(Exchange.CONTENT_TYPE, constant("multipart/form-data"))
>>>     .setHeader(Exchange.HTTP_PATH, constant("/api/tasks"))
>>>     .to("http4://localhost:11380")
>>>     .transform().header("Content-Location")
>>>     .to("direct:await-import-complete")
>>> 
>>> 
>>>   from("direct:await-import-complete")
>>>     .setHeader(Exchange.HTTP_METHOD, constant(HttpMethods.GET))
>>>     .setHeader(Exchange.HTTP_PATH, body().convertToString())
>>>     .to("http4://localhost:11380")
>>>     .transform(body().convertToString())
>>>     .choice()
>>>       .when().jsonpath("[?(@.state == 'completed')]")
>>>         .transform().jsonpath("@.campaignId")
>>>         .to("direct:do-stuff")
>>>       .otherwise()
>>>         .log("Task was not yet completed retrying in 2 seconds")
>>>         .delay(2000)
>>>         .transform().header(Exchange.HTTP_PATH)
>>>         .to("direct:await-import-complete")
>>> 
>>> 
>>> Does this make any sense ?
>>> 
>>> On 2 March 2016 at 21:27, jelmer <jk...@gmail.com> wrote:
>>> 
>>>> Hi as part of a camel route i upload a file to a REST service, the
>> service
>>>> will return status 202 and a Content-Location header that points to a
>> json
>>>> resource with a status field
>>>> i want to wait for the status of this resource to change to completed,
>> and
>>>> only then continue. so i need some sort of polling
>>>> But i don't see an obvious way to do this in camel
>>>> can anyone offer any suggestions?
>>>> 
>> 
>> 


Re: Polling http endpoints

Posted by jelmer <jk...@gmail.com>.
It does not look like loop takes a predicate, it expects the expression to
be a number, which i think makes it unsuited for this sort of thing.

I would this expect this to be a fairly common case, i am surprised its
this difficult to figure out how to do this

On 4 March 2016 at 16:25, Quinn Stevenson <qu...@pronoia-solutions.com>
wrote:

> The “direct:await-import-complete” calling itself makes me a little
> nervous - the call stack could get pretty deep if it has to wait very long.
>
> Could you use the loop DSL (http://camel.apache.org/loop.html <
> http://camel.apache.org/loop.html>)?
>
>
> > On Mar 3, 2016, at 11:44 AM, jelmer <jk...@gmail.com> wrote:
> >
> > Since no one answered I came up with this :
> >
> >    from("file:/Users/jkuperus/foo")
> >      .process(ToMultiPartRequestProcessor)
> >      .setHeader(Exchange.HTTP_METHOD, constant(HttpMethods.POST))
> >      .setHeader(Exchange.CONTENT_TYPE, constant("multipart/form-data"))
> >      .setHeader(Exchange.HTTP_PATH, constant("/api/tasks"))
> >      .to("http4://localhost:11380")
> >      .transform().header("Content-Location")
> >      .to("direct:await-import-complete")
> >
> >
> >    from("direct:await-import-complete")
> >      .setHeader(Exchange.HTTP_METHOD, constant(HttpMethods.GET))
> >      .setHeader(Exchange.HTTP_PATH, body().convertToString())
> >      .to("http4://localhost:11380")
> >      .transform(body().convertToString())
> >      .choice()
> >        .when().jsonpath("[?(@.state == 'completed')]")
> >          .transform().jsonpath("@.campaignId")
> >          .to("direct:do-stuff")
> >        .otherwise()
> >          .log("Task was not yet completed retrying in 2 seconds")
> >          .delay(2000)
> >          .transform().header(Exchange.HTTP_PATH)
> >          .to("direct:await-import-complete")
> >
> >
> > Does this make any sense ?
> >
> > On 2 March 2016 at 21:27, jelmer <jk...@gmail.com> wrote:
> >
> >> Hi as part of a camel route i upload a file to a REST service, the
> service
> >> will return status 202 and a Content-Location header that points to a
> json
> >> resource with a status field
> >> i want to wait for the status of this resource to change to completed,
> and
> >> only then continue. so i need some sort of polling
> >> But i don't see an obvious way to do this in camel
> >> can anyone offer any suggestions?
> >>
>
>

Re: Polling http endpoints

Posted by Quinn Stevenson <qu...@pronoia-solutions.com>.
The “direct:await-import-complete” calling itself makes me a little nervous - the call stack could get pretty deep if it has to wait very long.

Could you use the loop DSL (http://camel.apache.org/loop.html <http://camel.apache.org/loop.html>)?


> On Mar 3, 2016, at 11:44 AM, jelmer <jk...@gmail.com> wrote:
> 
> Since no one answered I came up with this :
> 
>    from("file:/Users/jkuperus/foo")
>      .process(ToMultiPartRequestProcessor)
>      .setHeader(Exchange.HTTP_METHOD, constant(HttpMethods.POST))
>      .setHeader(Exchange.CONTENT_TYPE, constant("multipart/form-data"))
>      .setHeader(Exchange.HTTP_PATH, constant("/api/tasks"))
>      .to("http4://localhost:11380")
>      .transform().header("Content-Location")
>      .to("direct:await-import-complete")
> 
> 
>    from("direct:await-import-complete")
>      .setHeader(Exchange.HTTP_METHOD, constant(HttpMethods.GET))
>      .setHeader(Exchange.HTTP_PATH, body().convertToString())
>      .to("http4://localhost:11380")
>      .transform(body().convertToString())
>      .choice()
>        .when().jsonpath("[?(@.state == 'completed')]")
>          .transform().jsonpath("@.campaignId")
>          .to("direct:do-stuff")
>        .otherwise()
>          .log("Task was not yet completed retrying in 2 seconds")
>          .delay(2000)
>          .transform().header(Exchange.HTTP_PATH)
>          .to("direct:await-import-complete")
> 
> 
> Does this make any sense ?
> 
> On 2 March 2016 at 21:27, jelmer <jk...@gmail.com> wrote:
> 
>> Hi as part of a camel route i upload a file to a REST service, the service
>> will return status 202 and a Content-Location header that points to a json
>> resource with a status field
>> i want to wait for the status of this resource to change to completed, and
>> only then continue. so i need some sort of polling
>> But i don't see an obvious way to do this in camel
>> can anyone offer any suggestions?
>> 


Re: Polling http endpoints

Posted by jelmer <jk...@gmail.com>.
Since no one answered I came up with this :

    from("file:/Users/jkuperus/foo")
      .process(ToMultiPartRequestProcessor)
      .setHeader(Exchange.HTTP_METHOD, constant(HttpMethods.POST))
      .setHeader(Exchange.CONTENT_TYPE, constant("multipart/form-data"))
      .setHeader(Exchange.HTTP_PATH, constant("/api/tasks"))
      .to("http4://localhost:11380")
      .transform().header("Content-Location")
      .to("direct:await-import-complete")


    from("direct:await-import-complete")
      .setHeader(Exchange.HTTP_METHOD, constant(HttpMethods.GET))
      .setHeader(Exchange.HTTP_PATH, body().convertToString())
      .to("http4://localhost:11380")
      .transform(body().convertToString())
      .choice()
        .when().jsonpath("[?(@.state == 'completed')]")
          .transform().jsonpath("@.campaignId")
          .to("direct:do-stuff")
        .otherwise()
          .log("Task was not yet completed retrying in 2 seconds")
          .delay(2000)
          .transform().header(Exchange.HTTP_PATH)
          .to("direct:await-import-complete")


Does this make any sense ?

On 2 March 2016 at 21:27, jelmer <jk...@gmail.com> wrote:

> Hi as part of a camel route i upload a file to a REST service, the service
> will return status 202 and a Content-Location header that points to a json
> resource with a status field
> i want to wait for the status of this resource to change to completed, and
> only then continue. so i need some sort of polling
> But i don't see an obvious way to do this in camel
> can anyone offer any suggestions?
>