AMQP unable to receive message back from listener - spring-boot

I have a issue with Receive message back from Listener to publisher. I am getting
**AmqpReplyTimeoutException **. Below is the code of Publisher from where i am publishing to queue.
for(CsvWrapperPojo item : items){
resultList.addAll(item.getDbResultList());
for(CSVPojo pojo :item.getQueueRequestList()){
sampleResponseMessageRabbitConverterFuture= asyncRabbitTemplate.convertSendAndReceive("spring-boot-rabbitmq-Interactive.async_Solve_InteractiveMsg", "Interactive_RequestQueue", pojo);
//CSVPojo res =(CSVPojo)rabbitTemplate.convertSendAndReceive("spring-boot-rabbitmq-Interactive.async_Solve_InteractiveMsg", "Interactive_RequestQueue", pojo);
System.out.println("heyyyyyy:" + sampleResponseMessageRabbitConverterFuture.get().getLatitute());
//resultList.add(res);
//resultList.add(sampleResponseMessageRabbitConverterFuture.get());
}
}
By using it i am able to publish to queue, i have subscriber code below.
#EnableRabbit
public class ListenerQueueSubscriber {
#RabbitHandler
#RabbitListener(containerFactory = "simpleMessageListenerContainerFactory", queues ="Interactive_RequestQueue")
public void subscribeToRequestQueue(#Payload CSVPojo sampleRequestMessage, Message message) throws InterruptedException {
System.out.println("inside listener");
sampleRequestMessage.setResult("Hello");
Thread.sleep(120000);
System.out.println("After sleep:" +sampleRequestMessage.getLongitude());
//return sampleRequestMessage;
}
}
By using above subscriber able to listen message and i am appending "Hello and put sleep for 2 minutes and after that i have to receive the message back to publisher from where i have published . But unfortunately not receiving the message with Hello appended getting **AmqpReplyTimeoutException **. Can please help to achieve this behavior.
Thanks in advance!!!!

Related

How to ensure multiple jms listener instances process messages only when currently executing listener instance acknowlege

I'm currently trying to build a messaging application using JMS Listener and IBM MQ, and I need to ensure that I can run two instances of the same listener at the same time. However, I want to make sure that the second instance waits until the first instance has fully processed and acknowledged the message.
I'm using Spring Boot for my application, JMS Listener and IBM MQ.
Below is the my config class which is annotated with #component and #EnableJMS
public class jmsconfig{
#Bean
public MQConnectionfactory getConnectionFactory(){
MQConnectionFactory connectionFactory = new MQConnectionFactory();
connectionFactory.setQueueManagerName("AA");
connectionFactory.setExpirationTimeOut(3600000);
connectionFactory.setPerformExpiration(true);
connectionFactory.setPerformValidation(true);
connectionFactory.setPerformOptimalSizeCheck(false);
connectionFactory.setValidationTimeOut(180000);
connectionFactory.setMinIdle(3);
connectionFactory.setMaxIdle(5);
reurn connectionFactory ;
}
#Bean(name="jmsListenerContainerFactory")
public JmsListenerContainerFactory jmsListenerContainerFactory(MQConnectionfactory mqConnectionfactory){
DefaultJmsListenerContainerFactory containerFactory = new DefaultJmsListenerContainerFactory();
containerFactory.setConnectionFactor(mqConnectionfactory);
containerFactory.setSessionTransacted(true);
containerFactory.setSessionAcknowledgementMode(Session.CLIENT_ACKNOWLEDE)
reurn containerFactory ;
}
}
Listener code:
#Component
public class Receiver {
public sttaic int count = 0;
#JmsListener(destination = "${inwardQueueName}", containerFactory = "jmsListenerContainerFactory")
public void receiveMessage(javax.jms.Message message) throws javax.jms.JMSException {
String messagetxt = "";
OrderObject order = null;
if (message instanceof javax.jms.TextMessage) {
messagetxt = ((TextMessage)message).getText();
OrderObject order = //code to covert messagetxt to object
System.out.println("Message pciked up with Order Id : " +order.getOrderId)
TimeUnit.SECONDS.sleep(15);
count++;
if(count<=4){
throw new Exception("Exception occurred");
}
}
TimeUnit.SECONDS.sleep(15);
System.out.println("Message Acknowledged for orderId: " +order.getOrderId)
message.acknowledge();
}
}
I start the first instance and the push first message to MQ with orderId 1. I can see the below output on the console. It prints the below statement and then waits for 15 seconds
Message picked up with Order Id : 1
Immediately, I start the second instance and the push second message to MQ with orderId 2. I can see the below output on the console.
First Instance picks first message with orderId 2
Message Acknowledged for orderId: 2
After some time, when the first instance completes(since there is a wait of 15 sec), I can see the below output.
Message pciked up with Order Id : 1
Message pciked up with Order Id : 1
Message pciked up with Order Id : 1
Message Acknowledged for orderId: 1
With the above output, the Second instance is picking up second messages from the MQ in parallel and processing them while the first instance is still processing the first message.
Can anyone help with what is wrong with the above implementation?

WebSphere MQ Messages Disappear From Queue

I figured I would toss a question on here incase anyone has ideas. My MQ Admin created a new queue and alias queue for me to write messages to. I have one application writing to the queue, and another application listening on the alias queue. I am using spring jmsTemplate to write to my queue. We are seeing a behavior where the message is being written to the queue but then instantly being discarded. We disabled gets and to see if an expiry parameter was being set somehow, I used the jms template to set the expiry setting (timeToLive). I set the expiry to 10 minutes but my message still disappears instantly. A snippet of my code and settings are below.
public void publish(ModifyRequestType response) {
jmsTemplate.setExplicitQosEnabled(true);
jmsTemplate.setTimeToLive(600000);
jmsTemplate.send(CM_QUEUE_NAME, new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
String responseXML = null;
try {
responseXML myJAXBContext.getInstance().toXML(response);
log.info(responseXML);
TextMessage message = session.createTextMessage(responseXML);
return message;
} catch (myException e) {
e.printStackTrace();
log.info(responseXML);
return null;
}
}
});
}
/////////////////My settings
QUEUE.PUB_SUB_DOMAIN=false
QUEUE.SUBSCRIPTION_DURABLE=false
QUEUE.CLONE_SUPPORT=0
QUEUE.SHARE_CONV_ALLOWED=1
QUEUE.MQ_PROVIDER_VERSION=6
I found my issue. I had a parent method that had the #Transactional annotation. I do not want my new jms message to be part of that transaction so I am going to add jmsTemplate.setSessionTransacted(false); before performing a jmsTemplate.send. I have created a separate jmsTempalte for sending my new message instead of reusing the one that was existing, which needs to be managed.

RabbitMQ - How multiple consumers can consume same message from single queue?

Most of the RabbitMQ documentation seems to be focused on round-robin, ie where a single message is consumed by a single consumer. I have a requirement wherein would like to receive the same message from a single queue to multiple subscribed consumers.
Below is my sample consumers code. Here there are 2 listeners listening to the same Queue, but the message is getting received by only one of the consumer. How do I configure it so that the same message gets delivered to both the Consumers? (Consumer1 and Consumer2).
Any help will be highly appreciated.
#Component
public class Consumer1 {
#RabbitListener(queues="test.queue.jsa")
public void recievedMessage(Employee msg) {
System.out.println("Recieved Message: " + msg);
}
}
#Component
public class Consumer2 {
#RabbitListener(queues="test.queue.jsa")
public void recievedMessage(Employee msg) {
System.out.println("Consumed Message: " + msg);
}
}
This is not possible; it just doesn't work that way. Each consumer needs its own queue; use a fanout exchange.

Sending a Message with Spring Cloud Stream and RabbitMq changes ID

I'm using Spring Cloud Stream and RabbitMq to exchange Messages between different microservices.
Thats my setup to publish a message.
public interface OutputChannels {
static final String OUTPUT_CHANNEL = "outputChannel";
#Output
MessageChannel outputChannel();
}
.
#EnableBinding(OutputChannels.class)
#Log4j
public class OutputProducer {
#Autowired
private OutputChannels outputChannels;
public void createMessage(MyContent myContent) {
Message<MyContent> message = MessageBuilder
.withPayload(myContent)
.build();
outputChannels.outputChannel().send(message);
log.info("Sent message: " + message.getHeaders().getId() + myContent);
}
}
And the setup to receive the message
public interface InputChannels {
String INPUT_CHANNEL = "inputChannel";
#Input
SubscribableChannel inputChannel();
}
.
#EnableBinding(InputChannels.class)
#Log
public class InputConsumer {
#StreamListener(InputChannels.INPUT_CHANNEL)
public void receive(Message<MyContent> message) {
MyContent myContent = message.getPayload();
log.info("Received message: " + message.getHeaders().getId() + ", " + myContent);
}
}
I am able to successfully exchange messages with this setup. I would expect, that the IDs of the sent message and the received message are equal. But they are always different UUIDs.
Is there a way that the message keeps the same ID all the way from the producer, through the RabbitMq, to the consumer?
Spring Messaging messages are immutable; they get a new ID each time they are mutated.
You can use a custom header or IntegrationMessageHeaderAccessor.CORRELATION_ID to convey a constant value; in most use cases, the correlation id header is set by the application to the ID header at the start of a message's journey.

How to subscribe to STOMP messages from an application itself

Is there any way how to subscribe from a topic and forward messaged to another layer of an application (have a new Listener for given topic) using Spring?
Consider following message handler it handler which sends messages to a topic topic/chat/{conversationId}
public class ConversationController{
#MessageMapping("/chat/{conversationId}")
#SendTo("/topic/chat/{conversationId}")
public ConversationMessage createMesage(
#Payload CreateMessage message,
#DestinationVariable String conversationId) {
log.info("handleMessage {}", message);
return conversationService.create( message );
}
}
I would like to listen on this topic and do an action on some messages.
public class Bot{
#SubscribeMapping("/topic/chat/{conversationId}")
public void subscribeUserMessages(
#Payload ConversationMessage message,
#DestinationVariable String conversationId){
// doesn't work
}
}
I've also tried use SimpMessagingTemplate.convertAndSend(..) but it doesn't work neither. Maybe I am doing something wrong.
My application doesn't use full flagged message broker, just the default one in memory broker.

Resources