Spring integration - Processing 2 same messages in aggregation differently - spring

I am connecting to TCP socket using spring integration. I send 2 different messages on an outbound gateway which returns same outputs i.e. header as well as payload.
Now I want to process reply messages differently and then aggregate into a single message which can then be processed by main service class.
I tried various techniques but nothing worked.
Is it feasible to do so? If yes, kindly help me out.

You need something to correlate the messages, maybe a header (e.g. the standard correlation id).
Use a header-enricher to set the correlation id header on each outbound message. Send the reply messages to an <aggregator /> with a simple release strategy (release-strategy-expression="size() == 2"). When the second reply is received, a message with a payload (collection of the 2 payloads) will be released.

Related

How to capture group specific messages with OutputDestination?

We have integration tests that end up dispatching many messages on the same destination, but many different groups. In rabbitMQ terms, same exchange with different topics.
spring.cloud.stream.bindings.userEdited-out-0.destination=user.exchange
spring.cloud.stream.rabbit.bindings.userEdited-out-0.producer.routing-key-expression='user-edited.v1'
spring.cloud.stream.bindings.userEdited-out-0.content-type=application/json
spring.cloud.stream.bindings.userCreated-out-0.destination=user.exchange
spring.cloud.stream.rabbit.bindings.userCreated-out-0.producer.routing-key-expression='user-created.v1'
spring.cloud.stream.bindings.userCreated-out-0.content-type=application/json
I have been successful with reading these messages using OutputDestination, but it appears that I'm only able to pull messages sent to a destination (exchange), and not able to also filter by the group (topic) it was sent to.
Is there any way to pull messages from the OutputDestination by destination and group?
That is correct and is by design, since grouping is specific to a binder implementation (i.e., rabbit) OR part of native functionality of the broker (kafka).
So the test binder is designed to ensure that all core components involved in receiving and sending messages are tested.

Restrict incoming message signature for message broker

My goal is to define some API using REST arch style and spring boot in order to store messages to activemq message broker. I would like to have REST on top of message broker to have possibility to restrict message format. Actually the main goal is to allow only messages which contains all nessessary fields inside message payload.
Could you please suggest if it is rigth way to go and if there are any alternative ways to achive the goal?
Yes. This is a REST-to-Messaging Proxy design and can work just fine for the use case you described.
Alternatively, you could do the message inspection in the broker, but since this inspection sounds logic-related, it is best suited for something running outside the broker.

Is there any way to find the status of RabbitMq consumer/listener

I've written a RabbitMq listener application using spring-boot and want to know the status whether it is processing the messages or idle.
I've been through the rabbitMq HTTP API doc and found /api/queues/vhost/name/get endpoint gives the message count and message body. I see an opportunity in that, decided to compare the message count and message body for two successive responses. If both responses are same then the listener is idle else it's processing.
I used RestTemplate's postForEntity() with {"count":1,"requeue":true,"encoding":"auto"} as request body. But strangely rabbitmq-server isn't responding for this API, however its responding for other API endpoint in the doc.
If there's any way to get the status of the listener, please share the details. Thanks in advance.
Spring AMQP listener containers emit a ListenerContainerIdleEvent objects when there is no messages during some interval.
See docs for more info: https://docs.spring.io/spring-amqp/docs/2.1.7.RELEASE/reference/html/#idle-containers
For the RabbitMQ REST API, there is a Java wrapper - Hop: https://github.com/rabbitmq/hop
So, consider to use its Client.getQueue(String vhost, String name) for your goal, if a ListenerContainerIdleEvent doesn't fit your requirements.

MassTransit3 how to make request from consumer

I want to make a req/res request from IConsumer.Consume() method, but I don't see any method on ConsumeContext<> that returns a reference to IRequestClient<,>. Do I need to hold a reference to IBusControl somewhere and use it or I can use context somehow?
In this case, it is best to create the request client outside of the consumer and pass it as a dependency to the consumer as an IRequestClient<,> interface. The request client is created with IBus, which is outside of the consumer context.
It also ensures that the request will be less likely to deadlock with the broker because responses are received on the bus endpoint, and not the receive endpoint of the consumer (which, if you had a concurrency limit of 1, would never finish).
It's also not possible to connect consumers to a started receive endpoint, which is a requirement of the request/response handling (it happens under the covers). The bus, however, can connect consumers for messages which are sent (responses are sent to the bus address, versus being published) which is why it is used for responses to the requests.
To keep message tracking continuous, it may be nice to set the InitiatorId on the outbound request to the CorrelationId of the consumer message, as well as copying the ConversationId. This helps with tracing and keeping track of the overall message command/event flow.

camel jms request / reply

I'm quite new to camel so excuse me if this is obvious.
We're trying to set up a camel route (in talend esb) which does the following:
receive a Message by JMS
db update
send the message to another system by JMS using request/reply
use the information in the reply to do another db update
This is all in one route.
What I have found out is that the route doesn't accept any more Messages in 1. while it is waiting for the reply in 3.
I have tried to use the "asyncConsumer" parameter on the JMS component but that didn't help.
How can I design the route so that it can process a second (and more) Message while it is still waiting for a reply in 3. ?
Thanks,
Laci
The parameter Petter explained will help but you will still block threads. Another approach is to design the integration as two separate routes. In the first route you receive the jms message, update the db and send out the second message.
If you use InOnly on the producer of this route and set a JMSReplyTo as well as preserveMessageQuo=true then camel will send out the message but not wait for a reply.
Then you use a second route that listens on the reply to queue you specified and does the second db update. This way you do not block any threads.
Use the concurrentConsumers attribute. It will enable multiple threads to handle your load. Note that you have to specify the number of threads. This can be a bit complex with all options, so be sure to read the Camel JMS documentation properly.
example
from("jms:myQueue?concurrentConsumers=10")
You may want to specify concurrentConsumers on the reply queue for the request reply as well:
.inOut().to("jms:requestQueue:foo?concurrentConsumers=10")
The last part Requires version 2.10.3 though.

Resources