adeelmahmood
adeelmahmood

Reputation: 2431

Using barrier to wait for integration flow to complete

I have an integration flow where some of the steps are async and some of sync. I want to use the barrier to block the Main thread until all async tasks have completed. Based on the documentation, there are two ways to use the barrier.

  1. Send a second trigger message to the input channel of the barrier.
  2. Invoke the trigger method manually of the barrier

In my use case a message comes in the flow and then goes through several components until it reaches the completed channel. I want the main thread to be blocked until the original messages reaches the completed channel. So it seems appropriate to use the option #2 and invoke the barrier trigger method after reaching the completed state. This doesnt seem to work. Here is a simplified version of my flow.

<int:gateway
    service-interface="...BarrierGateway"
    id="barrierGateway" default-request-channel="input">
</int:gateway>

<int:channel id="input">
    <int:dispatcher task-executor="executor" />
</int:channel>

<int:service-activator input-channel="input" output-channel="completed">
    <bean class="...BarrierSA" />
</int:service-activator>

<int:channel id="completed" />
<int:service-activator input-channel="completed"
    ref="barrier1.handler" method="trigger" />

<int:barrier id="barrier1" input-channel="input" timeout="10000" />

I am sending a message to the gateway which passes it to the input channel which is using a dispatcher so a new thread is started to pass the message forward. At this point, I want to block the main thread while the Executor-1 thread goes through the flow. The rest of the flow is simple. My service-activator sleeps for 3 seconds before returning the message to simulate a delay. Once the message is received in the completed channel, the service-activator should invoke the barrier trigger method and only at this point, the main thread should be released. Instead, the main thread is released right after the dispatcher starts a new thread. I have tried specifying a constant correlation id ('abc') but that didnt help.

Upvotes: 2

Views: 1095

Answers (1)

Artem Bilan
Artem Bilan

Reputation: 121442

I see you're caught in a trap.

The <int:barrier> suspends the Thread just on the message message, but only that Thread which brings that message to him. Looking to your config it is the same input channel with Executor. The purpose of the ExecutorChannel to shift message to a different thread, but not suspend the caller's thread.

From other side you have one more mistake around that input. You declare two subscribers for him, where only one of them will be called by the round-robin balancing strategy.

To fix your task we should have one more top-level channel as <publish-subscribe-channel>. And right, already now you can have two subscribers.

One of them should be a <bridge> to your input ExecutorChannel. And another the desired <barrier>. And only now it can suspend (block in your terms) the main thread from the <gateway>.

From other side the more simpler solution would be don't use the <barrier> at all. The <gateway> has an ability to to block the caller's thread and wait for reply. Of course, that works when the gateway methods isn't void.

And one more point to your config: if you don't wait for reply in the gateway, the <barrier> will fail with the

throw new DestinationResolutionException("no output-channel or replyChannel header available");

So, consider to use something as an output-channel there a well.

Upvotes: 2

Related Questions