How to stop a spring integration process - spring

I have a spring integration xml file as below: I want to introduce a new mechanism to stop the running process whenever needed by the user. How do I include the mechanism below:
<integration:gateway id="inputGateway"
service-interface="com.service.integration.gateways.inputGateway"
default-request-channel="inputGatewayChannel"/>
<integration:channel id="inputGatewayChannel">
<integration:queue capacity="1000"/>
</integration:channel>
<integration:service-activator id="ServiceActivatorA" input-channel="inputGatewayChannel" ref="initiateService" method="process" output-channel="cleanUpServiceChannel" />
<integration:channel id="cleanUpServiceChannel"/>
<integration:service-activator id="ServiceActivatorB" input-channel="cleanUpServiceChannel" ref="processService" method="process" output-channel="luceneIndexReBuilderChannel" />
<integration:channel id="luceneIndexReBuilderChannel"/>
<integration:service-activator id="luceneIndexReBuilderServiceActivator" input-channel="luceneIndexReBuilderChannel" ref="cleanUpLuceneIndexBuilderService" method="process" output-channel="completeChannel"/>
<integration:channel id="completeChannel"/>
<integration:service-activator id="cleanCardPullCompleteServiceActivator" input-channel="completeChannel" ref="completeService" method="processFinalStep"/>

I am going to guess over here because your question is not clear. Please, clarify what exactly you'd like to stop.
But let's assume you start some long process with that flow and you'd like to interrupt it via some end-user hook.
So, consider to have an AtomicBoolean bean the state of which could be checked from time to time in your long process to interrup and can be changed externally by end-user. It can be done also per message where you store such an AtomicBoolean in the headers and check and change it same way as I explained before. Only the problem here that your long process should consult with such a state. Otherwise it cannot be stopped. Even we Thread.currentThread().interrupt().

Related

Recipient list Router with selector expression

I am getting the string messages in a Queue. I am consuming it and doing further processing using the below channel processMessage.
Now I have a requirement where I need to send this messages to another queue based on the selector expression mentioned below.
At the same time I need to make sure that the I am not missing any records in processMessage channel. Assuming that the below configuration is good to go?
or is there any better way to handle this situtaion:
<int:recipient-list-router id="router" input-channel="incomingMsg">
<int:recipient channel="publishToQueue" selector-expression="payload.contains('test trade') "/>
<int:recipient channel="processMessage"/>
</int:recipient-list-router>
<task:executor id="executor" pool-size="10" />
<int:publish-subscribe-channel id="publishToQueue" task-executor="executor"/>
The logical explanation is :
IF payload.contains(test trade)
THEN
PublishToQueue
END IF
ProcessMessage
Your configuration is correct and it is really a classical sample for the Recipient List Router. You send message to the processMessage unconditionally and the same message is sent to the publishToQueue if it fits to the selector expression.
Another way to reach the same is possible via Publish-Subscribe Channel and a Filter in the beginning of the second flow. But I would say your way with the Recipient List Router is really good.
Otherwise it isn't clear what is your question and why you are in doubt to go ahead.

Consume from channel only if the number of messages reaches a count or the message is in the channel since a while

I have a custom sink module and I would like to consume the messages from the input only if the the number of messages reaches a count or if they are in the channel since some time. In nutshell, I want to do a bulk push.
I have tried aggregating the number of messages after consuming and storing them in an aggregated channel backed by SimpleMessageStore and have MessageGroupStoreReaper checking for messages in the channel.
I am not satisfied with this approach as I am consuming the messages and storing them in an in-memory store, I am aware of the JDBC store as well but I don't want to follow this approach as the message channels in spring XD are backed by redis/mq I would like to consume from the input channel based on my conditions.
My current bean configuration is as shown below:
<int:aggregator id="messageAggregator" ref="messageAggregatorBean"
method="aggregate" input-channel="input" output-channel="aggregatorOutputChannel"
release-strategy="messageReleaseStrategyBean" release-strategy-method="canRelease"
send-partial-result-on-expiry="true" message-store="resultMessageStore">
</int:aggregator>
<int:service-activator id="contributionIndexerService"
ref="contributionIndexerBean" method="bulkIndex" input-channel="aggregatorOutChannel" />
<bean id="resultMessageStore"
class="org.springframework.integration.store.SimpleMessageStore" />
<bean id="resultMessageStoreReaper"
class="org.springframework.integration.store.MessageGroupStoreReaper">
<property name="messageGroupStore" ref="resultMessageStore" />
<property name="timeout" value="60000" />
</bean>
<task:scheduled-tasks>
<task:scheduled ref="resultMessageStoreReaper" method="run"
fixed-rate="10000" />
</task:scheduled-tasks>
Any thoughts or comments?
Thanks in advance.
I'm not sure that you will be able to determine the count of messages in the Broker's queue (Redis/RabbitMQ or even just normal JMS), more over how much they have been there.
You definitely should consume them to do such a logic.
And yes, I think Aggregator can help you. But right: that must be a Persistent Message Store.
for the case
if they are in the channel since some time
The Aggregator suggest an option like group-timeout to release those groups which haven't reached the releaseStrategy condition, but you would like to emit them anyway over some time: http://docs.spring.io/spring-integration/reference/html/messaging-routing-chapter.html#agg-and-group-to

Why PollSkipStrategy.skipPoll method is getting called on every message polled from queue?

I'm using inbound poller to process failed requests from backout queue. For scheduling, I'm using corn expression '0 0/2 * * * *' i.e. execute poller every two minutes. The scheduling is working fine as per corn, but PollSkipStrategy.skipPoll method is getting called for every message polled. I was under impression is, poll skip strategy will be execute once for each poll and not for each record polled. I have implementation for PollSkipStrategy.skipPoll, which returns true or false based on peoperty. I'm missing something here? Here is my configuration
<bean id="RegistrationEventPoller"
class="com.poller.RegistrationEventPoller">
<property name="RegistrationEventRetryCount" value="$env{RegistrationEventRetryCount}"/>
</bean>
<bean id="PollSkipAdvice" class="org.springframework.integration.scheduling.PollSkipAdvice">
<constructor-arg ref="PollSkipStrategy"/>
</bean>
<bean id="PollSkipStrategy"
class="com..poller.PollSkipStrategy">
<property name="RegistrationPollerOnOff" value="$env{RegistrationPollerOnOff}"/>
</bean>
The advice is an around advice on the whole flow (MessageSource.receive() and sending the message). When the poller fires it calls the flow for up to maxMessagesPerPoll so, yes, the advice is actually called for each message found within the poll, not just on the first poll. It simply provides a mechanism to stop calling the message source if some condition prevents you from handling messages.
A more sophisticated Smart Polling feature was added in 4.2 which gives you much more flexibility.

How to add/delete listener from listener container at run time

I want to know how can we add/delete some listener from listener container at run time.
I have configured listener container as below :
<rabbit:listener-container connection-factory="connectionFactory">
<rabbit:listener ref="Listener0" queues="ListenerQueue0" />
<rabbit:listener ref="Listener1" queues="ListenerQueue1" />
<rabbit:listener ref="Listener2" queues="ListenerQueue2" />
One method comes to mind is we can add/remove 'rabbit:listener' from xml at run time and refresh application context, so new config will be loaded.
Is this good way of doing ?
Please let me know other suggestions as well. Thanks in advance.
I would not use the approach you describe.
Each <rabbit:listener/> child element is actually a SimpleMessageListenerContainer, the <rabbit:listener-container/> is just syntactic sugar to provide common attributes for the "child" containers.
If your listener is a POJO (i.e. not a MessageListener), wrap it in a MessageListenerAdapter.
So, you can simply create a new SimpleMessageListenerContainer at runtime - be sure to call afterPropertiesSet() after configuring it and then start().

Spring Integration flow (Outbound and inbound)

I have a situation I don't know how to manage it.
The flow I neeed is the following one:
The first service makes its job and creates a message that needs to be retrieved in the chain's end.
When the first service finishes, I need to invoke a push notification server via a new service with a particular message but with some info related to the one created in step 1.
Finally, I the push notification has been sent successfully, I have to retrieve the message created in step 1.
The question is, how can I keep message created in step 1 when the outbound-gateway calling was produced and retrieved me the message from notification push server?
<int:chain input-channel="v1.inputChannel.input" output-channel="v1.inputChannel.output" send-timeout="50000">
<int:header-enricher>
<int:error-channel ref="v1.inputChannel.error" />
</int:header-enricher>
<int:service-activator ref="v1.input.service" method="methodName"/>
<int:service-activator ref="v1.notificationPusher.service" method="pushNotification"/>
<int-http:outbound-gateway url="http://example.com/api/elements/:element_id/objects" http-method="POST">
<int-http:uri-variable name="element_id" expression="#pathVariables.elementId"/>
</int-http:outbound-gateway>
<!-- here the transformer needs to get the messsage from v1.input.service -->
<int:object-to-json-transformer/>
</int:chain>
After some researching in 'Spring Integration in Action' I think the best option for resolving this situation is to use the wire tap pattern, having the push notification service as secondary flow.
Here you can see the book's example where, If I have understood it in a correct way, the auditChannel acts as a secondary flow separated from the main one.
<channel id="debitChannel">
<interceptors>
<wire-tap channel="auditChannel"/>
</interceptors>
</channel>
<service-activator input-channel="debitChannel" method="process">
<beans:bean class="siia.monitoring.wiretap.DebitService"/>
</service-activator>
<filter input-channel="auditChannel" expression="payload.amount > 10000" output-channel="logger"/>
<logging-channel-adapter id="logger" expression="'auditing debit: ' + payload"/>
I think you could achieve this with something like that:
Dupĺicate your message before send it to the outbound
Send one to the outbound and the another one to some channel
Use an Aggregator with the same timeout of your outbound to "join" them, but you could, in fact, only pass the message from the first step through (I haven't tested it)
Send it to the json transformer
To use this approach, I believe, you have to put the outbound and the json-transformer outside the chain as well as your logic to duplicate the message.
I can think of one way, which is to squirrel away the payload into a header after step 1, then retrieve and repopulate the payload right before you invoke step 3:
<int:service-activator ref="v1.input.service" method="methodName"/>
<int:header-enricher>
<int:header name="originalpayload" expression="payload"/>
</int:header-enricher>
<int:service-activator ref="v1.notificationPusher.service" method="pushNotification"/>
<int:enricher expression="headers.originalpayload"/>
<int-http:outbound-gateway url="http://xxx.com/api/elements/:element_id/objects" http-method="POST">
<int-http:uri-variable name="element_id" expression="#pathVariables.elementId"/>
</int-http:outbound-gateway>

Resources