5 Replies Latest reply on May 30, 2013 9:37 PM by atulkc

    Questions on MDB

    atulkc

      I faced a couple of issues when deploying MDB in our application and wanted to check if anyone could give some information on it. I am using JBoss 7.2.0.

       

      1) In our application we have defined jms desitnations in hornetq-jms.xml and packaged it in META-INF folder of the ear file. There are some MDBs for some of the topics within our ear. When we deploy the jms destinations this way (in a separate hornetq-jms.xml in META-INF folder) then we observed that the order of jms topic deployment and MDB deployment is not guaranteed. If jms topic deployment happens before MDB deployment then the MDB receives the messages published on the topic else it does not receive anything. Can someone please let me know if there is a way I can define the order of deployment of MDB to be after jms topics/queues are deployed? If I move the jms destinations to standalone-full.xml in messaging subsystem then the order is OK and jms topics/queues always get deployed before MDB as expected. Here is the hornetq-jms.xml and MDB for one of the topics:

       

      hornetq-jms.xml:

       

      <messaging-deployment xmlns="urn:jboss:messaging-deployment:1.0">
          <hornetq-server>
                     <jms-destinations>                              
                                    <jms-topic name="topic.dcfm.common">
                                     <entry name="java:jboss/exported/topic/dcfm/Common" />
                                  </jms-topic>
                                    <!-- more topic declarations -->
                          </jms-destinations>        
          </hornetq-server>
      </messaging-deployment>
      

       

      CommonMDB.java:

       

      @MessageDriven(name = "CommonMDB", activationConfig = {
              @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Topic"),
              @ActivationConfigProperty(propertyName = "destination", propertyValue = "java:jboss/exported/topic/dcfm/Common"),
              @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge") })
      public class CommonMDB implements MessageListener {
      
                private final Logger log = LoggerFactory.getLogger(CommonMDB.class);
      
      
                @Override
                public void onMessage(Message arg0) {
                          log.info("Received message: {0}", arg0); 
                               // do something with the message
                }
      
      }
      
      
      

       

      2) Second problem I am seeing is that if in the above MDB I change the topic name to be some non existent topic ( e.g say I change it to

      java:jboss/exported/topic/dcfm/NonExistentTopic
      ) then I do not see any messages in server log indicating that the topic for which the MDB is created does not exist. In JBoss 5.1.0 we were seeing messages like "awaiting topic/queue creation <topic name>. Attempting to reconnect ...". I found this issue accidentally when one of the MDBs had wrong topic name and we were debugging why the MDB is not getting any message. I was expecting to see some indication in server log indicating that MDB is trying to listen to non-existent/undefined topic. Any idea why this is not indicated?

        • 1. Re: Questions on MDB
          jbertram

          Couple of points:

           

          1. Using deployment files, while technically viable, is not really recommended because it's more difficult (if not impossible) to manage resources deployed this way via the standard management interfaces (e.g. web console, CLI, etc.).
          2. Your MDB should be using the HornetQ name of the topic, not the JNDI name.  In other words, use this: @ActivationConfigProperty(propertyName = "destination", propertyValue = "topic.dcfm.common")
          3. I believe that when the HornetQ JCA RA doesn't find the destination configured in the MDB then it will create one.  You should see a message in the log about this.
          1 of 1 people found this helpful
          • 2. Re: Questions on MDB
            atulkc

            Thanks.

             

            So I should not be using hornetq-jms.xml if I want to make sure that jms topics get deployed before MDBs? It should always be part of standalone-full.xml or are you suggesting some other mechanism when you say using deployment files is not recommended?

             

            I changed my MDB to use the hornetq name instead of JNDI name and it works fine. But if I use non-existent/undefined hornetq name it doesn't complain or create one.

             

            Also, I am now facing another weird issue. Our application client is a standalone java swing client. It needs to listen to bunch of topics to update its state. But none of my message listeners are getting any messages. Weird part is that MDB listening to the same topic are getting the messages. Here is the sample code of standalone message listener for same topic for which I had posted the MDB code before:

             

             

            public class CommonTopicListener implements MessageListener {
            
               public CommonTopicListener() {
               }
            
              public void setup() throws NamingException, JMSException {
                Properties environment = new Properties();
                
                environment.setProperty(Context.PROVIDER_URL, "remote://10.24.49.148:4447");
                environment.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
                environment.put(Context.SECURITY_PRINCIPAL, "testuser");
                environment.put(Context.SECURITY_CREDENTIALS, "passw0rd!");
            
                InitialContext context = new InitialContext(environment;
                ConnectionFactory connFactory = (ConnectionFactory) context.lookup("jms/RemoteConnectionFactory");
                System.out.println("Got connection factory");
                Connection connection = connFactory.createConnection("testuser", "passw0rd!");
                System.out.println("Created Connection");
                
                Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
                System.out.println("Created session");
                
                Destination dest = (Destination) context.lookup("topic/dcfm/Common");
                System.out.println("Got common destination");
                
                MessageConsumer consumer = session.createConsumer(dest);
                System.out.println("Created Consumer");
                
                consumer.setMessageListener(this);
            
            
                connection.setExceptionListener(new ExceptionListener() {
                  
                  @Override
                  public void onException(JMSException arg0) {
                    System.out.println("Exception received:" + arg0);
                    System.exit(-1);
                  }
                });
                System.out.println("Added message listener");
              }
            
            
              public static void main(String[] args) {
                try {
                  System.out.println("Setting up common topic listener");      
                  CommonTopicListener listener = new CommonTopicListener();
                  listener.setup();
                  System.out.println("Common topic listener setup");
                  // Wait indefinitely
                  while (true) {
                    Thread.sleep(10000);
                  }
                } catch (Exception e) {
                  e.printStackTrace();
                }
              }
            
            
              @Override
              public void onMessage(javax.jms.Message arg0) {
                System.out.println("Received message: " + arg0);
              }
            
            }
            
            

             

            I have created a user "testuser" with role as "guest" and am using it for getting connection. There are no exceptions anywhere and am able to get ConnectionFactory, Connection, Session and Consumer. Since this is a standalone client I am using JNDI name to get the destination (I tried with hornetq name too but that doesn't work).

             

            I am attaching the standalone-full.xml that has all the configuration.

            • 3. Re: Questions on MDB
              jbertram

              So I should not be using hornetq-jms.xml if I want to make sure that jms topics get deployed before MDBs? It should always be part of standalone-full.xml or are you suggesting some other mechanism when you say using deployment files is not recommended?

              I would dissuade you from using hornetq-jms.xml no matter what your goal is for deployment order.  At the end of the day, however, it shouldn't matter one way or the other if your MDB is configure properly (which yours wasn't since it was using the JNDI name and useJNDI defaults to "false").

               

              I took a look at the source for the HornetQ JCA RA and here's basically how it works:

               

               

              An important thing to note here is that if useJNDI = false (which it is by default) then it doesn't matter if the destination is actually deployed or not before the MDB is deployed.  As long as the MDB is configured with the same HornetQ name as the relevant destination then it will receive messages sent to that destination whenever it is eventually deployed.

               

              I'm not sure what's going on with your remote message listeners.  Everything looks fine to me.  What's the ConsumerCount of the destination before and after you start the message listeners?

              • 4. Re: Questions on MDB
                atulkc

                I tried by using hornetq-jms.xml after making changes to MDB to use hornetq name and yes, as you indicated the order didn't matter. MDB is receiving the message irrespective of the order.

                 

                For messagelistener:

                 

                The subscription count actually goes up when I start my message listener. I am attaching the screen shot of jconsole for that topic. It has three subscriptions: one from MDB, one from the message listener that I setup from standalone client and one from the message listener that I setup in Singleton EJB. Both message listeners (standalone client and the one in Singleton EJB) do not receive messages.

                 

                Below given is the code that publishes the message to this topic. Note that this publisher is a standalone client too...the messages seem to get published properly from standalone publisher, just the consumption is the problem.

                 

                 

                public class CommonTopicPublisher {
                
                
                  private MessageProducer producer;
                  private Session session;
                  private Connection connection;
                
                
                  public CommonTopicPublisher() {
                
                
                  }
                
                
                  public void setup() throws NamingException, JMSException {
                     Properties environment = new Properties();
                     
                    environment.setProperty(Context.PROVIDER_URL, "remote://10.24.49.148:4447");
                    environment.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");    
                    environment.put(Context.SECURITY_PRINCIPAL, "testuser");
                    environment.put(Context.SECURITY_CREDENTIALS, "passw0rd!");      
                
                    InitialContext context = new InitialContext(environment);
                    ConnectionFactory connFactory = (ConnectionFactory) context.lookup("jms/RemoteConnectionFactory");
                    System.out.println("Got connection factory");
                    connection = connFactory.createConnection("testuser", "passw0rd!");
                    System.out.println("Created Connection");
                    
                    session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
                    System.out.println("Created session");
                    
                    Destination dest = (Destination) context.lookup("topic/dcfm/Common");
                    System.out.println("Got common destination");
                    
                    producer = session.createProducer(dest);
                    System.out.println("Created Producer");
                    
                    System.out.println("Added message listener");
                  }
                  
                  public void sendMessage() throws JMSException {
                    TextMessage msg = session.createTextMessage("Hello There");
                    producer.send(msg);
                    System.out.println("Message sent");
                  }
                  
                  public void cleanUp() throws JMSException {
                    producer.close();
                    session.close();
                    connection.close();
                  }
                
                
                  public static void main(String[] args) {
                    CommonTopicPublisher publisher = null;
                    try {
                      System.out.println("Setting up common topic listener");
                      publisher = new CommonTopicPublisher();
                      publisher.setup();
                      System.out.println("Common topic publisher setup");
                      publisher.sendMessage();
                    } catch (Exception e) {
                      e.printStackTrace();
                    } finally {
                      if (publisher != null) {
                        try {
                          publisher.cleanUp();
                        } catch (JMSException e) {
                          e.printStackTrace();
                        }
                      }
                    }
                
                
                  }
                
                
                }
                
                
                • 5. Re: Questions on MDB
                  atulkc

                  So I was able to solve the issue of standalone message listener not getting messages. I had not called connection.start(). Once I did that I started receiving the messages.

                   

                  Thanks a lot Justin for help with the MDBs.