single jms consumer for multiple jms servers - jms

I am using a distributed jms queue and weblogic is my app server. There are three jms servers deployed in my clustered enviroment. The producers just send the message using name of queue jndi lookup 'udq' for example. Now I have associated a consumer for each jms server and I was able to consume the message, no problem so far.
Here is question, can I have a single consumer to consume the messages from the 3 jms servers. The weblogic allows jndi naming for destination lookup with following syntax #
qsession1 = qcon1.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
qsession2 = qcon2.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
qsession3 = qcon3.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
queue1 = (Queue)ctx.lookup("JMSServer-1#UDQ");
queue2 = (Queue)ctx.lookup("JMSServer-2#UDQ");
queue3 = (Queue)ctx.lookup("JMSServer-3#UDQ");
qreceiver1 = qsession1.createReceiver(queue1);
qreceiver2 = qsession2.createReceiver(queue2);
qreceiver3 = qsession3.createReceiver(queue3);
qreceiver1.setMessageListener(this);
qreceiver2.setMessageListener(this);
qreceiver3.setMessageListener(this);
qcon1.start();
qcon2.start();
qcon3.start();
I have only one OnMessage implemented for the above consumer. This does not work. Any suggestions please..

No, you can't have a consumer receiving messages from more than one JMS server. A consumer can receive messages from only one JMS server. You need to create multiple consumers to receive messages from multiple JMS servers.

you can use "Queue Forwarding" function.
From online documentation of wls 10.3:
"Queue members can forward messages to other queue members by configuring the Forward Delay attribute in the Administration Console, which is disabled by default. This attribute defines the amount of time, in seconds, that a distributed queue member with messages, but which has no consumers, will wait before forwarding its messages to other queue members that do have consumers."
here a link: http://docs.oracle.com/cd/E13222_01/wls/docs103/jms/dds.html#wp1260816
You can configure this feature from administration of each single queue.

Related

Loading balancing consumers on topics on ActiveMQ Artemis

I am using ActiveMQ Artemis 2.10 and JMS Client 1.1 client.
If I used the multicast routing type on my address and needed durable subscriptions, how do I achieve load balancing on the consumer side?
With ActiveMQ 5 it would be virtual destinations.
It is unclear how a consumer side load-balancing could be achieved with ActiveMQ Artemis 7.2 and JMS Client 1.1 client when consuming off durable subscriptions on a topic.
In the example above:
Each of the consumers would set the clientId (client123 and client456) in the example, but this would mean there can be only one instance of client123 consuming from client123.topic.foo.
My current understanding is that ActiveMQ Artemis 2.10 and JMS Client 1.1 client implies you cannot have load balancing on topics, would that be correct?
The only option seems to be ActiveMQ Artemis 2.10 and JMS Client 2.0 which allows you to create Shared Durable subscriptions, would that be correct?
Is there a 3rd option?
My current understanding is that Active MQ Artemis 7.2 and JMS Client 1.1 client implies you cannot have load balancing on topics, would that be correct?
No.
The only option seems to be Active MQ Artemis 7.2 and JMS Client 2.0 which allows you to create Shared Durable subscriptions, would that be correct?
No.
Is there a 3rd option?
Yes. You can use the durable subscription's fully qualified queue name with a JMS consumer. As noted in the JMS-to-core mapping document, a JMS topic is mapped to a core address and a subscription on that JMS topic is mapped to a core queue on the core address. In the case of a durable JMS subscription the name of that queue follows the pattern "<clientID>.<subscriptionName>". Here's some example code to demonstrate:
ConnectionFactory cf = new ActiveMQConnectionFactory("tcp://127.0.0.1:61616");
Connection connection1 = cf.createConnection();
connection1.setClientID("myClientID");
Session session1 = connection1.createSession(false, Session.AUTO_ACKNOWLEDGE);
Topic topic = new ActiveMQTopic("myTopic");
MessageConsumer consumer1 = session1.createDurableSubscriber(topic, "mySubscriptionName");
Connection connection2 = cf.createConnection();
Session session2 = connection2.createSession();
Destination destination = new ActiveMQQueue("myTopic::myClientID.mySubscriptionName");
MessageConsumer consumer2 = session2.createConsumer(destination);
// Send 2 messages
MessageProducer producer = session1.createProducer(topic);
producer.send(session1.createMessage());
producer.send(session1.createMessage());
producer.close();
// Receive the first message with the first consumer
connection1.start();
Message message1 = consumer1.receive();
consumer1.close();
// Receive the second message with the second consumer
connection2.start();
Message message2 = consumer2.receive();
consumer2.close();
To say it another way...
Since JMS 1.1 doesn't explicitly allow shared durable subscriptions then you can't horizontally scale applications using createDurableSubscriber on the same topic with the same client identifier and subscription name. However, you can scale horizontally if one application uses createDurableSubscriber and all the others simply consume directly from the underlying subscription queue using its "fully qualified queue name" (which is derived from the client identifier and subscription name used when it was first created using createDurableSubscriber).

Multiple instances of the same Springboot application but only 1 instance consumes messages from ActiveMQ queue

I am running multiple instances of the same Spring Boot 2.0.4 Application, for scaling purposes, that consume messages from an ActiveMQ queue using the following:
#JmsListener(destination = "myQ")
Only the first consumer receives messages and if I stop the first consumer the second instance starts receiving the messages. I want each consumer to consume a message, not the same message, in a round robin fashion. But only the first consumer consumes messages.
It sounds like you want a JMS Topic rather than a Queue. You should also research durable subscriptions, shared subscriptions, and durable topics before you settle on the configuration you need for your setup.
See:
JMS API Programming Model (Search for JMS Message Consumers)
Queues vs Topics
Durable Queues and Topics

How does a Topic Message Driven Bean behave in Websphere 8.5.5 Cluster Environment

What I would like is to run a Message Driven Bean that listens onto a (Websphere MQ7) topic. I would like to deploy my application on a Websphere 8.5.5 Cluster containing two cluster members.
If a message for the topic arrives I would expect that only one of my two MDBs gets the message and process it.
IBM states that I should set identically ClientIds and Subscription Names to ensure that only one instance is able to process a message on a Topic:
http://www-01.ibm.com/support/docview.wss?uid=swg21442559
Will the second MDB receive the mentioned MQRC_SUBSCRIPTION_IN_USE Exception, or will the cluster take care that one and only one MDB in the cluster will consume the topic-message?
Maybe someone can point me to the IBM Documentation where this behaviour is defined.
To allow multiple concurrent instances of an MDB to access the same subscription on an MQ queue manager you can enable "Allow cloned durable subscriptions" in the activation spec for the MDB.
https://www-01.ibm.com/support/knowledgecenter/SSAW57_8.5.5/com.ibm.websphere.nd.doc/ae/umj_pasm.html
Running like this means both instances of the MDB will start (no IN_USE errors) and each message for that single subscription will be processed by one instance of the MDB. You would use this to workload balance messages across the multiple WAS servers.
This is only true for durable subscriptions. And only when the MDB instances are connected to the same queue manager.

What does Spring JMS ActiveMQ use to determine when a broker should switch Exclusive Consumers?

An exclusive consumer in Activemq is one that is sent every message from a broker until the consumer dies or goes away, at which time the broker switches consumer.
What is it that defines when the switchover takes place? How do you configure this in Spring JMS/ActiveMQ?
It's not Spring JMS doing the checking; it's the JMS provider, ActiveMQ.
JMS is an API specification; an empty framework, essentially. ActiveMQ provides the implementation backing for managing connections, message brokering, load-balancing, fail-over, etc.
The ActiveMQ broker handles switching-over consumers based on queue properties (you don't need to do anything special in your code):
queue = new ActiveMQQueue("TEST.QUEUE?consumer.exclusive=true");
The switch-over takes place when either the consumer disconnects gracefully or the broker determines that the consumer has disappeared (via the wireFormat.maxInactivityDuration elapsing without any messages or keep-alives being received). You don't have to configure anything if you're happy with the default value of wireFormat.maxInactivityDuration (30 seconds), but you can tweak that if you want to change how long it takes before the broker gives up on a client.

JMS Set Reply To Queue Manager

I want to set the required queue manager when sending a JMS message.
Currently I am able to set the destination queue in the JMSReplyTO method, but I don't know how to also specify the queue manager.
TextMessage message = queueSession.createTextMessage();
message.setText(messageStr);
message.setJMSReplyTo(destinationQueue);
queueSender.send(message);
Here you go (for WebSphere MQ):
MQQueue replyToQ = new MQQueue(QMgrName, ReplyQueue);
Destination replyTo = (Destination) replyToQ;
message.setJMSReplyTo(replyTo);
I don't know which MQ you're using, but your class names look like WebSphere's ones, so I'll guess that's it.
The queue manager name can be set on the connection factory, before you get a connection from it. Use MQConnectionFactory#setBrokerQueueManager(String).
The IBM javadocs for the method are here, on publib.
If you're using ActiveMQ, then you can't set the queue manager, since ActiveMQ doesn't support that abstraction. You could name your broker to be whatever you want your messages to use as their queue manager, since ActiveMQ brokers and MQ managers are roughly equivalent. I have no idea if that will help at all, though. You may have to switch to using WebSphere's own MQ.

Resources