Subscribe to multiple topic destination in ActiveMQ Messaging - java

A publisher publishes messages to different destinations. My client needs to subscribe and get all those messages in those destinations one by one.Means i want to consume messages from multiple topics. Also I want the topic messages (different destinations) to be received in a button action, not by using Message Listener. Can anyone please help on this?
Part of my code is.
MessageConsumer consumer = null;
if (isDurableSubscription) {
// the subscription Name assigned to a durable subscription must be unique within a given client ID.
consumer = session.createDurableSubscriber( topic, subscriptionName );
} else {
consumer = session.createConsumer( topic );
}
log.finest("consumer = " + consumer );
consumer.setMessageListener( this );
conn.start();
}
public void onMessage(Message message) {
if ( message instanceof TextMessage ) {
try {
TextMessage txtMessage = (TextMessage) message;
String text = txtMessage.getText();
this.msg = text;
System.out.println(text);
log.finest("Message processed ...");
session.commit();
}

Also i want the topic messages (different destinations) to be
received in a button action, not by using Message Listener.
The whole point of a JMS provider is to listen to messages published by a producer and have an async communication channel in which the producer and the listener are decoupled. When you say you want to receive messages in a button action, it's equivalent of saying "I don't really care when the publisher produced the message, but I'll listen when I feel like" - which doesn't fit the use of a JMS. May be a queue where you have messages and pick one after the other based on some user action.
The publisher will not mark the message as delivered (based on how you have configured it) until the client acknowledges it and in your case (even if it were possible), it may be a long time and the message might expire. One way to achieve this, with JMS, is to have your internal data structure where you keep all your messages (after picking them up from the topic using a listener) and then process it on a button action. But you'll lose all the benefits of a JMS provider (durability, loss of messages upon client shut down, and the likes).

Related

Spring Boot/RabbitMQ avoid unack msg

#RabbitListener(queues="XYZ")
public void rabbitMsgReceiver(#Payload final UserProfile up, Message msg, Channel channel) {
}
If the message that is received is not a valid JSON of UserProfile, then ListenerExecutionFailedException occurs and the message goes to the
unack state. How can I send the message into the dead letter queue?
You can configure a dead letter queue policy in order to send unacked message to dlq instead of putting them to the original queue
https://www.rabbitmq.com/dlx.html#using-policies
example for your queue XYZ, suppose your set XYZ-dlq for it :
sudo rabbitmqctl set_policy XYZ-dlq "^XYZ$" '{"dead-letter-exchange":"", "dead-letter-routing-key":"XYZ-dlq"}' --apply-to queues

Mqtt Pub-Sub with Quality of Service=2 in java

I have some doubts regarding QoS=2 settings.
Mqtt publisher-subscriber am using Qos=2. Up to my knowledge by setting Qos=2 avoid duplication of message delivery among subscribers. In publisher i have set the Qos=2. I have two subscribers listening the same TOPIC. My code is running correctly but both subscribers getting the same message.
By setting Qos=2 Only one subscriber can get the message right?
How to solve this issue?
public class PubSync {
public static void main(String[] args) {
try {
MqttClient client = new MqttClient(TCPAddress,MqttClient.generateClientId());
MqttTopic topic = client.getTopic(MYTOPIC);
MqttMessage message = new MqttMessage(msg.getBytes());
message.setQos(2);
client.connect();
MqttDeliveryToken token = topic.publish(message);
token.waitForCompletion();
client.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
}
QOS 2 means the that each subscriber will only receive 1 copy of any given message.
This differs from QOS 1 where it is possible that a subscriber may receive multiple copies of the same message as the broker ensures that message is delivered.
The QOS levels do not change in any way how many subscribers will see a message.
Depending on the MQTT messaging provider you are using, you should be able to share a subscription to a topic across multiple subscribers so that only one subscriber receives each message. In this case the messaging provider handles distributing the workload evently across all the subscribers.
This is known as shared subscriptions and you can read more about how it works in IBM's MessageSight product here: http://pic.dhe.ibm.com/infocenter/ism/v1r0m0/topic/com.ibm.ism.doc/Overview/ov30010.html

How to push message from Activemq

i am new to activemq. i read some article and doing this.please help me to solve the following task.
i produce one message to activemq from my java application and i have a consumer for that message in another java application.so i will get the message from activemq. every time this consumer(listener) looking for the message in activemq. my question is activemq can push the message to consumer(listener).
activemq only for storing the message ? it will do any push or pull operation ? activemq always need producer(produce the message) and consumer(consume the message) ?
can anyone help me
thanks
ActiveMq, WebLogic, IBM MQ, and any JMS compatible provider are destination-based messaging systems; the destination, or subject, is a queue or topic. When sending a message, producer can send the message and disconnect immediately; ActiveMq will store message on queue. When receiving, message consumer can receive sync or async, independent of sender.
Send Message
Message producer sends message to destination; it's job is done.
QueueSender queueSender = queueSession.createSender(myQueue);
queueSender.send(message);
Receive Message
Message consumer can receive message one of two ways:
Synchrounous, here you call receive() explicitly
QueueReceiver queueReceiver = queueSession.createReceiver(myQueue);
queueConnection.start();
Message m = queueReceiver.receive();
Asynchronous, here you implement callback method from MessageListener interface:
class MyQueueReceiver implements javax.jms.MessageListener {
QueueReceiver queueReceiver = queueSession.createReceiver(myQueue);
queueReceiver.setMessageListener(this);
...
public void onMessage(Message msg){
//consume message here
}
}

JMS Queue with 2 Listeners

I have a question as regards JMS Queues.
I have implemented a jms sender/reciever using a shared queue as its the only queue avaialbe to me and the only one i can use.
The problem that i am now faced with is that i as this first come first served i cannot guarentee that the messages that i am sending from my producer will be consumed by my consumer and not the other sharing this queue and vice versa. So i am consuming the other apps messages and they are consuming mine.
Is there a way i can just listen for my messages and not consume them from the queue or is this more of a topic implementation?
Or perhaps i can explicitly set an identifier that only my consumer will pick up.
My main code:
public class AsyncReceiver implements MessageListener, ExceptionListener
{
public static void main(String[] args) throws Exception
{
//create queue factory
factory = new TibjmsQueueConnectionFactory(serverUrl);
//create queue connection
queueConn = factory.createQueueConnection(userName, password);
queueConn.setExceptionListener(this);
//create queue session
session = queueConn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
//receive message by QueueReceiver
final Queue queue = session.createQueue(queueName);
final QueueReceiver queueReceiver = session.createReceiver(queue);
queueReceiver.setMessageListener(this);
queueConn.start ();
}
You should use JMS selector. Every JMS message can contain properties that you initiate at sender's side.
Message consumer can register to JMS destination (either queue or topic) specifying selector - SQL-like statement that explains which messages does it want to consume. So you can specify your application specific property and then receive relevant messages only.
You could use message selector as shown below
queueReceiver = queueSession.createReceiver(responseQueue, "JMSCorrelationID='"
+ requestMessage.getJMSCorrelationID() +"'");
Here i am using the JMS correlation ID to identify the correct message I need.
Please note that the filter will only work on Message Header and Message properties.
It will not work on the message content.
Details on Message Header & Properties: http://docs.oracle.com/javaee/1.4/tutorial/doc/JMS4.html#wp79367
If you need to filter based on message content, you may have to use QueueSession.MANUAL_ACKNOWLEDGE mode and acknowledge messages that you want. In this case the application has to have the logic to identify messages based on content. Not the ideal design though.

JmsCorrelationId for async messaging send

Are there any set norms for what a JMSCorrId should be set to. My application is simply sending a message async to a queue and it doesn't care about waiting for any acknowledgement.
When the JMS client receives the reply message, it can match the JMSCorrelationID of the new message with the corresponding JMSMessageID of the message it sent, so that it knows which message received a reply.
The JMSCorrelationID can be any value, not just a JMSMessageID.
For example you can use JMSCorrelationID to identify the sender.
If you decide to use your own ID, be aware that you should not start an application-specific JMSCorrelationID with ID:. That prefix is reserved for IDs generated by JMS providers.
Typically implementation:
public void onMessage(Message message){
try {
TextMessage textMessage = (TextMessage)message;
Queue replyQueue = (Queue)textMessage.getJMSReplyTo();
Message replyMessage = session.createMessage();
replyMessage.setJMSCorrelationID(message.getJMSMessageID());
sender.send(replyQueue, replyMessage);
} catch (JMSException jmse){jmse.printStackTrace();}
}

Categories

Resources