How to process message in order with spring integration - spring-integration

Does the spring integration framework have any features I can use to guarantee message order?
We are needing to run our spring integration flow on two different nodes to keep up with the message volume. I have seen several solutions for solving this issue, but I wanted to see if the framework already has something.
This article might better explain what I'm trying to ask.
http://sleeplessinslc.blogspot.com/2010/02/message-ordering-in-jms-using-coherence.html

Yes, it is here. And its name Resequencer.
From Spring Integration Reference Manual: http://docs.spring.io/spring-integration/docs/latest-ga/reference/html/messaging-routing-chapter.html#resequencer.
Each of message for reordering has to have a correlationId header to compare with other messages and sequenceNumber to determine the real order of that message to emit.
The release-partial-sequences="true" does the stuff to release messages, when the correct order is achieved by default SequenceSizeReleaseStrategy on the next message.

Related

Is it possible to make a Poller (or PollableMessageSource) to poll messages as List?

Following the example found in GitHub https://github.com/spring-cloud/spring-cloud-gcp/tree/master/spring-cloud-gcp-samples/spring-cloud-gcp-pubsub-polling-binder-sample regarding polling messages from a PubSub subscription, I was wondering...
Is it possible to make a PollableMessageSource retrieve List<Message<?>> instead of a single message per poll?
I've seen the #Poller notation only being used in Source typed objects, never in Processor or Sink. Is it possible to use in such context when for example using #StreamListener or with a functional approach?
The PollableMessageSource binding and Source stream applications are fully based on the Poller and MessageSource abstraction from Spring Integration where its contract is to produce a single message to the channel configured. The point of the messaging is really to process a single message not affecting others. The failure for one message doesn't mean to fail others in the flow.
On the other hand you probably mean GCP Pub/Sub messages to be produced as a list in the Spring message payload. That is really possible, but via some custom code from Pub/Sub consumer and MessageSource impl. Although I would think twice to expect some batched from the source. Probably you may utilize an aggregator to build some small windows if your further logic is about processing as list. But again: it is going to be a single Spring message.
May be better to start thinking about a reactive function implementation where you indeed can expect a Flux<Message<?>> as an input and Spring Cloud Stream framework will take care for you how to emit the data from Pub/Sub into the reactive stream you expect.
See more info in docs: https://docs.spring.io/spring-cloud-stream/docs/3.1.0/reference/html/spring-cloud-stream.html#_reactive_functions_support

Spring Cloud Stream #StreamListener and Spring Integration's Resequencer Pattern

AFAIK the Spring Cloud Stream project is based on Spring Integration. Hence I was wondering if there is a nice way to resequence a subset of inbound messages before the StreamListener handler is triggered? Or do I need to assemble the whole IntegrationFlow from scratch using XML or Java DSL config from Spring Integration?
My use case is as follows. Most of the time I process inbound messages on a Kafka topic as they come. However, a few events have to be resequenced based on CORRELATION_ID, SEQUENCE_NUMBER, and SEQUENCE_SIZE headers. In other words I'd like to keep using StreamListener as much as possible and simply plug in resequencing strategy for some events.
Yes, you would need to use Spring Integration for it. In fact Spring Cloud Stream is effectively a binding framework only. It binds message handlers to the message brokers via binders. The message handlers themselves are provided by the users.
The #StreamListener annotation is pretty much an equivalent of Spring Integration's #ServiceActivator with few extra features (e.g., conditional routing), but other then it is just a message handler.
Now, as you eluded to, you are aware that you can use Spring Integration (SI) to implement a message handler or an internal SI flow, and that is normal and recommended for complex cases.
That said, we do provide out of the box apps that implements certain EIP components and we do have, for example, and aggregator app which you can use as a starting point in implementing resequencer. Further more, given that we have an aggregator app and not resequencer, we would be glad to accept a contribution for it if you're interested.
I hope this answers you question.

Message persistence in Spring Integration Aggregator without MessageStore by using AMQP?

I would like to know if I can have persistence in my Spring Integration setup when I use a aggregator, which is not backed by a MessageStore, by leveraging the persistence of AMQP (RabbitMQ) queues before and after the aggregator.
I imagine that this would use ack's: The aggregator won't ack a message before it's collected all the parts and sent out the resulting message.
Additionally I would like to know if this is ever a good idea :)
I am new working with queue's, and am trying to get a good feel for patterns to use.
My business logic for this is as follows:
I receive a messages on one queue.
Each message must result in two unrelated webservice calls (preferably in parallel).
The results of these two calls must be combined with details from the original message.
The combination must then be sent out as a new message on a queue.
Messages are important, so they must not be lost.
I was/am hoping to use only one 'persistent' system, namely RabbitMQ, and not having to add a database as well.
I've tried to keep the question specific, but any other suggestions on how to approach this are greatly appreciated :)
What you would like to do recalls me Scatter-Gather EI Pattern.
So, you get a message from the AMQP send it into the ScatterGather endpoint and wait for the aggregated reply. That's enough for to stick with the default acknowledge.
Right, the scatterChannel can be PublishSubscribeChannel with an executor to call Web Services in parallel. Anyway the gatherer process will wait for replies according the release strategy and will block the original AMQP listener do not ack the message prematurely.

Spring Integration Multiple Endpoints

Currently i am working on a Spring Integration application which has a following scenario.
There is a Transformer which transforms incoming message in to a particular object type
Once the transformation is done, we need to write it to a log file and to a database table and then finally send to a JMS outbound adapter.
I was reading the Spring Integration reference and found out there are two ways we can approach this scenario.
Introduce a pub-sub channel as the output channel of the above mentioned transformer and have File-outbound, DB-outbound and JMS-outbound as the subscribers.
Introduce a Recipient List Router just after the transformer and specify the File-outbound, DB-outbound and JMS-outbound as the recipients.
When it comes to Enterprise Integration Patterns what is the best way to handle this scenario? Any new suggestions and improvements are welcome
Thanks,
Keth
There is no "best way" - both solutions are equivalent and there is little difference at runtime. So it's your preference; I generally use pub/sub for the simple case and an RLR if the recipients are conditional (with selectors).

Pick jms message when required in spring integration

I have a requirement to fetch jms message from IBM MQ. But the messages should be fetched only when required, say when a method is invoked. The picked up message need to be put to another queue in turn. That is , this scenario is for copying message from one queue to another when required.
How could I achieve this in Spring Integration.
I believe i could create a flow using inbound-channel-adapter, set to poll message at regular interval, along with outbound-channel-adapter. But with this, I could not pick the message as and when required.
Please advise.
Question updated:
1) While searching on the web to implement the suggested solution, I stepped on the spring documentation for JmsDestinationPollingSource saying - "This source is only recommended for very low message volume".
2) Since we need for high volume environment and in need of local transaction, I looked into the suggested JmsMessageDrivenEndpoint solution which looked like using MessageDrivenChannelAdapter. Can you please adviseas how i could proceed.
3) Also, in that case how can i detect if all messages have been read to stop the listener . Please advise
Question updated:
I am able to invoke start and stop on DefaultMessageListener container used with MessageDrivenChannelAdapter.
Can you also please advise as how I could find when there are no messages on the queue or when the queue is empty so that I could invoke stop.
Question updated:
Thanks Gary. Sorry for the late update.
To find when the queue becomes empty, can we override noMessageReceived method of DefaultMessageListenerContainer (inherited from AbstractPollingMessageListenerContainer) and invoke stop on the DMLC. This kind of solution is given in
Spring integration inbound-gateway Fire an event when queue is empty.
I thought this might be easier to implement. Please advise if it will be correct to do in that way.
Set auto-startup="false" on the inbound channel adapter (so it won't poll).
Get a reference to its MessageSource (either by #Autowire or otherwise injecting or context.getBean()). The bean name is adapterid.source and is of type JmsDestinationPollingSource.
Then invoke the receive() method.
Or you can just wire up a JmsDestinationPollingSource bean yourself without using the namespace support.

Resources