7 Replies Latest reply on Apr 21, 2011 12:22 PM by clebert.suconic

    MessageConsumer.receive receiving messages even with server down

    tyler_durden

      Hello everyone. I'm a bit lost on this.

      First I'll post the snippet, which is basically taken from the reattach-node example:

       

      // Step 1. Create an initial context to perform the JNDI lookup.

      initialContext = getContext(0);

       

       

      // Step 2. Perform a lookup on the queue

      Queue queue = (Queue)initialContext.lookup("/queue/ExampleQueue");

       

       

      // Step 3. Perform a lookup on the Connection Factory

      ConnectionFactory cf = (ConnectionFactory)initialContext.lookup("/ConnectionFactory");

       

       

      // Step 4. Create a JMS Connection

      Connection = cf.createConnection();

       

       

      // Step 5. Create a JMS Session

      Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

       

       

      // Step 6. Create a JMS Message Producer

      MessageProducer producer = session.createProducer(queue);

       

       

      // Step 7. Create a Text Message

      TextMessage message = session.createTextMessage("This is a text message");

       

       

      System.out.println("Sent message: " + message.getText());

       

       

      // Step 8. Send the Message

      producer.send(message);

       

       

      // Step 9. Create a JMS Message Consumer

      MessageConsumer messageConsumer = session.createConsumer(queue);

       

       

      // Step 10. Start the Connection

      Connection.start();

       

       

      // Step 11. To simulate a temporary problem on the network, we stop the remoting acceptor on the

      // server which will close all connections

      stopAcceptor(initialContext);

       

       

      System.out.println("Acceptor now stopped, will wait for 5 seconds. This simulates the network connection failing for a while");

       

       

      // Step 12. Wait a while then restart the acceptor

      Thread.sleep(5000);

       

       

      System.out.println("Acceptor now stopped, trying to read before restarting");

      TextMessage messageReceived2 = (TextMessage)messageConsumer.receive(10000);

      if(messageReceived2!=null){

          System.out.println("Received message: " + messageReceived2.getText());

      }

       

       

      System.out.println("Re-starting acceptor");

       

       

      startAcceptor(initialContext);

       

       

      System.out.println("Restarted acceptor. The client will now reconnect in 10 sec.");

      // Step 12.1 Wait a while then restart the acceptor

      Thread.sleep(10000);

       

       

      // Step 13. We receive the message

      TextMessage messageReceived = (TextMessage)messageConsumer.receive(5000);

      System.out.println("Received message: " + messageReceived.getText());

      return true;

       

      Contrary to what I was expecting, the receive() before the restart is reading and removing the message from the server, and ofc the following receive is timing out, resulting in a nullpointerexception on the System.out.

       

      Why is the message received between the stop and startAcceptor?

       

      Here is the log:

       

      21-apr-2011 13.24.48 jmsproducertester.HornetQExample run

      INFO: hornetq.example.runServer is true

      Sent message: This is a text message

      Acceptor now stopped, will wait for 5 seconds. This simulates the network connection failing for a while

      Acceptor now stopped, trying to read before restarting

      Received message: This is a text message

      Re-starting acceptor

      Restarted acceptor. The client will now reconnect in 10 sec.

      java.lang.NullPointerException

      example complete

              at jmsproducertester.ReattachExample.runExample(ReattachExample.java:103)

              at jmsproducertester.HornetQExample.run(HornetQExample.java:60)

              at jmsproducertester.ReattachExample.main(ReattachExample.java:28)

       

       

      #####################

      ###    FAILURE!   ###

      #####################

      Java Result: 1

       

       

        • 1. MessageConsumer.receive receiving messages even with server down
          clebert.suconic

          The message was already received at the client before you restarted the node.

           

           

          You wouldn't be able to acknowledge the message with the server down, or even commit a transaction.

           

           

           

          You have a client buffer at the client. To guarantee the message won't be redelivered and to make sure you have successfully processed your message, you must ack it. If you need a single transaction between receiving and processing your own data, then you need to perform 2PC using a Transaction manager.

          • 2. MessageConsumer.receive receiving messages even with server down
            tyler_durden

            First of all thank you for the very quick answer, I'll flag the thread as answered.

             

            If you don't mind me asking, can I ask you when the actual receiving / buffering is taking place?

            I'd have thought that maybe calling messageConsumer.receive() would receive more than just one message, assuming that more than one was present and that the buffer was big enough to hold more than one message, but the receiving / buffering is happening before my receive() call (since the first time that I call receive() the connection is already gone).

            Is it actually receiving / buffering at the MessageConsumer messageConsumer = session.createConsumer(queue); instruction?

             

            Thanks a lot for your time!

            • 3. Re: MessageConsumer.receive receiving messages even with server down
              tyler_durden

              Actually I still have an issue. I modified the code like this:

               

              // Step 5. Create a JMS Session

              Session session = connection.createSession(true, -1);

               

              ...

               

              // Step 8. Send the Message

              producer.send(message);

              session.commit();

               

              stopAcceptor(initialContext);

              System.out.println("Acceptor now stopped, will wait for 5 seconds. This simulates the network connection failing for a while");

               

              try{

                        System.out.println("Acceptor now stopped, trying to read before restarting");

                        TextMessage messageReceived2 = (TextMessage)messageConsumer.receive(10000);

                        session.commit();

                        if(messageReceived2!=null){

                     System.out.println("Received message2: " + messageReceived2.getText());

                        }

              } catch (javax.jms.JMSException jmse){ jmse.printStackTrace(); }

               

              System.out.println("Re-starting acceptor");

              startAcceptor(initialContext);

               

              // Step 13. We receive the message

              TextMessage messageReceived = (TextMessage)messageConsumer.receive(5000);

              System.out.println("Received message: " + messageReceived.getText());

              session.commit();

               

              I'd have expected that the first receive, the one called with the connection down, would have not consumed the message, since the session.commit() throws a JMSException (Timed out waiting for response when sending packet 43). Yet after the second receive() two messages are removed from the queue... What am I missing here?

              • 4. Re: MessageConsumer.receive receiving messages even with server down
                clebert.suconic

                You stopped the acceptor on your test, but the connection is still live. You would need to stop/close the connection on the server for a proper test.

                1 of 1 people found this helpful
                • 5. MessageConsumer.receive receiving messages even with server down
                  tyler_durden

                  Ahhh, my bad, sorry for the silly question.

                  Thanks once more!

                  • 6. Re: MessageConsumer.receive receiving messages even with server down
                    clebert.suconic

                    Roberto Fabrizi wrote:

                     

                    First of all thank you for the very quick answer, I'll flag the thread as answered.

                     

                    If you don't mind me asking, can I ask you when the actual receiving / buffering is taking place?

                    I'd have thought that maybe calling messageConsumer.receive() would receive more than just one message, assuming that more than one was present and that the buffer was big enough to hold more than one message, but the receiving / buffering is happening before my receive() call (since the first time that I call receive() the connection is already gone).

                    Is it actually receiving / buffering at the MessageConsumer messageConsumer = session.createConsumer(queue); instruction?

                     

                    Thanks a lot for your time!

                     

                    The message is sent to the client as long as you have enough consumer, and that's done as soon as the session.start happened.

                     

                     

                    if you set it to consumerWindowSize=0, then the system would only send the message when you requested via receive()

                    1 of 1 people found this helpful
                    • 7. Re: MessageConsumer.receive receiving messages even with server down
                      clebert.suconic

                      typo on my previous message:

                       

                      ... as long as you have enough consumer *credits*, ...