Quantcast

How to call a route, wait to finish, and ignore any changes when this returns?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

How to call a route, wait to finish, and ignore any changes when this returns?

sim085
Hello,

I have a route "A" which calls a route "B", route "B" adds some headers, removes some others, changes the body, etc. Is there a way how I can call route "B" from route "A", wait for route "B" to finish and once route "B" returns, route "A" will be in the same state as before calling route "B" (i.e. - same headers, same body)?

I tried using the SEDA component with the "waitForTaskToComplete" set to "Always" but this does not seem to work, i.e. - if I use InOnly("seda:B?waitForTaskToComplete=Always") then this works as if calling the SEDA component with inOut(...).

For example:

[code]
                from("seda:A")
                        .log("Hello From A")
                        .setHeader("MyHeader", constant("A-HEADER"))
                        .transform(constant("A-BODY"))
                        .inOnly("seda:B?waitForTaskToComplete=Always")
                        .log("MyHeader is ${in.header.MyHeader}")
                        .log("Body is ${body}")
                ;
               
                from("seda:B")
                        .log("Hello From B")
                        .setHeader("MyHeader", constant("B-HEADER"))
                        .transform(constant("B-BODY"))
                        .log("Ready from B")
                ;
[/code]

Will Print:

[(camel-1) thread #0 - seda://A] route2                         INFO  Hello From A
[(camel-1) thread #1 - seda://B] route3                         INFO  Hello From B
[(camel-1) thread #1 - seda://B] route3                         INFO  Ready from B
[(camel-1) thread #0 - seda://A] route2                         INFO  MyHeader is B-HEADER
[(camel-1) thread #0 - seda://A] route2                         INFO  Body is B-BODY

I was under the impression that calling seda:B with InOnly would force the component not to return however it seems that waitForTaskToComplete=Always makes it work like InOut rather than just wait for the task to complete.

Is there a way how I can achieve the above? i.e. - call a route, wait for this to finish, but message from the caller route (in my case "A") remains the same as before calling the second route.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: How to call a route, wait to finish, and ignore any changes when this returns?

Colin Sharples
I just had a very similar situation, which I got round by using a
ProducerTemplate to call the second route. So instead of the inOnly() in
route A, you would have a Processor which invokes route B synchronously,
which will leave the Exchange in route A unaltered. For example:

.transform(constant("A-BODY"))
.process(exchange -> template.sendBody("seda:B", exchange.getIn().getBody()))
.log("MyHeader is ${in.header.MyHeader}")

which produces the following output:

21:40:35.673 [Camel (camel-1) thread #0 - seda://A] INFO route1 - Hello
 From A
21:40:35.676 [Camel (camel-1) thread #1 - seda://B] INFO route2 - Hello
 From B
21:40:35.676 [Camel (camel-1) thread #1 - seda://B] INFO route2 - Ready
from B
21:40:35.676 [Camel (camel-1) thread #0 - seda://A] INFO route1 -
MyHeader is A-HEADER
21:40:35.677 [Camel (camel-1) thread #0 - seda://A] INFO route1 - Body
is A-BODY

Happy for someone to point out a better way, but this worked for me.

-- ctg

On 9/01/2017 12:48 p.m., sim085 wrote:

> Hello,
>
> I have a route "A" which calls a route "B", route "B" adds some headers,
> removes some others, changes the body, etc. Is there a way how I can call
> route "B" from route "A", wait for route "B" to finish and once route "B"
> returns, route "A" will be in the same state as before calling route "B"
> (i.e. - same headers, same body)?
>
> I tried using the SEDA component with the "waitForTaskToComplete" set to
> "Always" but this does not seem to work, i.e. - if I use
> InOnly("seda:B?waitForTaskToComplete=Always") then this works as if calling
> the SEDA component with inOut(...).
>
> For example:
>
> [code]
> from("seda:A")
> .log("Hello From A")
> .setHeader("MyHeader", constant("A-HEADER"))
> .transform(constant("A-BODY"))
> .inOnly("seda:B?waitForTaskToComplete=Always")
> .log("MyHeader is ${in.header.MyHeader}")
> .log("Body is ${body}")
> ;
>
> from("seda:B")
> .log("Hello From B")
> .setHeader("MyHeader", constant("B-HEADER"))
> .transform(constant("B-BODY"))
> .log("Ready from B")
> ;
> [/code]
>
> Will Print:
>
> [(camel-1) thread #0 - seda://A] route2                         INFO  Hello
> >From A
> [(camel-1) thread #1 - seda://B] route3                         INFO  Hello
> >From B
> [(camel-1) thread #1 - seda://B] route3                         INFO  Ready
> from B
> [(camel-1) thread #0 - seda://A] route2                         INFO
> MyHeader is B-HEADER
> [(camel-1) thread #0 - seda://A] route2                         INFO  Body
> is B-BODY
>
> I was under the impression that calling seda:B with InOnly would force the
> component not to return however it seems that waitForTaskToComplete=Always
> makes it work like InOut rather than just wait for the task to complete.
>
> Is there a way how I can achieve the above? i.e. - call a route, wait for
> this to finish, but message from the caller route (in my case "A") remains
> the same as before calling the second route.
>
>
>
>
> --
> View this message in context: http://camel.465427.n5.nabble.com/How-to-call-a-route-wait-to-finish-and-ignore-any-changes-when-this-returns-tp5792288.html
> Sent from the Camel - Users mailing list archive at Nabble.com.
>
>
>


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: How to call a route, wait to finish, and ignore any changes when this returns?

sim085
Hi Colin,

Thanks for your answer. I tried your example:

[code]
                from("seda:A")
                        .log("Hello From A")
                        .setHeader("MyHeader", constant("A-HEADER"))
                        .transform(constant("A-BODY"))
                        //.inOnly("seda:B")
                        .process(exchange -> exchange.getContext().createProducerTemplate().sendBody("seda:B", exchange.getIn().getBody()))
                        .log("MyHeader is ${in.header.MyHeader}")
                        .log("Body is ${body}")
                ;
               
                from("seda:B")
                        .log("Hello From B")
                        .setHeader("MyHeader", constant("B-HEADER"))
                        .transform(constant("B-BODY"))
                        .log("Ready from B")
                ;
[/code]

However this gives me the following:

[(camel-1) thread #0 - seda://A] route2                         INFO  Hello From A
[(camel-1) thread #1 - seda://B] route3                         INFO  Hello From B
[(camel-1) thread #0 - seda://A] route2                         INFO  MyHeader is A-HEADER
[(camel-1) thread #0 - seda://A] route2                         INFO  Body is A-BODY
[(camel-1) thread #1 - seda://B] route3                         INFO  Ready from B

If I add "?waitForTaskToComplete=Always" when calling "B" I get the correct answer:

[(camel-1) thread #0 - seda://A] route2                         INFO  Hello From A
[(camel-1) thread #0 - seda://A] SedaEndpoint                   INFO  Endpoint Endpoint[seda://B?waitForTaskToComplete=Always] is using shared queue: seda://B with size: 2147483647
[(camel-1) thread #1 - seda://B] route3                         INFO  Hello From B
[(camel-1) thread #1 - seda://B] route3                         INFO  Ready from B
[(camel-1) thread #0 - seda://A] route2                         INFO  MyHeader is A-HEADER
[(camel-1) thread #0 - seda://A] route2                         INFO  Body is A-BODY

So it looks that like that it works.

Likewise I would like to know if there are more "standard" options - if any...
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: How to call a route, wait to finish, and ignore any changes when this returns?

taariq
Hi,
Content enricher seems like a good fit.

Cheers


On 09 Jan 2017 20:35, "sim085" <[hidden email]> wrote:

Hi Colin,

Thanks for your answer. I tried your example:

[code]
                from("seda:A")
                        .log("Hello From A")
                        .setHeader("MyHeader", constant("A-HEADER"))
                        .transform(constant("A-BODY"))
                        //.inOnly("seda:B")
                        .process(exchange ->
exchange.getContext().createProducerTemplate().sendBody("seda:B",
exchange.getIn().getBody()))
                        .log("MyHeader is ${in.header.MyHeader}")
                        .log("Body is ${body}")
                ;

                from("seda:B")
                        .log("Hello From B")
                        .setHeader("MyHeader", constant("B-HEADER"))
                        .transform(constant("B-BODY"))
                        .log("Ready from B")
                ;
[/code]

However this gives me the following:

[(camel-1) thread #0 - seda://A] route2                         INFO  Hello
From A
[(camel-1) thread #1 - seda://B] route3                         INFO  Hello
From B
[(camel-1) thread #0 - seda://A] route2                         INFO
MyHeader is A-HEADER
[(camel-1) thread #0 - seda://A] route2                         INFO  Body
is A-BODY
[(camel-1) thread #1 - seda://B] route3                         INFO  Ready
from B

If I add "?waitForTaskToComplete=Always" when calling "B" I get the correct
answer:

[(camel-1) thread #0 - seda://A] route2                         INFO  Hello
From A
[(camel-1) thread #0 - seda://A] SedaEndpoint                   INFO
Endpoint Endpoint[seda://B?waitForTaskToComplete=Always] is using shared
queue: seda://B with size: 2147483647
[(camel-1) thread #1 - seda://B] route3                         INFO  Hello
From B
[(camel-1) thread #1 - seda://B] route3                         INFO  Ready
from B
[(camel-1) thread #0 - seda://A] route2                         INFO
MyHeader is A-HEADER
[(camel-1) thread #0 - seda://A] route2                         INFO  Body
is A-BODY

So it looks that like that it works.

Likewise I would like to know if there are more "standard" options - if
any...



--
View this message in context: http://camel.465427.n5.nabble.
com/How-to-call-a-route-wait-to-finish-and-ignore-any-change
s-when-this-returns-tp5792288p5792331.html
Sent from the Camel - Users mailing list archive at Nabble.com.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: How to call a route, wait to finish, and ignore any changes when this returns?

sim085
Hi taariq,

thanks for pointing this out. This worked fine.

[code]
                class KeepOriginalAggregationStrategy implements AggregationStrategy {
                    public Exchange aggregate(Exchange original, Exchange resource) {
                        return original;
                    }
                }
                               
                from("seda:A")
                        .log("Hello From A")
                        .setHeader("MyHeader", constant("A-HEADER"))
                        .transform(constant("A-BODY"))
                        .enrich("seda:B", new KeepOriginalAggregationStrategy())
                        .log("MyHeader is ${in.header.MyHeader}")
                        .log("Body is ${body}")
                ;
               
                from("seda:B")
                        .log("Hello From B")
                        .log("MyHeader value frm B is : '${in.header.MyHeader}'")
                        .setHeader("MyHeader", constant("B-HEADER"))
                        .transform(constant("B-BODY"))
                        .log("Ready from B")
                ;
[/code]

Result:

[(camel-1) thread #0 - seda://A] route2                         INFO  Hello From A
[(camel-1) thread #1 - seda://B] route3                         INFO  Hello From B
[(camel-1) thread #1 - seda://B] route3                         INFO  MyHeader value frm B is : 'A-HEADER'
[(camel-1) thread #1 - seda://B] route3                         INFO  Ready from B
[(camel-1) thread #0 - seda://A] route2                         INFO  MyHeader is A-HEADER
[(camel-1) thread #0 - seda://A] route2                         INFO  Body is A-BODY

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: How to call a route, wait to finish, and ignore any changes when this returns?

sim085
However thinking out loud ... is this the right way to do it? This is actually the opposite of message enriching.

It works, I just wonder if it is the right approach.

For example imagine a scenario where you have a CSV file which has a list of users that have to be deleted from a system. You load the CSV file, loop through each line and then have to call a route "seda:deleteuser" but want to keep the original message when this returns. You want to do this synchronous so everything is in order in the logs (so one user after the other). The route "seda:deleteuser" does not enrich the message, it actually does an action on a system (delete a user).

So is it correct to call this route with enrich()?

sim085 wrote
thanks for pointing this out. This worked fine.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: How to call a route, wait to finish, and ignore any changes when this returns?

taariq
In that scenario you might consider multicasting to a route that processes
the deletes in order, as well as to the next/result route.
Just don't process in parallel in that case.

Also, I wouldn't suggest the enricher for each delete like in your example,
perhaps rather route to something that splits and aggregates and then you
might enrich your original exchange with the aggregated result, or
disregard as you did just now.


On 10 Jan 2017 10:15, "sim085" <[hidden email]> wrote:

However thinking out loud ... is this the right way to do it? This is
actually the opposite of message enriching.

It works, I just wonder if it is the right approach.

For example imagine a scenario where you have a CSV file which has a list of
users that have to be deleted from a system. You load the CSV file, loop
through each line and then have to call a route "seda:deleteuser" but want
to keep the original message when this returns. You want to do this
synchronous so everything is in order in the logs (so one user after the
other). The route "seda:deleteuser" does not enrich the message, it actually
does an action on a system (delete a user).

So is it correct to call this route with enrich()?


sim085 wrote
> thanks for pointing this out. This worked fine.





--
View this message in context: http://camel.465427.n5.nabble.
com/How-to-call-a-route-wait-to-finish-and-ignore-any-change
s-when-this-returns-tp5792288p5792341.html
Sent from the Camel - Users mailing list archive at Nabble.com.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: How to call a route, wait to finish, and ignore any changes when this returns?

Christian Schaefer
UNSUBSCRIBE

    Taariq Levack <[hidden email]> schrieb am 18:28 Dienstag, 10.Januar 2017:
 

 In that scenario you might consider multicasting to a route that processes
the deletes in order, as well as to the next/result route.
Just don't process in parallel in that case.

Also, I wouldn't suggest the enricher for each delete like in your example,
perhaps rather route to something that splits and aggregates and then you
might enrich your original exchange with the aggregated result, or
disregard as you did just now.


On 10 Jan 2017 10:15, "sim085" <[hidden email]> wrote:

However thinking out loud ... is this the right way to do it? This is
actually the opposite of message enriching.

It works, I just wonder if it is the right approach.

For example imagine a scenario where you have a CSV file which has a list of
users that have to be deleted from a system. You load the CSV file, loop
through each line and then have to call a route "seda:deleteuser" but want
to keep the original message when this returns. You want to do this
synchronous so everything is in order in the logs (so one user after the
other). The route "seda:deleteuser" does not enrich the message, it actually
does an action on a system (delete a user).

So is it correct to call this route with enrich()?


sim085 wrote
> thanks for pointing this out. This worked fine.





--
View this message in context: http://camel.465427.n5.nabble.
com/How-to-call-a-route-wait-to-finish-and-ignore-any-change
s-when-this-returns-tp5792288p5792341.html
Sent from the Camel - Users mailing list archive at Nabble.com.


   
Loading...