Package org.jboss.test.messaging.jms.clustering

Source Code of org.jboss.test.messaging.jms.clustering.FailoverTest$ReceiveThread

/**
* JBoss, Home of Professional Open Source
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.test.messaging.jms.clustering;

import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.DeliveryMode;
import javax.jms.ExceptionListener;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.QueueBrowser;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.management.ObjectName;
import javax.naming.InitialContext;

import org.jboss.jms.client.FailoverEvent;
import org.jboss.jms.client.JBossConnection;
import org.jboss.jms.client.delegate.ClientConnectionDelegate;
import org.jboss.jms.client.remoting.JMSRemotingConnection;
import org.jboss.test.messaging.tools.ServerManagement;
import org.jboss.test.messaging.tools.aop.PoisonInterceptor;

/**
* @author <a href="mailto:ovidiu@feodorov.com">Ovidiu Feodorov</a>
* @author <a href="mailto:hgao@redhat.com">Howard Gao</a>
* @version <tt>$Revision: 8322 $</tt>
*
* $Id: FailoverTest.java 8322 2011-06-08 05:42:20Z gaohoward $
*/
public class FailoverTest extends ClusteringTestBase
{
   // Constants ------------------------------------------------------------------------------------

   // Static ---------------------------------------------------------------------------------------

   // Attributes -----------------------------------------------------------------------------------

   // Constructors ---------------------------------------------------------------------------------

   public FailoverTest(String name)
   {
      super(name);
   }

   // Public ---------------------------------------------------------------------------------------

   //https://jira.jboss.org/jira/browse/JBMESSAGING-1547
   //the dead lock happens when node0 is trying to deliver while node1
   //was shutdown.
   public void testMessageSuckerStopDeadLock() throws Exception
   {
      Connection conn = null;

      try
      {
         conn = createConnectionOnServer(cf, 0);
         conn.start();

         Session session0 = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);

         //killing node 1
         ServerManagement.kill(1);

         //this will cause the MessagingQueue.informSuckers() called.
         //there is a chance when nodeLeft is detected, MessageSucker.stop() is being called
         //just to collide with the informSuckers() call.
         for (int i = 0; i < 10000; i++)
         {
            MessageConsumer consumer1 = session0.createConsumer(queue[0]);
            consumer1.close();
            Thread.yield();
         }
        
         //if the deak lock happens, server1 won't be delivering any messages.
         MessageProducer prod = session0.createProducer(queue[0]);
         TextMessage msg = session0.createTextMessage("deadlock");
         prod.send(msg);
        
         MessageConsumer cons = session0.createConsumer(queue[0]);
         msg = (TextMessage)cons.receive(5000);
        
         assertNotNull(msg);
         assertEquals("deadlock", msg.getText());
        
      }
      finally
      {
         if (conn != null)
         {
            conn.close();
         }
      }
   }
  
   public void testSimpleConnectionFailover() throws Exception
   {
     //We need to sleep and relookup the connection factory due to http://jira.jboss.com/jira/browse/JBMESSAGING-1038
     //remove this when this task is complete
     Thread.sleep(2000);

     ConnectionFactory theCF = (ConnectionFactory)ic[0].lookup("/ClusteredConnectionFactory");

      Connection conn = null;

      try
      {
         conn = createConnectionOnServer(theCF, 1);
         conn.start();

         // register a failover listener
         SimpleFailoverListener failoverListener = new SimpleFailoverListener();
         ((JBossConnection)conn).registerFailoverListener(failoverListener);

         ServerManagement.kill(1);

         // wait for the client-side failover to complete

         while(true)
         {
            FailoverEvent event = failoverListener.getEvent(30000);
            if (event != null && FailoverEvent.FAILOVER_COMPLETED == event.getType())
            {
               break;
            }
            if (event == null)
            {
               fail("Did not get expected FAILOVER_COMPLETED event");
            }
         }

         assertEquals(0, getServerId(conn));
      }
      finally
      {
         if (conn != null)
         {
            conn.close();
         }
      }
   }

   public void testSessionFailover() throws Exception
   {
      Connection conn = null;

      try
      {
         conn = createConnectionOnServer(cf, 1);
         conn.start();

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

         // register a failover listener
         SimpleFailoverListener failoverListener = new SimpleFailoverListener();
         ((JBossConnection)conn).registerFailoverListener(failoverListener);

         ServerManagement.kill(1);

         // wait for the client-side failover to complete

         while(true)
         {
            FailoverEvent event = failoverListener.getEvent(30000);
            if (event != null && FailoverEvent.FAILOVER_COMPLETED == event.getType())
            {
               break;
            }
            if (event == null)
            {
               fail("Did not get expected FAILOVER_COMPLETED event");
            }
         }

         // failover complete
         assertEquals(0, getServerId(conn));

         // use the old session to send/receive a message
         session.createProducer(queue[0]).send(session.createTextMessage("blik"));

         TextMessage m = (TextMessage)session.createConsumer(queue[0]).receive(5000);

         assertNotNull(m);

         assertEquals("blik", m.getText());
      }
      finally
      {
         if (conn != null)
         {
            conn.close();
         }
      }
   }

   public void testProducerFailover() throws Exception
   {
      Connection conn = null;

      try
      {
         conn = createConnectionOnServer(cf, 1);

         conn.start();

         Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
         MessageProducer prod = session.createProducer(queue[1]);

         // register a failover listener
         SimpleFailoverListener failoverListener = new SimpleFailoverListener();
         ((JBossConnection)conn).registerFailoverListener(failoverListener);

         ServerManagement.kill(1);

         // wait for the client-side failover to complete

         while(true)
         {
            FailoverEvent event = failoverListener.getEvent(30000);
            if (event != null && FailoverEvent.FAILOVER_COMPLETED == event.getType())
            {
               break;
            }
            if (event == null)
            {
               fail("Did not get expected FAILOVER_COMPLETED event");
            }
         }

         assertEquals(0, getServerId(conn));

         // send a message, send it with the failed over producer and make sure I can receive it
         Message m = session.createTextMessage("clik");
         prod.send(m);

         MessageConsumer cons = session.createConsumer(queue[0]);
         TextMessage tm = (TextMessage)cons.receive(2000);

         assertNotNull(tm);
         assertEquals("clik", tm.getText());
      }
      finally
      {
         if (conn != null)
         {
            conn.close();
         }
      }
   }

   public void testConsumerFailoverWithConnectionStopped() throws Exception
   {
      Connection conn = null;

      try
      {
         conn = createConnectionOnServer(cf, 1);

         Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
         MessageConsumer cons = session.createConsumer(queue[1]);
         MessageProducer prod = session.createProducer(queue[1]);

         // send a message (connection is stopped, so it will stay on the server), and I expect
         // to receive it with the failed-over consumer after crash

         Message m = session.createTextMessage("plik");
         prod.send(m);


         // register a failover listener
         SimpleFailoverListener failoverListener = new SimpleFailoverListener();
         ((JBossConnection)conn).registerFailoverListener(failoverListener);

         ServerManagement.kill(1);

         // wait for the client-side failover to complete

         while(true)
         {
            FailoverEvent event = failoverListener.getEvent(30000);
            if (event != null && FailoverEvent.FAILOVER_COMPLETED == event.getType())
            {
               break;
            }
            if (event == null)
            {
               fail("Did not get expected FAILOVER_COMPLETED event");
            }
         }

         // failover complete
         assertEquals(0, getServerId(conn));

         // activate the failed-over consumer
         conn.start();

         TextMessage rm = (TextMessage)cons.receive(2000);
         assertNotNull(rm);
         assertEquals("plik", rm.getText());
      }
      finally
      {
         if (conn != null)
         {
            conn.close();
         }
      }
   }

   public void testConsumerFailoverWithConnectionStarted() throws Exception
   {
      Connection conn = null;

      try
      {
         conn = createConnectionOnServer(cf, 1);

         Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
         MessageConsumer cons = session.createConsumer(queue[1]);
         MessageProducer prod = session.createProducer(queue[1]);

         // start the connection, so the message makes it to the client-side MessageCallbackHandler
         // buffer

         conn.start();

         Message m = session.createTextMessage("nik");
         prod.send(m);

         // wait a bit so the message makes it to the client
         Thread.sleep(2000);

         // register a failover listener
         SimpleFailoverListener failoverListener = new SimpleFailoverListener();
         ((JBossConnection)conn).registerFailoverListener(failoverListener);

         ServerManagement.kill(1);

         // wait for the client-side failover to complete

         while(true)
         {
            FailoverEvent event = failoverListener.getEvent(30000);
            if (event != null && FailoverEvent.FAILOVER_COMPLETED == event.getType())
            {
               break;
            }
            if (event == null)
            {
               fail("Did not get expected FAILOVER_COMPLETED event");
            }
         }

         // failover complete
         assertEquals(0, getServerId(conn));

         TextMessage rm = (TextMessage)cons.receive(2000);
         assertNotNull(rm);
         assertEquals("nik", rm.getText());

      }
      finally
      {
         if (conn != null)
         {
            conn.close();
         }
      }
   }

   public void testBrowserFailoverSendMessagesPreFailure() throws Exception
   {
      Connection conn = null;

      try
      {
         // create a connection to node 1
         conn = createConnectionOnServer(cf, 1);

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

         QueueBrowser browser = session.createBrowser(queue[1]);

         Enumeration en = browser.getEnumeration();
         assertFalse(en.hasMoreElements());

         // send one persistent and one non-persistent message

         MessageProducer prod = session.createProducer(queue[1]);
         prod.setDeliveryMode(DeliveryMode.PERSISTENT);
         prod.send(session.createTextMessage("click"));
         prod.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
         prod.send(session.createTextMessage("clack"));

         //Give time for the NP message to arrive
         Thread.sleep(2000);

         // register a failover listener
         SimpleFailoverListener failoverListener = new SimpleFailoverListener();
         ((JBossConnection)conn).registerFailoverListener(failoverListener);

         ServerManagement.kill(1);

         // wait for the client-side failover to complete

         while(true)
         {
            FailoverEvent event = failoverListener.getEvent(30000);
            if (event != null && FailoverEvent.FAILOVER_COMPLETED == event.getType())
            {
               break;
            }
            if (event == null)
            {
               fail("Did not get expected FAILOVER_COMPLETED event");
            }
         }

         // failover complete
         assertEquals(0, getServerId(conn));

         en = browser.getEnumeration();

         // we expect to only be able to browse the persistent message
         assertTrue(en.hasMoreElements());
         TextMessage tm = (TextMessage)en.nextElement();
         assertEquals("click", tm.getText());

         assertFalse(en.hasMoreElements());

         removeAllMessages(queue[1].getQueueName(), true, 0);
      }
      finally
      {
         if (conn != null)
         {
            conn.close();
         }
      }
   }

   public void testBrowserFailoverSendMessagesPostFailure() throws Exception
   {
      Connection conn = null;

      try
      {
         // create a connection to node 1
         conn = createConnectionOnServer(cf, 1);

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

         QueueBrowser browser = session.createBrowser(queue[1]);

         Enumeration en = browser.getEnumeration();
         assertFalse(en.hasMoreElements());

         // register a failover listener
         SimpleFailoverListener failoverListener = new SimpleFailoverListener();
         ((JBossConnection)conn).registerFailoverListener(failoverListener);

         ServerManagement.kill(1);

         // wait for the client-side failover to complete

         while(true)
         {
            FailoverEvent event = failoverListener.getEvent(30000);
            if (event != null && FailoverEvent.FAILOVER_COMPLETED == event.getType())
            {
               break;
            }
            if (event == null)
            {
               fail("Did not get expected FAILOVER_COMPLETED event");
            }
         }

         // failover complete
         assertEquals(0, getServerId(conn));

         // send one persistent and one non-persistent message

         MessageProducer prod = session.createProducer(queue[1]);
         prod.setDeliveryMode(DeliveryMode.PERSISTENT);
         prod.send(session.createTextMessage("click"));
         prod.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
         prod.send(session.createTextMessage("clack"));

         //Give time for the NP message to arrive
         Thread.sleep(2000);

         en = browser.getEnumeration();

         // we expect to be able to browse persistent and non-persistent messages
         Set texts = new HashSet();

         assertTrue(en.hasMoreElements());
         TextMessage tm = (TextMessage)en.nextElement();
         texts.add(tm.getText());

         assertTrue(en.hasMoreElements());
         tm = (TextMessage)en.nextElement();
         texts.add(tm.getText());

         assertFalse(en.hasMoreElements());

         assertTrue(texts.contains("click"));
         assertTrue(texts.contains("clack"));

         removeAllMessages(queue[1].getQueueName(), true, 0);
      }
      finally
      {
         if (conn != null)
         {
            conn.close();
         }
      }
   }

   /**
    * Sending one persistent message.
    */
   public void testSessionWithOneTransactedPersistentMessageFailover() throws Exception
   {
      Connection conn = null;

      try
      {
         conn = createConnectionOnServer(cf, 1);

         conn.start();

         Session session = conn.createSession(true, Session.SESSION_TRANSACTED);

         // send 2 transacted messages (one persistent and one non-persistent) but don't commit
         MessageProducer prod = session.createProducer(queue[1]);

         prod.setDeliveryMode(DeliveryMode.PERSISTENT);
         prod.send(session.createTextMessage("clik-persistent"));

         // close the producer
         prod.close();

         log.debug("producer closed");

         // create a consumer on the same local queue (creating a consumer AFTER failover will end
         // up getting messages from a local queue, not a failed over queue; at least until
         // redistribution is implemented.

         Session session2 = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
         MessageConsumer cons = session2.createConsumer(queue[1]);

         // register a failover listener
         SimpleFailoverListener failoverListener = new SimpleFailoverListener();
         ((JBossConnection)conn).registerFailoverListener(failoverListener);

         ServerManagement.kill(1);

         // wait for the client-side failover to complete

         while(true)
         {
            FailoverEvent event = failoverListener.getEvent(30000);
            if (event != null && FailoverEvent.FAILOVER_COMPLETED == event.getType())
            {
               break;
            }
            if (event == null)
            {
               fail("Did not get expected FAILOVER_COMPLETED event");
            }
         }

         // failover complete
         assertEquals(0, getServerId(conn));

         // commit the failed-over session
         session.commit();

         // make sure messages made it to the queue

         TextMessage tm = (TextMessage)cons.receive(2000);
         assertNotNull(tm);
         assertEquals("clik-persistent", tm.getText());
      }
      finally
      {
         if (conn != null)
         {
            conn.close();
         }
      }
   }

   /**
    * Sending one non-persistent message.
    */
   public void testSessionWithOneTransactedNonPersistentMessageFailover() throws Exception
   {
      Connection conn = null;

      try
      {
         conn = createConnectionOnServer(cf, 1);

         conn.start();

         Session session = conn.createSession(true, Session.SESSION_TRANSACTED);

         MessageProducer prod = session.createProducer(queue[1]);

         prod.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
         prod.send(session.createTextMessage("clik-non-persistent"));

         // close the producer
         prod.close();

         log.debug("producer closed");

         // create a consumer on the same local queue (creating a consumer AFTER failover will end
         // up getting messages from a local queue, not a failed over queue; at least until
         // redistribution is implemented.

         Session session2 = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
         MessageConsumer cons = session2.createConsumer(queue[1]);

         // register a failover listener
         SimpleFailoverListener failoverListener = new SimpleFailoverListener();
         ((JBossConnection)conn).registerFailoverListener(failoverListener);

         ServerManagement.kill(1);

         // wait for the client-side failover to complete

         while(true)
         {
            FailoverEvent event = failoverListener.getEvent(30000);
            if (event != null && FailoverEvent.FAILOVER_COMPLETED == event.getType())
            {
               break;
            }
            if (event == null)
            {
               fail("Did not get expected FAILOVER_COMPLETED event");
            }
         }

         // failover complete

         assertEquals(0, getServerId(conn));

         // commit the failed-over session
         session.commit();

         // make sure messages made it to the queue

         TextMessage tm = (TextMessage)cons.receive(2000);
         assertNotNull(tm);
         assertEquals("clik-non-persistent", tm.getText());
      }
      finally
      {
         if (conn != null)
         {
            conn.close();
         }
      }
   }

   /**
    * Sending 2 non-persistent messages.
    */
   public void testSessionWithTwoTransactedNonPersistentMessagesFailover() throws Exception
   {
      Connection conn = null;

      try
      {
         conn = createConnectionOnServer(cf, 1);

         conn.start();

         Session session = conn.createSession(true, Session.SESSION_TRANSACTED);

         // send 2 transacted messages (one persistent and one non-persistent) but don't commit
         MessageProducer prod = session.createProducer(queue[1]);

         prod.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
         prod.send(session.createTextMessage("clik-non-persistent"));
         prod.send(session.createTextMessage("clak-non-persistent"));

         // close the producer
         prod.close();

         log.debug("producer closed");

         // create a consumer on the same local queue (creating a consumer AFTER failover will end
         // up getting messages from a local queue, not a failed over queue; at least until
         // redistribution is implemented.

         Session session2 = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
         MessageConsumer cons = session2.createConsumer(queue[1]);

         // register a failover listener
         SimpleFailoverListener failoverListener = new SimpleFailoverListener();
         ((JBossConnection)conn).registerFailoverListener(failoverListener);

         ServerManagement.kill(1);

         // wait for the client-side failover to complete

         while(true)
         {
            FailoverEvent event = failoverListener.getEvent(30000);
            if (event != null && FailoverEvent.FAILOVER_COMPLETED == event.getType())
            {
               break;
            }
            if (event == null)
            {
               fail("Did not get expected FAILOVER_COMPLETED event");
            }
         }

         // failover complete
         assertEquals(0, getServerId(conn));

         // commit the failed-over session
         session.commit();

         // make sure messages made it to the queue

         TextMessage tm = (TextMessage)cons.receive(2000);
         assertNotNull(tm);
         assertEquals("clik-non-persistent", tm.getText());

         tm = (TextMessage)cons.receive(2000);
         assertNotNull(tm);
         assertEquals("clak-non-persistent", tm.getText());
      }
      finally
      {
         if (conn != null)
         {
            conn.close();
         }
      }
   }

   /**
    * Sending 2 persistent messages.
    */
   public void testSessionWithTwoTransactedPersistentMessagesFailover() throws Exception
   {
      Connection conn = null;

      try
      {
         conn = createConnectionOnServer(cf, 1);

         conn.start();

         Session session = conn.createSession(true, Session.SESSION_TRANSACTED);

         // send 2 transacted messages (one persistent and one non-persistent) but don't commit
         MessageProducer prod = session.createProducer(queue[1]);

         prod.setDeliveryMode(DeliveryMode.PERSISTENT);
         prod.send(session.createTextMessage("clik-persistent"));
         prod.send(session.createTextMessage("clak-persistent"));

         // close the producer
         prod.close();

         log.debug("producer closed");

         // create a consumer on the same local queue (creating a consumer AFTER failover will end
         // up getting messages from a local queue, not a failed over queue; at least until
         // redistribution is implemented.

         Session session2 = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
         MessageConsumer cons = session2.createConsumer(queue[1]);

         // register a failover listener
         SimpleFailoverListener failoverListener = new SimpleFailoverListener();
         ((JBossConnection)conn).registerFailoverListener(failoverListener);

         ServerManagement.kill(1);

         // wait for the client-side failover to complete

         while(true)
         {
            FailoverEvent event = failoverListener.getEvent(30000);
            if (event != null && FailoverEvent.FAILOVER_COMPLETED == event.getType())
            {
               break;
            }
            if (event == null)
            {
               fail("Did not get expected FAILOVER_COMPLETED event");
            }
         }

         // failover complete
         assertEquals(0, getServerId(conn));

         // commit the failed-over session
         session.commit();

         // make sure messages made it to the queue

         TextMessage tm = (TextMessage)cons.receive(2000);
         assertNotNull(tm);
         assertEquals("clik-persistent", tm.getText());

         tm = (TextMessage)cons.receive(2000);
         assertNotNull(tm);
         assertEquals("clak-persistent", tm.getText());

      }
      finally
      {
         if (conn != null)
         {
            conn.close();
         }
      }
   }

   /**
    * Sending a mix of persistent and non-persistent messages.
    */
   public void testSessionWithTwoTransactedMixedMessagesFailover() throws Exception
   {
      Connection conn = null;

      try
      {
         conn = createConnectionOnServer(cf, 1);

         conn.start();

         Session session = conn.createSession(true, Session.SESSION_TRANSACTED);

         // send 2 transacted messages (one persistent and one non-persistent) but don't commit
         MessageProducer prod = session.createProducer(queue[1]);

         prod.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
         prod.send(session.createTextMessage("clik-non-persistent"));

         prod.setDeliveryMode(DeliveryMode.PERSISTENT);
         prod.send(session.createTextMessage("clak-persistent"));

         // close the producer
         prod.close();

         log.debug("producer closed");

         // create a consumer on the same local queue (creating a consumer AFTER failover will end
         // up getting messages from a local queue, not a failed over queue; at least until
         // redistribution is implemented.

         Session session2 = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
         MessageConsumer cons = session2.createConsumer(queue[1]);

         // register a failover listener
         SimpleFailoverListener failoverListener = new SimpleFailoverListener();
         ((JBossConnection)conn).registerFailoverListener(failoverListener);

         ServerManagement.kill(1);

         // wait for the client-side failover to complete

         while(true)
         {
            FailoverEvent event = failoverListener.getEvent(30000);
            if (event != null && FailoverEvent.FAILOVER_COMPLETED == event.getType())
            {
               break;
            }
            if (event == null)
            {
               fail("Did not get expected FAILOVER_COMPLETED event");
            }
         }

         // failover complete
         assertEquals(0, getServerId(conn));

         // commit the failed-over session
         session.commit();

         // make sure messages made it to the queue

         TextMessage tm = (TextMessage)cons.receive(2000);
         assertNotNull(tm);
         assertEquals("clik-non-persistent", tm.getText());

         tm = (TextMessage)cons.receive(2000);
         assertNotNull(tm);
         assertEquals("clak-persistent", tm.getText());
      }
      finally
      {
         if (conn != null)
         {
            conn.close();
         }
      }
   }

   public void testSessionWithAcknowledgmentsFailover() throws Exception
   {
      Connection conn = null;

      try
      {
         conn = createConnectionOnServer(cf, 1);

         conn.start();

         Session session = conn.createSession(false, Session.CLIENT_ACKNOWLEDGE);

         // send 2 messages (one persistent and one non-persistent)

         MessageProducer prod = session.createProducer(queue[1]);

         prod.setDeliveryMode(DeliveryMode.PERSISTENT);
         prod.send(session.createTextMessage("clik-persistent"));
         prod.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
         prod.send(session.createTextMessage("clak-non-persistent"));

         // close the producer
         prod.close();

         // create a consumer and receive messages, but don't acknowledge

         MessageConsumer cons = session.createConsumer(queue[1]);
         TextMessage clik = (TextMessage)cons.receive(2000);
         assertEquals("clik-persistent", clik.getText());
         TextMessage clak = (TextMessage)cons.receive(2000);
         assertEquals("clak-non-persistent", clak.getText());

         // register a failover listener
         SimpleFailoverListener failoverListener = new SimpleFailoverListener();
         ((JBossConnection)conn).registerFailoverListener(failoverListener);

         ServerManagement.kill(1);

         // wait for the client-side failover to complete

         while(true)
         {
            FailoverEvent event = failoverListener.getEvent(30000);
            if (event != null && FailoverEvent.FAILOVER_COMPLETED == event.getType())
            {
               break;
            }
            if (event == null)
            {
               fail("Did not get expected FAILOVER_COMPLETED event");
            }
         }

         // failover complete
         assertEquals(0, getServerId(conn));

         // acknowledge the messages
         clik.acknowledge();
         clak.acknowledge();

         // make sure no messages are left in the queue
         checkEmpty(queue[1], 0);
      }
      finally
      {
         if (conn != null)
         {
            conn.close();
         }
      }
   }

   public void testTransactedSessionWithAcknowledgmentsCommitOnFailover() throws Exception
   {
      Connection conn = null;

      try
      {
         // create a connection to node 1
         conn = this.createConnectionOnServer(cf, 1);

         conn.start();

         assertEquals(1, getServerId(conn));

         Session session = conn.createSession(true, Session.SESSION_TRANSACTED);

         // send 2 messages (one persistent and one non-persistent)

         MessageProducer prod = session.createProducer(queue[1]);

         prod.setDeliveryMode(DeliveryMode.PERSISTENT);
         prod.send(session.createTextMessage("clik-persistent"));
         prod.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
         prod.send(session.createTextMessage("clak-non-persistent"));

         session.commit();

         // close the producer

         prod.close();

         // create a consumer and receive messages, but don't acknowledge

         MessageConsumer cons = session.createConsumer(queue[1]);
         TextMessage clik = (TextMessage)cons.receive(2000);
         assertEquals("clik-persistent", clik.getText());
         TextMessage clak = (TextMessage)cons.receive(2000);
         assertEquals("clak-non-persistent", clak.getText());

         // register a failover listener
         SimpleFailoverListener failoverListener = new SimpleFailoverListener();
         ((JBossConnection)conn).registerFailoverListener(failoverListener);

         ServerManagement.kill(1);

         // wait for the client-side failover to complete

         while(true)
         {
            FailoverEvent event = failoverListener.getEvent(30000);
            if (event != null && FailoverEvent.FAILOVER_COMPLETED == event.getType())
            {
               break;
            }
            if (event == null)
            {
               fail("Did not get expected FAILOVER_COMPLETED event");
            }
         }

         // failover complete
         assertEquals(0, getServerId(conn));

         // acknowledge the messages
         session.commit();

         // make sure no messages are left in the queue
         checkEmpty(queue[1], 0);
      }
      finally
      {
         if (conn != null)
         {
            conn.close();
         }
      }
   }


   public void testTransactedSessionWithAcknowledgmentsRollbackOnFailover() throws Exception
   {
      Connection conn = null;

      try
      {
         conn = createConnectionOnServer(cf, 1);

         conn.start();

         Session session = conn.createSession(true, Session.SESSION_TRANSACTED);

         // send 2 messages (one persistent and one non-persistent)

         MessageProducer prod = session.createProducer(queue[1]);

         prod.setDeliveryMode(DeliveryMode.PERSISTENT);
         prod.send(session.createTextMessage("clik-persistent"));
         prod.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
         prod.send(session.createTextMessage("clak-non-persistent"));

         session.commit();

         // close the producer
         prod.close();

         // create a consumer and receive messages, but don't acknowledge

         MessageConsumer cons = session.createConsumer(queue[1]);
         TextMessage clik = (TextMessage)cons.receive(2000);
         assertEquals("clik-persistent", clik.getText());
         TextMessage clak = (TextMessage)cons.receive(2000);
         assertEquals("clak-non-persistent", clak.getText());

         // register a failover listener
         SimpleFailoverListener failoverListener = new SimpleFailoverListener();
         ((JBossConnection)conn).registerFailoverListener(failoverListener);

         ServerManagement.kill(1);

         // wait for the client-side failover to complete

         while(true)
         {
            FailoverEvent event = failoverListener.getEvent(30000);
            if (event != null && FailoverEvent.FAILOVER_COMPLETED == event.getType())
            {
               break;
            }
            if (event == null)
            {
               fail("Did not get expected FAILOVER_COMPLETED event");
            }
         }

         // failover complete
         assertEquals(0, getServerId(conn));

         session.rollback();

         TextMessage m = (TextMessage)cons.receive(2000);
         assertNotNull(m);
         assertEquals("clik-persistent", m.getText());

         session.commit();

         checkEmpty(queue[1], 0);
      }
      finally
      {
         if (conn != null)
         {
            conn.close();
         }
      }
   }


   public void testFailoverListener() throws Exception
   {
      Connection conn = null;

      try
      {
         conn = createConnectionOnServer(cf, 1);
         conn.start();

         SimpleFailoverListener failoverListener = new SimpleFailoverListener();
         ((JBossConnection)conn).registerFailoverListener(failoverListener);

         // kill node 1

         ServerManagement.kill(1);

         FailoverEvent event = failoverListener.getEvent(30000);

         assertNotNull(event);
         assertEquals(FailoverEvent.FAILURE_DETECTED, event.getType());

         event = failoverListener.getEvent(30000);

         assertNotNull(event);
         assertEquals(FailoverEvent.FAILOVER_STARTED, event.getType());

         event = failoverListener.getEvent(30000);

         assertNotNull(event);
         assertEquals(FailoverEvent.FAILOVER_COMPLETED, event.getType());
      }
      finally
      {
         if (conn != null)
         {
            conn.close();
         }
      }
}

   public void testFailoverMessageOnServer() throws Exception
   {
      Connection conn = null;

      try
      {
         conn = createConnectionOnServer(cf, 1);
         conn.start();

         SimpleFailoverListener listener = new SimpleFailoverListener();
         ((JBossConnection)conn).registerFailoverListener(listener);

         Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
         MessageProducer prod = session.createProducer(queue[1]);
         prod.setDeliveryMode(DeliveryMode.PERSISTENT);
         MessageConsumer cons = session.createConsumer(queue[0]);

         // send a message

         prod.send(session.createTextMessage("blip"));

         // kill node 1

         ServerManagement.kill(1);

         // wait until the failure (not the completion of client-side failover) is detected

         while(true)
         {
            FailoverEvent event = listener.getEvent(30000);
            if (event != null && FailoverEvent.FAILOVER_STARTED == event.getType())
            {
               break;
            }
            if (event == null)
            {
               fail("Did not get expected FAILOVER_STARTED event");
            }
         }

         // start to receive the very next moment the failure is detected. This way, we also
         // test the client-side failover valve

         TextMessage tm = (TextMessage)cons.receive(60000);

         assertNotNull(tm);
         assertEquals("blip", tm.getText());

         tm = (TextMessage)cons.receive(1000);
         assertNull(tm);
      }
      finally
      {
         if (conn != null)
         {
            conn.close();
         }
      }
   }

   public void testFailoverMessageOnServer2() throws Exception
   {
      Connection conn = null;

      try
      {
         conn = createConnectionOnServer(cf, 1);
         conn.start();

         SimpleFailoverListener listener = new SimpleFailoverListener();
         ((JBossConnection)conn).registerFailoverListener(listener);

         Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
         MessageProducer prod = session.createProducer(queue[1]);
         prod.setDeliveryMode(DeliveryMode.PERSISTENT);

         // send a message

         prod.send(session.createTextMessage("blip"));

         // kill node 1

         ServerManagement.kill(1);

         // wait until the failure (not the completion of client-side failover) is detected

         assertEquals(FailoverEvent.FAILURE_DETECTED, listener.getEvent(60000).getType());

         // create a consumer the very next moment the failure is detected. This way, we also
         // test the client-side failover valve

         MessageConsumer cons = session.createConsumer(queue[1]);

         // we must receive the message

         TextMessage tm = (TextMessage)cons.receive(60000);
         assertEquals("blip", tm.getText());
      }
      finally
      {
         if (conn != null)
         {
            conn.close();
         }
      }
   }

   public void testSimpleFailover() throws Exception
   {
      simpleFailover(null, null);
   }

   public void testSimpleFailoverUserPassword() throws Exception
   {
      final String testTopicConf =
         "<security>" +
            "<role name=\"guest\" read=\"true\" write=\"true\"/>" +
            "<role name=\"publisher\" read=\"true\" write=\"true\" create=\"false\"/>" +
            "<role name=\"durpublisher\" read=\"true\" write=\"true\" create=\"true\"/>" +
         "</security>";

      ServerManagement.configureSecurityForDestination(0, "testDistributedQueue", testTopicConf);
      ServerManagement.configureSecurityForDestination(1, "testDistributedQueue", testTopicConf);

      simpleFailover("john", "needle");
   }

   public void testMethodSmackingIntoFailure() throws Exception
   {
      Connection conn = null;

      try
      {
         conn = createConnectionOnServer(cf, 1);

         // we "cripple" the remoting connection by removing ConnectionListener. This way, failures
         // cannot be "cleanly" detected by the client-side pinger, and we'll fail on an invocation
         JMSRemotingConnection rc = ((ClientConnectionDelegate)((JBossConnection)conn).
            getDelegate()).getRemotingConnection();
         rc.removeConnectionListener();

         ServerManagement.kill(1);

         conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
      }
      finally
      {
         if (conn != null)
         {
            conn.close();
         }
      }
   }

   public void testFailureInTheMiddleOfAnInvocation() throws Exception
   {
      Connection conn = null;

      try
      {
         conn = createConnectionOnServer(cf, 1);

         // we "cripple" the remoting connection by removing ConnectionListener. This way, failures
         // cannot be "cleanly" detected by the client-side pinger, and we'll fail on an invocation
         JMSRemotingConnection rc = ((ClientConnectionDelegate)((JBossConnection)conn).
            getDelegate()).getRemotingConnection();
         rc.removeConnectionListener();

         SimpleFailoverListener failoverListener = new SimpleFailoverListener();
         ((JBossConnection)conn).registerFailoverListener(failoverListener);

         // poison the server
         ServerManagement.poisonTheServer(1, PoisonInterceptor.TYPE_CREATE_SESSION);

         // this invocation will halt the server ...
         Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);

         // ... and hopefully it be failed over

         MessageConsumer cons = session.createConsumer(queue[0]);
         MessageProducer prod = session.createProducer(queue[0]);

         prod.send(session.createTextMessage("after-poison"));

         conn.start();

         TextMessage tm = (TextMessage)cons.receive(2000);

         assertNotNull(tm);
         assertEquals("after-poison", tm.getText());

      }
      finally
      {
         if (conn != null)
         {
            conn.close();
         }
      }
   }

   public void testSimpleFailoverWithRemotingListenerEnabled() throws Exception
   {
      Connection conn = null;

      try
      {
         conn = createConnectionOnServer(cf, 1);
         conn.start();

         Session s1 = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
         MessageConsumer c1 = s1.createConsumer(queue[1]);
         MessageProducer p1 = s1.createProducer(queue[1]);
         p1.setDeliveryMode(DeliveryMode.PERSISTENT);

         // send a message

         p1.send(s1.createTextMessage("blip"));

         // kill node 1

         ServerManagement.kill(1);

         try
         {
            ic[1].lookup("queue"); // looking up anything
            fail("The server still alive, kill didn't work yet");
         }
         catch (Exception e)
         {
         }

         // we must receive the message

         TextMessage tm = (TextMessage)c1.receive(30000);
         assertEquals("blip", tm.getText());

      }
      finally
      {
         if (conn != null)
         {
            conn.close();
         }
      }
   }

   public void testFailureRightAfterACK() throws Exception
   {
      failureOnInvocation(PoisonInterceptor.FAIL_AFTER_ACKNOWLEDGE_DELIVERY);
   }

   public void testFailureRightBeforeACK() throws Exception
   {
      failureOnInvocation(PoisonInterceptor.FAIL_BEFORE_ACKNOWLEDGE_DELIVERY);
   }

   public void testFailureRightBeforeSend() throws Exception
   {
      failureOnInvocation(PoisonInterceptor.FAIL_BEFORE_SEND);
   }

   public void testFailureRightAfterSend() throws Exception
   {
      failureOnInvocation(PoisonInterceptor.FAIL_AFTER_SEND);
   }

   public void testFailureRightAfterSendTransaction() throws Exception
   {
      Connection conn = null;

      try
      {
         conn = this.createConnectionOnServer(cf, 1);

         assertEquals(1, getServerId(conn));

         // we "cripple" the remoting connection by removing ConnectionListener. This way, failures
         // cannot be "cleanly" detected by the client-side pinger, and we'll fail on an invocation
         JMSRemotingConnection rc = ((ClientConnectionDelegate)((JBossConnection)conn).
            getDelegate()).getRemotingConnection();
         rc.removeConnectionListener();

         // poison the server
         ServerManagement.poisonTheServer(1, PoisonInterceptor.FAIL_AFTER_SENDTRANSACTION);

         Session session = conn.createSession(true, Session.SESSION_TRANSACTED);

         conn.start();

         MessageProducer producer = session.createProducer(queue[0]);

         producer.setDeliveryMode(DeliveryMode.PERSISTENT);

         MessageConsumer consumer = session.createConsumer(queue[0]);

         producer.send(session.createTextMessage("before-poison1"));
         producer.send(session.createTextMessage("before-poison2"));
         producer.send(session.createTextMessage("before-poison3"));
         session.commit();

         Thread.sleep(2000);

         for (int i = 1; i <= 3; i++)
         {
            TextMessage tm = (TextMessage) consumer.receive(5000);

            assertNotNull(tm);

            assertEquals("before-poison" + i, tm.getText());
         }

         assertNull(consumer.receive(3000));

         session.commit();
      }
      finally
      {
         if (conn != null)
         {
            conn.close();
         }
      }
   }

   public void testFailureRightBeforeSendTransaction() throws Exception
   {
      Connection conn = null;

      try
      {
         conn = this.createConnectionOnServer(cf, 1);

         assertEquals(1, getServerId(conn));

         // we "cripple" the remoting connection by removing ConnectionListener. This way, failures
         // cannot be "cleanly" detected by the client-side pinger, and we'll fail on an invocation
         JMSRemotingConnection rc = ((ClientConnectionDelegate)((JBossConnection)conn).
            getDelegate()).getRemotingConnection();
         rc.removeConnectionListener();

         // poison the server
         ServerManagement.poisonTheServer(1, PoisonInterceptor.FAIL_BEFORE_SENDTRANSACTION);

         Session session = conn.createSession(true, Session.SESSION_TRANSACTED);

         conn.start();

         MessageProducer producer = session.createProducer(queue[0]);

         producer.setDeliveryMode(DeliveryMode.PERSISTENT);

         MessageConsumer consumer = session.createConsumer(queue[0]);

         producer.send(session.createTextMessage("before-poison1"));
         producer.send(session.createTextMessage("before-poison2"));
         producer.send(session.createTextMessage("before-poison3"));
         session.commit();

         Thread.sleep(2000);

         for (int i = 1; i <= 3; i++)
         {
            TextMessage tm = (TextMessage) consumer.receive(5000);

            assertNotNull(tm);

            assertEquals("before-poison" + i, tm.getText());
         }

         assertNull(consumer.receive(3000));

         session.commit();
      }
      finally
      {
         if (conn != null)
         {
            conn.close();
         }
      }
   }



   public void testCloseConsumer() throws Exception
   {
      Connection conn0 = null;
      Connection conn1 = null;

      try
      {
         conn0 = createConnectionOnServer(cf, 0);

         // Objects Server1
         conn1 = createConnectionOnServer(cf, 1);

         assertEquals(1, getServerId(conn1));

         JMSRemotingConnection rc = ((ClientConnectionDelegate)((JBossConnection)conn1).
            getDelegate()).getRemotingConnection();
         rc.removeConnectionListener();

         Session session1 = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE);

         MessageConsumer consumer = session1.createConsumer(queue[1]);

         ServerManagement.kill(1);

         consumer.close();
      }
      finally
      {
         if (conn1 != null)
         {
            conn1.close();
         }

         if (conn0 != null)
         {
            conn0.close();
         }
      }
   }

   public void testCloseBrowser() throws Exception
   {
      Connection conn0 = null;
      Connection conn1 = null;

      try
      {
         conn0 = createConnectionOnServer(cf, 0);

         // Objects Server1
         conn1 = createConnectionOnServer(cf, 1);

         assertEquals(1, getServerId(conn1));

         JMSRemotingConnection rc = ((ClientConnectionDelegate)((JBossConnection)conn1).
            getDelegate()).getRemotingConnection();
         rc.removeConnectionListener();

         Session session1 = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE);

         QueueBrowser browser = session1.createBrowser(queue[1]);

         ServerManagement.kill(1);

         browser.close();
      }
      finally
      {
         if (conn1 != null)
         {
            conn1.close();
         }

         if (conn0 != null)
         {
            conn0.close();
         }
      }
   }


   public void testCloseSession() throws Exception
   {
      Connection conn0 = null;
      Connection conn1 = null;

      try
      {
         conn0 = createConnectionOnServer(cf, 0);

         conn1 = createConnectionOnServer(cf, 1);

         assertEquals(1, getServerId(conn1));

         JMSRemotingConnection rc = ((ClientConnectionDelegate)((JBossConnection)conn1).
            getDelegate()).getRemotingConnection();
         rc.removeConnectionListener();

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

         ServerManagement.kill(1);

         session.close();
      }
      finally
      {
         if (conn1 != null)
         {
            conn1.close();
         }

         if (conn0 != null)
         {
            conn0.close();
         }
      }
   }

   public void testCloseConnection() throws Exception
   {
      Connection conn0 = null;
      Connection conn1 = null;

      try
      {
         conn0 = createConnectionOnServer(cf, 0);

         conn1 = createConnectionOnServer(cf, 1);

         assertEquals(1, getServerId(conn1));

         JMSRemotingConnection rc = ((ClientConnectionDelegate)((JBossConnection)conn1).
            getDelegate()).getRemotingConnection();
         rc.removeConnectionListener();

         ServerManagement.kill(1);

         conn1.close();
      }
      finally
      {
         if (conn0 != null)
         {
            conn0.close();
         }
      }
   }



   public void testDurableSubscriptionFailover() throws Exception
   {
      Connection conn = null;

      try
      {
         conn = createConnectionOnServer(cf, 1);

         conn.setClientID("myclientid1");

         conn.start();

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

         // register a failover listener
         SimpleFailoverListener failoverListener = new SimpleFailoverListener();
         ((JBossConnection)conn).registerFailoverListener(failoverListener);

         MessageConsumer cons = session.createDurableSubscriber(topic[1], "mysub1");

         MessageProducer prod = session.createProducer(topic[1]);

         for (int i = 0; i < 5; i++)
         {
            TextMessage tm = session.createTextMessage("message" + i);

            prod.send(tm);
         }

         ServerManagement.kill(1);

         // wait for the client-side failover to complete

         while(true)
         {
            FailoverEvent event = failoverListener.getEvent(30000);
            if (event != null && FailoverEvent.FAILOVER_COMPLETED == event.getType())
            {
               break;
            }
            if (event == null)
            {
               fail("Did not get expected FAILOVER_COMPLETED event");
            }
         }

         // failover complete
         assertEquals(0, getServerId(conn));

         for (int i = 5; i < 10; i++)
         {
            TextMessage tm = session.createTextMessage("message" + i);

            prod.send(tm);
         }

         for (int i = 0; i < 10; i++)
         {
            TextMessage tm = (TextMessage)cons.receive(30000);

            assertNotNull(tm);

            assertEquals("message" + i, tm.getText());
         }

         cons.close();

         session.unsubscribe("mysub1");
      }
      finally
      {
         if (conn != null)
         {
            conn.close();
         }
      }
   }

   public void testDurableSubscriptionFailoverTwosubscribers() throws Exception
   {
      Connection conn = null;

      Connection conn0 = null;

      try
      {
         conn = createConnectionOnServer(cf, 1);

         conn.setClientID("myclientid1");

         conn.start();

         conn0 = this.createConnectionOnServer(cf, 0);

         //same client id
         conn0.setClientID("myclientid1");

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

         Session session0 = conn0.createSession(false, Session.AUTO_ACKNOWLEDGE);

         // register a failover listener
         SimpleFailoverListener failoverListener = new SimpleFailoverListener();
         ((JBossConnection)conn).registerFailoverListener(failoverListener);

         MessageConsumer cons = session.createDurableSubscriber(topic[1], "mysub1");

         //Durable sub on different node with same client id and sub name
         MessageConsumer cons0 = session0.createDurableSubscriber(topic[0], "mysub1");

         MessageProducer prod = session.createProducer(topic[1]);

         for (int i = 0; i < 5; i++)
         {
            TextMessage tm = session.createTextMessage("message" + i);

            prod.send(tm);
         }

         ServerManagement.kill(1);

         // wait for the client-side failover to complete

         while(true)
         {
            FailoverEvent event = failoverListener.getEvent(30000);
            if (event != null && FailoverEvent.FAILOVER_COMPLETED == event.getType())
            {
               break;
            }
            if (event == null)
            {
               fail("Did not get expected FAILOVER_COMPLETED event");
            }
         }

         // failover complete
         assertEquals(0, getServerId(conn));

         for (int i = 5; i < 10; i++)
         {
            TextMessage tm = session.createTextMessage("message" + i);

            prod.send(tm);
         }

         for (int i = 0; i < 10; i++)
         {
            TextMessage tm = (TextMessage)cons.receive(30000);

            assertNotNull(tm);

            assertEquals("message" + i, tm.getText());
         }

         cons.close();

         cons0.close();

         session.unsubscribe("mysub1");
      }
      finally
      {
         if (conn != null)
         {
            conn.close();
         }

         if (conn0 != null)
         {
            conn0.close();
         }
      }
   }


   public void testDurableSubscriptionFailoverWithClientIDOnConnectionFactory() throws Exception
   {
      Connection conn = null;

      final String clientID = "ooble";

      ServerManagement.getServer(0).deployConnectionFactory("jboss.messaging.connectionfactory:service=WibbleConnectionFactory",
                                               new String[] { "/WibbleCF"},
                                               true, true, clientID);
      ServerManagement.getServer(1).deployConnectionFactory("jboss.messaging.connectionfactory:service=WibbleConnectionFactory",
            new String[] { "/WibbleCF"},
            true, true, clientID);

      ConnectionFactory myCF = (ConnectionFactory)ic[0].lookup("/WibbleCF");

      try
      {
         conn = createConnectionOnServer(myCF, 1);

         conn.start();

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

         // register a failover listener
         SimpleFailoverListener failoverListener = new SimpleFailoverListener();
         ((JBossConnection)conn).registerFailoverListener(failoverListener);

         MessageConsumer cons = session.createDurableSubscriber(topic[1], "mysub1");

         MessageProducer prod = session.createProducer(topic[1]);

         for (int i = 0; i < 5; i++)
         {
            TextMessage tm = session.createTextMessage("message" + i);

            prod.send(tm);
         }

         ServerManagement.kill(1);

         // wait for the client-side failover to complete

         while(true)
         {
            FailoverEvent event = failoverListener.getEvent(30000);
            if (event != null && FailoverEvent.FAILOVER_COMPLETED == event.getType())
            {
               break;
            }
            if (event == null)
            {
               fail("Did not get expected FAILOVER_COMPLETED event");
            }
         }

         // failover complete
         assertEquals(0, getServerId(conn));

         for (int i = 5; i < 10; i++)
         {
            TextMessage tm = session.createTextMessage("message" + i);

            prod.send(tm);
         }

         for (int i = 0; i < 10; i++)
         {
            TextMessage tm = (TextMessage)cons.receive(30000);

            assertNotNull(tm);

            assertEquals("message" + i, tm.getText());
         }

         cons.close();

         session.unsubscribe("mysub1");
      }
      finally
      {
         if (conn != null)
         {
            conn.close();
         }

         ServerManagement.getServer(0).undeployConnectionFactory(new ObjectName("jboss.messaging.connectionfactory:service=WibbleConnectionFactory"));
      }
   }

   public void testFailoverDeliveryRecoveryTransacted() throws Exception
   {
      Connection conn0 = null;
      Connection conn1 = null;

      try
      {
         conn0 = this.createConnectionOnServer(cf, 0);

         assertEquals(0, ((JBossConnection)conn0).getServerID());

         // Objects Server1
         conn1 = this.createConnectionOnServer(cf, 1);

         assertEquals(1, ((JBossConnection)conn1).getServerID());

         Session session1 = conn1.createSession(true, Session.SESSION_TRANSACTED);

         Session session2 = conn1.createSession(true, Session.SESSION_TRANSACTED);

         MessageConsumer cons1 = session1.createConsumer(queue[1]);

         MessageConsumer cons2 = session2.createConsumer(queue[1]);

         MessageProducer prod = session1.createProducer(queue[1]);

         conn1.start();

         TextMessage tm1 = session1.createTextMessage("message1");

         TextMessage tm2 = session1.createTextMessage("message2");

         TextMessage tm3 = session1.createTextMessage("message3");

         prod.send(tm1);

         prod.send(tm2);

         prod.send(tm3);

         session1.commit();

         TextMessage rm1 = (TextMessage)cons1.receive(3000);

         assertNotNull(rm1);

         assertEquals(tm1.getText(), rm1.getText());

         TextMessage rm2 = (TextMessage)cons2.receive(3000);

         assertNotNull(rm2);

         assertEquals(tm2.getText(), rm2.getText());

         SimpleFailoverListener failoverListener = new SimpleFailoverListener();
         ((JBossConnection)conn1).registerFailoverListener(failoverListener);

         ServerManagement.kill(1);

         // wait for the client-side failover to complete

         while(true)
         {
            FailoverEvent event = failoverListener.getEvent(30000);
            if (event != null && FailoverEvent.FAILOVER_COMPLETED == event.getType())
            {
               break;
            }
            if (event == null)
            {
               fail("Did not get expected FAILOVER_COMPLETED event");
            }
         }

         // failover complete

         //now commit

         session1.commit();

         session2.commit();

         session1.close();

         session2.close();;

         Session session3 = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE);

         MessageConsumer cons3 = session3.createConsumer(queue[0]);

         TextMessage rm3 = (TextMessage)cons3.receive(2000);

         assertNotNull(rm3);

         assertEquals(tm3.getText(), rm3.getText());

         checkEmpty(queue[1], 0);
      }
      finally
      {
         if (conn1 != null)
         {
            conn1.close();
         }

         if (conn0 != null)
         {
            conn0.close();
         }
      }
   }

   /**
    * deploy a distributed queue on only one node and then perform failover
    * The failover for other nodes should not be affected.
    * https://jira.jboss.org/jira/browse/JBMESSAGING-1457
    */
   public void testFailoverWithSingleDistributedTargetNoMessage() throws Exception
   {
      Connection conn = null;

      try
      {
         ServerManagement.deployQueue("singleDeployedDistributedQueue", 1);

         conn = createConnectionOnServer(cf, 1);

         Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
         MessageProducer prod = session.createProducer(queue[1]);

         Message m = session.createTextMessage("blimey");
         prod.send(m);

         // register a failover listener
         SimpleFailoverListener failoverListener = new SimpleFailoverListener();
         ((JBossConnection)conn).registerFailoverListener(failoverListener);

         ServerManagement.kill(1);

         // wait for the client-side failover to complete

         while(true)
         {
            FailoverEvent event = failoverListener.getEvent(30000);
            if (event != null && FailoverEvent.FAILOVER_COMPLETED == event.getType())
            {
               break;
            }
            if (event == null)
            {
               fail("Did not get expected FAILOVER_COMPLETED event");
            }
         }
        
         MessageConsumer cons = session.createConsumer(queue[1]);

         // failover complete
         assertEquals(0, getServerId(conn));

         conn.start();
        
         TextMessage rm = (TextMessage)cons.receive(2000);
         assertNotNull(rm);
         assertEquals("blimey", rm.getText());

      }
      finally
      {
         if (conn != null)
         {
            conn.close();
         }
      }
   }

   /**
    * deploy a distributed queue on only one node and send some messages, then perform failover
    * The failover for other nodes should not be affected.
    * https://jira.jboss.org/jira/browse/JBMESSAGING-1457
    */
   public void testFailoverWithSingleDistributedTargetWithMessage() throws Exception
   {
      Connection conn = null;
      Connection conn1 = null;

      try
      {
         ServerManagement.deployQueue("singleDeployedDistributedQueue", 1);
         Queue lameClusteredQueue = (Queue)ic[1].lookup("queue/singleDeployedDistributedQueue");

         conn = createConnectionOnServer(cf, 1);

         Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
         MessageProducer prod = session.createProducer(queue[1]);
         MessageProducer prod1 = session.createProducer(lameClusteredQueue);

         Message m = session.createTextMessage("blimey");
         prod.send(m);
         Message m1 = session.createTextMessage("message-to-lose");
         prod1.send(m1);

         // register a failover listener
         SimpleFailoverListener failoverListener = new SimpleFailoverListener();
         ((JBossConnection)conn).registerFailoverListener(failoverListener);

         ServerManagement.kill(1);

         // wait for the client-side failover to complete

         while(true)
         {
            FailoverEvent event = failoverListener.getEvent(30000);
            if (event != null && FailoverEvent.FAILOVER_COMPLETED == event.getType())
            {
               break;
            }
            if (event == null)
            {
               fail("Did not get expected FAILOVER_COMPLETED event");
            }
         }
        
         MessageConsumer cons = session.createConsumer(queue[1]);

         // failover complete
         assertEquals(0, getServerId(conn));

         conn.start();
        
         TextMessage rm = (TextMessage)cons.receive(2000);
         assertNotNull(rm);
         assertEquals("blimey", rm.getText());
        
         //simulate restarting node 1, do not clean db
         ServerManagement.start(1, config, overrides, false);
         ServerManagement.deployQueue("singleDeployedDistributedQueue", 1);
         conn1 = createConnectionOnServer(cf, 1);
         ic[1] = new InitialContext(ServerManagement.getJNDIEnvironment(1));
        
         lameClusteredQueue = (Queue)ic[1].lookup("queue/singleDeployedDistributedQueue");
        
         Session session1 = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE);
         conn1.start();

         MessageConsumer cons1 = session1.createConsumer(lameClusteredQueue);
         TextMessage rm1 = (TextMessage)cons1.receive(2000);
         assertNotNull(rm1);
         assertEquals("message-to-lose", rm1.getText());
        
      }
      finally
      {
         if (conn != null)
         {
            conn.close();
         }
         if (conn1 != null)
         {
            conn1.close();
         }
      }
   }

   // Package protected ----------------------------------------------------------------------------

   // Protected ------------------------------------------------------------------------------------

   protected void setUp() throws Exception
   {
      nodeCount = 2;

      super.setUp();
   }

   // Private --------------------------------------------------------------------------------------

   private void simpleFailover(String userName, String password) throws Exception
   {
      Connection conn = null;

      try
      {
         if (userName!=null)
         {
            conn = createConnectionOnServer(cf, 1, userName, password);
         }
         else
         {
            conn = createConnectionOnServer(cf, 1);
         }

         conn.start();

         // Disable Lease for this test.. as the ValveAspect should capture this
         getConnectionState(conn).getRemotingConnection().removeConnectionListener();

         // make sure we're connecting to node 1

         int nodeID = getServerId(conn);

         assertEquals(1, nodeID);

         Session s1 = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
         MessageConsumer c1 = s1.createConsumer(queue[1]);
         MessageProducer p1 = s1.createProducer(queue[1]);
         p1.setDeliveryMode(DeliveryMode.PERSISTENT);

         // send a message

         p1.send(s1.createTextMessage("blip"));

         // kill node 1

         ServerManagement.kill(1);

         try
         {
            ic[1].lookup("queue"); // looking up anything
            fail("The server still alive, kill didn't work yet");
         }
         catch (Exception e)
         {
         }

         // we must receive the message

         TextMessage tm = (TextMessage)c1.receive(30000);
         assertNotNull(tm);
         assertEquals("blip", tm.getText());

      }
      finally
      {
         if (conn != null)
         {
            conn.close();
         }
      }
   }

   // Used for both testFailureRightAfterACK and  testFailureRightBeforeACK
   private void failureOnInvocation(int typeOfFailure) throws Exception
   {
      Connection conn = null;
      Connection conn0 = null;

      try
      {
         conn = createConnectionOnServer(cf, 1);

         assertEquals(1, getServerId(conn));

         // we "cripple" the remoting connection by removing ConnectionListener. This way, failures
         // cannot be "cleanly" detected by the client-side pinger, and we'll fail on an invocation
         JMSRemotingConnection rc = ((ClientConnectionDelegate)((JBossConnection)conn).
            getDelegate()).getRemotingConnection();
         rc.removeConnectionListener();

         // poison the server
         ServerManagement.poisonTheServer(1, typeOfFailure);

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

         conn.start();

         MessageProducer producer = session.createProducer(queue[0]);

         producer.setDeliveryMode(DeliveryMode.PERSISTENT);

         MessageConsumer consumer = session.createConsumer(queue[0]);

         producer.send(session.createTextMessage("before-poison"));

         TextMessage tm = (TextMessage)consumer.receive(10000);

         if(typeOfFailure == PoisonInterceptor.FAIL_AFTER_ACKNOWLEDGE_DELIVERY)
         {
           //With auto_ack we won't the message - remember auto ack is "at most once"
           assertNull(tm);
         }
         else
         {
            assertNotNull(tm);

            assertEquals("before-poison", tm.getText());
         }

         checkEmpty(queue[1], 0);
      }
      finally
      {
         if (conn != null)
         {
            conn.close();
         }
         if (conn0 != null)
         {
            conn0.close();
         }
      }
   }

  
   public void testExceptionListenerOnFailoverFailure() throws Exception
   {

      Connection conn = null;

      try
      {
         conn = createConnectionOnServer(cf, 1);
        
         SimpleExceptionListener listener = new SimpleExceptionListener();
         conn.setExceptionListener(listener);
        
         conn.start();
        
         Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
        
         //start a thread to receive
         ReceiveThread thr = new ReceiveThread(session, queue[1]);
         thr.start();

         // register a failover listener
         SimpleFailoverListener failoverListener = new SimpleFailoverListener();
         ((JBossConnection)conn).registerFailoverListener(failoverListener);

         try
         {
            Thread.sleep(5000);
         }
         catch(InterruptedException e)
         {
         }
        
         ServerManagement.stop(1);

         // wait for the client-side failover to complete

         while(true)
         {
            FailoverEvent event = failoverListener.getEvent(120000);
            if (event != null && FailoverEvent.FAILOVER_FAILED == event.getType())
            {
               break;
            }
            if (event == null)
            {
               fail("Did not get expected FAILOVER_FAILED event");
            }
         }
        
         thr.join();
        
         try
         {
            //give time for notification
            Thread.sleep(5000);
         }
         catch(InterruptedException e)
         {
         }
        
         assertTrue(listener.getNotified());
      }
      finally
      {
         if (conn != null)
         {
            JBossConnection c = (JBossConnection)conn;
            System.out.println("Server id for connectio is : " + c.getServerID());
            conn.close();
         }
      }
   }

   // Inner classes --------------------------------------------------------------------------------
   public static class SimpleExceptionListener implements ExceptionListener
   {
      AtomicBoolean getNotified = new AtomicBoolean(false);
     
      public void onException(JMSException arg0)
      {
         getNotified.set(true);
      }
     
      public boolean getNotified()
      {
         return getNotified.get();
      }
   }
  
   public static class ReceiveThread extends Thread
   {
      Session session;
      Queue queue;
     
      public ReceiveThread(Session session, Queue queue)
      {
         this.session = session;
         this.queue = queue;
      }
     
      public void run()
      {
         try
         {
            MessageConsumer consumer = session.createConsumer(queue);
            consumer.receive(0);
         }
         catch (JMSException e)
         {
            fail("Failed to run receiver " + e);
         }
      }
   }
}
TOP

Related Classes of org.jboss.test.messaging.jms.clustering.FailoverTest$ReceiveThread

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.
0639858-1', 'auto'); ga('send', 'pageview');