why message getting re-delivered to a MDB - jms

We have a MDB running on weblogic 12c with the following definition
#TransactionManagement(TransactionManagementType.BEAN)
#MessageDriven(activationConfig = { #ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue") })
public class NonPersistentSalesMessageBean implements MessageListener
{
}
The functionality of this bean is
Receives the message
uses session beans for all business logic (session bean in turn use entity beans(JPA2.0))
reply with the response message back to the destination queue
The bean is receiving duplicate messages frequently. As stated earlier there are some exceptions at the entity bean level while inserting into the database but that's not related to the reply message. The MDB is successfully posting the response back to the destination queue but after 6 or 7 seconds am seeing the same message being sent again.
Why is the message getting redelivered when the app is successfully sending the response back to the destination queue?
Can someone please tell me what are the scenarios for a message to be redelivered ?
I can check using message.getJMSRedelivered() but would like to understand why is this getting redelivered? any help or answer s will be highly appreciated. please
Please note this is a MDB which was running fine on weblogic 10 and we upgraded to 12c when we started to have this issue. So we reverted to weblogic 10 and now its back to working fine.
Thanks...Venkat

Related

Spring Boot JMS listener won't deploy on EAP 7.3 (JBoss/Wildfly)

I'm trying to deploy on EAP 7.3 (ex JBoss, commercial release of Wildfly) an JMS listener like below:
...
#JmsListener(destination = "${jms.destination.name}")
public void onMessage(final Message msg) throws JMSException {
logger.info("*** MessageReceiver.onMessage(): got message {}", ((TextMessage) msg).getText());
}
...
Deploying it on the app server I get the following warning:
2021-06-03 15:57:45,836 WARN [org.springframework.jms.listener.DefaultMessageListenerContainer] (DefaultMessageListenerContainer-7) Setup of JMS message listener invoker failed for destination 'jms.queue.BanQ' - trying to recover. Cause: There is no queue with name jms.queue.BanQ
The deployment gets stuck and the warning above is displayed continuously, every couple of seconds.
So what seems to happen is that the mention queue doesn't exist. However, looking in the console I can see that:
So, as shown in the figure above, the queue named jms.queue.Bank exists. What might be the problem here ?
Many thanks in advance for any help.
Kind regards,
Seymour

Redeliver message to MQ when using #JmsListener

I'm using #EnableJms and #JmsListener annotation to register a queue listener in my application, basing on this tutorial. I'm connecting to IBM MQ, getting connection factory using jndi. I have read about acknowledge modes etc. but still it's a new thing to me. And my problem is that the message is not being returned to a queue (the listener is never called again).
#Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
DefaultJmsListenerContainerFactory factory
= new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(connectionFactory());
factory.setSessionTransacted(true);
factory.setSessionAcknowledgeMode(Session.AUTO_ACKNOWLEDGE); //I have tried also CLIENT_ACKNOWLEDGE
return factory;
}
#JmsListener(containerFactory = "jmsListenerContainerFactory", destination = "myQueue")
#SendTo("secondQueue")
public String testListener(String message){
if(true) throw new NullPointerException();
else return message;
}
Any help would be much appreciated.
I would have also a second question. From what I understand if I would like to implement any operation on a database, only way to rollback a commit (if something went wrong after this) would be to create a transaction manager? If not, I would need to detect a duplicated message.
First set the acknowledgement mode to Session.CLIENT_ACKNOWLEDGE
and when receiving the messages, if it's processed correctly then just call message.acknowledge() method or else don't call.
It will automatically stay in the queue and you don't need to resend it.
You need to use
import javax.jms.Message
I created simple Spring Boot app and Docker container of IBM MQ to test your case.
I found good instructions in this tutorial: https://developer.ibm.com/tutorials/mq-jms-application-development-with-spring-boot/
And in your case this environment behaves as expected: endless cycle of receive message -> NullPointerException -> return message -> ...
Than I found feature of IBM MQ called "Backout Queues & Thresholds", you'll found the explanation in this blog post: https://community.ibm.com/community/user/imwuc/browse/blogs/blogviewer?BlogKey=28814801-083d-4c80-be5f-90aaaf81cdfb
Briefly, it is possible to restrict number of times message returned to queue after exception, and after this limit send message to another queue.
May be in your case this feature used on your destination queue.

How to stop consumers

I made a simple Jms project with 2 java files names are MessageSender.java,MessageConsumer.java.one for sending messages to Activemq:Queue and another for consuming messages from Activemq:Queue.Deployed this project in Apache Tomcat.following code was consumer code.
ActiveMQConnectionFactory connectionFactory=new ActiveMQConnectionFactory("admin","admin","tcp://localhost:61617?jms.prefetchPolicy.queuePrefetch=1");
Connection connection=connectionFactory.createConnection();
final Session session=connection.createSession(true, Session.CLIENT_ACKNOWLEDGE);
Queue queue=session.createQueue("ThermalMap");
javax.jms.MessageConsumer consumer=session.createConsumer(queue);
//anonymous class
MessageListener listener = new MessageListener() {
#Override
public void onMessage(Message msg) {
// My business code
}
};
Later If I want to change consumer code,I don't want to stop Tomcatbecause If I stop Tomcat entire jms project should not work. So clients can't able to sent messages to Activemq:Queue.So I don't want to follow this way.
I am thinking, If I stop consumers through Activemq console page.I don't need to stop Tomcat So clients can able to send messages normally.For this I check AMQ console page,I didn't seen any consumers.
Is it correct way to do this.
If it is correct way, How can I do this.
can anyone suggest me.
Thanks.
Call the .close() method on your MessageConsumer.

org.apache.activemq.ActiveMQConnectionFactory cannot be cast to javax.jms.QueueConnectionFactory

I have integrated JMS in my project and getting the Exception as ActiveMQConnectionFactory cannot be cast to javax.jms.QueueConnectionFactory while calling the JMS receiver from servletcontext listener but it works fine from public static void main method and able to receive message from queue asynchronously.I am able to send the message to queue using queueconnection and queuesession from my web app and using the same qconnection approach in JMS receiver function which implements MessageListener interface.
Can any one suggest me what is the best way to start the JMS receiver or consumer automatically when web app starts because i use servletcontextlistener to start listening the message queue automatically.
(both JMS queuesender and queuereceiver works fine from public static void main method and problem starts only after calling the queuereceiver from contextinitialize method)
Maybe this post can help you.
The cause there were two version of the ActiveMQ-jars in the classpath, said the poster.
In my case, the cause was 2 versions of javax.jms in the classpath: the one that came with ActiveMQ, and the one I was using to compile my sources (ActiveMQ is supposed to be just a test dependency for my application). I changed the scope of my maven dependency javax.jms:jms:1.1 from compile to provided, which removed the javax.jms-jar from my WAR file, and the exception disappeared.
Yes there's a version problem, I was able to fix this problem by using these version of activemq, jms and j2ee dependencies.
ActiveMQ 5.8.0 and above
activemq-broker-5.8.0
activemq-client-5.8.0
geronimo-jms_1.1_spec-1.1.1
geronimo-j2ee-management_1.1_spec-1.0.1
Earlier version of ActiveMQ
activemq-core-5.5.1
geronimo-j2ee-management_1.0_spec-1.0
geronimo-jms_1.1_spec-1.1.1
Check the versions it'll help

Not seeing message properties that I set explicitly (Spring/JMS/MQ)

Two separate processes are communicating via JMS over MQ.
The writer sets a string property:
new MessageAction() {
public void actOn(Message message) throws JMSException {
logger.debug("Setting message property (GmmThreadId, CASHFLOW-1234)");
message.setStringProperty("GmmThreadId", "CASHFLOW-1234");
}
});
This MessageAction is executed, as shown in the logs:
Setting message property (GmmThreadId, CASHFLOW-1234)
The reader uses a message selector to obtain this message. (using Spring's JmsTemplate v1 - an old version I know, but it's baked into our vendor's framework and we're compelled to use it.)
template.receiveSelected(queue, "GmmThreadId = 'CASHFLOW-1234' or GmmThreadId IS NULL");
The only messages on the queue are ones for which the logs show that the writer set the message property. In the logs for the reader, I enumerate the properties and also try to log the value of GmmThreadId. It also shows that the property GmmThreadId does not exist.
message property JMS_IBM_PutDate = 20111003
message property JMSXAppID = WebSphere MQ Client for Java
message property JMS_IBM_Format = MQSTR
message property JMS_IBM_PutApplType = 28
message property JMS_IBM_MsgType = 8
message property JMSXUserID = MUSR_MQADMIN
message property JMS_IBM_PutTime = 23551798
message property JMSXDeliveryCount = 2
message had GmmThreadId property of null
Note, if my message selector is only "GmmThreadId = 'CASHFLOW-1234'" then nothing is dequeued.
Using WebSphere MQ Explorer to view the message, I cannot find anywhere to view the application set message properties. The message type is MQSTR, if that makes any difference.
Both reader and writer applications are running in WebSphere v6.
Where am I going wrong?
As indicated by this thread the message properties will be suppressed if the destination type is 'MQ'. For me, this is configured in the WebSphere App Server console. I changed the queue type to 'JMS' and the message properties were persisted.

Resources