/**
   * Typically used before asserts to give producers and consumers some time to finish their tasks
   * before the final state is tested.
   *
   * @param broker BrokerService on which the destinations are looked up
   * @param destinationName
   * @param topic true if the destination is a Topic, false if it is a Queue
   * @param numEnqueueMsgs expected number of enqueued messages in the destination
   * @param numDequeueMsgs expected number of dequeued messages in the destination
   * @param waitTime number of milliseconds to wait for completion
   * @throws Exception
   */
  private void waitForMessagesToBeConsumed(
      final BrokerService broker,
      final String destinationName,
      final boolean topic,
      final int numEnqueueMsgs,
      final int numDequeueMsgs,
      int waitTime)
      throws Exception {
    final ActiveMQDestination destination;
    if (topic) {
      destination = new ActiveMQTopic(destinationName);
    } else {
      destination = new ActiveMQQueue(destinationName);
    }

    Wait.waitFor(
        new Wait.Condition() {
          @Override
          public boolean isSatisified() throws Exception {

            return broker
                    .getDestination(destination)
                    .getDestinationStatistics()
                    .getEnqueues()
                    .getCount()
                == numEnqueueMsgs;
          }
        },
        waitTime);

    Wait.waitFor(
        new Wait.Condition() {
          @Override
          public boolean isSatisified() throws Exception {

            return broker
                    .getDestination(destination)
                    .getDestinationStatistics()
                    .getDequeues()
                    .getCount()
                == numDequeueMsgs;
          }
        },
        waitTime);
  }
 private boolean verifyMessageCount(final int i, final AtomicInteger count) throws Exception {
   return Wait.waitFor(
       new Wait.Condition() {
         @Override
         public boolean isSatisified() throws Exception {
           return i == count.get();
         }
       });
 }
  public void testSlowConnection() throws Exception {

    MockBroker broker = new MockBroker();
    broker.start();

    socketReadyLatch.await();
    int timeout = 1000;
    URI tcpUri =
        new URI(
            "tcp://localhost:"
                + broker.ss.getLocalPort()
                + "?soTimeout="
                + timeout
                + "&trace=true&connectionTimeout="
                + timeout
                + "&wireFormat.maxInactivityDurationInitalDelay="
                + timeout);

    ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory("failover:(" + tcpUri + ")");
    final Connection connection = cf.createConnection();

    new Thread(
            new Runnable() {
              @Override
              public void run() {
                try {
                  connection.start();
                } catch (Throwable ignored) {
                }
              }
            })
        .start();

    int count = 0;
    assertTrue(
        "Transport count: " + count + ", expected <= 1",
        Wait.waitFor(
            new Wait.Condition() {
              @Override
              public boolean isSatisified() throws Exception {
                int count = 0;
                for (Thread thread : Thread.getAllStackTraces().keySet()) {
                  if (thread.getName().contains("ActiveMQ Transport")) {
                    count++;
                  }
                }
                return count == 1;
              }
            }));

    broker.interrupt();
    broker.join();
  }
  private void check(String connectionProperties) throws Exception {
    String s1URL = newURI(0), s2URL = newURI(1);
    String uri = "failover://(" + s1URL + "," + s2URL + ")?" + connectionProperties;
    ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(uri);
    final int initCount1 = getConnectionCount(s1);
    final int initCount2 = getConnectionCount(s2);

    for (int i = 0; i < 10; i++) {
      buildConnection(factory);
    }

    assertTrue(
        connectionProperties
            + " broker1 connection count not zero: was["
            + getConnectionCount(s1)
            + "]",
        Wait.waitFor(
            new Wait.Condition() {

              @Override
              public boolean isSatisified() throws Exception {
                return getConnectionCount(s1) == initCount1;
              }
            }));

    assertTrue(
        connectionProperties
            + " broker2 connection count not zero: was["
            + getConnectionCount(s2)
            + "]",
        Wait.waitFor(
            new Wait.Condition() {

              @Override
              public boolean isSatisified() throws Exception {
                return getConnectionCount(s2) == initCount2;
              }
            }));
  }
  public void testJMX() throws Exception {
    clearSelectorCacheFiles();
    // borkerA is local and brokerB is remote
    bridgeAndConfigureBrokers("BrokerA", "BrokerB");
    startAllBrokers();
    waitForBridgeFormation();

    createConsumer(
        "BrokerB", createDestination("Consumer.B.VirtualTopic.tempTopic", false), "foo = 'bar'");

    final BrokerService brokerA = brokers.get("BrokerA").broker;

    String testQueue = "queue://Consumer.B.VirtualTopic.tempTopic";
    VirtualDestinationSelectorCacheViewMBean cache =
        getVirtualDestinationSelectorCacheMBean(brokerA);
    Set<String> selectors = cache.selectorsForDestination(testQueue);

    assertEquals(1, selectors.size());
    assertTrue(selectors.contains("foo = 'bar'"));

    boolean removed = cache.deleteSelectorForDestination(testQueue, "foo = 'bar'");
    assertTrue(removed);

    selectors = cache.selectorsForDestination(testQueue);
    assertEquals(0, selectors.size());

    createConsumer(
        "BrokerB",
        createDestination("Consumer.B.VirtualTopic.tempTopic", false),
        "ceposta = 'redhat'");

    Wait.waitFor(
        new Wait.Condition() {

          Destination dest =
              brokerA.getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"));

          @Override
          public boolean isSatisified() throws Exception {
            return dest.getConsumers().size() == 2;
          }
        },
        500);

    selectors = cache.selectorsForDestination(testQueue);
    assertEquals(1, selectors.size());
    cache.deleteAllSelectorsForDestination(testQueue);
    selectors = cache.selectorsForDestination(testQueue);
    assertEquals(0, selectors.size());
  }
示例#6
0
  @Test
  public void testSendToDlq() throws Exception {
    sendJMSMessageToKickOffRoute();

    LOG.info("Wait for dlq message...");

    assertTrue(
        Wait.waitFor(
            new Wait.Condition() {
              @Override
              public boolean isSatisified() throws Exception {
                return broker.getAdminView().getTotalEnqueueCount() == 2;
              }
            }));
  }
示例#7
0
  @Test(timeout = 60000)
  public void testSendAfterMissingHeartbeat() throws Exception {

    String connectFrame =
        "STOMP\n"
            + "login:system\n"
            + "passcode:manager\n"
            + "accept-version:1.1\n"
            + "heart-beat:1000,0\n"
            + "host:localhost\n"
            + "\n"
            + Stomp.NULL;

    stompConnection.sendFrame(connectFrame);
    String f = stompConnection.receiveFrame();
    assertTrue(f.startsWith("CONNECTED"));
    assertTrue(f.indexOf("version:1.1") >= 0);
    assertTrue(f.indexOf("heart-beat:") >= 0);
    assertTrue(f.indexOf("session:") >= 0);
    LOG.debug("Broker sent: " + f);

    Wait.waitFor(
        new Wait.Condition() {

          @Override
          public boolean isSatisified() throws Exception {
            return getProxyToBroker().getCurrentConnectionsCount() == 0;
          }
        },
        TimeUnit.SECONDS.toMillis(5),
        TimeUnit.MILLISECONDS.toMillis(25));

    try {
      String message =
          "SEND\n"
              + "destination:/queue/"
              + getQueueName()
              + "\n"
              + "receipt:1\n\n"
              + "Hello World"
              + Stomp.NULL;
      stompConnection.sendFrame(message);
      stompConnection.receiveFrame();
      fail("SEND frame has been accepted after missing heart beat");
    } catch (Exception ex) {
      LOG.info(ex.getMessage());
    }
  }
  // JMX Helper Methods
  private boolean verifyConsumerCount(
      final long expectedCount, final ActiveMQDestination destination, final BrokerService broker)
      throws Exception {
    return Wait.waitFor(
        new Wait.Condition() {
          @Override
          public boolean isSatisified() throws Exception {
            boolean result = false;
            try {

              ObjectName[] destinations;

              if (destination.isQueue()) {
                destinations = broker.getAdminView().getQueues();
              } else {
                destinations = broker.getAdminView().getTopics();
              }

              // We should have 1 consumer for the queue on the local broker
              for (ObjectName name : destinations) {
                DestinationViewMBean view =
                    (DestinationViewMBean)
                        broker
                            .getManagementContext()
                            .newProxyInstance(name, DestinationViewMBean.class, true);

                if (view.getName().equals(destination.getPhysicalName())) {
                  LOG.info(
                      "Consumers for "
                          + destination.getPhysicalName()
                          + " on "
                          + broker
                          + " : "
                          + view.getConsumerCount());
                  LOG.info("Subs: " + Arrays.asList(view.getSubscriptions()));
                  if (expectedCount == view.getConsumerCount()) {
                    result = true;
                  }
                }
              }

            } catch (Exception ignoreAndRetry) {
            }
            return result;
          }
        });
  }
  @Test
  public void testIndexRebuildsAfterSomeJobsExpire() throws Exception {
    IOHelper.deleteFile(schedulerStoreDir);

    JobSchedulerStoreImpl schedulerStore = createScheduler();
    broker = createBroker(schedulerStore);
    broker.start();
    ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory("vm://localhost");
    Connection connection = cf.createConnection();
    connection.start();
    for (int i = 0; i < NUM_JOBS; ++i) {
      scheduleRepeating(connection);
      scheduleOneShot(connection);
    }
    connection.close();

    JobScheduler scheduler = schedulerStore.getJobScheduler("JMS");
    assertNotNull(scheduler);
    assertEquals(NUM_JOBS * 2, scheduler.getAllJobs().size());

    final JobScheduler awaitingOneShotTimeout = scheduler;
    assertTrue(
        "One shot jobs should time out",
        Wait.waitFor(
            new Wait.Condition() {

              @Override
              public boolean isSatisified() throws Exception {
                return awaitingOneShotTimeout.getAllJobs().size() == NUM_JOBS;
              }
            },
            TimeUnit.MINUTES.toMillis(2)));

    broker.stop();

    IOHelper.delete(new File(schedulerStoreDir, "scheduleDB.data"));

    schedulerStore = createScheduler();
    broker = createBroker(schedulerStore);
    broker.start();

    scheduler = schedulerStore.getJobScheduler("JMS");
    assertNotNull(scheduler);
    assertEquals(NUM_JOBS, scheduler.getAllJobs().size());
  }
  private boolean verifyDurableConsumerCount(final long expectedCount, final BrokerService broker)
      throws Exception {
    return Wait.waitFor(
        new Wait.Condition() {
          @Override
          public boolean isSatisified() throws Exception {
            boolean result = false;
            BrokerView view = broker.getAdminView();

            if (view != null) {
              ObjectName[] subs = broker.getAdminView().getInactiveDurableTopicSubscribers();
              if (subs != null) {
                LOG.info("inactive durable subs on " + broker + " : " + Arrays.asList(subs));
                if (expectedCount == subs.length) {
                  result = true;
                }
              }
            }
            return result;
          }
        });
  }
  @Test(timeout = 30000)
  @Ignore("Test fails on windows")
  public void testReconnectUnlimited() throws Exception {

    Transport transport =
        TransportFactory.connect(
            new URI(
                "failover://(tcp://0.0.0.0:61616)?useExponentialBackOff=false&reconnectDelay=0&initialReconnectDelay=0"));

    transport.setTransportListener(
        new TransportListener() {

          @Override
          public void onCommand(Object command) {}

          @Override
          public void onException(IOException error) {}

          @Override
          public void transportInterupted() {}

          @Override
          public void transportResumed() {}
        });
    transport.start();

    this.failoverTransport = transport.narrow(FailoverTransport.class);

    assertTrue(
        "no implicit limit of 1000",
        Wait.waitFor(
            new Wait.Condition() {
              @Override
              public boolean isSatisified() throws Exception {
                return failoverTransport.getConnectFailures() > 1002;
              }
            }));
  }
  @Test
  public void testNew() throws Exception {
    final BrokerService brokerService = new BrokerService();
    startBroker(brokerService);
    assertTrue("broker alive", brokerService.isStarted());
    assertEquals("no network connectors", 0, brokerService.getNetworkConnectors().size());

    DiscoveryNetworkConnector nc = createNetworkConnector();

    javaConfigBroker.addNetworkConnector(nc);

    assertTrue(
        "new network connectors",
        Wait.waitFor(
            new Wait.Condition() {
              @Override
              public boolean isSatisified() throws Exception {
                return 1 == brokerService.getNetworkConnectors().size();
              }
            }));

    NetworkConnector networkConnector = brokerService.getNetworkConnectors().get(0);
    javaConfigBroker.addNetworkConnector(nc);
    TimeUnit.SECONDS.sleep(SLEEP);
    assertEquals("no new network connectors", 1, brokerService.getNetworkConnectors().size());
    assertSame("same instance", networkConnector, brokerService.getNetworkConnectors().get(0));

    // verify nested elements
    assertEquals("has exclusions", 2, networkConnector.getExcludedDestinations().size());

    assertEquals(
        "one statically included", 1, networkConnector.getStaticallyIncludedDestinations().size());
    assertEquals(
        "one dynamically included",
        1,
        networkConnector.getDynamicallyIncludedDestinations().size());
    assertEquals("one durable", 1, networkConnector.getDurableDestinations().size());
  }
  @Test
  public void testRemove() throws Exception {
    final BrokerService brokerService = new BrokerService();
    startBroker(brokerService);
    assertTrue("broker alive", brokerService.isStarted());
    assertEquals("no network connectors", 0, brokerService.getNetworkConnectors().size());

    DiscoveryNetworkConnector nc1 = new DiscoveryNetworkConnector();
    nc1.setUri(new URI("static:(tcp://localhost:5555)"));
    nc1.setNetworkTTL(1);
    nc1.setName("one");

    DiscoveryNetworkConnector nc2 = new DiscoveryNetworkConnector();
    nc2.setUri(new URI("static:(tcp://localhost:5555)"));
    nc2.setNetworkTTL(1);
    nc2.setName("one");

    javaConfigBroker.addNetworkConnector(nc1);
    javaConfigBroker.addNetworkConnector(nc2);

    TimeUnit.SECONDS.sleep(SLEEP);
    assertEquals("correct network connectors", 2, brokerService.getNetworkConnectors().size());

    javaConfigBroker.removeNetworkConnector(nc2);

    assertTrue(
        "expected mod on time",
        Wait.waitFor(
            new Wait.Condition() {
              @Override
              public boolean isSatisified() throws Exception {
                return 1 == brokerService.getNetworkConnectors().size();
              }
            }));

    NetworkConnector remainingNetworkConnector = brokerService.getNetworkConnectors().get(0);
    assertEquals("name match", "one", remainingNetworkConnector.getName());
  }
  public void testLoadBalancing() throws Exception {
    bridgeBrokers("BrokerA", "BrokerB");
    bridgeBrokers("BrokerB", "BrokerA");

    startAllBrokers();
    waitForBridgeFormation();

    // Setup destination
    Destination dest = createDestination("TEST.FOO", false);

    // Setup consumers
    MessageConsumer clientA = createConsumer("BrokerA", dest);

    // Setup consumers
    MessageConsumer clientB = createConsumer("BrokerB", dest);

    // Send messages
    sendMessages("BrokerA", dest, 5000);

    // Send messages
    sendMessages("BrokerB", dest, 1000);

    // Get message count
    final MessageIdList msgsA = getConsumerMessages("BrokerA", clientA);
    final MessageIdList msgsB = getConsumerMessages("BrokerB", clientB);

    Wait.waitFor(
        new Wait.Condition() {
          public boolean isSatisified() throws Exception {
            return msgsA.getMessageCount() + msgsB.getMessageCount() == 6000;
          }
        });

    LOG.info("A got: " + msgsA.getMessageCount());
    LOG.info("B got: " + msgsB.getMessageCount());

    assertTrue("B got is fair share: " + msgsB.getMessageCount(), msgsB.getMessageCount() > 2000);
  }
  public void testExpireMessagesForDurableSubscriber() throws Exception {
    createBroker();
    ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(connectionUri);
    connection = factory.createConnection();
    connection.setClientID("myConnection");
    session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
    connection.start();
    Topic destination = session.createTopic("test");
    producer = session.createProducer(destination);
    final int ttl = 1000;
    producer.setTimeToLive(ttl);

    final long sendCount = 10;

    TopicSubscriber sub = session.createDurableSubscriber(destination, "mySub");
    sub.close();

    for (int i = 0; i < sendCount; i++) {
      producer.send(session.createTextMessage("test"));
    }

    DestinationViewMBean view = createView((ActiveMQTopic) destination);

    LOG.info("messages sent");
    LOG.info("expired=" + view.getExpiredCount() + " " + view.getEnqueueCount());
    assertEquals(0, view.getExpiredCount());
    assertEquals(10, view.getEnqueueCount());

    Thread.sleep(5000);

    LOG.info("expired=" + view.getExpiredCount() + " " + view.getEnqueueCount());
    assertEquals(10, view.getExpiredCount());
    assertEquals(10, view.getEnqueueCount());

    final AtomicLong received = new AtomicLong();
    sub = session.createDurableSubscriber(destination, "mySub");
    sub.setMessageListener(
        new MessageListener() {
          @Override
          public void onMessage(Message message) {
            received.incrementAndGet();
          }
        });

    LOG.info("Waiting for messages to arrive");

    Wait.waitFor(
        new Wait.Condition() {
          @Override
          public boolean isSatisified() throws Exception {
            return received.get() >= sendCount;
          }
        },
        1000);

    LOG.info("received=" + received.get());
    LOG.info("expired=" + view.getExpiredCount() + " " + view.getEnqueueCount());

    assertEquals(0, received.get());
    assertEquals(10, view.getExpiredCount());
    assertEquals(10, view.getEnqueueCount());
  }
  public void testExpiredMessagesWithVerySlowConsumerCanContinue() throws Exception {
    createBroker();
    final long queuePrefetch = 600;
    ActiveMQConnectionFactory factory =
        new ActiveMQConnectionFactory(
            connectionUri + "?jms.prefetchPolicy.queuePrefetch=" + queuePrefetch);
    connection = factory.createConnection();
    session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
    producer = session.createProducer(destination);
    final int ttl = 4000;
    producer.setTimeToLive(ttl);

    final long sendCount = 1500;
    final CountDownLatch receivedOneCondition = new CountDownLatch(1);
    final CountDownLatch waitCondition = new CountDownLatch(1);
    final AtomicLong received = new AtomicLong();
    MessageConsumer consumer = session.createConsumer(destination);
    consumer.setMessageListener(
        new MessageListener() {

          @Override
          public void onMessage(Message message) {
            try {
              if (LOG.isDebugEnabled()) {
                LOG.debug("Got my message: " + message);
              }
              receivedOneCondition.countDown();
              received.incrementAndGet();
              waitCondition.await(5, TimeUnit.MINUTES);
              if (LOG.isDebugEnabled()) {
                LOG.debug("acking message: " + message);
              }
              message.acknowledge();
            } catch (Exception e) {
              e.printStackTrace();
              fail(e.toString());
            }
          }
        });

    connection.start();

    final Thread producingThread =
        new Thread("Producing Thread") {
          @Override
          public void run() {
            try {
              int i = 0;
              long tStamp = System.currentTimeMillis();
              while (i++ < sendCount) {
                producer.send(session.createTextMessage("test"));
                if (i % 100 == 0) {
                  LOG.info(
                      "sent: "
                          + i
                          + " @ "
                          + ((System.currentTimeMillis() - tStamp) / 100)
                          + "m/ms");
                  tStamp = System.currentTimeMillis();
                }
              }
            } catch (Throwable ex) {
              ex.printStackTrace();
            }
          }
        };

    producingThread.start();
    assertTrue("got one message", receivedOneCondition.await(20, TimeUnit.SECONDS));

    assertTrue(
        "producer failed to complete within allocated time",
        Wait.waitFor(
            new Wait.Condition() {
              @Override
              public boolean isSatisified() throws Exception {
                producingThread.join(1000);
                return !producingThread.isAlive();
              }
            },
            Wait.MAX_WAIT_MILLIS * 10));

    final DestinationViewMBean view = createView(destination);

    assertTrue(
        "Not all dispatched up to default prefetch ",
        Wait.waitFor(
            new Wait.Condition() {
              @Override
              public boolean isSatisified() throws Exception {
                return queuePrefetch == view.getDispatchCount();
              }
            }));

    assertTrue(
        "all non inflight have expired ",
        Wait.waitFor(
            new Wait.Condition() {
              @Override
              public boolean isSatisified() throws Exception {
                LOG.info(
                    "enqueue="
                        + view.getEnqueueCount()
                        + ", dequeue="
                        + view.getDequeueCount()
                        + ", inflight="
                        + view.getInFlightCount()
                        + ", expired= "
                        + view.getExpiredCount()
                        + ", size= "
                        + view.getQueueSize());

                return view.getExpiredCount() > 0
                    && (view.getEnqueueCount() - view.getInFlightCount()) == view.getExpiredCount();
              }
            }));

    LOG.info(
        "enqueue="
            + view.getEnqueueCount()
            + ", dequeue="
            + view.getDequeueCount()
            + ", inflight="
            + view.getInFlightCount()
            + ", expired= "
            + view.getExpiredCount()
            + ", size= "
            + view.getQueueSize());

    // let the ack happen
    waitCondition.countDown();

    Wait.waitFor(
        new Wait.Condition() {
          @Override
          public boolean isSatisified() throws Exception {
            return 0 == view.getInFlightCount();
          }
        });
    LOG.info(
        "enqueue="
            + view.getEnqueueCount()
            + ", dequeue="
            + view.getDequeueCount()
            + ", inflight="
            + view.getInFlightCount()
            + ", expired= "
            + view.getExpiredCount()
            + ", size= "
            + view.getQueueSize());

    assertEquals("inflight didn't reduce to duck", 0, view.getInFlightCount());
    assertEquals("size doesn't get back to 0 ", 0, view.getQueueSize());
    assertEquals("dequeues don't match sent/expired ", sendCount, view.getDequeueCount());

    // produce some more
    producer.setTimeToLive(0);
    long tStamp = System.currentTimeMillis();
    for (int i = 0; i < sendCount; i++) {
      producer.send(session.createTextMessage("test-" + i));
      if (i % 100 == 0) {
        LOG.info("sent: " + i + " @ " + ((System.currentTimeMillis() - tStamp) / 100) + "m/ms");
        tStamp = System.currentTimeMillis();
      }
    }

    Wait.waitFor(
        new Wait.Condition() {
          @Override
          public boolean isSatisified() throws Exception {
            return received.get() >= sendCount;
          }
        });

    consumer.close();

    Wait.waitFor(
        new Wait.Condition() {
          @Override
          public boolean isSatisified() throws Exception {
            return 0 == view.getInFlightCount();
          }
        });
    assertEquals("inflight did not go to zero on close", 0, view.getInFlightCount());

    LOG.info("done: " + getName());
  }
  public void testExpiredMessagesWithNoConsumer() throws Exception {

    createBrokerWithMemoryLimit();

    ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(connectionUri);
    connection = factory.createConnection();
    session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
    producer = session.createProducer(destination);
    producer.setTimeToLive(1000);
    connection.start();
    final long sendCount = 2000;

    final Thread producingThread =
        new Thread("Producing Thread") {
          @Override
          public void run() {
            try {
              int i = 0;
              long tStamp = System.currentTimeMillis();
              while (i++ < sendCount) {
                producer.send(session.createTextMessage("test"));
                if (i % 100 == 0) {
                  LOG.info(
                      "sent: "
                          + i
                          + " @ "
                          + ((System.currentTimeMillis() - tStamp) / 100)
                          + "m/ms");
                  tStamp = System.currentTimeMillis();
                }
              }
            } catch (Throwable ex) {
              ex.printStackTrace();
            }
          }
        };

    producingThread.start();

    assertTrue(
        "producer failed to complete within allocated time",
        Wait.waitFor(
            new Wait.Condition() {
              @Override
              public boolean isSatisified() throws Exception {
                producingThread.join(TimeUnit.SECONDS.toMillis(3000));
                return !producingThread.isAlive();
              }
            }));

    final DestinationViewMBean view = createView(destination);
    Wait.waitFor(
        new Wait.Condition() {
          @Override
          public boolean isSatisified() throws Exception {
            LOG.info(
                "enqueue="
                    + view.getEnqueueCount()
                    + ", dequeue="
                    + view.getDequeueCount()
                    + ", inflight="
                    + view.getInFlightCount()
                    + ", expired= "
                    + view.getExpiredCount()
                    + ", size= "
                    + view.getQueueSize());
            return sendCount == view.getExpiredCount();
          }
        },
        Wait.MAX_WAIT_MILLIS * 10);
    LOG.info(
        "enqueue="
            + view.getEnqueueCount()
            + ", dequeue="
            + view.getDequeueCount()
            + ", inflight="
            + view.getInFlightCount()
            + ", expired= "
            + view.getExpiredCount()
            + ", size= "
            + view.getQueueSize());

    assertEquals("Not all sent messages have expired", sendCount, view.getExpiredCount());
    assertEquals("memory usage doesn't go to duck egg", 0, view.getMemoryPercentUsage());
  }
示例#18
0
  @Test(timeout = 60000)
  public void testDurableSubAndUnSubOnTwoTopics() throws Exception {
    stompConnection.setVersion(Stomp.V1_1);

    String domain = "org.apache.activemq";
    ObjectName brokerName = new ObjectName(domain + ":type=Broker,brokerName=localhost");

    BrokerViewMBean view =
        (BrokerViewMBean)
            brokerService
                .getManagementContext()
                .newProxyInstance(brokerName, BrokerViewMBean.class, true);

    String connectFrame =
        "STOMP\n"
            + "login:system\n"
            + "passcode:manager\n"
            + "accept-version:1.1\n"
            + "host:localhost\n"
            + "client-id:test\n"
            + "\n"
            + Stomp.NULL;
    stompConnection.sendFrame(connectFrame);

    String frame = stompConnection.receiveFrame();
    LOG.debug("Broker sent: " + frame);

    assertTrue(frame.startsWith("CONNECTED"));
    assertEquals(view.getDurableTopicSubscribers().length, 0);

    // subscribe to first destination durably
    frame =
        "SUBSCRIBE\n"
            + "destination:/topic/"
            + getQueueName()
            + "1"
            + "\n"
            + "ack:auto\n"
            + "receipt:1\n"
            + "id:durablesub-1\n"
            + "activemq.subscriptionName:test1\n\n"
            + Stomp.NULL;
    stompConnection.sendFrame(frame);

    StompFrame receipt = stompConnection.receive();
    LOG.debug("Broker sent: " + receipt);
    assertTrue(receipt.getAction().startsWith("RECEIPT"));
    assertEquals("1", receipt.getHeaders().get("receipt-id"));
    assertEquals(view.getDurableTopicSubscribers().length, 1);

    // subscribe to second destination durably
    frame =
        "SUBSCRIBE\n"
            + "destination:/topic/"
            + getQueueName()
            + "2"
            + "\n"
            + "ack:auto\n"
            + "receipt:2\n"
            + "id:durablesub-2\n"
            + "activemq.subscriptionName:test2\n\n"
            + Stomp.NULL;
    stompConnection.sendFrame(frame);

    receipt = stompConnection.receive();
    LOG.debug("Broker sent: " + receipt);
    assertTrue(receipt.getAction().startsWith("RECEIPT"));
    assertEquals("2", receipt.getHeaders().get("receipt-id"));
    assertEquals(view.getDurableTopicSubscribers().length, 2);

    frame = "DISCONNECT\nclient-id:test\n\n" + Stomp.NULL;
    stompConnection.sendFrame(frame);
    Wait.waitFor(
        new Wait.Condition() {

          @Override
          public boolean isSatisified() throws Exception {
            return getProxyToBroker().getCurrentConnectionsCount() == 0;
          }
        },
        TimeUnit.SECONDS.toMillis(5),
        TimeUnit.MILLISECONDS.toMillis(25));

    // reconnect and send some messages to the offline subscribers and then try to get
    // them after subscribing again.
    stompConnect();
    stompConnection.sendFrame(connectFrame);
    frame = stompConnection.receiveFrame();
    LOG.debug("Broker sent: " + frame);
    assertTrue(frame.startsWith("CONNECTED"));
    assertEquals(view.getDurableTopicSubscribers().length, 0);
    assertEquals(view.getInactiveDurableTopicSubscribers().length, 2);

    // unsubscribe from topic 1
    frame =
        "UNSUBSCRIBE\n"
            + "destination:/topic/"
            + getQueueName()
            + "1\n"
            + "id:durablesub-1\n"
            + "receipt:3\n"
            + "activemq.subscriptionName:test1\n\n"
            + Stomp.NULL;
    stompConnection.sendFrame(frame);
    receipt = stompConnection.receive();
    LOG.debug("Broker sent: " + frame);
    assertTrue(receipt.getAction().startsWith("RECEIPT"));
    assertEquals("3", receipt.getHeaders().get("receipt-id"));

    assertEquals(view.getInactiveDurableTopicSubscribers().length, 1);

    // unsubscribe from topic 2
    frame =
        "UNSUBSCRIBE\n"
            + "destination:/topic/"
            + getQueueName()
            + "2\n"
            + "id:durablesub-2\n"
            + "receipt:4\n"
            + "activemq.subscriptionName:test2\n\n"
            + Stomp.NULL;
    stompConnection.sendFrame(frame);
    receipt = stompConnection.receive();
    LOG.debug("Broker sent: " + frame);
    assertTrue(receipt.getAction().startsWith("RECEIPT"));
    assertEquals("4", receipt.getHeaders().get("receipt-id"));

    assertEquals(view.getInactiveDurableTopicSubscribers().length, 0);
  }
示例#19
0
  @Test(timeout = 60000)
  public void testMultipleDurableSubsWithOfflineMessages() throws Exception {
    stompConnection.setVersion(Stomp.V1_1);

    final BrokerViewMBean view = getProxyToBroker();

    String connectFrame =
        "STOMP\n"
            + "login:system\n"
            + "passcode:manager\n"
            + "accept-version:1.1\n"
            + "host:localhost\n"
            + "client-id:test\n"
            + "\n"
            + Stomp.NULL;
    stompConnection.sendFrame(connectFrame);

    String frame = stompConnection.receiveFrame();
    LOG.debug("Broker sent: " + frame);

    assertTrue(frame.startsWith("CONNECTED"));
    assertEquals(view.getDurableTopicSubscribers().length, 0);

    // subscribe to first destination durably
    frame =
        "SUBSCRIBE\n"
            + "destination:/topic/"
            + getQueueName()
            + "1"
            + "\n"
            + "ack:auto\n"
            + "receipt:1\n"
            + "id:durablesub-1\n"
            + "activemq.subscriptionName:test1\n\n"
            + Stomp.NULL;
    stompConnection.sendFrame(frame);

    StompFrame receipt = stompConnection.receive();
    LOG.debug("Broker sent: " + receipt);
    assertTrue(receipt.getAction().startsWith("RECEIPT"));
    assertEquals("1", receipt.getHeaders().get("receipt-id"));
    assertEquals(view.getDurableTopicSubscribers().length, 1);

    // subscribe to second destination durably
    frame =
        "SUBSCRIBE\n"
            + "destination:/topic/"
            + getQueueName()
            + "2"
            + "\n"
            + "ack:auto\n"
            + "receipt:2\n"
            + "id:durablesub-2\n"
            + "activemq.subscriptionName:test2\n\n"
            + Stomp.NULL;
    stompConnection.sendFrame(frame);

    receipt = stompConnection.receive();
    LOG.debug("Broker sent: " + receipt);
    assertTrue(receipt.getAction().startsWith("RECEIPT"));
    assertEquals("2", receipt.getHeaders().get("receipt-id"));
    assertEquals(view.getDurableTopicSubscribers().length, 2);

    frame = "DISCONNECT\nclient-id:test\n\n" + Stomp.NULL;
    stompConnection.sendFrame(frame);
    assertTrue(
        Wait.waitFor(
            new Wait.Condition() {

              @Override
              public boolean isSatisified() throws Exception {
                return view.getCurrentConnectionsCount() == 1;
              }
            },
            TimeUnit.SECONDS.toMillis(5),
            TimeUnit.MILLISECONDS.toMillis(25)));

    // reconnect and send some messages to the offline subscribers and then try to get
    // them after subscribing again.
    stompConnect();
    stompConnection.sendFrame(connectFrame);
    frame = stompConnection.receiveFrame();
    LOG.debug("Broker sent: " + frame);
    assertTrue(frame.contains("CONNECTED"));
    assertEquals(view.getDurableTopicSubscribers().length, 0);
    assertEquals(view.getInactiveDurableTopicSubscribers().length, 2);

    frame =
        "SEND\n"
            + "destination:/topic/"
            + getQueueName()
            + "1\n"
            + "receipt:10\n"
            + "\n"
            + "Hello World 1"
            + Stomp.NULL;
    stompConnection.sendFrame(frame);
    receipt = stompConnection.receive();
    assertEquals("10", receipt.getHeaders().get(Stomp.Headers.Response.RECEIPT_ID));

    frame =
        "SEND\n"
            + "destination:/topic/"
            + getQueueName()
            + "2\n"
            + "receipt:11\n"
            + "\n"
            + "Hello World 2"
            + Stomp.NULL;
    stompConnection.sendFrame(frame);
    receipt = stompConnection.receive();
    assertEquals("11", receipt.getHeaders().get(Stomp.Headers.Response.RECEIPT_ID));

    // subscribe to first destination durably
    frame =
        "SUBSCRIBE\n"
            + "destination:/topic/"
            + getQueueName()
            + "1"
            + "\n"
            + "ack:auto\n"
            + "receipt:3\n"
            + "id:durablesub-1\n"
            + "activemq.subscriptionName:test1\n\n"
            + Stomp.NULL;
    stompConnection.sendFrame(frame);

    receipt = stompConnection.receive();
    LOG.debug("Broker sent: " + receipt);
    assertTrue(receipt.getAction().startsWith("RECEIPT"));
    assertEquals("3", receipt.getHeaders().get("receipt-id"));
    assertEquals(view.getDurableTopicSubscribers().length, 1);

    StompFrame message = stompConnection.receive();
    assertEquals(Stomp.Responses.MESSAGE, message.getAction());
    assertEquals("durablesub-1", message.getHeaders().get(Stomp.Headers.Message.SUBSCRIPTION));

    assertEquals(view.getDurableTopicSubscribers().length, 1);
    assertEquals(view.getInactiveDurableTopicSubscribers().length, 1);

    // subscribe to second destination durably
    frame =
        "SUBSCRIBE\n"
            + "destination:/topic/"
            + getQueueName()
            + "2"
            + "\n"
            + "ack:auto\n"
            + "receipt:4\n"
            + "id:durablesub-2\n"
            + "activemq.subscriptionName:test2\n\n"
            + Stomp.NULL;
    stompConnection.sendFrame(frame);

    receipt = stompConnection.receive();
    LOG.debug("Broker sent: " + receipt);
    assertTrue(receipt.getAction().startsWith("RECEIPT"));
    assertEquals("4", receipt.getHeaders().get("receipt-id"));
    assertEquals(view.getDurableTopicSubscribers().length, 2);

    message = stompConnection.receive();
    assertEquals(Stomp.Responses.MESSAGE, message.getAction());
    assertEquals("durablesub-2", message.getHeaders().get(Stomp.Headers.Message.SUBSCRIPTION));

    assertEquals(view.getDurableTopicSubscribers().length, 2);
    assertEquals(view.getInactiveDurableTopicSubscribers().length, 0);
  }
  public void testSelectorAwareForwarding() throws Exception {
    clearSelectorCacheFiles();
    // borkerA is local and brokerB is remote
    bridgeAndConfigureBrokers("BrokerA", "BrokerB");
    startAllBrokers();
    waitForBridgeFormation();

    final BrokerService brokerB = brokers.get("BrokerB").broker;
    final BrokerService brokerA = brokers.get("BrokerA").broker;

    // Create the remote virtual topic consumer with selector
    MessageConsumer remoteConsumer =
        createConsumer(
            "BrokerB",
            createDestination("Consumer.B.VirtualTopic.tempTopic", false),
            "foo = 'bar'");

    // let advisories propogate
    Wait.waitFor(
        new Wait.Condition() {
          Destination dest =
              brokerA.getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"));

          @Override
          public boolean isSatisified() throws Exception {
            return dest.getConsumers().size() == 1;
          }
        },
        500);

    ActiveMQQueue queueB = new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic");
    Destination destination = getDestination(brokers.get("BrokerB").broker, queueB);
    assertEquals(1, destination.getConsumers().size());

    ActiveMQTopic virtualTopic = new ActiveMQTopic("VirtualTopic.tempTopic");
    assertNull(getDestination(brokers.get("BrokerA").broker, virtualTopic));
    assertNull(getDestination(brokers.get("BrokerB").broker, virtualTopic));

    // send two types of messages, one unwanted and the other wanted
    sendMessages("BrokerA", virtualTopic, 1, asMap("foo", "bar"));
    sendMessages("BrokerA", virtualTopic, 1, asMap("ceposta", "redhat"));

    MessageIdList msgsB = getConsumerMessages("BrokerB", remoteConsumer);
    // wait for the wanted one to arrive at the remote consumer
    msgsB.waitForMessagesToArrive(1);

    // ensure we don't get any more messages
    msgsB.waitForMessagesToArrive(1, 1000);

    // remote consumer should only get one of the messages
    assertEquals(1, msgsB.getMessageCount());

    // and the enqueue count for the remote queue should only be 1
    assertEquals(
        1,
        brokerB
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getEnqueues()
            .getCount());

    // now let's remove the consumer on broker B and recreate it with new selector
    remoteConsumer.close();

    // now let's shut down broker A and clear its persistent selector cache
    brokerA.stop();
    brokerA.waitUntilStopped();
    deleteSelectorCacheFile("BrokerA");

    assertEquals(0, destination.getConsumers().size());

    remoteConsumer =
        createConsumer(
            "BrokerB",
            createDestination("Consumer.B.VirtualTopic.tempTopic", false),
            "ceposta = 'redhat'");

    assertEquals(1, destination.getConsumers().size());

    // now let's start broker A back up
    brokerA.start(true);
    brokerA.waitUntilStarted();

    System.out.println(brokerA.getNetworkConnectors());

    // give a sec to let advisories propogate
    // let advisories propogate
    Wait.waitFor(
        new Wait.Condition() {
          Destination dest =
              brokerA.getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"));

          @Override
          public boolean isSatisified() throws Exception {
            return dest.getConsumers().size() == 1;
          }
        },
        500);

    // send two types of messages, one unwanted and the other wanted
    sendMessages("BrokerA", virtualTopic, 1, asMap("foo", "bar"));
    sendMessages("BrokerB", virtualTopic, 1, asMap("foo", "bar"));
    sendMessages("BrokerA", virtualTopic, 1, asMap("ceposta", "redhat"));
    sendMessages("BrokerB", virtualTopic, 1, asMap("ceposta", "redhat"));

    // lets get messages on consumer B
    msgsB = getConsumerMessages("BrokerB", remoteConsumer);
    msgsB.waitForMessagesToArrive(2);

    // ensure we don't get any more messages
    msgsB.waitForMessagesToArrive(1, 1000);

    // remote consumer should only get 10 of the messages
    assertEquals(2, msgsB.getMessageCount());

    // queue should be drained
    assertEquals(
        0,
        brokerB
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getMessages()
            .getCount());
    // and the enqueue count for the remote queue should only be 1
    assertEquals(
        3,
        brokerB
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getEnqueues()
            .getCount());
  }
  public void testMessageLeaks() throws Exception {
    clearSelectorCacheFiles();
    startAllBrokers();

    final BrokerService brokerA = brokers.get("BrokerA").broker;

    // Create the remote virtual topic consumer with selector
    ActiveMQDestination consumerQueue =
        createDestination("Consumer.B.VirtualTopic.tempTopic", false);
    // create it so that the queue is there and messages don't get lost
    MessageConsumer consumer1 = createConsumer("BrokerA", consumerQueue, "SYMBOL = 'AAPL'");
    MessageConsumer consumer2 = createConsumer("BrokerA", consumerQueue, "SYMBOL = 'AAPL'");

    ActiveMQTopic virtualTopic = new ActiveMQTopic("VirtualTopic.tempTopic");
    ProducerThreadTester producerTester = createProducerTester("BrokerA", virtualTopic);
    producerTester.setRunIndefinitely(true);
    producerTester.setSleep(5);
    producerTester.addMessageProperty("AAPL");
    producerTester.addMessageProperty("VIX");
    producerTester.start();

    int currentCount = producerTester.getSentCount();
    LOG.info(
        ">>>> currently sent: total="
            + currentCount
            + ", AAPL="
            + producerTester.getCountForProperty("AAPL")
            + ", VIX="
            + producerTester.getCountForProperty("VIX"));

    // let some messages get sent
    Thread.sleep(2000);

    MessageIdList consumer1Messages = getConsumerMessages("BrokerA", consumer1);
    consumer1Messages.waitForMessagesToArrive(50, 1000);

    // switch one of the consumers to SYMBOL = 'VIX'
    consumer1.close();
    consumer1 = createConsumer("BrokerA", consumerQueue, "SYMBOL = 'VIX'");

    // wait till new consumer is on board
    Wait.waitFor(
        new Wait.Condition() {
          @Override
          public boolean isSatisified() throws Exception {
            return brokerA
                    .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
                    .getConsumers()
                    .size()
                == 2;
          }
        });

    currentCount = producerTester.getSentCount();
    LOG.info(
        ">>>> currently sent: total="
            + currentCount
            + ", AAPL="
            + producerTester.getCountForProperty("AAPL")
            + ", VIX="
            + producerTester.getCountForProperty("VIX"));

    // let some messages get sent
    Thread.sleep(2000);

    // switch the other consumer to SYMBOL = 'VIX'
    consumer2.close();
    consumer2 = createConsumer("BrokerA", consumerQueue, "SYMBOL = 'VIX'");

    // wait till new consumer is on board
    Wait.waitFor(
        new Wait.Condition() {
          @Override
          public boolean isSatisified() throws Exception {
            return brokerA
                    .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
                    .getConsumers()
                    .size()
                == 2;
          }
        });

    currentCount = producerTester.getSentCount();
    LOG.info(
        ">>>> currently sent: total="
            + currentCount
            + ", AAPL="
            + producerTester.getCountForProperty("AAPL")
            + ", VIX="
            + producerTester.getCountForProperty("VIX"));

    // let some messages get sent
    Thread.sleep(2000);

    currentCount = producerTester.getSentCount();
    LOG.info(
        ">>>> currently sent: total="
            + currentCount
            + ", AAPL="
            + producerTester.getCountForProperty("AAPL")
            + ", VIX="
            + producerTester.getCountForProperty("VIX"));

    // make sure if there are messages that are orphaned in the queue that this number doesn't
    // grow...
    final long currentDepth =
        brokerA
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getMessages()
            .getCount();

    LOG.info(">>>>> Orphaned messages? " + currentDepth);

    // wait 5s to see if we can get a growth in the depth of the queue
    Wait.waitFor(
        new Wait.Condition() {
          @Override
          public boolean isSatisified() throws Exception {
            return brokerA
                    .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
                    .getDestinationStatistics()
                    .getMessages()
                    .getCount()
                > currentDepth;
          }
        },
        5000);

    // stop producers
    producerTester.setRunning(false);
    producerTester.join();

    // pause to let consumers catch up
    Thread.sleep(1000);

    assertTrue(
        brokerA
                .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
                .getDestinationStatistics()
                .getMessages()
                .getCount()
            <= currentDepth);
  }
  public void testSelectorsAndNonSelectors() throws Exception {
    clearSelectorCacheFiles();
    // borkerA is local and brokerB is remote
    bridgeAndConfigureBrokers("BrokerA", "BrokerB");
    startAllBrokers();
    waitForBridgeFormation();

    final BrokerService brokerA = brokers.get("BrokerA").broker;
    final BrokerService brokerB = brokers.get("BrokerB").broker;

    // Create the remote virtual topic consumer with selector
    ActiveMQDestination consumerBQueue =
        createDestination("Consumer.B.VirtualTopic.tempTopic", false);

    MessageConsumer selectingConsumer = createConsumer("BrokerB", consumerBQueue, "foo = 'bar'");
    MessageConsumer nonSelectingConsumer = createConsumer("BrokerB", consumerBQueue);

    // let advisories propogate
    Wait.waitFor(
        new Wait.Condition() {
          Destination dest =
              brokerA.getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"));

          @Override
          public boolean isSatisified() throws Exception {
            return dest.getConsumers().size() == 2;
          }
        },
        500);

    Destination destination = getDestination(brokerB, consumerBQueue);
    assertEquals(2, destination.getConsumers().size());

    // publisher publishes to this
    ActiveMQTopic virtualTopic = new ActiveMQTopic("VirtualTopic.tempTopic");
    sendMessages("BrokerA", virtualTopic, 10, asMap("foo", "bar"));
    sendMessages("BrokerA", virtualTopic, 10);

    MessageIdList selectingConsumerMessages = getConsumerMessages("BrokerB", selectingConsumer);

    MessageIdList nonSelectingConsumerMessages =
        getConsumerMessages("BrokerB", nonSelectingConsumer);

    // we only expect half of the messages that get sent with the selector, because they get load
    // balanced
    selectingConsumerMessages.waitForMessagesToArrive(5, 1000L);
    assertEquals(5, selectingConsumerMessages.getMessageCount());

    nonSelectingConsumerMessages.waitForMessagesToArrive(15, 1000L);
    assertEquals(15, nonSelectingConsumerMessages.getMessageCount());

    // assert broker A stats
    waitForMessagesToBeConsumed(brokerA, "Consumer.B.VirtualTopic.tempTopic", false, 20, 20, 5000);
    assertEquals(
        20,
        brokerA
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getEnqueues()
            .getCount());
    assertEquals(
        20,
        brokerA
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getDequeues()
            .getCount());
    assertEquals(
        0,
        brokerA
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getMessages()
            .getCount());

    // assert broker B stats
    waitForMessagesToBeConsumed(brokerB, "Consumer.B.VirtualTopic.tempTopic", false, 20, 20, 5000);
    assertEquals(
        20,
        brokerB
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getEnqueues()
            .getCount());
    assertEquals(
        20,
        brokerB
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getDequeues()
            .getCount());
    assertEquals(
        0,
        brokerB
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getMessages()
            .getCount());

    // now let's close the consumer without the selector
    nonSelectingConsumer.close();

    // let advisories propogate
    Wait.waitFor(
        new Wait.Condition() {
          Destination dest =
              brokerA.getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"));

          @Override
          public boolean isSatisified() throws Exception {
            return dest.getConsumers().size() == 1;
          }
        },
        500);

    // and let's send messages with a selector that doesnt' match
    selectingConsumerMessages.flushMessages();

    sendMessages("BrokerA", virtualTopic, 10, asMap("ceposta", "redhat"));

    selectingConsumerMessages = getConsumerMessages("BrokerB", selectingConsumer);
    selectingConsumerMessages.waitForMessagesToArrive(1, 1000L);
    assertEquals(0, selectingConsumerMessages.getMessageCount());

    // assert broker A stats
    waitForMessagesToBeConsumed(brokerA, "Consumer.B.VirtualTopic.tempTopic", false, 20, 20, 5000);
    assertEquals(
        20,
        brokerA
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getEnqueues()
            .getCount());
    assertEquals(
        20,
        brokerA
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getDequeues()
            .getCount());
    assertEquals(
        0,
        brokerA
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getMessages()
            .getCount());

    // assert broker B stats
    waitForMessagesToBeConsumed(brokerB, "Consumer.B.VirtualTopic.tempTopic", false, 20, 20, 5000);
    assertEquals(
        20,
        brokerB
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getEnqueues()
            .getCount());
    assertEquals(
        20,
        brokerB
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getDequeues()
            .getCount());
    assertEquals(
        0,
        brokerB
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getMessages()
            .getCount());

    // now lets disconect the selecting consumer for a sec and send messages with a selector that
    // DOES match
    selectingConsumer.close();

    // let advisories propogate
    Wait.waitFor(
        new Wait.Condition() {
          Destination dest =
              brokerA.getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"));

          @Override
          public boolean isSatisified() throws Exception {
            return dest.getConsumers().size() == 0;
          }
        },
        500);

    selectingConsumerMessages.flushMessages();

    sendMessages("BrokerA", virtualTopic, 10, asMap("foo", "bar"));

    // assert broker A stats
    waitForMessagesToBeConsumed(brokerA, "Consumer.B.VirtualTopic.tempTopic", false, 20, 20, 5000);
    assertEquals(
        30,
        brokerA
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getEnqueues()
            .getCount());
    assertEquals(
        20,
        brokerA
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getDequeues()
            .getCount());
    assertEquals(
        10,
        brokerA
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getMessages()
            .getCount());

    // assert broker B stats
    waitForMessagesToBeConsumed(brokerB, "Consumer.B.VirtualTopic.tempTopic", false, 20, 20, 5000);
    assertEquals(
        20,
        brokerB
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getEnqueues()
            .getCount());
    assertEquals(
        20,
        brokerB
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getDequeues()
            .getCount());
    assertEquals(
        0,
        brokerB
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getMessages()
            .getCount());

    selectingConsumer = createConsumer("BrokerB", consumerBQueue, "foo = 'bar'");
    selectingConsumerMessages = getConsumerMessages("BrokerB", selectingConsumer);
    selectingConsumerMessages.waitForMessagesToArrive(10);
    assertEquals(10, selectingConsumerMessages.getMessageCount());

    // let advisories propogate
    Wait.waitFor(
        new Wait.Condition() {
          Destination dest =
              brokerA.getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"));

          @Override
          public boolean isSatisified() throws Exception {
            return dest.getConsumers().size() == 1;
          }
        },
        500);

    // assert broker A stats
    waitForMessagesToBeConsumed(brokerA, "Consumer.B.VirtualTopic.tempTopic", false, 30, 30, 5000);
    assertEquals(
        30,
        brokerA
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getEnqueues()
            .getCount());
    assertEquals(
        30,
        brokerA
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getDequeues()
            .getCount());
    assertEquals(
        0,
        brokerA
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getMessages()
            .getCount());

    // assert broker B stats
    waitForMessagesToBeConsumed(brokerB, "Consumer.B.VirtualTopic.tempTopic", false, 30, 30, 5000);
    assertEquals(
        30,
        brokerB
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getEnqueues()
            .getCount());
    assertEquals(
        30,
        brokerB
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getDequeues()
            .getCount());
    assertEquals(
        0,
        brokerB
            .getDestination(new ActiveMQQueue("Consumer.B.VirtualTopic.tempTopic"))
            .getDestinationStatistics()
            .getMessages()
            .getCount());
  }