I list down queues and messages from each queue. The following is my code. But, QueueBrowser does not retrieve messages correctly.
Let's say, I have a queue named TestQueue which has 1000 message.
first time i run my program it shows only 200 messages.
second - 400
third - 600
forth - 800
fifth - 1000
Can you tell me how to fix this problem?
ConnectionFactory out = new ActiveMQConnectionFactory("tcp://localhost:61616?jms.prefetchPolicy.all=10000");
ActiveMQConnection connection = (ActiveMQConnection) out.createConnection();
connection.start();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Set<ActiveMQQueue> amqs = connection.getDestinationSource().getQueues();
Iterator<ActiveMQQueue> queues = amqs.iterator();
while ( queues.hasNext() )
{
ActiveMQQueue queue_t = aqueues.next();
String q_name = queue_t.getPhysicalName();
List<ActiveMQMessage> msgList = ((ActiveMQSession) session).getUnconsumedMessages();
System.out.println( "\nQueue = " + q_name);
QueueBrowser queueBrowser = session.createBrowser(queue_t);
Enumeration e = queueBrowser.getEnumeration();
int numMsgs = 0;
while(e.hasMoreElements())
{
Message message = (Message) e.nextElement();
numMsgs++;
}
System.out.println("No of messages = " + numMsgs);
queueBrowser.close();
}
session.close();
connection.close();
From the javax.jms.QueueBrowser API:
Messages may be arriving and expiring while the scan is done. The JMS API does not require the content of an enumeration to be a static snapshot of queue content. Whether these changes are visible or not depends on the JMS provider.
Have you tried specifying the prefetch policy?
Just connect using JMX to Broker (use jconsole for example). On specific queue set MaxPageSize properties more than 200 then you can list more messages.
Related
I am able to set correlation id for IBM mq but unable to set message id for the message the message id I am setting is being overridden by the MQ how to set this message id below one is the code I am trying please help me on this task. Is there any thing I need do in the code???
public static void main(String args[])
{
try{
MQQueueConnectionFactory cf = new MQQueueConnectionFactory();
cf.setHostName("xxx");
cf.setPort(4444);
cf.setTransportType(1);
cf.setQueueManager("xxxx");
cf.setChannel("CLIENT.xyZ");
MQQueueConnection connection = (MQQueueConnection) cf.createQueueConnection();
MQQueueSession session = (MQQueueSession) connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
MQQueue queue = (MQQueue) session.createQueue("WW.ESB.ENTRY.SERVICE.IN");
queue.setBooleanProperty(WMQConstants.WMQ_MQMD_WRITE_ENABLED, true);
queue.setIntProperty(WMQConstants.WMQ_MQMD_MESSAGE_CONTEXT, WMQConstants.WMQ_MDCTX_SET_IDENTITY_CONTEXT);
MQQueueSender sender = (MQQueueSender) session.createSender(queue);
true);
File f=new File("C:/InputPayloads/Payloads/test4.xml");
JMSTextMessage message = (JMSTextMessage) session.createTextMessage(FileUtils.readFileToString(f));
message.setStringProperty("JMS_IBM_MQMD_UserIdentifier", "avada2");
// Hex-string 010203040506070801020304050607080102030405060708
byte[] customMessageId = new byte[24];
for (int i = 0; i < 24; i++) {
customMessageId[i] = (byte) ((i % 8) + 1);
}
message.setObjectProperty(WMQConstants.JMS_IBM_MQMD_MSGID, customMessageId);
message.setStringProperty("xxx", "SH_TEST04");
message.setStringProperty("yyy", "JP");
message.setStringProperty("zzz", "1");
connection.start();
System.out.println("before Sent message:\\n" + message);
sender.send(message);
System.out.println("Sent message:\\n" + message);
sender.close();
session.close();
connection.close();
}catch(Exception e)
{
System.out.println(e);
}
}
}
I am getting below error
com.ibm.msg.client.jms.DetailedJMSSecurityException: JMSWMQ2008: Failed to open MQ queue 'WW.zzz.xxx.yyy.zz'.
JMS attempted to perform an MQOPEN, but IBM MQ reported an error.
Use the linked exception to determine the cause of this error. Check that the specified queue and queue manager are defined correctly.
due to this line
The JMS Spec indicates that the message ID must be set by the JMS provider and that it must either be unique or null, i.e. you can't set it yourself.
However, you can use an IBM MQ specific extension to set the Message ID yourself, bearing in mind that you are now breaking the JMS Spec.
To do so, you need to set JMS_IBM_MQMD_MsgId, whose value is then copied into JMSMessageID (i.e. you can't set it directly).
Now you know the name of the attribute to set, see this other question for more details and a code example in an answer from an IBM MQ JMS expert (#Calanais).
Further reading
JMS message object properties
Reading and writing the message descriptor from a WebSphere MQ classes for JMS application
I have an application with several activeMq queues. I would like to list the messages in them and remove any of them from any of the queues based on the id of the message.
Here is my code so far.
public void killMessage(String id) {
try {
ActiveMQConnection activeMqConnection = (ActiveMQConnection) connectionFactory.createConnection();
activeMqConnection.start();
DestinationSource destinationSource = activeMqConnection.getDestinationSource();
Set<ActiveMQQueue> queues = destinationSource.getQueues();
QueueSession queueSession = activeMqConnection.createQueueSession(true, Session.CLIENT_ACKNOWLEDGE);
for(ActiveMQQueue queue : queues) {
QueueBrowser browser = queueSession.createBrowser(queue);
Enumeration<?> messagesInQueue = browser.getEnumeration();
while (messagesInQueue.hasMoreElements()) {
Message message = (Message) messagesInQueue.nextElement();
System.out.println("Current id: " + message.getJMSMessageID());
if(message.getJMSMessageID().equals(id)){
System.out.println("-----message id found-------");
}
}
}
activeMqConnection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
I iterate through all the queues, then I iterate through all messages in each queue. I even find the message I want to delete, but I cannot find a way to remove it from the queue.
Edit:
I also created a consumer. I am not sure how the consumer should make the messages disappear from the queue. My attempt at it, which have no effect at all, messages remain in the queue, and I get no error message and no exception is thrown which could indicate the consumer did not match a message:
if(message.getJMSMessageID().equals(id)){
System.out.println("-----message id found-------");
MessageConsumer consumer = queueSession.createConsumer(queue, "JMSMessageID='" + id + "'");
consumer.receive();
consumer.close();
}
If you want to use the JMS API to do this then you'll have to create a consumer and use a selector to consume the message with the ID that you want. A queue browser cannot consume messages; it can only browse them.
In the code you pasted you're creating a transacted session which means when you consume the message you'll need to commit the session otherwise the message will never be acknowledged. That said, you're probably better off creating a non-transacted session with AUTO_ACKNOWLEDGE instead.
Also, you probably want to call receive(int) (i.e. with a timeout) so that if the selector can't find the message for some reason your application doesn't just sit there forever waiting on the method to return.
I have a requirement to fetch the pending messages from tibco ems queue. Below is my program using spring jms template. However, I published 5000 messages to queue and tried fetching the count of same with out consuming, and realized it took nearly 20 minutes to browse and get the count. Please advise on any performance improvement here or any other better way to get the pending message count
jmsTemplate.execute(new SessionCallback<QueueBrowser>() {
public QueueBrowser doInJms(Session session) throws JMSException {
javax.jms.Queue queue = session.createQueue(queueName);
QueueBrowser browser = session.createBrowser(queue);
Enumeration messages = browser.getEnumeration();
int num = 0;
while(messages.hasMoreElements()) {
messages.nextElement();
num +=1;
LOG.info("num={}",num);
}
return null;
}
}, true);
From EMS 8.3 samples:
javax.jms.QueueBrowser browser = session.createBrowser(queue);
Enumeration msgs = browser.getEnumeration();
int browseCount=0;
while (msgs.hasMoreElements())
{
message = (javax.jms.Message)msgs.nextElement();
System.err.println("Browsed message: number="+message.getIntProperty("msg_num"));
browseCount++;
}
I've got this scenario:
a JMS message elaboration via an MDB might fail (throws a RuntimeException in this case)
the message should be redelivered, though after a delay (ideal, but not strictly necessary: after an increasing delay depending on the number of fails)
after x failures, the message should be disregarded and never sent again
Right now, the behaviour I have is that the failed message is redelivered instantly for 10 times, and I haven't been able to customize this.
Is there a way I can achieve this via #JMSdefinition (or other annotations as well) or setting the correct properties in the message? If so, how to do?
You can schedule the message with _AMQ_SCHED_DELIVERY property:
Queue q = (Queue) ServiceLocator.getInstance().getDestination("QUEUE");
QueueConnectionFactory factory = (QueueConnectionFactory) ServiceLocator.getInstance().getConnectionFactory(
"java:/ConnectionFactory");
QueueConnection connection = factory.createQueueConnection();
QueueSession session = null;
QueueSender sender = null;
session = connection.createQueueSession(false, javax.jms.Session.AUTO_ACKNOWLEDGE);
sender = session.createSender(q);
ObjectMessage msg = session.createObjectMessage();
if (redelivedCount > 0) {
msg.setIntProperty("redelivedCount", redelivedCount);
// schedule to run in 10 secs
msg.setLongProperty("_AMQ_SCHED_DELIVERY", System.currentTimeMillis() + 10000);
}
msg.setStringProperty("action", action);
msg.setObject(params);
sender.send(msg);
I am using Apache Active MQ with Spring..... the problem I am facing is that I am creating producer on one machine let say Machine1 and I am creating one consumer on second machine let say Machine2...
I am creating producer on Machine1 by calling a simple servlet call.... and then create a consumer on Machine2....
Problem I am facing is that suppose in anyway if my producer is not able to send any data packet in specified time duration then I want to delete my consumer and Queue from Machine2...
Is there anyway I can set my Consumer and Queue to get auto delete and perform some business logic if I do not get any packet from producer in a specified time duration....
connectionFactory = new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_USER,ActiveMQConnection.DEFAULT_PASSWORD,ConnectorURL);
connection = connectionFactory.createConnection();
connection.start();
session = connection.createSession(transacted, Session.AUTO_ACKNOWLEDGE);
destination = session.createQueue(queueID+"");
connection = connectionFactory.createConnection();
connection.start();
consumer = session.createConsumer(destination);
basically this code create consumer for my application....then I assign this consumer to my application listener that listen if producer send any message to consumer....
ScenarioExecutionQueueListenerImpl executionQueueListener = new ScenarioExecutionQueueListenerImpl(scenario,result, host);
beanFactory.autowireBean(executionQueueListener);
connection.setExceptionListener(executionQueueListener);
Message message = consumer.receive();
consumer.setMessageListener(executionQueueListener);
executionQueueListener.setConsumer(consumer);
executionQueueListener.onMessage(message);
I would not setup a messagelistener for that case, but just use the consumer.receive() method. The MessageListener is more for time independent/asynchronous consuming.
public void run(){
Message m = consumer.receive(timeout_value_in_millisec);
if( m != null ){
// got a message, handle it.
processMessage(msg);
}else{
// no message received in specified time,
}
// close session, connection etc.
}
public void processMessage(Message msg){
}