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
}
}
Related
Im trying to put a message in a MQ Queue. Here is my source code:
QueueConnection queueConn;
QueueSession queueSession;
QueueSender queueSender;
queueConn = connectionFactory.getConnection();
queueSession = queueConn.createQueueSession(false,
Session.AUTO_ACKNOWLEDGE);
queueSender = queueSession.createSender(queueSession
.createQueue(KEY_CONFIG_QUEUE_NAME));
queueSender.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
TextMessage message = queueSession.createTextMessage(logBase);
queueSender.send(message);
I don't have the source code from the queue consumer, that is the one who sends the messages to SPLUNK. But at SPLUNK console, I could realize that the message is composed by JMS HEADER + my text message (logBase).
Id like the messages without JMS Header. Could someone help me to understand where the problem is? Could be at consumer? Maybe a wrong or missing SPLUNK config??
Assuming that you cannot change the source code at the consumer, there is a way to administratively do this. You can change the queue definition so that these message properties are not given to the getting application.
ALTER QLOCAL(q-name) PROPCTL(NONE)
Related Links
PROPCTL queue options
If you able and happy to change the producer, you could look into the Target Client property of the MQ JMS destination.
This informs the JMS client that the consuming application is not a JMS app so it removes the extra headers.
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).
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.
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();}
}
Here's my scenario. The program is developed with publisher/subscriber methodology. Have two topics (topic1, topic2) in producer and consumer part. I need to get the acknowledgement of the received topic1 from consumer in producer program so that when the acknowledgement status is true, the producer program will have to send the message on topic2.
Had googled links suggesting session.CLIENT_ACKNOWLEDGE in consumer. But I'm in need of the Acknowledgement status to be returned to producer for further process.
JMS specification does not define any API for a publisher to know if a message was consumed by a subscriber or not. A publisher just publishes a message and it is the messaging provider/broker to deliver that message to subscriber. A broker will deliver the message if there is a subscription otherwise that message is discarded.
The session.CLIENT_ACKNOWLEDGE option is one of the way a consumer tells a messaging provider (not producer) to remove the message from it's queue/memory. There are couple of other acknowledgement options as well but all these options are for telling a messaging provider to remove the message but not telling a producer.
If producer requires an acknowledgement from a consumer, then consumer will have to publish an acknowledgement message on another topic and producer subscribes to that topic to receive those acknowledgements. For example:
Producer publishes on TOPIC1
Producer subscribes to TOPIC1/ACKS
Consumer subscribes to TOPIC1
After receiving a message
Consumer publishes an acknowledgement message to TOPIC1/ACKS
Producer will receive the acknowledgement message.
It can then publish on TOPIC2
You must note that there can be multiple acknowledgement messages as there can be more than one subscribers on TOPIC1.
If your program contains only one message producer, you can create a Queue in the message consumer and let the producer subscribe to that Queue. In the Queue mode, it's point-to-point. So the message will only be delivered from the consumer to the producer.
Alternatively, you can also use setJMSReplyTo method to specify the Queue you want the consumer reply to when it receives the message from the producer. This way you don't need to create the Queue explicitly in the consumer but you can create the Queue in the producer as well. But you still need to let the producer listen to that Queue to received the acknowledgement.