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

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

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

Verfiy/Test Acknowledgment was called in spring boot kafka

I've written integration tests for my Spring Boot Kafka (Consumer/Producer) service everything gone well. So I'm committing the offsets of my consumer manually after some processing.
I want to verify whether acknowledgment.acknowledge() was called in the consumer. Is is to possible verify?
Here is my method signature of the service:
#KafkaListener(topics = {TOPIC_XXX_V1}, containerFactory = "XXXListener")
private void consumer(#Payload XXXXRequestEvent xxxxRequestEvent, Acknowledgment acknowledgment) {
.....
// do something with the database
acknowledgment.acknowledge()
For the testing side I'm using #SpyBean for the Service and a MockBean for the database interaction. I want verify somehow whether in the test case the .acknowledge() was called. FYI: the .acknowledge() is a public abstract void method
As the Acknowledge instance is injected and created as part of Spring Kafka when consuming a message, I guess there is no way to use something like verify() of Mockito for this.
When writing a unit test instead you could pass a mocked version of Acknowledge here and then verify that this method was invoked. However, with a unit test, you can't test the actual consumption of a message (serialization, correct message handler, etc.).
So in your case, I would try to verify that your message was acknowledged by e.g. using Testcontainers to execute commands inside the Kafka container and ensuring that the already acknowledged message is not returned any more.
Another approach could be to create a Kafka client as part of your test and then try to consume messages from the same topic for X seconds and expect zero results. Awaitility might help you here.

Starting Spring Boot application without check for Kafka Server

I have got an application that uses SpringBoot 2.10.0.Release and kafka in the version 2.10.0. The application has got a simple producer and consumer: The sender works with KafkaTemplate and the consumer with KafkaListener.
What I try to achieve is to be able to start the SpringBoot application even if the KafkaServer is not running.
Currently without a running KafkaBroker the application cannot be started with this error message:
org.springframework.context.ApplicationContextException:
Failed to start bean 'org.springframework.kafka.config.internalKafkaListenerEndpointRegistry';
nested exception is org.apache.kafka.common.errors.TimeoutException
Is there a way to achieve this and if yes could anybody give me hint or a keyword how to manage this?
When running the Spring-Boot application with a KafkaListener, the listener will per default try to listen to Kafka. If the KafkaBroker is invalid or missing, then you will get a org.apache.kafka.common.KafkaException.
You can change the default behaviour of the container factory by setting the autoStartup property to false. One way to do this is by adding autoStartup = "false" element to your KafkaListener annotation:
#KafkaListener(topics = "some_topic", autoStartup = "false")
public void fooEventListener(){
Now your spring boot application will start. You will still get an error when trying to use the KafkaListener if the broker is still down or invalid, but you will now be able to handle the error within your Java code instead of a Spring Boot server crash.
Documentation about KafkaListner autoStartup element.
It have to be mentioned that the error you are receiving (TimeoutException) is not because the broker is down, it is what Kafka will throw if the buffer is full.
The batch records will then be removed from the queue and will not be delivered to the broker. This error will not be the reason for you application using Kafka not to start.

Spring JMS Message Redelivery not working as expected for CLIENT_ACKNOWLEDGE mode

My environment: spring 4.1, JBoss EAP 6.4, IBM MQ 8.0:
Messages are not redelivered in the case where Listener throws RuntimeException.
I have the following in JmsConfig:
#Bean
DefaultMessageListenerContainer defaultMessageListenerContainer(QueueConnectionFactory connectionFactory, JndiDestinationResolver dr, MessageListener ml) {
DefaultMessageListenerContainer mlc = new DefaultMessageListenerContainer();
mlc.setConnectionFactory(connectionFactory);
mlc.setMessageListener(ml);
mlc.setDestinationName(jndiInQueue);
mlc.setDestinationResolver(dr);
mlc.setSessionTransacted(true);
mlc.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE);
return mlc;
}
If I use a JmsTransactionManager and pass it to the above method and use like so:
mlc.setTransactionManager(tm)
Following warnings are written to the log:
It is not valid to commit a non-transacted session, and the behavior is the same, no redelivery.
ConnectionFactory is obtained via JNDI, I wonder if sourcing the ConnectionFactory through jndi has something to do with this?
From the AbstractMessageListenerContainer Javadocs:
In order to consistently arrange for redelivery with any container variant, consider "CLIENT_ACKNOWLEDGE" mode or - preferably - setting "sessionTransacted" to "true" instead
There is a similar question on SO.
Flip your ack mode to Session.SESSION_TRANSACTED instead of CLIENT_ACKNOWLEDGE.
Client Ack mode doesn't work as most folks want it.. and is a common "gotcha" in JMS. It acknowledges current message AND all previous messages in the session. It is not per-message acknowledgement.
Edit:
Also check related post-- IBM MQ may require you to use the "XA" versions of the connection factory class.
ref: Websphere Liberty profile - transacted Websphere MQ connection factory

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.

Resources