1 2 Previous Next 24 Replies Latest reply on May 30, 2007 5:16 PM by Matthew Parrish

    Viewing message contents in a queue

    Matthew Parrish Newbie

      Does anyone have any suggestions for how to be able to see the contents of the messages in a queue? Is there anything built into JBM to do this? Otherwise, is it pretty straightforward to open up a separate database connection and simply query the table?

      Thanks,
      Matt

        • 1. Re: Viewing message contents in a queue
          Tim Fox Master

          I would suggest against query a database table since this couples your application to implementation details of JBM.

          Have you thought about using a QueueBrowser?

          • 2. Re: Viewing message contents in a queue
            Matthew Parrish Newbie

            Yeah, I'd rather not hit the database directly. What is a QueueBrowser? Where can I find that?

            • 4. Re: Viewing message contents in a queue
              Matthew Parrish Newbie

              Hi Tim. I've written a QueueBrowser to look at the messages on the queue. But it's not quite working if I have an MDB configured to listen on the queue. Once I do that, I no longer see the messages on the queue. It does show the messages when I remove the MDB. On the JMX console, it shows the message counts properly whether I have the MDB or not, but the QueueBrowser only shows the messages without the MDB.

              My feeling is that this is a bug, another issue of JBM + MDB's. However, is there something differently that I need to be doing? Here's more or less the code snippet I'm using:

               QueueConnection conn = null;
               QueueSession session = null;
               QueueBrowser browser = null;
               conn = qcf.createQueueConnection();
               session = conn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
               List<String> leads = new ArrayList<String>();
               browser = session.createBrowser(leadQueue);
               Enumeration messages = browser.getEnumeration();
               while (messages.hasMoreElements()) {
               TextMessage message = (TextMessage) messages.nextElement();
               leads.add(message.getText());
               }
              


              • 5. Re: Viewing message contents in a queue
                Tim Fox Master

                An MDB is a consumer of messages.

                Consumers buffer messages locally (default size = 200 if I remember rightly - see userguide for details).

                So if you create a consumer and there are say 1000 messages on the queue, then the first 200 messages will be taken off the queue and buffered in the consumer.

                Therefore you won't see them when you browse - since they're no longer on the queue.

                If you have < 200 messages then you won't see any until you close the consumer (or the MDB).

                This is expected behaviour.

                • 6. Re: Viewing message contents in a queue
                  Matthew Parrish Newbie

                  So, it would make sense for the JMX MBean for the queue to show a message count of 20, but for the QueueBrowser to not see any messages? So that inconsistency is normal?

                  I'm looking through the docs now to see how to configure the number of messages pulled down from JMS, but I'm not sure I've found it yet. I have the following config in standardjboss.xml, which sets the MaximumSize property to 3. However, the problem is seen when there are 20+ messages, so this must not be the setting you're referring to.

                   <invoker-proxy-binding>
                   <name>message-driven-bean</name>
                   <invoker-mbean>default</invoker-mbean>
                   <proxy-factory>org.jboss.ejb.plugins.jms.JMSContainerInvoker</proxy-factory>
                   <proxy-factory-config>
                   <JMSProviderAdapterJNDI>DefaultJMSProvider</JMSProviderAdapterJNDI>
                   <ServerSessionPoolFactoryJNDI>StdJMSPool</ServerSessionPoolFactoryJNDI>
                   <CreateJBossMQDestination>true</CreateJBossMQDestination>
                   <!-- WARN: Don't set this to zero until a bug in the pooled executor is fixed -->
                   <MinimumSize>1</MinimumSize>
                   <MaximumSize>3</MaximumSize>
                   <KeepAliveMillis>30000</KeepAliveMillis>
                   <MaxMessages>1</MaxMessages>
                   <MDBConfig>
                   <ReconnectIntervalSec>10</ReconnectIntervalSec>
                   <DLQConfig>
                   <DestinationQueue>queue/DLQ</DestinationQueue>
                   <MaxTimesRedelivered>10</MaxTimesRedelivered>
                   <TimeToLive>0</TimeToLive>
                   </DLQConfig>
                   </MDBConfig>
                   </proxy-factory-config>
                   </invoker-proxy-binding>
                  


                  Also, I would have thought that the messages would still be on the queue until the MDB finishes and the transaction commits. But it looks like you're saying that messages can be pulled down, but not processed yet, and they're not considered to be on the queue. Did I understand that correctly?

                  Thanks

                  • 7. Re: Viewing message contents in a queue
                    Tim Fox Master

                     

                    "parressh" wrote:
                    So, it would make sense for the JMX MBean for the queue to show a message count of 20, but for the QueueBrowser to not see any messages? So that inconsistency is normal?


                    The Message Count attribute is defined as:

                    Number of messages in queue + Number of messages that have been delivered but not acknowledged yet + Number of scheduled message


                    I'm looking through the docs now to see how to configure the number of messages pulled down from JMS, but I'm not sure I've found it yet.

                    http://labs.jboss.com/file-access/default/members/jbossmessaging/freezone/docs/userguide-1.2.0.GA/html_single/index.html#conf.destination.connectionfactory.attributes.prefetchsize


                    Also, I would have thought that the messages would still be on the queue until the MDB finishes and the transaction commits.


                    No, they're removed from the queue at delivery time, and put back if the transaction subsequently rolls back.

                    If they're not in the queue, you can see its going to be quite difficult for you to browse them.



                    • 8. Re: Viewing message contents in a queue
                      Tim Fox Master

                      Theoretically it would be possible to browse over the union of the set of messages actually in the queue, and the set in the delivery state, but this would be fairly tricky to implement since they are scattered over the various server side consumers.

                      Also please be warned that setting prefetchsize to a very low value can have an adverse effect on performance.

                      Finally, bear in mind, that, according to the JMS spec, queue browsers are not required to give an accurate or static picture of the queue.

                      The moral of the story is never use queue browsers if you want an absolutely accurate picture of what's in a queue at any one time, especially if it's active.

                      • 9. Re: Viewing message contents in a queue
                        Matthew Parrish Newbie

                        Tim, thanks for pointing me to the correct documentation. However, changing the PrefetchSize property didn't work for me. I set it to 3 and then sent 15 messages to the queue. However, the QueueBrowser never saw any of them. I did see the MessageCount of the Queue slowly drop to zero over time. So, it looks like this approach doesn't work.

                        • 10. Re: Viewing message contents in a queue
                          Tim Fox Master

                          If you want to see an example of browsing working, please see the test suite.

                          • 11. Re: Viewing message contents in a queue
                            Matthew Parrish Newbie

                            Tim, the browser is also working for me... when there is not an MDB attached to the queue. The test cases in the suite do not have any MDB's or other message listeners when testing the browser which is why they are working just fine.

                            • 12. Re: Viewing message contents in a queue
                              Tim Fox Master

                              Ok, so in order for me to help you here you need to give me more information.

                              Please post the version of JBM you are using, the version of JBAS you are using, and your MDB config and source that replicates the issue.

                              Please also post instructions on how you send messages to the queue, and your browser code, and also explain how you send prevent messages from being consumed by the MDB before you browse them.

                              Thanks.

                              • 13. Re: Viewing message contents in a queue
                                Matthew Parrish Newbie

                                Tim, I'll get you all that information, but quickly, you said

                                and also explain how you send prevent messages from being consumed by the MDB before you browse them.


                                This is the information I was asking for previously. Your suggestion was to alter the PrefetchSize to be less than the number of messages in the queue (e.g. PrefetchSize to 1 and MDB MaximumSize to 3 and send 20 messages which takes about 30 seconds for all the messages to be consumed in my code), which would prevent some of the messages from being immediately consumed by the MDB. Would that be a sufficient explanation for how I prevent messages from being consumed by the MDB before I browse them?

                                Thanks

                                • 14. Re: Viewing message contents in a queue
                                  Matthew Parrish Newbie

                                  Tim, here are the details of my setup:

                                  jboss-messaging-1.2.0.sp1
                                  jboss-as-4.0.5.GA

                                  MDB is configured to consume on one thread, one message at a time.

                                  From standardjboss.xml

                                   <invoker-proxy-binding>
                                   <name>message-driven-bean</name>
                                   <invoker-mbean>default</invoker-mbean>
                                   <proxy-factory>org.jboss.ejb.plugins.jms.JMSContainerInvoker</proxy-factory>
                                   <proxy-factory-config>
                                   <JMSProviderAdapterJNDI>DefaultJMSProvider</JMSProviderAdapterJNDI>
                                   <ServerSessionPoolFactoryJNDI>StdJMSPool</ServerSessionPoolFactoryJNDI>
                                   <CreateJBossMQDestination>true</CreateJBossMQDestination>
                                   <!-- WARN: Don't set this to zero until a bug in the pooled executor is fixed -->
                                   <MinimumSize>1</MinimumSize>
                                   <MaximumSize>1</MaximumSize>
                                   <KeepAliveMillis>30000</KeepAliveMillis>
                                   <MaxMessages>1</MaxMessages>
                                   <MDBConfig>
                                   <ReconnectIntervalSec>10</ReconnectIntervalSec>
                                   <DLQConfig>
                                   <DestinationQueue>queue/DLQ</DestinationQueue>
                                   <MaxTimesRedelivered>10</MaxTimesRedelivered>
                                   <TimeToLive>0</TimeToLive>
                                   </DLQConfig>
                                   </MDBConfig>
                                   </proxy-factory-config>
                                   </invoker-proxy-binding>
                                  


                                  From connection-factories-service.xml
                                   <mbean code="org.jboss.jms.server.connectionfactory.ConnectionFactory"
                                   name="jboss.messaging.connectionfactory:service=ConnectionFactory"
                                   xmbean-dd="xmdesc/ConnectionFactory-xmbean.xml">
                                   <depends optional-attribute-name="ServerPeer">jboss.messaging:service=ServerPeer</depends>
                                   <depends optional-attribute-name="Connector">jboss.messaging:service=Connector,transport=bisocket</depends>
                                   <depends>jboss.messaging:service=PostOffice</depends>
                                  
                                   <attribute name="JNDIBindings">
                                   <bindings>
                                   <binding>/ConnectionFactory</binding>
                                   <binding>/XAConnectionFactory</binding>
                                   <binding>java:/ConnectionFactory</binding>
                                   <binding>java:/XAConnectionFactory</binding>
                                   </bindings>
                                   </attribute>
                                   <attribute name="PrefetchSize">1</attribute>
                                   <attribute name="Clustered">true</attribute>
                                   <attribute name="LoadBalancingFactory">org.jboss.jms.client.plugin.RoundRobinLoadBalancingFactory</attribute>
                                   </mbean>
                                  


                                  Message sender code:

                                  Following beans set by Spring:
                                  qcf is retrieved from JNDI name XAConnectionFactory
                                  leadQueue is retrieved from JNDI name queue/leadQueue

                                   public void processLead(String leadXml, int messageAttempts) {
                                   QueueConnection conn = null;
                                   try {
                                   conn = qcf.createQueueConnection();
                                   QueueSession session = conn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
                                   QueueSender sender = session.createSender(leadQueue);
                                   TextMessage msg = session.createTextMessage(leadXml);
                                   msg.setIntProperty(MESSAGE_ATTEMPTS_PROPERTY, messageAttempts);
                                   msg.setJMSDeliveryMode(DeliveryMode.PERSISTENT);
                                   sender.send(msg);
                                   } catch (JMSException ex) {
                                   LeadProcessingException lpe = new LeadProcessingException(
                                   "Queue down: cannot send lead to Queue", ex);
                                   throw lpe;
                                   } finally {
                                   if (conn != null) {
                                   try {
                                   conn.close();
                                   } catch (Exception ex) {
                                   logger.error("Error disconnecting from JMS Queue", ex);
                                   }
                                   }
                                   }
                                   }
                                  


                                  Simplified MDB Code:
                                   public void onMessage(Message msg) {
                                   logger.info("Processing jms message");
                                   String message;
                                   try {
                                   message = ((TextMessage) msg).getText();
                                   Thread.sleep(2000);
                                   } catch (Exception e) {
                                   throw new RuntimeException("Unable to read message text", e);
                                   }
                                   }
                                  


                                  The log file shows that only one MDB is active and consuming messages once every 2 seconds.

                                  I really appreciate your time Tim. Let me know if you need more info.

                                  1 2 Previous Next