<int-jms:message-driven-channel-adapter>
Using message driven adapter , i want to filter message from AMQ broker using selector .
message has to filtered against dynamic bean variable value which is validated using selector bean ref option
In reply to your comments..
Thanks for your reply , I want to filter message using selector attribute in Message driven channel adaptor . i was able to call bean method inside selector attribute #bean.method() , but not able to pass header parameter to that method #bean.method(header.param) . I am expecting selector should validate dynamically passing the header parameter to bean method and return boolean result so that message can be filtered.
<int-jms:message-driven-channel-adapter connection-factory="connectionFactoryName"
destination="destinationName" channel="channelName"
selector="#{#bean.method(header.param)}" auto-startup="false"/>
the above selector attribute has bean method configured to receive header param dynamically whenever pick message from AMQ . but it is syntactically wrong not able to pass header param. can you help?
You don't seem to understand what a JMS message selector is...
selector="foo='bar'"
...tells the broker to only send messages with the foo property equal to bar.
It is configured on the consumer during startup.
What you have is not "dynamic". #{...} expressions are evaluated once during context initialization.
What you are trying to do makes no sense; there is no "message" from which to evaluate a header yet. You can't tell the broker which message(s) to send, based on the contents of a message. The filtering is done on the broker before sending the message(s).
If you don't mind "losing" the messages you are not interested in (or are consuming from a topic) and you want to filter the messages you want to process, then add a
<filter ... expression="#{#bean.method(header.param)}" />
after the adapter. You could use the discard channel to republish the ignored message(s) to another queue (or do something else with them).
Related
So,
I have 2 Spring Boot applications (2.6.10) that need to communicate via RabbitMQ / AMQP. App #1 is Spring Integration based and uses
Amqp.outboundAdapter(rabbitTemplate).routingKey("app1-to-2")
to send messages in flow #1
Amqp.inboundAdapter(connectionFactory, "app2-to-1")
to receive messages in flow #2
App #2 is using RabbitListener to receive messages from App #1, process them immediately and return a reply:
#RabbitListener(queues={"app1-to-2"})
public MyResponse handleMessage(final MyRequest request) {
var myResponse = this.process(myRequest);
rabbitTemplate.convertAndSend("app2-to-1",myResponse);
}
However, upon receiving myRequest in App #2, the response cannot be send, due to:
AmqpException: Cannot determine ReplyTo message property value: Request message does not contain reply-to property, and no default response Exchange was set.
Question is: Why is the routing key from convertAndSend ignored or how to set reply-to property with Amqp.outboundAdapter?
Your error has nothing to do with the convertAndSend().
It is the problem of the #RabbitListener method signature.
Since you don't deal with request-reply pattern, your listener method must have a void return type. Otherwise it tries to send that MyResponse object as a reply message body and therefore we see that error trying to resolve ReplyTo from default strategy.
In my code I have a inbound adapter channel and a service activator I want not to connect service activator with out bound channel ,
Code I am using
<file:inbound-channel-adapter id="filesIn"
directory="E:/usmandata/logs/input" filter="onlyLogFiles"
auto-startup="true">
<int:poller id="poller" fixed-delay="5000" />
</file:inbound-channel-adapter>
<int:service-activator input-channel="filesIn" ref="handler" />
As mentioned in the docs , simply make it as void return type or set it to nullChannel
If the method returns a result and no "output-channel" is defined, the framework will then check the request Message’s replyChannel header value. If that value is available, it will then check its type. If it is a MessageChannel, the reply message will be sent to that channel. If it is a String, then the endpoint will attempt to resolve the channel name to a channel instance. If the channel cannot be resolved, then a DestinationResolutionException will be thrown. It it can be resolved, the Message will be sent there. If the request Message doesn’t have replyChannel header and and the reply object is a Message, its replyChannel header is consulted for a target destination. This is the technique used for Request Reply messaging in Spring Integration, and it is also an example of the Return Address pattern.
If your method returns a result, and you want to discard it and end the flow, you should configure the output-channel to send to a NullChannel. For convenience, the framework registers one with the name nullChannel. See Section 4.1.6, “Special Channels” for more information.
The Service Activator is one of those components that is not required to produce a reply message. If your method returns null or has a void return type, the Service Activator exits after the method invocation, without any signals. This behavior can be controlled by the AbstractReplyProducingMessageHandler.requiresReply option, also exposed as requires-reply when configuring with the XML namespace. If the flag is set to true and the method returns null, a ReplyRequiredException is thrown.
I have got a question about Spring AMQP Message:
During processing I was able to update headers of message properties in String AMQP Message with some specific values.
After DeadLettering of this message, all specific headers were disappeared/removed.
Is this behaviour correct ?
Looking forward to your response.
Regards, Anton.
spring-rabbit.version: 1.3.5.RELEASE
spring.version: 4.1.1.RELEASE
The broker knows nothing about your client-side consumer changes; the original message (with its orignal headers) is dead-lettered by the broker (with an x-death header added to indicate the reason - rejection, expiry etc).
In order to do what you want, you need to publish your modified message yourself rather than using dead-lettering.
See the RepublishMessageRecoverer for an example using Spring retry. You can make a custom recover, or simply catch the exception in your listener to republish.
I am using spring integration based Component. That components receives some XML and enriched that XML with some more content.
However, if an exception occurs , then i want to sent the received input XML as the failed message, however in current scenario, it will hold the partially enriched XML as there failed Message.
Is there any way through which I can change the failed message of the Exception , which in turn is wrapped by the Messaging Exception.
As it is so specific case, we need to see your configuration and especially where is an error-channel and how you enrich XML.
However, keep in mind, that Message is immutable object and each interaction with it provides a new Message. But the payload is out of scope of the messsaging and it might not be immutable. And if change of some property of your payload and then you get some exception, you end up in the ErrorMessage with inbound message (failed), but payload might change its state.
Looks like it is your case.
You should think about some payload-cloning variant before you start to enrich it.
Here are some advices on the matter: https://jira.springsource.org/browse/INT-2979
On my gateway, I have a method
#Gateway
String commsTest();
The idea is that I can call commsTest from the bean and use spring integration to wire it up to the service activator that will check comms.
When I do that I get a receive is not supported, because no pollable reply channel has been configured error. I realise that this is because a method with no params means "I am trying to poll a message from the channel"
This is a two part question.
What does it mean to poll a message from the channel.
How can I get the functionality I want.
Spring Integration currently has no concept of a message without a payload. By default, a gateway method with no arguments implies you want to receive data (rather than sending data or sending and receiving data).
You can change that default behavior, as described in the reference documentation.