Esempio n. 1
0
  /*
   * Source and target on same server
   * --------------------------------
   * If the source and target destinations are on the same server (same resource manager) then,
   * in order to get ONCE_AND_ONLY_ONCE, we simply need to consuming and send in a single
   * local JMS transaction.
   *
   * We actually use a single local transacted session for the other QoS modes too since this
   * is more performant than using DUPS_OK_ACKNOWLEDGE or AUTO_ACKNOWLEDGE session ack modes, so effectively
   * the QoS is upgraded.
   *
   * Source and target on different server
   * -------------------------------------
   * If the source and target destinations are on a different servers (different resource managers) then:
   *
   * If desired QoS is ONCE_AND_ONLY_ONCE, then we start a JTA transaction and enlist the consuming and sending
   * XAResources in that.
   *
   * If desired QoS is DUPLICATES_OK then, we use CLIENT_ACKNOWLEDGE for the consuming session and
   * AUTO_ACKNOWLEDGE (this is ignored) for the sending session if the maxBatchSize == 1, otherwise we
   * use a local transacted session for the sending session where maxBatchSize > 1, since this is more performant
   * When bridging a batch, we make sure to manually acknowledge the consuming session, if it is CLIENT_ACKNOWLEDGE
   * *after* the batch has been sent
   *
   * If desired QoS is AT_MOST_ONCE then, if maxBatchSize == 1, we use AUTO_ACKNOWLEDGE for the consuming session,
   * and AUTO_ACKNOWLEDGE for the sending session.
   * If maxBatchSize > 1, we use CLIENT_ACKNOWLEDGE for the consuming session and a local transacted session for the
   * sending session.
   *
   * When bridging a batch, we make sure to manually acknowledge the consuming session, if it is CLIENT_ACKNOWLEDGE
   * *before* the batch has been sent
   *
   */
  private boolean setupJMSObjects() {
    try {
      if (sourceCff == targetCff) {
        // Source and target destinations are on the server - we can get once and only once
        // just using a local transacted session
        // everything becomes once and only once

        forwardMode = JMSBridgeImpl.FORWARD_MODE_LOCALTX;
      } else {
        // Different servers
        if (qualityOfServiceMode == QualityOfServiceMode.ONCE_AND_ONLY_ONCE) {
          // Use XA

          forwardMode = JMSBridgeImpl.FORWARD_MODE_XA;
        } else {
          forwardMode = JMSBridgeImpl.FORWARD_MODE_NONTX;
        }
      }

      // Lookup the destinations
      sourceDestination = sourceDestinationFactory.createDestination();

      targetDestination = targetDestinationFactory.createDestination();

      if (forwardMode == JMSBridgeImpl.FORWARD_MODE_LOCALTX) {
        // We simply use a single local transacted session for consuming and sending

        sourceConn = createConnection(sourceUsername, sourcePassword, sourceCff, clientID, false);
        sourceSession = sourceConn.createSession(true, Session.SESSION_TRANSACTED);
      } else {
        if (forwardMode == JMSBridgeImpl.FORWARD_MODE_XA) {
          // Create an XASession for consuming from the source
          if (JMSBridgeImpl.trace) {
            HornetQJMSServerLogger.LOGGER.trace("Creating XA source session");
          }

          sourceConn = createConnection(sourceUsername, sourcePassword, sourceCff, clientID, true);
          sourceSession = ((XAConnection) sourceConn).createXASession();
        } else {
          if (JMSBridgeImpl.trace) {
            HornetQJMSServerLogger.LOGGER.trace("Creating non XA source session");
          }

          // Create a standard session for consuming from the source

          // We use ack mode client ack

          sourceConn = createConnection(sourceUsername, sourcePassword, sourceCff, clientID, false);
          sourceSession = sourceConn.createSession(false, Session.CLIENT_ACKNOWLEDGE);
        }
      }

      if (subName == null) {
        if (selector == null) {
          sourceConsumer = sourceSession.createConsumer(sourceDestination);
        } else {
          sourceConsumer = sourceSession.createConsumer(sourceDestination, selector, false);
        }
      } else {
        // Durable subscription
        if (selector == null) {
          sourceConsumer =
              sourceSession.createDurableSubscriber((Topic) sourceDestination, subName);
        } else {
          sourceConsumer =
              sourceSession.createDurableSubscriber(
                  (Topic) sourceDestination, subName, selector, false);
        }
      }

      // Now the sending session

      if (forwardMode == JMSBridgeImpl.FORWARD_MODE_LOCALTX) {
        targetConn = sourceConn;
        targetSession = sourceSession;
      } else {
        if (forwardMode == JMSBridgeImpl.FORWARD_MODE_XA) {
          if (JMSBridgeImpl.trace) {
            HornetQJMSServerLogger.LOGGER.trace("Creating XA dest session");
          }

          // Create an XA sesion for sending to the destination

          targetConn = createConnection(targetUsername, targetPassword, targetCff, null, true);

          targetSession = ((XAConnection) targetConn).createXASession();
        } else {
          if (JMSBridgeImpl.trace) {
            HornetQJMSServerLogger.LOGGER.trace("Creating non XA dest session");
          }

          // Create a standard session for sending to the target

          // If batch size > 1 we use a transacted session since is more efficient

          boolean transacted = maxBatchSize > 1;

          targetConn = createConnection(targetUsername, targetPassword, targetCff, null, false);

          targetSession =
              targetConn.createSession(
                  transacted, transacted ? Session.SESSION_TRANSACTED : Session.AUTO_ACKNOWLEDGE);
        }
      }

      if (forwardMode == JMSBridgeImpl.FORWARD_MODE_XA) {
        if (JMSBridgeImpl.trace) {
          HornetQJMSServerLogger.LOGGER.trace("Starting JTA transaction");
        }

        tx = startTx();

        enlistResources(tx);
      }

      targetProducer = targetSession.createProducer(null);

      return true;
    } catch (Exception e) {
      // We shouldn't log this, as it's expected when trying to connect when target/source is not
      // available

      // If this fails we should attempt to cleanup or we might end up in some weird state

      // Adding a log.warn, so the use may see the cause of the failure and take actions
      HornetQJMSServerLogger.LOGGER.bridgeConnectError(e);

      cleanup();

      return false;
    }
  }
Esempio n. 2
0
  @Test
  public void testSendMessagesWithMaxBatchSize() throws Exception {
    final int numMessages = 10;

    ConnectionFactoryFactory sourceCFF =
        JMSBridgeImplTest.newConnectionFactoryFactory(JMSBridgeImplTest.createConnectionFactory());
    ConnectionFactoryFactory targetCFF =
        JMSBridgeImplTest.newConnectionFactoryFactory(JMSBridgeImplTest.createConnectionFactory());
    DestinationFactory sourceDF =
        JMSBridgeImplTest.newDestinationFactory(
            HornetQJMSClient.createQueue(JMSBridgeImplTest.SOURCE));
    DestinationFactory targetDF =
        JMSBridgeImplTest.newDestinationFactory(
            HornetQJMSClient.createQueue(JMSBridgeImplTest.TARGET));
    TransactionManager tm = JMSBridgeImplTest.newTransactionManager();

    JMSBridgeImpl bridge = new JMSBridgeImpl();
    Assert.assertNotNull(bridge);

    bridge.setSourceConnectionFactoryFactory(sourceCFF);
    bridge.setSourceDestinationFactory(sourceDF);
    bridge.setTargetConnectionFactoryFactory(targetCFF);
    bridge.setTargetDestinationFactory(targetDF);
    bridge.setFailureRetryInterval(10);
    bridge.setMaxRetries(-1);
    bridge.setMaxBatchSize(numMessages);
    bridge.setMaxBatchTime(-1);
    bridge.setTransactionManager(tm);
    bridge.setQualityOfServiceMode(QualityOfServiceMode.AT_MOST_ONCE);

    Assert.assertFalse(bridge.isStarted());
    bridge.start();
    Assert.assertTrue(bridge.isStarted());

    Connection targetConn = JMSBridgeImplTest.createConnectionFactory().createConnection();
    Session targetSess = targetConn.createSession(false, Session.AUTO_ACKNOWLEDGE);
    MessageConsumer consumer = targetSess.createConsumer(targetDF.createDestination());
    final List<Message> messages = new LinkedList<Message>();
    final CountDownLatch latch = new CountDownLatch(numMessages);
    MessageListener listener =
        new MessageListener() {
          public void onMessage(final Message message) {
            messages.add(message);
            latch.countDown();
          }
        };
    consumer.setMessageListener(listener);
    targetConn.start();

    Connection sourceConn = JMSBridgeImplTest.createConnectionFactory().createConnection();
    Session sourceSess = sourceConn.createSession(false, Session.AUTO_ACKNOWLEDGE);

    MessageProducer producer = sourceSess.createProducer(sourceDF.createDestination());

    for (int i = 0; i < numMessages - 1; i++) {
      TextMessage msg = sourceSess.createTextMessage();
      producer.send(msg);
      JMSBridgeImplTest.log.info("sent message " + i);
    }

    Thread.sleep(1000);

    Assert.assertEquals(0, messages.size());

    TextMessage msg = sourceSess.createTextMessage();

    producer.send(msg);

    Assert.assertTrue(latch.await(10000, TimeUnit.MILLISECONDS));

    sourceConn.close();

    Assert.assertEquals(numMessages, messages.size());

    bridge.stop();
    Assert.assertFalse(bridge.isStarted());

    targetConn.close();
  }
Esempio n. 3
0
  protected void setUpAdministeredObjects() throws Exception {
    cff0LowProducerWindow =
        new ConnectionFactoryFactory() {
          public ConnectionFactory createConnectionFactory() throws Exception {
            HornetQConnectionFactory cf =
                HornetQJMSClient.createConnectionFactoryWithoutHA(
                    JMSFactoryType.CF, new TransportConfiguration(INVM_CONNECTOR_FACTORY));

            // Note! We disable automatic reconnection on the session factory. The bridge needs to
            // do the reconnection
            cf.setReconnectAttempts(0);
            cf.setBlockOnNonDurableSend(true);
            cf.setBlockOnDurableSend(true);
            cf.setCacheLargeMessagesClient(true);
            cf.setProducerWindowSize(100);

            return cf;
          }
        };

    cff0 =
        new ConnectionFactoryFactory() {
          public ConnectionFactory createConnectionFactory() throws Exception {
            HornetQConnectionFactory cf =
                HornetQJMSClient.createConnectionFactoryWithoutHA(
                    JMSFactoryType.CF, new TransportConfiguration(INVM_CONNECTOR_FACTORY));

            // Note! We disable automatic reconnection on the session factory. The bridge needs to
            // do the reconnection
            cf.setReconnectAttempts(0);
            cf.setBlockOnNonDurableSend(true);
            cf.setBlockOnDurableSend(true);
            cf.setCacheLargeMessagesClient(true);

            return cf;
          }
        };

    cff0xa =
        new ConnectionFactoryFactory() {
          public Object createConnectionFactory() throws Exception {
            HornetQXAConnectionFactory cf =
                (HornetQXAConnectionFactory)
                    HornetQJMSClient.createConnectionFactoryWithoutHA(
                        JMSFactoryType.XA_CF, new TransportConfiguration(INVM_CONNECTOR_FACTORY));

            // Note! We disable automatic reconnection on the session factory. The bridge needs to
            // do the reconnection
            cf.setReconnectAttempts(0);
            cf.setBlockOnNonDurableSend(true);
            cf.setBlockOnDurableSend(true);
            cf.setCacheLargeMessagesClient(true);

            return cf;
          }
        };

    cf0 = (ConnectionFactory) cff0.createConnectionFactory();
    cf0xa = (XAConnectionFactory) cff0xa.createConnectionFactory();

    cff1 =
        new ConnectionFactoryFactory() {

          public ConnectionFactory createConnectionFactory() throws Exception {
            HornetQJMSConnectionFactory cf =
                (HornetQJMSConnectionFactory)
                    HornetQJMSClient.createConnectionFactoryWithoutHA(
                        JMSFactoryType.CF,
                        new TransportConfiguration(INVM_CONNECTOR_FACTORY, params1));

            // Note! We disable automatic reconnection on the session factory. The bridge needs to
            // do the reconnection
            cf.setReconnectAttempts(0);
            cf.setBlockOnNonDurableSend(true);
            cf.setBlockOnDurableSend(true);
            cf.setCacheLargeMessagesClient(true);

            return cf;
          }
        };

    cff1xa =
        new ConnectionFactoryFactory() {

          public XAConnectionFactory createConnectionFactory() throws Exception {
            HornetQXAConnectionFactory cf =
                (HornetQXAConnectionFactory)
                    HornetQJMSClient.createConnectionFactoryWithoutHA(
                        JMSFactoryType.XA_CF,
                        new TransportConfiguration(INVM_CONNECTOR_FACTORY, params1));

            // Note! We disable automatic reconnection on the session factory. The bridge needs to
            // do the reconnection
            cf.setReconnectAttempts(0);
            cf.setBlockOnNonDurableSend(true);
            cf.setBlockOnDurableSend(true);
            cf.setCacheLargeMessagesClient(true);

            return cf;
          }
        };

    cf1 = (ConnectionFactory) cff1.createConnectionFactory();
    cf1xa = (XAConnectionFactory) cff1xa.createConnectionFactory();

    sourceQueueFactory =
        new DestinationFactory() {
          public Destination createDestination() throws Exception {
            return (Destination) context0.lookup("/queue/sourceQueue");
          }
        };

    sourceQueue = (Queue) sourceQueueFactory.createDestination();

    targetQueueFactory =
        new DestinationFactory() {
          public Destination createDestination() throws Exception {
            return (Destination) context1.lookup("/queue/targetQueue");
          }
        };

    targetQueue = (Queue) targetQueueFactory.createDestination();

    sourceTopicFactory =
        new DestinationFactory() {
          public Destination createDestination() throws Exception {
            return (Destination) context0.lookup("/topic/sourceTopic");
          }
        };

    sourceTopic = (Topic) sourceTopicFactory.createDestination();

    localTargetQueueFactory =
        new DestinationFactory() {
          public Destination createDestination() throws Exception {
            return (Destination) context0.lookup("/queue/localTargetQueue");
          }
        };

    localTargetQueue = (Queue) localTargetQueueFactory.createDestination();
  }
Esempio n. 4
0
  /*
   * we receive only 1 message. The message is sent when the maxBatchTime
   * expires even if the maxBatchSize is not reached
   */
  @Test
  public void testSendMessagesWhenMaxBatchTimeExpires() throws Exception {
    int maxBatchSize = 2;
    long maxBatchTime = 500;

    ConnectionFactoryFactory sourceCFF =
        JMSBridgeImplTest.newConnectionFactoryFactory(JMSBridgeImplTest.createConnectionFactory());
    ConnectionFactoryFactory targetCFF =
        JMSBridgeImplTest.newConnectionFactoryFactory(JMSBridgeImplTest.createConnectionFactory());
    DestinationFactory sourceDF =
        JMSBridgeImplTest.newDestinationFactory(
            HornetQJMSClient.createQueue(JMSBridgeImplTest.SOURCE));
    DestinationFactory targetDF =
        JMSBridgeImplTest.newDestinationFactory(
            HornetQJMSClient.createQueue(JMSBridgeImplTest.TARGET));
    TransactionManager tm = JMSBridgeImplTest.newTransactionManager();

    JMSBridgeImpl bridge = new JMSBridgeImpl();
    Assert.assertNotNull(bridge);

    bridge.setSourceConnectionFactoryFactory(sourceCFF);
    bridge.setSourceDestinationFactory(sourceDF);
    bridge.setTargetConnectionFactoryFactory(targetCFF);
    bridge.setTargetDestinationFactory(targetDF);
    bridge.setFailureRetryInterval(10);
    bridge.setMaxRetries(-1);
    bridge.setMaxBatchSize(maxBatchSize);
    bridge.setMaxBatchTime(maxBatchTime);
    bridge.setTransactionManager(tm);
    bridge.setQualityOfServiceMode(QualityOfServiceMode.AT_MOST_ONCE);

    Assert.assertFalse(bridge.isStarted());
    bridge.start();
    Assert.assertTrue(bridge.isStarted());

    Connection targetConn = JMSBridgeImplTest.createConnectionFactory().createConnection();
    Session targetSess = targetConn.createSession(false, Session.AUTO_ACKNOWLEDGE);
    MessageConsumer consumer = targetSess.createConsumer(targetDF.createDestination());
    final List<Message> messages = new LinkedList<Message>();
    MessageListener listener =
        new MessageListener() {

          public void onMessage(final Message message) {
            messages.add(message);
          }
        };
    consumer.setMessageListener(listener);
    targetConn.start();

    Connection sourceConn = JMSBridgeImplTest.createConnectionFactory().createConnection();
    Session sourceSess = sourceConn.createSession(false, Session.AUTO_ACKNOWLEDGE);
    MessageProducer producer = sourceSess.createProducer(sourceDF.createDestination());
    producer.send(sourceSess.createTextMessage());
    sourceConn.close();

    Assert.assertEquals(0, messages.size());
    Thread.sleep(3 * maxBatchTime);

    Assert.assertEquals(1, messages.size());

    bridge.stop();
    Assert.assertFalse(bridge.isStarted());

    targetConn.close();
  }