[jboss-cvs] JBoss Messaging SVN: r6299 - in trunk: src/main/org/jboss/messaging/core/server/cluster and 6 other directories.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Fri Apr 3 10:12:53 EDT 2009
Author: timfox
Date: 2009-04-03 10:12:53 -0400 (Fri, 03 Apr 2009)
New Revision: 6299
Added:
trunk/src/main/org/jboss/messaging/jms/bridge/JMSBridge.java
trunk/src/main/org/jboss/messaging/jms/bridge/impl/JMSBridgeImpl.java
trunk/tests/src/org/jboss/messaging/tests/integration/jms/bridge/JMSBridgeReconnectionTest.java
trunk/tests/src/org/jboss/messaging/tests/integration/jms/bridge/JMSBridgeTest.java
trunk/tests/src/org/jboss/messaging/tests/timing/jms/bridge/impl/JMSBridgeImplTest.java
Removed:
trunk/src/main/org/jboss/messaging/jms/bridge/Bridge.java
trunk/src/main/org/jboss/messaging/jms/bridge/impl/BridgeImpl.java
trunk/tests/src/org/jboss/messaging/tests/integration/jms/bridge/BridgeReconnectionTest.java
trunk/tests/src/org/jboss/messaging/tests/integration/jms/bridge/BridgeTest.java
trunk/tests/src/org/jboss/messaging/tests/timing/jms/bridge/impl/BridgeImplTest.java
Modified:
trunk/src/main/org/jboss/messaging/core/management/ObjectNames.java
trunk/src/main/org/jboss/messaging/core/server/cluster/Bridge.java
trunk/src/main/org/jboss/messaging/core/server/cluster/impl/BridgeImpl.java
trunk/src/main/org/jboss/messaging/jms/bridge/BridgeService.java
trunk/tests/src/org/jboss/messaging/tests/integration/cluster/bridge/BridgeStartTest.java
trunk/tests/src/org/jboss/messaging/tests/integration/cluster/bridge/BridgeTest.java
Log:
renamed JMS bridge to JMSBridge
Modified: trunk/src/main/org/jboss/messaging/core/management/ObjectNames.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/management/ObjectNames.java 2009-04-03 14:08:30 UTC (rev 6298)
+++ trunk/src/main/org/jboss/messaging/core/management/ObjectNames.java 2009-04-03 14:12:53 UTC (rev 6299)
@@ -93,7 +93,7 @@
public static ObjectName getBridgeObjectName(final String name) throws Exception
{
- return createObjectName(CORE_MODULE, "Bridge", name);
+ return createObjectName(CORE_MODULE, "JMSBridge", name);
}
public static ObjectName getClusterConnectionObjectName(String name) throws Exception
Modified: trunk/src/main/org/jboss/messaging/core/server/cluster/Bridge.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/server/cluster/Bridge.java 2009-04-03 14:08:30 UTC (rev 6298)
+++ trunk/src/main/org/jboss/messaging/core/server/cluster/Bridge.java 2009-04-03 14:12:53 UTC (rev 6299)
@@ -30,7 +30,7 @@
/**
- * A Bridge
+ * A JMSBridge
*
* @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
*
Modified: trunk/src/main/org/jboss/messaging/core/server/cluster/impl/BridgeImpl.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/server/cluster/impl/BridgeImpl.java 2009-04-03 14:08:30 UTC (rev 6298)
+++ trunk/src/main/org/jboss/messaging/core/server/cluster/impl/BridgeImpl.java 2009-04-03 14:12:53 UTC (rev 6299)
@@ -86,7 +86,7 @@
import org.jboss.messaging.utils.UUID;
/**
- * A BridgeImpl
+ * A JMSBridgeImpl
*
* @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
*
@@ -709,7 +709,7 @@
}
catch (Exception e)
{
- log.warn("Unable to connect. Bridge is now disabled.", e);
+ log.warn("Unable to connect. JMSBridge is now disabled.", e);
return false;
}
Deleted: trunk/src/main/org/jboss/messaging/jms/bridge/Bridge.java
===================================================================
--- trunk/src/main/org/jboss/messaging/jms/bridge/Bridge.java 2009-04-03 14:08:30 UTC (rev 6298)
+++ trunk/src/main/org/jboss/messaging/jms/bridge/Bridge.java 2009-04-03 14:12:53 UTC (rev 6299)
@@ -1,111 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2008, Red Hat Middleware LLC, and individual contributors
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-
-package org.jboss.messaging.jms.bridge;
-
-import javax.transaction.TransactionManager;
-
-import org.jboss.messaging.core.server.MessagingComponent;
-
-/**
- * @author <a href="mailto:jmesnil at redhat.com">Jeff Mesnil</a>
- *
- * @version <tt>$Revision$</tt>
- *
- */
-public interface Bridge extends MessagingComponent
-{
- void pause() throws Exception;
-
- void resume() throws Exception;
-
- DestinationFactory getSourceDestinationFactory();
-
- void setSourceDestinationFactory(DestinationFactory dest);
-
- DestinationFactory getTargetDestinationFactory();
-
- void setTargetDestinationFactory(DestinationFactory dest);
-
- String getSourceUsername();
-
- void setSourceUsername(String name);
-
- String getSourcePassword();
-
- void setSourcePassword(String pwd);
-
- String getTargetUsername();
-
- void setTargetUsername(String name);
-
- String getTargetPassword();
-
- void setTargetPassword(String pwd);
-
- String getSelector();
-
- void setSelector(String selector);
-
- long getFailureRetryInterval();
-
- void setFailureRetryInterval(long interval);
-
- int getMaxRetries();
-
- void setMaxRetries(int retries);
-
- QualityOfServiceMode getQualityOfServiceMode();
-
- void setQualityOfServiceMode(QualityOfServiceMode mode);
-
- int getMaxBatchSize();
-
- void setMaxBatchSize(int size);
-
- long getMaxBatchTime();
-
- void setMaxBatchTime(long time);
-
- String getSubscriptionName();
-
- void setSubscriptionName(String subname);
-
- String getClientID();
-
- void setClientID(String clientID);
-
- boolean isAddMessageIDInHeader();
-
- void setAddMessageIDInHeader(boolean value);
-
- boolean isPaused();
-
- boolean isFailed();
-
- void setSourceConnectionFactoryFactory(ConnectionFactoryFactory cff);
-
- void setTargetConnectionFactoryFactory(ConnectionFactoryFactory cff);
-
- void setTransactionManager(TransactionManager tm);
-
-}
\ No newline at end of file
Modified: trunk/src/main/org/jboss/messaging/jms/bridge/BridgeService.java
===================================================================
--- trunk/src/main/org/jboss/messaging/jms/bridge/BridgeService.java 2009-04-03 14:08:30 UTC (rev 6298)
+++ trunk/src/main/org/jboss/messaging/jms/bridge/BridgeService.java 2009-04-03 14:12:53 UTC (rev 6299)
@@ -26,7 +26,7 @@
import org.jboss.messaging.core.logging.Logger;
import org.jboss.messaging.core.server.MessagingComponent;
-import org.jboss.messaging.jms.bridge.impl.BridgeImpl;
+import org.jboss.messaging.jms.bridge.impl.JMSBridgeImpl;
/**
* A BridgeService
@@ -40,7 +40,7 @@
public class BridgeService implements BridgeMBean
{
private static final Logger log = Logger.getLogger(BridgeService.class);
- private Bridge bridge;
+ private JMSBridge bridge;
private String sourceDestinationLookup;
@@ -53,7 +53,7 @@
public BridgeService()
{
- bridge = new BridgeImpl();
+ bridge = new JMSBridgeImpl();
}
// JMX attributes ----------------------------------------------------------------
Copied: trunk/src/main/org/jboss/messaging/jms/bridge/JMSBridge.java (from rev 6295, trunk/src/main/org/jboss/messaging/jms/bridge/Bridge.java)
===================================================================
--- trunk/src/main/org/jboss/messaging/jms/bridge/JMSBridge.java (rev 0)
+++ trunk/src/main/org/jboss/messaging/jms/bridge/JMSBridge.java 2009-04-03 14:12:53 UTC (rev 6299)
@@ -0,0 +1,113 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.messaging.jms.bridge;
+
+import javax.transaction.TransactionManager;
+
+import org.jboss.messaging.core.server.MessagingComponent;
+
+/**
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @author <a href="mailto:jmesnil at redhat.com">Jeff Mesnil</a>
+ *
+ * @version <tt>$Revision$</tt>
+ *
+ */
+public interface JMSBridge extends MessagingComponent
+{
+ void pause() throws Exception;
+
+ void resume() throws Exception;
+
+ DestinationFactory getSourceDestinationFactory();
+
+ void setSourceDestinationFactory(DestinationFactory dest);
+
+ DestinationFactory getTargetDestinationFactory();
+
+ void setTargetDestinationFactory(DestinationFactory dest);
+
+ String getSourceUsername();
+
+ void setSourceUsername(String name);
+
+ String getSourcePassword();
+
+ void setSourcePassword(String pwd);
+
+ String getTargetUsername();
+
+ void setTargetUsername(String name);
+
+ String getTargetPassword();
+
+ void setTargetPassword(String pwd);
+
+ String getSelector();
+
+ void setSelector(String selector);
+
+ long getFailureRetryInterval();
+
+ void setFailureRetryInterval(long interval);
+
+ int getMaxRetries();
+
+ void setMaxRetries(int retries);
+
+ QualityOfServiceMode getQualityOfServiceMode();
+
+ void setQualityOfServiceMode(QualityOfServiceMode mode);
+
+ int getMaxBatchSize();
+
+ void setMaxBatchSize(int size);
+
+ long getMaxBatchTime();
+
+ void setMaxBatchTime(long time);
+
+ String getSubscriptionName();
+
+ void setSubscriptionName(String subname);
+
+ String getClientID();
+
+ void setClientID(String clientID);
+
+ boolean isAddMessageIDInHeader();
+
+ void setAddMessageIDInHeader(boolean value);
+
+ boolean isPaused();
+
+ boolean isFailed();
+
+ void setSourceConnectionFactoryFactory(ConnectionFactoryFactory cff);
+
+ void setTargetConnectionFactoryFactory(ConnectionFactoryFactory cff);
+
+ void setTransactionManager(TransactionManager tm);
+
+}
\ No newline at end of file
Deleted: trunk/src/main/org/jboss/messaging/jms/bridge/impl/BridgeImpl.java
===================================================================
--- trunk/src/main/org/jboss/messaging/jms/bridge/impl/BridgeImpl.java 2009-04-03 14:08:30 UTC (rev 6298)
+++ trunk/src/main/org/jboss/messaging/jms/bridge/impl/BridgeImpl.java 2009-04-03 14:12:53 UTC (rev 6299)
@@ -1,1602 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-
-package org.jboss.messaging.jms.bridge.impl;
-
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.Map;
-
-import javax.jms.Connection;
-import javax.jms.ConnectionFactory;
-import javax.jms.Destination;
-import javax.jms.ExceptionListener;
-import javax.jms.JMSException;
-import javax.jms.Message;
-import javax.jms.MessageConsumer;
-import javax.jms.MessageListener;
-import javax.jms.MessageProducer;
-import javax.jms.Session;
-import javax.jms.Topic;
-import javax.jms.XAConnection;
-import javax.jms.XAConnectionFactory;
-import javax.jms.XASession;
-import javax.transaction.Transaction;
-import javax.transaction.TransactionManager;
-import javax.transaction.xa.XAResource;
-
-import org.jboss.messaging.core.client.ClientSession;
-import org.jboss.messaging.core.logging.Logger;
-import org.jboss.messaging.core.server.MessagingComponent;
-import org.jboss.messaging.jms.bridge.Bridge;
-import org.jboss.messaging.jms.bridge.ConnectionFactoryFactory;
-import org.jboss.messaging.jms.bridge.DestinationFactory;
-import org.jboss.messaging.jms.bridge.QualityOfServiceMode;
-import org.jboss.messaging.jms.client.JBossMessage;
-import org.jboss.messaging.jms.client.JBossSession;
-import org.jboss.tm.TransactionManagerLocator;
-
-/**
- *
- * A Bridge
- *
- * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
- * @version <tt>$Revision:4566 $</tt>
- *
- * $Id:Bridge.java 4566 2008-06-24 08:01:35Z jmesnil $
- *
- */
-public class BridgeImpl implements MessagingComponent, Bridge
-{
- private static final Logger log;
-
- private static boolean trace;
-
- static
- {
- log = Logger.getLogger(BridgeImpl.class);
-
- trace = log.isTraceEnabled();
- }
-
- private static final int TEN_YEARS = 60 * 60 * 24 * 365 * 10; // in ms
-
- private final Object lock = new Object();
-
- private String sourceUsername;
-
- private String sourcePassword;
-
- private String targetUsername;
-
- private String targetPassword;
-
- private TransactionManager tm;
-
- private String selector;
-
- private long failureRetryInterval;
-
- private int maxRetries;
-
- private QualityOfServiceMode qualityOfServiceMode;
-
- private int maxBatchSize;
-
- private long maxBatchTime;
-
- private String subName;
-
- private String clientID;
-
- private volatile boolean addMessageIDInHeader;
-
- private boolean started;
-
- private LinkedList<Message> messages;
-
- private ConnectionFactoryFactory sourceCff;
-
- private ConnectionFactoryFactory targetCff;
-
- private DestinationFactory sourceDestinationFactory;
-
- private DestinationFactory targetDestinationFactory;
-
- private Connection sourceConn;
-
- private Connection targetConn;
-
- private Destination sourceDestination;
-
- private Destination targetDestination;
-
- private Session sourceSession;
-
- private Session targetSession;
-
- private MessageConsumer sourceConsumer;
-
- private MessageProducer targetProducer;
-
- private BatchTimeChecker timeChecker;
-
- private Thread checkerThread;
-
- private long batchExpiryTime;
-
- private boolean paused;
-
- private Transaction tx;
-
- private boolean failed;
-
- private int forwardMode;
-
- private static final int FORWARD_MODE_XA = 0;
-
- private static final int FORWARD_MODE_LOCALTX = 1;
-
- private static final int FORWARD_MODE_NONTX = 2;
-
- /*
- * Constructor for MBean
- */
- public BridgeImpl()
- {
- this.messages = new LinkedList<Message>();
- }
-
- public BridgeImpl(ConnectionFactoryFactory sourceCff, ConnectionFactoryFactory targetCff,
- DestinationFactory sourceDestinationFactory, DestinationFactory targetDestinationFactory,
- String sourceUsername, String sourcePassword,
- String targetUsername, String targetPassword,
- String selector, long failureRetryInterval,
- int maxRetries,
- QualityOfServiceMode qosMode,
- int maxBatchSize, long maxBatchTime,
- String subName, String clientID,
- boolean addMessageIDInHeader)
- {
- this();
-
- this.sourceCff = sourceCff;
-
- this.targetCff = targetCff;
-
- this.sourceDestinationFactory = sourceDestinationFactory;
-
- this.targetDestinationFactory = targetDestinationFactory;
-
- this.sourceUsername = sourceUsername;
-
- this.sourcePassword = sourcePassword;
-
- this.targetUsername = targetUsername;
-
- this.targetPassword = targetPassword;
-
- this.selector = selector;
-
- this.failureRetryInterval = failureRetryInterval;
-
- this.maxRetries = maxRetries;
-
- this.qualityOfServiceMode = qosMode;
-
- this.maxBatchSize = maxBatchSize;
-
- this.maxBatchTime = maxBatchTime;
-
- this.subName = subName;
-
- this.clientID = clientID;
-
- this.addMessageIDInHeader = addMessageIDInHeader;
-
- checkParams();
-
- if (trace)
- {
- log.trace("Created " + this);
- }
- }
-
- // MessagingComponent overrides --------------------------------------------------
-
- public synchronized void start() throws Exception
- {
- if (started)
- {
- log.warn("Attempt to start, but is already started");
- return;
- }
-
- if (trace) { log.trace("Starting " + this); }
-
- checkParams();
-
- TransactionManager tm = getTm();
-
- //There may already be a JTA transaction associated to the thread
-
- boolean ok;
-
- Transaction toResume = null;
- try
- {
- toResume = tm.suspend();
-
- ok = setupJMSObjects();
- }
- finally
- {
- if (toResume != null)
- {
- tm.resume(toResume);
- }
- }
-
- if (ok)
- {
- //start the source connection
-
- sourceConn.start();
-
- started = true;
-
- if (maxBatchTime != -1)
- {
- if (trace) { log.trace("Starting time checker thread"); }
-
- timeChecker = new BatchTimeChecker();
-
- checkerThread = new Thread(timeChecker);
-
- batchExpiryTime = System.currentTimeMillis() + maxBatchTime;
-
- checkerThread.start();
-
- if (trace) { log.trace("Started time checker thread"); }
- }
-
- if (trace) { log.trace("Started " + this); }
- }
- else
- {
- log.warn("Failed to start bridge");
- handleFailureOnStartup();
- }
- }
-
- public synchronized void stop() throws Exception
- {
- if (!started)
- {
- log.warn("Attempt to stop, but is already stopped");
- return;
- }
-
- if (trace) { log.trace("Stopping " + this); }
-
- synchronized (lock)
- {
- started = false;
-
- //This must be inside sync block
- if (checkerThread != null)
- {
- checkerThread.interrupt();
- }
- }
-
- //This must be outside sync block
- if (checkerThread != null)
- {
- if (trace) { log.trace("Waiting for checker thread to finish");}
-
- checkerThread.join();
-
- if (trace) { log.trace("Checker thread has finished"); }
- }
-
- if (tx != null)
- {
- //Terminate any transaction
- if (trace) { log.trace("Rolling back remaining tx"); }
-
- try
- {
- tx.rollback();
- }
- catch (Exception ignore)
- {
- if (trace) { log.trace("Failed to rollback", ignore); }
- }
-
- if (trace) { log.trace("Rolled back remaining tx"); }
- }
-
- try
- {
- sourceConn.close();
- }
- catch (Exception ignore)
- {
- if (trace) { log.trace("Failed to close source conn", ignore); }
- }
-
- if (targetConn != null)
- {
- try
- {
- targetConn.close();
- }
- catch (Exception ignore)
- {
- if (trace) { log.trace("Failed to close target conn", ignore); }
- }
- }
-
- if (trace) { log.trace("Stopped " + this); }
- }
-
- public synchronized boolean isStarted()
- {
- return started;
- }
-
- // Bridge implementation ------------------------------------------------------------
-
- public synchronized void pause() throws Exception
- {
- if (trace) { log.trace("Pausing " + this); }
-
- synchronized (lock)
- {
- paused = true;
-
- sourceConn.stop();
- }
-
- if (trace) { log.trace("Paused " + this); }
- }
-
- public synchronized void resume() throws Exception
- {
- if (trace) { log.trace("Resuming " + this); }
-
- synchronized (lock)
- {
- paused = false;
-
- sourceConn.start();
- }
-
- if (trace) { log.trace("Resumed " + this); }
- }
-
- public DestinationFactory getSourceDestinationFactory()
- {
- return sourceDestinationFactory;
- }
-
- public void setSourceDestinationFactory(DestinationFactory dest)
- {
- checkBridgeNotStarted();
- checkNotNull(dest, "TargetDestinationFactory");
-
- sourceDestinationFactory = dest;
- }
-
- public DestinationFactory getTargetDestinationFactory()
- {
- return targetDestinationFactory;
- }
-
- public void setTargetDestinationFactory(DestinationFactory dest)
- {
- checkBridgeNotStarted();
- checkNotNull(dest, "TargetDestinationFactory");
-
- targetDestinationFactory = dest;
- }
-
- public String getSourceUsername()
- {
- return sourceUsername;
- }
-
- public synchronized void setSourceUsername(String name)
- {
- checkBridgeNotStarted();
-
- sourceUsername = name;
- }
-
- public synchronized String getSourcePassword()
- {
- return sourcePassword;
- }
-
- public synchronized void setSourcePassword(String pwd)
- {
- checkBridgeNotStarted();
-
- sourcePassword = pwd;
- }
-
- public synchronized String getTargetUsername()
- {
- return targetUsername;
- }
-
- public synchronized void setTargetUsername(String name)
- {
- checkBridgeNotStarted();
-
- this.targetUsername = name;
- }
-
- public synchronized String getTargetPassword()
- {
- return this.targetPassword;
- }
-
- public synchronized void setTargetPassword(String pwd)
- {
- checkBridgeNotStarted();
-
- this.targetPassword = pwd;
- }
-
- public synchronized String getSelector()
- {
- return selector;
- }
-
- public synchronized void setSelector(String selector)
- {
- checkBridgeNotStarted();
-
- this.selector = selector;
- }
-
- public synchronized long getFailureRetryInterval()
- {
- return failureRetryInterval;
- }
-
- public synchronized void setFailureRetryInterval(long interval)
- {
- checkBridgeNotStarted();
- checkValidValue(interval, "FailureRetryInterval");
-
- this.failureRetryInterval = interval;
- }
-
- public synchronized int getMaxRetries()
- {
- return maxRetries;
- }
-
- public synchronized void setMaxRetries(int retries)
- {
- checkBridgeNotStarted();
- checkValidValue(retries, "MaxRetries");
-
- this.maxRetries = retries;
- }
-
- public synchronized QualityOfServiceMode getQualityOfServiceMode()
- {
- return qualityOfServiceMode;
- }
-
- public synchronized void setQualityOfServiceMode(QualityOfServiceMode mode)
- {
- checkBridgeNotStarted();
- checkNotNull(mode, "QualityOfServiceMode");
-
- qualityOfServiceMode = mode;
- }
-
- public synchronized int getMaxBatchSize()
- {
- return maxBatchSize;
- }
-
- public synchronized void setMaxBatchSize(int size)
- {
- checkBridgeNotStarted();
- checkMaxBatchSize(size);
-
- maxBatchSize = size;
- }
-
- public synchronized long getMaxBatchTime()
- {
- return maxBatchTime;
- }
-
- public synchronized void setMaxBatchTime(long time)
- {
- checkBridgeNotStarted();
- checkValidValue(time, "MaxBatchTime");
-
- maxBatchTime = time;
- }
-
- public synchronized String getSubscriptionName()
- {
- return this.subName;
- }
-
- public synchronized void setSubscriptionName(String subname)
- {
- checkBridgeNotStarted();
- this.subName = subname;
- }
-
- public synchronized String getClientID()
- {
- return clientID;
- }
-
- public synchronized void setClientID(String clientID)
- {
- checkBridgeNotStarted();
-
- this.clientID = clientID;
- }
-
- public boolean isAddMessageIDInHeader()
- {
- return this.addMessageIDInHeader;
- }
-
- public void setAddMessageIDInHeader(boolean value)
- {
- this.addMessageIDInHeader = value;
- }
-
- public synchronized boolean isPaused()
- {
- return paused;
- }
-
- public synchronized boolean isFailed()
- {
- return failed;
- }
-
- public synchronized void setSourceConnectionFactoryFactory(ConnectionFactoryFactory cff)
- {
- checkBridgeNotStarted();
- checkNotNull(cff, "SourceConnectionFactoryFactory");
-
- this.sourceCff = cff;
- }
-
- public synchronized void setTargetConnectionFactoryFactory(ConnectionFactoryFactory cff)
- {
- checkBridgeNotStarted();
- checkNotNull(cff, "TargetConnectionFactoryFactory");
-
- this.targetCff = cff;
- }
-
- public void setTransactionManager(TransactionManager tm)
- {
- this.tm = tm;
- }
-
- // Public ---------------------------------------------------------------------------
-
- // Private -------------------------------------------------------------------
-
- private void checkParams()
- {
- checkNotNull(sourceCff, "sourceCff");
- checkNotNull(targetCff, "targetCff");
- checkNotNull(sourceDestinationFactory, "sourceDestinationFactory");
- checkNotNull(targetDestinationFactory, "targetDestinationFactory");
- checkValidValue(failureRetryInterval, "failureRetryInterval");
- checkValidValue(maxRetries, "maxRetries");
- if (failureRetryInterval == -1 && maxRetries > 0)
- {
- throw new IllegalArgumentException("If failureRetryInterval == -1 maxRetries must be set to -1");
- }
- checkMaxBatchSize(maxBatchSize);
- checkValidValue(maxBatchTime, "maxBatchTime");
- checkNotNull(qualityOfServiceMode, "qualityOfServiceMode");
- }
-
- /**
- * Check the object is not null
- *
- * @throws IllegalArgumentException if the object is null
- */
- private static void checkNotNull(Object obj, String name)
- {
- if (obj == null)
- {
- throw new IllegalArgumentException(name + " cannot be null");
- }
- }
-
- /**
- * Check the bridge is not started
- *
- * @throws IllegalStateException if the bridge is started
- */
- private void checkBridgeNotStarted()
- {
- if (started)
- {
- throw new IllegalStateException("Cannot set bridge attributes while it is started");
- }
- }
-
- /**
- * Check that value is either equals to -1 or greater than 0
- *
- * @throws IllegalArgumentException if the value is not valid
- */
- private static void checkValidValue(long value, String name)
- {
- if (!(value == -1 || value > 0))
- {
- throw new IllegalArgumentException(name + " must be > 0 or -1");
- }
- }
-
- private static void checkMaxBatchSize(int size)
- {
- if (!(size >= 1))
- {
- throw new IllegalArgumentException("maxBatchSize must be >= 1");
- }
- }
-
- private void enlistResources(Transaction tx) throws Exception
- {
- if (trace) { log.trace("Enlisting resources in tx"); }
-
- XAResource resSource = ((XASession)sourceSession).getXAResource();
-
- tx.enlistResource(resSource);
-
- XAResource resDest = ((XASession)targetSession).getXAResource();
-
- tx.enlistResource(resDest);
-
- if (trace) { log.trace("Enlisted resources in tx"); }
- }
-
- private void delistResources(Transaction tx)
- {
- if (trace) { log.trace("Delisting resources from tx"); }
-
- XAResource resSource = ((XASession)sourceSession).getXAResource();
-
- try
- {
- tx.delistResource(resSource, XAResource.TMSUCCESS);
- }
- catch (Exception e)
- {
- if (trace) { log.trace("Failed to delist source resource", e); }
- }
-
-
- XAResource resDest = ((XASession)targetSession).getXAResource();
-
- try
- {
- tx.delistResource(resDest, XAResource.TMSUCCESS);
- }
- catch (Exception e)
- {
- if (trace) { log.trace("Failed to delist target resource", e); }
- }
-
- if (trace) { log.trace("Delisted resources from tx"); }
- }
-
- private Transaction startTx() throws Exception
- {
- if (trace) { log.trace("Starting JTA transaction"); }
-
- TransactionManager tm = getTm();
-
- //Set timeout to a large value since we do not want to time out while waiting for messages
- //to arrive - 10 years should be enough
- tm.setTransactionTimeout(TEN_YEARS);
-
- tm.begin();
-
- Transaction tx = tm.getTransaction();
-
- //Remove the association between current thread - we don't want it
- //we will be committing /rolling back directly on the transaction object
-
- tm.suspend();
-
- if (trace) { log.trace("Started JTA transaction"); }
-
- return tx;
- }
-
- private TransactionManager getTm()
- {
- if (tm == null)
- {
- tm = TransactionManagerLocator.getInstance().locate();
-
- if (tm == null)
- {
- throw new IllegalStateException("Cannot locate a transaction manager");
- }
- }
-
- return tm;
- }
-
- private Connection createConnection(String username, String password, ConnectionFactoryFactory cff)
- throws Exception
- {
- Connection conn;
-
- ConnectionFactory cf = cff.createConnectionFactory();
-
- if (qualityOfServiceMode == QualityOfServiceMode.ONCE_AND_ONLY_ONCE &&
- !(cf instanceof XAConnectionFactory))
- {
- throw new IllegalArgumentException("Connection factory must be XAConnectionFactory");
- }
-
- if (username == null)
- {
- if (qualityOfServiceMode == QualityOfServiceMode.ONCE_AND_ONLY_ONCE)
- {
- if (trace) { log.trace("Creating an XA connection"); }
- conn = ((XAConnectionFactory)cf).createXAConnection();
- }
- else
- {
- if (trace) { log.trace("Creating a non XA connection"); }
- conn = cf.createConnection();
- }
- }
- else
- {
- if (qualityOfServiceMode == QualityOfServiceMode.ONCE_AND_ONLY_ONCE)
- {
- if (trace) { log.trace("Creating an XA connection"); }
- conn = ((XAConnectionFactory)cf).createXAConnection(username, password);
- }
- else
- {
- if (trace) { log.trace("Creating a non XA connection"); }
- conn = cf.createConnection(username, password);
- }
- }
-
- return conn;
- }
-
- /*
- * 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 = FORWARD_MODE_LOCALTX;
- }
- else
- {
- //Different servers
- if (qualityOfServiceMode == QualityOfServiceMode.ONCE_AND_ONLY_ONCE)
- {
- //Use XA
-
- forwardMode = FORWARD_MODE_XA;
- }
- else
- {
- forwardMode = FORWARD_MODE_NONTX;
- }
- }
-
- //Lookup the destinations
- sourceDestination = sourceDestinationFactory.createDestination();
-
- targetDestination = targetDestinationFactory.createDestination();
-
- sourceConn = createConnection(sourceUsername, sourcePassword, sourceCff);
-
- if (forwardMode != FORWARD_MODE_LOCALTX)
- {
- targetConn = createConnection(targetUsername, targetPassword, targetCff);
-
- targetConn.setExceptionListener(new BridgeExceptionListener());
- }
-
- if (clientID != null)
- {
- sourceConn.setClientID(clientID);
- }
-
- sourceConn.setExceptionListener(new BridgeExceptionListener());
-
- Session sess;
-
- if (forwardMode == FORWARD_MODE_LOCALTX)
- {
- //We simply use a single local transacted session for consuming and sending
-
- sourceSession = sourceConn.createSession(true, Session.SESSION_TRANSACTED);
-
- sess = sourceSession;
- }
- else
- {
- if (forwardMode == FORWARD_MODE_XA)
- {
- //Create an XASession for consuming from the source
- if (trace) { log.trace("Creating XA source session"); }
-
- sourceSession = ((XAConnection)sourceConn).createXASession();
-
- sess = ((XASession)sourceSession).getSession();
- }
- else
- {
- if (trace) { log.trace("Creating non XA source session"); }
-
- //Create a standard session for consuming from the source
-
- //We use ack mode client ack
-
- sourceSession = sourceConn.createSession(false, Session.CLIENT_ACKNOWLEDGE);
-
- sess = sourceSession;
- }
- }
-
- if (forwardMode == FORWARD_MODE_XA && sourceSession instanceof JBossSession)
- {
- JBossSession jsession = (JBossSession)sourceSession;
-
- ClientSession clientSession = jsession.getCoreSession();
-
- //clientSession.setTreatAsNonTransactedWhenNotEnlisted(false);
- }
-
- if (subName == null)
- {
- if (selector == null)
- {
- sourceConsumer = sess.createConsumer(sourceDestination);
- }
- else
- {
- sourceConsumer = sess.createConsumer(sourceDestination, selector, false);
- }
- }
- else
- {
- //Durable subscription
- if (selector == null)
- {
- sourceConsumer = sess.createDurableSubscriber((Topic)sourceDestination, subName);
- }
- else
- {
- sourceConsumer = sess.createDurableSubscriber((Topic)sourceDestination, subName, selector, false);
- }
- }
-
- //Now the sending session
-
-
- if (forwardMode != FORWARD_MODE_LOCALTX)
- {
- if (forwardMode == FORWARD_MODE_XA)
- {
- if (trace) { log.trace("Creating XA dest session"); }
-
- //Create an XA sesion for sending to the destination
-
- targetSession = ((XAConnection)targetConn).createXASession();
-
- sess = ((XASession)targetSession).getSession();
- }
- else
- {
- if (trace) { log.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;
-
- targetSession = targetConn.createSession(transacted, transacted ? Session.SESSION_TRANSACTED : Session.AUTO_ACKNOWLEDGE);
-
- sess = targetSession;
- }
- }
-
- if (forwardMode == FORWARD_MODE_XA)
- {
- if (trace) { log.trace("Starting JTA transaction"); }
-
- tx = startTx();
-
- enlistResources(tx);
- }
-
- targetProducer = sess.createProducer(null);
-
- sourceConsumer.setMessageListener(new SourceListener());
-
- return true;
- }
- catch (Exception e)
- {
- log.warn("Failed to set up bridge connections");
-
- //If this fails we should attempt to cleanup or we might end up in some weird state
-
- cleanup();
-
- return false;
- }
- }
-
- private void cleanup()
- {
- //Stop the source connection
- try
- {
- sourceConn.stop();
- }
- catch (Throwable ignore)
- {
- if (trace) { log.trace("Failed to stop source connection", ignore); }
- }
-
- if (tx != null)
- {
- try
- {
- delistResources(tx);
- }
- catch (Throwable ignore)
- {
- if (trace) { log.trace("Failed to delist resources", ignore); }
- }
- try
- {
- //Terminate the tx
- tx.rollback();
- }
- catch (Throwable ignore)
- {
- if (trace) { log.trace("Failed to rollback", ignore); }
- }
- }
-
- //Close the old objects
- try
- {
- sourceConn.close();
- }
- catch (Throwable ignore)
- {
- if (trace) { log.trace("Failed to close source connection", ignore); }
- }
- try
- {
- if (targetConn != null)
- {
- targetConn.close();
- }
- }
- catch (Throwable ignore)
- {
- if (trace) { log.trace("Failed to close target connection", ignore); }
- }
- }
-
- private void pause(long interval)
- {
- long start = System.currentTimeMillis();
- while (System.currentTimeMillis() - start < failureRetryInterval)
- {
- try
- {
- Thread.sleep(failureRetryInterval);
- }
- catch (InterruptedException ex)
- {
- }
- }
- }
-
- private boolean setupJMSObjectsWithRetry()
- {
- if (trace) { log.trace("Setting up connections"); }
-
- int count = 0;
-
- while (true)
- {
- boolean ok = setupJMSObjects();
-
- if (ok)
- {
- return true;
- }
-
- count++;
-
- if (maxRetries != -1 && count == maxRetries)
- {
- break;
- }
-
- log.warn("Failed to set up connections, will retry after a pause of " + failureRetryInterval + " ms");
-
- pause(failureRetryInterval);
- }
-
- //If we get here then we exceed maxRetries
- return false;
- }
-
-
- private void sendBatch()
- {
- if (trace) { log.trace("Sending batch of " + messages.size() + " messages"); }
-
- if (paused)
- {
- //Don't send now
- if (trace) { log.trace("Paused, so not sending now"); }
-
- return;
- }
-
- if (forwardMode == FORWARD_MODE_LOCALTX)
- {
- sendBatchLocalTx();
- }
- else if (forwardMode == FORWARD_MODE_XA)
- {
- sendBatchXA();
- }
- else
- {
- sendBatchNonTransacted();
- }
- }
-
- private void sendBatchNonTransacted()
- {
- try
- {
- if (qualityOfServiceMode == QualityOfServiceMode.ONCE_AND_ONLY_ONCE)
- {
- //We client ack before sending
-
- if (trace) { log.trace("Client acking source session"); }
-
- ((Message)messages.getLast()).acknowledge();
-
- if (trace) { log.trace("Client acked source session"); }
- }
-
- sendMessages();
-
- if (maxBatchSize > 1)
- {
- //The sending session is transacted - we need to commit it
-
- if (trace) { log.trace("Committing target session"); }
-
- targetSession.commit();
-
- if (trace) { log.trace("Committed source session"); }
- }
-
- if (qualityOfServiceMode == QualityOfServiceMode.DUPLICATES_OK)
- {
- //We client ack after sending
-
- //Note we could actually use Session.DUPS_OK_ACKNOWLEDGE here
- //For a slightly less strong delivery guarantee
-
- if (trace) { log.trace("Client acking source session"); }
-
- messages.getLast().acknowledge();
-
- if (trace) { log.trace("Client acked source session"); }
- }
-
- //Clear the messages
- messages.clear();
- }
- catch (Exception e)
- {
- log.warn("Failed to send + acknowledge batch, closing JMS objects", e);
-
- handleFailureOnSend();
- }
- }
-
- private void sendBatchXA()
- {
- try
- {
- sendMessages();
-
- //Commit the JTA transaction and start another
-
- delistResources(tx);
-
- if (trace) { log.trace("Committing JTA transaction"); }
-
- tx.commit();
-
- if (trace) { log.trace("Committed JTA transaction"); }
-
- tx = startTx();
-
- enlistResources(tx);
-
- //Clear the messages
- messages.clear();
- }
- catch (Exception e)
- {
- log.warn("Failed to send + acknowledge batch, closing JMS objects", e);
-
- handleFailureOnSend();
- }
- }
-
- private void sendBatchLocalTx()
- {
- try
- {
- sendMessages();
-
- if (trace) { log.trace("Committing source session"); }
-
- sourceSession.commit();
-
- if (trace) { log.trace("Committed source session"); }
-
- //Clear the messages
- messages.clear();
- }
- catch (Exception e)
- {
- log.warn("Failed to send + acknowledge batch, closing JMS objects", e);
-
- handleFailureOnSend();
- }
- }
-
- private void sendMessages() throws Exception
- {
- Iterator iter = messages.iterator();
-
- Message msg = null;
-
- while (iter.hasNext())
- {
- msg = (Message)iter.next();
-
- if (addMessageIDInHeader)
- {
- addMessageIDInHeader(msg);
- }
-
- if (trace) { log.trace("Sending message " + msg); }
-
- //Make sure the correct time to live gets propagated
-
- long timeToLive = msg.getJMSExpiration();
-
- if (timeToLive != 0)
- {
- timeToLive -= System.currentTimeMillis();
-
- if (timeToLive <= 0)
- {
- timeToLive = 1; //Should have already expired - set to 1 so it expires when it is consumed or delivered
- }
- }
-
- targetProducer.send(targetDestination, msg, msg.getJMSDeliveryMode(), msg.getJMSPriority(), timeToLive);
-
- if (trace) { log.trace("Sent message " + msg); }
- }
- }
-
- private void handleFailureOnSend()
- {
- handleFailure(new FailureHandler());
- }
-
- private void handleFailureOnStartup()
- {
- handleFailure(new StartupFailureHandler());
- }
-
- private void handleFailure(Runnable failureHandler)
- {
- failed = true;
-
- //Failure must be handled on a separate thread to the calling thread (either onMessage or start).
- //In the case of onMessage we can't close the connection from inside the onMessage method
- //since it will block waiting for onMessage to complete. In the case of start we want to return
- //from the call before the connections are reestablished so that the caller is not blocked unnecessarily.
- Thread t = new Thread(failureHandler);
-
- t.start();
- }
-
- private void addMessageIDInHeader(Message msg) throws Exception
- {
- //We concatenate the old message id as a header in the message
- //This allows the target to then use this as the JMSCorrelationID of any response message
- //thus enabling a distributed request-response pattern.
- //Each bridge (if there are more than one) in the chain can concatenate the message id
- //So in the case of multiple bridges having routed the message this can be used in a multi-hop
- //distributed request/response
- if (trace) { log.trace("Adding old message id in Message header"); }
-
- copyProperties(msg);
-
- String val = null;
-
- val = msg.getStringProperty(JBossMessage.JBOSS_MESSAGING_BRIDGE_MESSAGE_ID_LIST);
-
- if (val == null)
- {
- val = msg.getJMSMessageID();
- }
- else
- {
- StringBuffer sb = new StringBuffer(val);
-
- sb.append(",").append(msg.getJMSMessageID());
-
- val = sb.toString();
- }
-
- msg.setStringProperty(JBossMessage.JBOSS_MESSAGING_BRIDGE_MESSAGE_ID_LIST, val);
- }
-
-
- /*
- * JMS does not let you add a property on received message without first
- * calling clearProperties, so we need to save and re-add all the old properties so we
- * don't lose them!!
- */
- private static void copyProperties(Message msg) throws JMSException
- {
- Enumeration en = msg.getPropertyNames();
-
- Map<String, Object> oldProps = null;
-
- while (en.hasMoreElements())
- {
- String propName = (String)en.nextElement();
-
- if (oldProps == null)
- {
- oldProps = new HashMap<String, Object>();
- }
-
- oldProps.put(propName, msg.getObjectProperty(propName));
- }
-
- msg.clearProperties();
-
- if (oldProps != null)
- {
- Iterator oldPropsIter = oldProps.entrySet().iterator();
-
- while (oldPropsIter.hasNext())
- {
- Map.Entry entry = (Map.Entry)oldPropsIter.next();
-
- String propName = (String)entry.getKey();
-
- msg.setObjectProperty(propName, entry.getValue());
- }
- }
- }
-
- // Inner classes ---------------------------------------------------------------
-
- private class FailureHandler implements Runnable
- {
- /**
- * Start the source connection - note the source connection must not be started before
- * otherwise messages will be received and ignored
- */
- protected void startSourceConnection()
- {
- try
- {
- sourceConn.start();
- }
- catch (JMSException e)
- {
- log.error("Failed to start source connection", e);
- }
- }
-
- protected void succeeded()
- {
- log.info("Succeeded in reconnecting to servers");
-
- synchronized (lock)
- {
- failed = false;
-
- startSourceConnection();
- }
- }
-
- protected void failed()
- {
- //We haven't managed to recreate connections or maxRetries = 0
- log.warn("Unable to set up connections, bridge will be stopped");
-
- try
- {
- stop();
- }
- catch (Exception ignore)
- {
- }
- }
-
- public void run()
- {
- if (trace) { log.trace("Failure handler running"); }
-
- // Clear the messages
- messages.clear();
-
- cleanup();
-
- boolean ok = false;
-
- if (maxRetries > 0 || maxRetries == -1)
- {
- log.warn("Will retry after a pause of " + failureRetryInterval + " ms");
-
- pause(failureRetryInterval);
-
- //Now we try
- ok = setupJMSObjectsWithRetry();
- }
-
- if (!ok)
- {
- failed();
- }
- else
- {
- succeeded();
- }
- }
- }
-
- private class StartupFailureHandler extends FailureHandler
- {
- protected void failed()
- {
- // Don't call super
- log.warn("Unable to set up connections, bridge will not be started");
- }
-
- protected void succeeded()
- {
- // Don't call super - a bit ugly in this case but better than taking the lock twice.
- log.info("Succeeded in connecting to servers");
-
- synchronized (lock)
- {
- failed = false;
- started = true;
-
- //Start the source connection - note the source connection must not be started before
- //otherwise messages will be received and ignored
-
- try
- {
- sourceConn.start();
- }
- catch (JMSException e)
- {
- log.error("Failed to start source connection", e);
- }
- }
- }
- }
-
- private class BatchTimeChecker implements Runnable
- {
- public void run()
- {
- if (trace) { log.trace(this + " running"); }
-
- synchronized (lock)
- {
- while (started)
- {
- long toWait = batchExpiryTime - System.currentTimeMillis();
-
- if (toWait <= 0)
- {
- if (trace) { log.trace(this + " waited enough"); }
-
- synchronized (lock)
- {
- if (!failed && !messages.isEmpty())
- {
- if (trace) { log.trace(this + " got some messages so sending batch"); }
-
- sendBatch();
-
- if (trace) { log.trace(this + " sent batch"); }
- }
- }
-
- batchExpiryTime = System.currentTimeMillis() + maxBatchTime;
- }
- else
- {
- try
- {
- if (trace) { log.trace(this + " waiting for " + toWait); }
-
- lock.wait(toWait);
-
- if (trace) { log.trace(this + " woke up"); }
- }
- catch (InterruptedException e)
- {
- //Ignore
- if (trace) { log.trace(this + " thread was interrupted"); }
- }
-
- }
- }
- }
- }
- }
-
- private class SourceListener implements MessageListener
- {
- public void onMessage(Message msg)
- {
- synchronized (lock)
- {
- if (failed)
- {
- //Ignore the message
- if (trace) { log.trace("Bridge has failed so ignoring message"); }
-
- return;
- }
-
- if (trace) { log.trace(this + " received message " + msg); }
-
- messages.add(msg);
-
- batchExpiryTime = System.currentTimeMillis() + maxBatchTime;
-
- if (trace) { log.trace(this + " rescheduled batchExpiryTime to " + batchExpiryTime); }
-
- if (maxBatchSize != -1 && messages.size() >= maxBatchSize)
- {
- if (trace) { log.trace(this + " maxBatchSize has been reached so sending batch"); }
-
- sendBatch();
-
- if (trace) { log.trace(this + " sent batch"); }
- }
- }
- }
- }
-
- private class BridgeExceptionListener implements ExceptionListener
- {
- public void onException(JMSException e)
- {
- log.warn("Detected failure on bridge connection");
-
- synchronized (lock)
- {
- if (failed)
- {
- //The failure has already been detected and is being handled
- if (trace) { log.trace("Failure recovery already in progress"); }
- }
- else
- {
- handleFailure(new FailureHandler());
- }
- }
- }
- }
-}
Copied: trunk/src/main/org/jboss/messaging/jms/bridge/impl/JMSBridgeImpl.java (from rev 6295, trunk/src/main/org/jboss/messaging/jms/bridge/impl/BridgeImpl.java)
===================================================================
--- trunk/src/main/org/jboss/messaging/jms/bridge/impl/JMSBridgeImpl.java (rev 0)
+++ trunk/src/main/org/jboss/messaging/jms/bridge/impl/JMSBridgeImpl.java 2009-04-03 14:12:53 UTC (rev 6299)
@@ -0,0 +1,1602 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.messaging.jms.bridge.impl;
+
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Map;
+
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.Destination;
+import javax.jms.ExceptionListener;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageListener;
+import javax.jms.MessageProducer;
+import javax.jms.Session;
+import javax.jms.Topic;
+import javax.jms.XAConnection;
+import javax.jms.XAConnectionFactory;
+import javax.jms.XASession;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+import javax.transaction.xa.XAResource;
+
+import org.jboss.messaging.core.client.ClientSession;
+import org.jboss.messaging.core.logging.Logger;
+import org.jboss.messaging.core.server.MessagingComponent;
+import org.jboss.messaging.jms.bridge.JMSBridge;
+import org.jboss.messaging.jms.bridge.ConnectionFactoryFactory;
+import org.jboss.messaging.jms.bridge.DestinationFactory;
+import org.jboss.messaging.jms.bridge.QualityOfServiceMode;
+import org.jboss.messaging.jms.client.JBossMessage;
+import org.jboss.messaging.jms.client.JBossSession;
+import org.jboss.tm.TransactionManagerLocator;
+
+/**
+ *
+ * A JMSBridge
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision:4566 $</tt>
+ *
+ * $Id:JMSBridge.java 4566 2008-06-24 08:01:35Z jmesnil $
+ *
+ */
+public class JMSBridgeImpl implements MessagingComponent, JMSBridge
+{
+ private static final Logger log;
+
+ private static boolean trace;
+
+ static
+ {
+ log = Logger.getLogger(JMSBridgeImpl.class);
+
+ trace = log.isTraceEnabled();
+ }
+
+ private static final int TEN_YEARS = 60 * 60 * 24 * 365 * 10; // in ms
+
+ private final Object lock = new Object();
+
+ private String sourceUsername;
+
+ private String sourcePassword;
+
+ private String targetUsername;
+
+ private String targetPassword;
+
+ private TransactionManager tm;
+
+ private String selector;
+
+ private long failureRetryInterval;
+
+ private int maxRetries;
+
+ private QualityOfServiceMode qualityOfServiceMode;
+
+ private int maxBatchSize;
+
+ private long maxBatchTime;
+
+ private String subName;
+
+ private String clientID;
+
+ private volatile boolean addMessageIDInHeader;
+
+ private boolean started;
+
+ private LinkedList<Message> messages;
+
+ private ConnectionFactoryFactory sourceCff;
+
+ private ConnectionFactoryFactory targetCff;
+
+ private DestinationFactory sourceDestinationFactory;
+
+ private DestinationFactory targetDestinationFactory;
+
+ private Connection sourceConn;
+
+ private Connection targetConn;
+
+ private Destination sourceDestination;
+
+ private Destination targetDestination;
+
+ private Session sourceSession;
+
+ private Session targetSession;
+
+ private MessageConsumer sourceConsumer;
+
+ private MessageProducer targetProducer;
+
+ private BatchTimeChecker timeChecker;
+
+ private Thread checkerThread;
+
+ private long batchExpiryTime;
+
+ private boolean paused;
+
+ private Transaction tx;
+
+ private boolean failed;
+
+ private int forwardMode;
+
+ private static final int FORWARD_MODE_XA = 0;
+
+ private static final int FORWARD_MODE_LOCALTX = 1;
+
+ private static final int FORWARD_MODE_NONTX = 2;
+
+ /*
+ * Constructor for MBean
+ */
+ public JMSBridgeImpl()
+ {
+ this.messages = new LinkedList<Message>();
+ }
+
+ public JMSBridgeImpl(ConnectionFactoryFactory sourceCff, ConnectionFactoryFactory targetCff,
+ DestinationFactory sourceDestinationFactory, DestinationFactory targetDestinationFactory,
+ String sourceUsername, String sourcePassword,
+ String targetUsername, String targetPassword,
+ String selector, long failureRetryInterval,
+ int maxRetries,
+ QualityOfServiceMode qosMode,
+ int maxBatchSize, long maxBatchTime,
+ String subName, String clientID,
+ boolean addMessageIDInHeader)
+ {
+ this();
+
+ this.sourceCff = sourceCff;
+
+ this.targetCff = targetCff;
+
+ this.sourceDestinationFactory = sourceDestinationFactory;
+
+ this.targetDestinationFactory = targetDestinationFactory;
+
+ this.sourceUsername = sourceUsername;
+
+ this.sourcePassword = sourcePassword;
+
+ this.targetUsername = targetUsername;
+
+ this.targetPassword = targetPassword;
+
+ this.selector = selector;
+
+ this.failureRetryInterval = failureRetryInterval;
+
+ this.maxRetries = maxRetries;
+
+ this.qualityOfServiceMode = qosMode;
+
+ this.maxBatchSize = maxBatchSize;
+
+ this.maxBatchTime = maxBatchTime;
+
+ this.subName = subName;
+
+ this.clientID = clientID;
+
+ this.addMessageIDInHeader = addMessageIDInHeader;
+
+ checkParams();
+
+ if (trace)
+ {
+ log.trace("Created " + this);
+ }
+ }
+
+ // MessagingComponent overrides --------------------------------------------------
+
+ public synchronized void start() throws Exception
+ {
+ if (started)
+ {
+ log.warn("Attempt to start, but is already started");
+ return;
+ }
+
+ if (trace) { log.trace("Starting " + this); }
+
+ checkParams();
+
+ TransactionManager tm = getTm();
+
+ //There may already be a JTA transaction associated to the thread
+
+ boolean ok;
+
+ Transaction toResume = null;
+ try
+ {
+ toResume = tm.suspend();
+
+ ok = setupJMSObjects();
+ }
+ finally
+ {
+ if (toResume != null)
+ {
+ tm.resume(toResume);
+ }
+ }
+
+ if (ok)
+ {
+ //start the source connection
+
+ sourceConn.start();
+
+ started = true;
+
+ if (maxBatchTime != -1)
+ {
+ if (trace) { log.trace("Starting time checker thread"); }
+
+ timeChecker = new BatchTimeChecker();
+
+ checkerThread = new Thread(timeChecker);
+
+ batchExpiryTime = System.currentTimeMillis() + maxBatchTime;
+
+ checkerThread.start();
+
+ if (trace) { log.trace("Started time checker thread"); }
+ }
+
+ if (trace) { log.trace("Started " + this); }
+ }
+ else
+ {
+ log.warn("Failed to start bridge");
+ handleFailureOnStartup();
+ }
+ }
+
+ public synchronized void stop() throws Exception
+ {
+ if (!started)
+ {
+ log.warn("Attempt to stop, but is already stopped");
+ return;
+ }
+
+ if (trace) { log.trace("Stopping " + this); }
+
+ synchronized (lock)
+ {
+ started = false;
+
+ //This must be inside sync block
+ if (checkerThread != null)
+ {
+ checkerThread.interrupt();
+ }
+ }
+
+ //This must be outside sync block
+ if (checkerThread != null)
+ {
+ if (trace) { log.trace("Waiting for checker thread to finish");}
+
+ checkerThread.join();
+
+ if (trace) { log.trace("Checker thread has finished"); }
+ }
+
+ if (tx != null)
+ {
+ //Terminate any transaction
+ if (trace) { log.trace("Rolling back remaining tx"); }
+
+ try
+ {
+ tx.rollback();
+ }
+ catch (Exception ignore)
+ {
+ if (trace) { log.trace("Failed to rollback", ignore); }
+ }
+
+ if (trace) { log.trace("Rolled back remaining tx"); }
+ }
+
+ try
+ {
+ sourceConn.close();
+ }
+ catch (Exception ignore)
+ {
+ if (trace) { log.trace("Failed to close source conn", ignore); }
+ }
+
+ if (targetConn != null)
+ {
+ try
+ {
+ targetConn.close();
+ }
+ catch (Exception ignore)
+ {
+ if (trace) { log.trace("Failed to close target conn", ignore); }
+ }
+ }
+
+ if (trace) { log.trace("Stopped " + this); }
+ }
+
+ public synchronized boolean isStarted()
+ {
+ return started;
+ }
+
+ // JMSBridge implementation ------------------------------------------------------------
+
+ public synchronized void pause() throws Exception
+ {
+ if (trace) { log.trace("Pausing " + this); }
+
+ synchronized (lock)
+ {
+ paused = true;
+
+ sourceConn.stop();
+ }
+
+ if (trace) { log.trace("Paused " + this); }
+ }
+
+ public synchronized void resume() throws Exception
+ {
+ if (trace) { log.trace("Resuming " + this); }
+
+ synchronized (lock)
+ {
+ paused = false;
+
+ sourceConn.start();
+ }
+
+ if (trace) { log.trace("Resumed " + this); }
+ }
+
+ public DestinationFactory getSourceDestinationFactory()
+ {
+ return sourceDestinationFactory;
+ }
+
+ public void setSourceDestinationFactory(DestinationFactory dest)
+ {
+ checkBridgeNotStarted();
+ checkNotNull(dest, "TargetDestinationFactory");
+
+ sourceDestinationFactory = dest;
+ }
+
+ public DestinationFactory getTargetDestinationFactory()
+ {
+ return targetDestinationFactory;
+ }
+
+ public void setTargetDestinationFactory(DestinationFactory dest)
+ {
+ checkBridgeNotStarted();
+ checkNotNull(dest, "TargetDestinationFactory");
+
+ targetDestinationFactory = dest;
+ }
+
+ public String getSourceUsername()
+ {
+ return sourceUsername;
+ }
+
+ public synchronized void setSourceUsername(String name)
+ {
+ checkBridgeNotStarted();
+
+ sourceUsername = name;
+ }
+
+ public synchronized String getSourcePassword()
+ {
+ return sourcePassword;
+ }
+
+ public synchronized void setSourcePassword(String pwd)
+ {
+ checkBridgeNotStarted();
+
+ sourcePassword = pwd;
+ }
+
+ public synchronized String getTargetUsername()
+ {
+ return targetUsername;
+ }
+
+ public synchronized void setTargetUsername(String name)
+ {
+ checkBridgeNotStarted();
+
+ this.targetUsername = name;
+ }
+
+ public synchronized String getTargetPassword()
+ {
+ return this.targetPassword;
+ }
+
+ public synchronized void setTargetPassword(String pwd)
+ {
+ checkBridgeNotStarted();
+
+ this.targetPassword = pwd;
+ }
+
+ public synchronized String getSelector()
+ {
+ return selector;
+ }
+
+ public synchronized void setSelector(String selector)
+ {
+ checkBridgeNotStarted();
+
+ this.selector = selector;
+ }
+
+ public synchronized long getFailureRetryInterval()
+ {
+ return failureRetryInterval;
+ }
+
+ public synchronized void setFailureRetryInterval(long interval)
+ {
+ checkBridgeNotStarted();
+ checkValidValue(interval, "FailureRetryInterval");
+
+ this.failureRetryInterval = interval;
+ }
+
+ public synchronized int getMaxRetries()
+ {
+ return maxRetries;
+ }
+
+ public synchronized void setMaxRetries(int retries)
+ {
+ checkBridgeNotStarted();
+ checkValidValue(retries, "MaxRetries");
+
+ this.maxRetries = retries;
+ }
+
+ public synchronized QualityOfServiceMode getQualityOfServiceMode()
+ {
+ return qualityOfServiceMode;
+ }
+
+ public synchronized void setQualityOfServiceMode(QualityOfServiceMode mode)
+ {
+ checkBridgeNotStarted();
+ checkNotNull(mode, "QualityOfServiceMode");
+
+ qualityOfServiceMode = mode;
+ }
+
+ public synchronized int getMaxBatchSize()
+ {
+ return maxBatchSize;
+ }
+
+ public synchronized void setMaxBatchSize(int size)
+ {
+ checkBridgeNotStarted();
+ checkMaxBatchSize(size);
+
+ maxBatchSize = size;
+ }
+
+ public synchronized long getMaxBatchTime()
+ {
+ return maxBatchTime;
+ }
+
+ public synchronized void setMaxBatchTime(long time)
+ {
+ checkBridgeNotStarted();
+ checkValidValue(time, "MaxBatchTime");
+
+ maxBatchTime = time;
+ }
+
+ public synchronized String getSubscriptionName()
+ {
+ return this.subName;
+ }
+
+ public synchronized void setSubscriptionName(String subname)
+ {
+ checkBridgeNotStarted();
+ this.subName = subname;
+ }
+
+ public synchronized String getClientID()
+ {
+ return clientID;
+ }
+
+ public synchronized void setClientID(String clientID)
+ {
+ checkBridgeNotStarted();
+
+ this.clientID = clientID;
+ }
+
+ public boolean isAddMessageIDInHeader()
+ {
+ return this.addMessageIDInHeader;
+ }
+
+ public void setAddMessageIDInHeader(boolean value)
+ {
+ this.addMessageIDInHeader = value;
+ }
+
+ public synchronized boolean isPaused()
+ {
+ return paused;
+ }
+
+ public synchronized boolean isFailed()
+ {
+ return failed;
+ }
+
+ public synchronized void setSourceConnectionFactoryFactory(ConnectionFactoryFactory cff)
+ {
+ checkBridgeNotStarted();
+ checkNotNull(cff, "SourceConnectionFactoryFactory");
+
+ this.sourceCff = cff;
+ }
+
+ public synchronized void setTargetConnectionFactoryFactory(ConnectionFactoryFactory cff)
+ {
+ checkBridgeNotStarted();
+ checkNotNull(cff, "TargetConnectionFactoryFactory");
+
+ this.targetCff = cff;
+ }
+
+ public void setTransactionManager(TransactionManager tm)
+ {
+ this.tm = tm;
+ }
+
+ // Public ---------------------------------------------------------------------------
+
+ // Private -------------------------------------------------------------------
+
+ private void checkParams()
+ {
+ checkNotNull(sourceCff, "sourceCff");
+ checkNotNull(targetCff, "targetCff");
+ checkNotNull(sourceDestinationFactory, "sourceDestinationFactory");
+ checkNotNull(targetDestinationFactory, "targetDestinationFactory");
+ checkValidValue(failureRetryInterval, "failureRetryInterval");
+ checkValidValue(maxRetries, "maxRetries");
+ if (failureRetryInterval == -1 && maxRetries > 0)
+ {
+ throw new IllegalArgumentException("If failureRetryInterval == -1 maxRetries must be set to -1");
+ }
+ checkMaxBatchSize(maxBatchSize);
+ checkValidValue(maxBatchTime, "maxBatchTime");
+ checkNotNull(qualityOfServiceMode, "qualityOfServiceMode");
+ }
+
+ /**
+ * Check the object is not null
+ *
+ * @throws IllegalArgumentException if the object is null
+ */
+ private static void checkNotNull(Object obj, String name)
+ {
+ if (obj == null)
+ {
+ throw new IllegalArgumentException(name + " cannot be null");
+ }
+ }
+
+ /**
+ * Check the bridge is not started
+ *
+ * @throws IllegalStateException if the bridge is started
+ */
+ private void checkBridgeNotStarted()
+ {
+ if (started)
+ {
+ throw new IllegalStateException("Cannot set bridge attributes while it is started");
+ }
+ }
+
+ /**
+ * Check that value is either equals to -1 or greater than 0
+ *
+ * @throws IllegalArgumentException if the value is not valid
+ */
+ private static void checkValidValue(long value, String name)
+ {
+ if (!(value == -1 || value > 0))
+ {
+ throw new IllegalArgumentException(name + " must be > 0 or -1");
+ }
+ }
+
+ private static void checkMaxBatchSize(int size)
+ {
+ if (!(size >= 1))
+ {
+ throw new IllegalArgumentException("maxBatchSize must be >= 1");
+ }
+ }
+
+ private void enlistResources(Transaction tx) throws Exception
+ {
+ if (trace) { log.trace("Enlisting resources in tx"); }
+
+ XAResource resSource = ((XASession)sourceSession).getXAResource();
+
+ tx.enlistResource(resSource);
+
+ XAResource resDest = ((XASession)targetSession).getXAResource();
+
+ tx.enlistResource(resDest);
+
+ if (trace) { log.trace("Enlisted resources in tx"); }
+ }
+
+ private void delistResources(Transaction tx)
+ {
+ if (trace) { log.trace("Delisting resources from tx"); }
+
+ XAResource resSource = ((XASession)sourceSession).getXAResource();
+
+ try
+ {
+ tx.delistResource(resSource, XAResource.TMSUCCESS);
+ }
+ catch (Exception e)
+ {
+ if (trace) { log.trace("Failed to delist source resource", e); }
+ }
+
+
+ XAResource resDest = ((XASession)targetSession).getXAResource();
+
+ try
+ {
+ tx.delistResource(resDest, XAResource.TMSUCCESS);
+ }
+ catch (Exception e)
+ {
+ if (trace) { log.trace("Failed to delist target resource", e); }
+ }
+
+ if (trace) { log.trace("Delisted resources from tx"); }
+ }
+
+ private Transaction startTx() throws Exception
+ {
+ if (trace) { log.trace("Starting JTA transaction"); }
+
+ TransactionManager tm = getTm();
+
+ //Set timeout to a large value since we do not want to time out while waiting for messages
+ //to arrive - 10 years should be enough
+ tm.setTransactionTimeout(TEN_YEARS);
+
+ tm.begin();
+
+ Transaction tx = tm.getTransaction();
+
+ //Remove the association between current thread - we don't want it
+ //we will be committing /rolling back directly on the transaction object
+
+ tm.suspend();
+
+ if (trace) { log.trace("Started JTA transaction"); }
+
+ return tx;
+ }
+
+ private TransactionManager getTm()
+ {
+ if (tm == null)
+ {
+ tm = TransactionManagerLocator.getInstance().locate();
+
+ if (tm == null)
+ {
+ throw new IllegalStateException("Cannot locate a transaction manager");
+ }
+ }
+
+ return tm;
+ }
+
+ private Connection createConnection(String username, String password, ConnectionFactoryFactory cff)
+ throws Exception
+ {
+ Connection conn;
+
+ ConnectionFactory cf = cff.createConnectionFactory();
+
+ if (qualityOfServiceMode == QualityOfServiceMode.ONCE_AND_ONLY_ONCE &&
+ !(cf instanceof XAConnectionFactory))
+ {
+ throw new IllegalArgumentException("Connection factory must be XAConnectionFactory");
+ }
+
+ if (username == null)
+ {
+ if (qualityOfServiceMode == QualityOfServiceMode.ONCE_AND_ONLY_ONCE)
+ {
+ if (trace) { log.trace("Creating an XA connection"); }
+ conn = ((XAConnectionFactory)cf).createXAConnection();
+ }
+ else
+ {
+ if (trace) { log.trace("Creating a non XA connection"); }
+ conn = cf.createConnection();
+ }
+ }
+ else
+ {
+ if (qualityOfServiceMode == QualityOfServiceMode.ONCE_AND_ONLY_ONCE)
+ {
+ if (trace) { log.trace("Creating an XA connection"); }
+ conn = ((XAConnectionFactory)cf).createXAConnection(username, password);
+ }
+ else
+ {
+ if (trace) { log.trace("Creating a non XA connection"); }
+ conn = cf.createConnection(username, password);
+ }
+ }
+
+ return conn;
+ }
+
+ /*
+ * 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 = FORWARD_MODE_LOCALTX;
+ }
+ else
+ {
+ //Different servers
+ if (qualityOfServiceMode == QualityOfServiceMode.ONCE_AND_ONLY_ONCE)
+ {
+ //Use XA
+
+ forwardMode = FORWARD_MODE_XA;
+ }
+ else
+ {
+ forwardMode = FORWARD_MODE_NONTX;
+ }
+ }
+
+ //Lookup the destinations
+ sourceDestination = sourceDestinationFactory.createDestination();
+
+ targetDestination = targetDestinationFactory.createDestination();
+
+ sourceConn = createConnection(sourceUsername, sourcePassword, sourceCff);
+
+ if (forwardMode != FORWARD_MODE_LOCALTX)
+ {
+ targetConn = createConnection(targetUsername, targetPassword, targetCff);
+
+ targetConn.setExceptionListener(new BridgeExceptionListener());
+ }
+
+ if (clientID != null)
+ {
+ sourceConn.setClientID(clientID);
+ }
+
+ sourceConn.setExceptionListener(new BridgeExceptionListener());
+
+ Session sess;
+
+ if (forwardMode == FORWARD_MODE_LOCALTX)
+ {
+ //We simply use a single local transacted session for consuming and sending
+
+ sourceSession = sourceConn.createSession(true, Session.SESSION_TRANSACTED);
+
+ sess = sourceSession;
+ }
+ else
+ {
+ if (forwardMode == FORWARD_MODE_XA)
+ {
+ //Create an XASession for consuming from the source
+ if (trace) { log.trace("Creating XA source session"); }
+
+ sourceSession = ((XAConnection)sourceConn).createXASession();
+
+ sess = ((XASession)sourceSession).getSession();
+ }
+ else
+ {
+ if (trace) { log.trace("Creating non XA source session"); }
+
+ //Create a standard session for consuming from the source
+
+ //We use ack mode client ack
+
+ sourceSession = sourceConn.createSession(false, Session.CLIENT_ACKNOWLEDGE);
+
+ sess = sourceSession;
+ }
+ }
+
+ if (forwardMode == FORWARD_MODE_XA && sourceSession instanceof JBossSession)
+ {
+ JBossSession jsession = (JBossSession)sourceSession;
+
+ ClientSession clientSession = jsession.getCoreSession();
+
+ //clientSession.setTreatAsNonTransactedWhenNotEnlisted(false);
+ }
+
+ if (subName == null)
+ {
+ if (selector == null)
+ {
+ sourceConsumer = sess.createConsumer(sourceDestination);
+ }
+ else
+ {
+ sourceConsumer = sess.createConsumer(sourceDestination, selector, false);
+ }
+ }
+ else
+ {
+ //Durable subscription
+ if (selector == null)
+ {
+ sourceConsumer = sess.createDurableSubscriber((Topic)sourceDestination, subName);
+ }
+ else
+ {
+ sourceConsumer = sess.createDurableSubscriber((Topic)sourceDestination, subName, selector, false);
+ }
+ }
+
+ //Now the sending session
+
+
+ if (forwardMode != FORWARD_MODE_LOCALTX)
+ {
+ if (forwardMode == FORWARD_MODE_XA)
+ {
+ if (trace) { log.trace("Creating XA dest session"); }
+
+ //Create an XA sesion for sending to the destination
+
+ targetSession = ((XAConnection)targetConn).createXASession();
+
+ sess = ((XASession)targetSession).getSession();
+ }
+ else
+ {
+ if (trace) { log.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;
+
+ targetSession = targetConn.createSession(transacted, transacted ? Session.SESSION_TRANSACTED : Session.AUTO_ACKNOWLEDGE);
+
+ sess = targetSession;
+ }
+ }
+
+ if (forwardMode == FORWARD_MODE_XA)
+ {
+ if (trace) { log.trace("Starting JTA transaction"); }
+
+ tx = startTx();
+
+ enlistResources(tx);
+ }
+
+ targetProducer = sess.createProducer(null);
+
+ sourceConsumer.setMessageListener(new SourceListener());
+
+ return true;
+ }
+ catch (Exception e)
+ {
+ log.warn("Failed to set up bridge connections");
+
+ //If this fails we should attempt to cleanup or we might end up in some weird state
+
+ cleanup();
+
+ return false;
+ }
+ }
+
+ private void cleanup()
+ {
+ //Stop the source connection
+ try
+ {
+ sourceConn.stop();
+ }
+ catch (Throwable ignore)
+ {
+ if (trace) { log.trace("Failed to stop source connection", ignore); }
+ }
+
+ if (tx != null)
+ {
+ try
+ {
+ delistResources(tx);
+ }
+ catch (Throwable ignore)
+ {
+ if (trace) { log.trace("Failed to delist resources", ignore); }
+ }
+ try
+ {
+ //Terminate the tx
+ tx.rollback();
+ }
+ catch (Throwable ignore)
+ {
+ if (trace) { log.trace("Failed to rollback", ignore); }
+ }
+ }
+
+ //Close the old objects
+ try
+ {
+ sourceConn.close();
+ }
+ catch (Throwable ignore)
+ {
+ if (trace) { log.trace("Failed to close source connection", ignore); }
+ }
+ try
+ {
+ if (targetConn != null)
+ {
+ targetConn.close();
+ }
+ }
+ catch (Throwable ignore)
+ {
+ if (trace) { log.trace("Failed to close target connection", ignore); }
+ }
+ }
+
+ private void pause(long interval)
+ {
+ long start = System.currentTimeMillis();
+ while (System.currentTimeMillis() - start < failureRetryInterval)
+ {
+ try
+ {
+ Thread.sleep(failureRetryInterval);
+ }
+ catch (InterruptedException ex)
+ {
+ }
+ }
+ }
+
+ private boolean setupJMSObjectsWithRetry()
+ {
+ if (trace) { log.trace("Setting up connections"); }
+
+ int count = 0;
+
+ while (true)
+ {
+ boolean ok = setupJMSObjects();
+
+ if (ok)
+ {
+ return true;
+ }
+
+ count++;
+
+ if (maxRetries != -1 && count == maxRetries)
+ {
+ break;
+ }
+
+ log.warn("Failed to set up connections, will retry after a pause of " + failureRetryInterval + " ms");
+
+ pause(failureRetryInterval);
+ }
+
+ //If we get here then we exceed maxRetries
+ return false;
+ }
+
+
+ private void sendBatch()
+ {
+ if (trace) { log.trace("Sending batch of " + messages.size() + " messages"); }
+
+ if (paused)
+ {
+ //Don't send now
+ if (trace) { log.trace("Paused, so not sending now"); }
+
+ return;
+ }
+
+ if (forwardMode == FORWARD_MODE_LOCALTX)
+ {
+ sendBatchLocalTx();
+ }
+ else if (forwardMode == FORWARD_MODE_XA)
+ {
+ sendBatchXA();
+ }
+ else
+ {
+ sendBatchNonTransacted();
+ }
+ }
+
+ private void sendBatchNonTransacted()
+ {
+ try
+ {
+ if (qualityOfServiceMode == QualityOfServiceMode.ONCE_AND_ONLY_ONCE)
+ {
+ //We client ack before sending
+
+ if (trace) { log.trace("Client acking source session"); }
+
+ ((Message)messages.getLast()).acknowledge();
+
+ if (trace) { log.trace("Client acked source session"); }
+ }
+
+ sendMessages();
+
+ if (maxBatchSize > 1)
+ {
+ //The sending session is transacted - we need to commit it
+
+ if (trace) { log.trace("Committing target session"); }
+
+ targetSession.commit();
+
+ if (trace) { log.trace("Committed source session"); }
+ }
+
+ if (qualityOfServiceMode == QualityOfServiceMode.DUPLICATES_OK)
+ {
+ //We client ack after sending
+
+ //Note we could actually use Session.DUPS_OK_ACKNOWLEDGE here
+ //For a slightly less strong delivery guarantee
+
+ if (trace) { log.trace("Client acking source session"); }
+
+ messages.getLast().acknowledge();
+
+ if (trace) { log.trace("Client acked source session"); }
+ }
+
+ //Clear the messages
+ messages.clear();
+ }
+ catch (Exception e)
+ {
+ log.warn("Failed to send + acknowledge batch, closing JMS objects", e);
+
+ handleFailureOnSend();
+ }
+ }
+
+ private void sendBatchXA()
+ {
+ try
+ {
+ sendMessages();
+
+ //Commit the JTA transaction and start another
+
+ delistResources(tx);
+
+ if (trace) { log.trace("Committing JTA transaction"); }
+
+ tx.commit();
+
+ if (trace) { log.trace("Committed JTA transaction"); }
+
+ tx = startTx();
+
+ enlistResources(tx);
+
+ //Clear the messages
+ messages.clear();
+ }
+ catch (Exception e)
+ {
+ log.warn("Failed to send + acknowledge batch, closing JMS objects", e);
+
+ handleFailureOnSend();
+ }
+ }
+
+ private void sendBatchLocalTx()
+ {
+ try
+ {
+ sendMessages();
+
+ if (trace) { log.trace("Committing source session"); }
+
+ sourceSession.commit();
+
+ if (trace) { log.trace("Committed source session"); }
+
+ //Clear the messages
+ messages.clear();
+ }
+ catch (Exception e)
+ {
+ log.warn("Failed to send + acknowledge batch, closing JMS objects", e);
+
+ handleFailureOnSend();
+ }
+ }
+
+ private void sendMessages() throws Exception
+ {
+ Iterator iter = messages.iterator();
+
+ Message msg = null;
+
+ while (iter.hasNext())
+ {
+ msg = (Message)iter.next();
+
+ if (addMessageIDInHeader)
+ {
+ addMessageIDInHeader(msg);
+ }
+
+ if (trace) { log.trace("Sending message " + msg); }
+
+ //Make sure the correct time to live gets propagated
+
+ long timeToLive = msg.getJMSExpiration();
+
+ if (timeToLive != 0)
+ {
+ timeToLive -= System.currentTimeMillis();
+
+ if (timeToLive <= 0)
+ {
+ timeToLive = 1; //Should have already expired - set to 1 so it expires when it is consumed or delivered
+ }
+ }
+
+ targetProducer.send(targetDestination, msg, msg.getJMSDeliveryMode(), msg.getJMSPriority(), timeToLive);
+
+ if (trace) { log.trace("Sent message " + msg); }
+ }
+ }
+
+ private void handleFailureOnSend()
+ {
+ handleFailure(new FailureHandler());
+ }
+
+ private void handleFailureOnStartup()
+ {
+ handleFailure(new StartupFailureHandler());
+ }
+
+ private void handleFailure(Runnable failureHandler)
+ {
+ failed = true;
+
+ //Failure must be handled on a separate thread to the calling thread (either onMessage or start).
+ //In the case of onMessage we can't close the connection from inside the onMessage method
+ //since it will block waiting for onMessage to complete. In the case of start we want to return
+ //from the call before the connections are reestablished so that the caller is not blocked unnecessarily.
+ Thread t = new Thread(failureHandler);
+
+ t.start();
+ }
+
+ private void addMessageIDInHeader(Message msg) throws Exception
+ {
+ //We concatenate the old message id as a header in the message
+ //This allows the target to then use this as the JMSCorrelationID of any response message
+ //thus enabling a distributed request-response pattern.
+ //Each bridge (if there are more than one) in the chain can concatenate the message id
+ //So in the case of multiple bridges having routed the message this can be used in a multi-hop
+ //distributed request/response
+ if (trace) { log.trace("Adding old message id in Message header"); }
+
+ copyProperties(msg);
+
+ String val = null;
+
+ val = msg.getStringProperty(JBossMessage.JBOSS_MESSAGING_BRIDGE_MESSAGE_ID_LIST);
+
+ if (val == null)
+ {
+ val = msg.getJMSMessageID();
+ }
+ else
+ {
+ StringBuffer sb = new StringBuffer(val);
+
+ sb.append(",").append(msg.getJMSMessageID());
+
+ val = sb.toString();
+ }
+
+ msg.setStringProperty(JBossMessage.JBOSS_MESSAGING_BRIDGE_MESSAGE_ID_LIST, val);
+ }
+
+
+ /*
+ * JMS does not let you add a property on received message without first
+ * calling clearProperties, so we need to save and re-add all the old properties so we
+ * don't lose them!!
+ */
+ private static void copyProperties(Message msg) throws JMSException
+ {
+ Enumeration en = msg.getPropertyNames();
+
+ Map<String, Object> oldProps = null;
+
+ while (en.hasMoreElements())
+ {
+ String propName = (String)en.nextElement();
+
+ if (oldProps == null)
+ {
+ oldProps = new HashMap<String, Object>();
+ }
+
+ oldProps.put(propName, msg.getObjectProperty(propName));
+ }
+
+ msg.clearProperties();
+
+ if (oldProps != null)
+ {
+ Iterator oldPropsIter = oldProps.entrySet().iterator();
+
+ while (oldPropsIter.hasNext())
+ {
+ Map.Entry entry = (Map.Entry)oldPropsIter.next();
+
+ String propName = (String)entry.getKey();
+
+ msg.setObjectProperty(propName, entry.getValue());
+ }
+ }
+ }
+
+ // Inner classes ---------------------------------------------------------------
+
+ private class FailureHandler implements Runnable
+ {
+ /**
+ * Start the source connection - note the source connection must not be started before
+ * otherwise messages will be received and ignored
+ */
+ protected void startSourceConnection()
+ {
+ try
+ {
+ sourceConn.start();
+ }
+ catch (JMSException e)
+ {
+ log.error("Failed to start source connection", e);
+ }
+ }
+
+ protected void succeeded()
+ {
+ log.info("Succeeded in reconnecting to servers");
+
+ synchronized (lock)
+ {
+ failed = false;
+
+ startSourceConnection();
+ }
+ }
+
+ protected void failed()
+ {
+ //We haven't managed to recreate connections or maxRetries = 0
+ log.warn("Unable to set up connections, bridge will be stopped");
+
+ try
+ {
+ stop();
+ }
+ catch (Exception ignore)
+ {
+ }
+ }
+
+ public void run()
+ {
+ if (trace) { log.trace("Failure handler running"); }
+
+ // Clear the messages
+ messages.clear();
+
+ cleanup();
+
+ boolean ok = false;
+
+ if (maxRetries > 0 || maxRetries == -1)
+ {
+ log.warn("Will retry after a pause of " + failureRetryInterval + " ms");
+
+ pause(failureRetryInterval);
+
+ //Now we try
+ ok = setupJMSObjectsWithRetry();
+ }
+
+ if (!ok)
+ {
+ failed();
+ }
+ else
+ {
+ succeeded();
+ }
+ }
+ }
+
+ private class StartupFailureHandler extends FailureHandler
+ {
+ protected void failed()
+ {
+ // Don't call super
+ log.warn("Unable to set up connections, bridge will not be started");
+ }
+
+ protected void succeeded()
+ {
+ // Don't call super - a bit ugly in this case but better than taking the lock twice.
+ log.info("Succeeded in connecting to servers");
+
+ synchronized (lock)
+ {
+ failed = false;
+ started = true;
+
+ //Start the source connection - note the source connection must not be started before
+ //otherwise messages will be received and ignored
+
+ try
+ {
+ sourceConn.start();
+ }
+ catch (JMSException e)
+ {
+ log.error("Failed to start source connection", e);
+ }
+ }
+ }
+ }
+
+ private class BatchTimeChecker implements Runnable
+ {
+ public void run()
+ {
+ if (trace) { log.trace(this + " running"); }
+
+ synchronized (lock)
+ {
+ while (started)
+ {
+ long toWait = batchExpiryTime - System.currentTimeMillis();
+
+ if (toWait <= 0)
+ {
+ if (trace) { log.trace(this + " waited enough"); }
+
+ synchronized (lock)
+ {
+ if (!failed && !messages.isEmpty())
+ {
+ if (trace) { log.trace(this + " got some messages so sending batch"); }
+
+ sendBatch();
+
+ if (trace) { log.trace(this + " sent batch"); }
+ }
+ }
+
+ batchExpiryTime = System.currentTimeMillis() + maxBatchTime;
+ }
+ else
+ {
+ try
+ {
+ if (trace) { log.trace(this + " waiting for " + toWait); }
+
+ lock.wait(toWait);
+
+ if (trace) { log.trace(this + " woke up"); }
+ }
+ catch (InterruptedException e)
+ {
+ //Ignore
+ if (trace) { log.trace(this + " thread was interrupted"); }
+ }
+
+ }
+ }
+ }
+ }
+ }
+
+ private class SourceListener implements MessageListener
+ {
+ public void onMessage(Message msg)
+ {
+ synchronized (lock)
+ {
+ if (failed)
+ {
+ //Ignore the message
+ if (trace) { log.trace("JMSBridge has failed so ignoring message"); }
+
+ return;
+ }
+
+ if (trace) { log.trace(this + " received message " + msg); }
+
+ messages.add(msg);
+
+ batchExpiryTime = System.currentTimeMillis() + maxBatchTime;
+
+ if (trace) { log.trace(this + " rescheduled batchExpiryTime to " + batchExpiryTime); }
+
+ if (maxBatchSize != -1 && messages.size() >= maxBatchSize)
+ {
+ if (trace) { log.trace(this + " maxBatchSize has been reached so sending batch"); }
+
+ sendBatch();
+
+ if (trace) { log.trace(this + " sent batch"); }
+ }
+ }
+ }
+ }
+
+ private class BridgeExceptionListener implements ExceptionListener
+ {
+ public void onException(JMSException e)
+ {
+ log.warn("Detected failure on bridge connection");
+
+ synchronized (lock)
+ {
+ if (failed)
+ {
+ //The failure has already been detected and is being handled
+ if (trace) { log.trace("Failure recovery already in progress"); }
+ }
+ else
+ {
+ handleFailure(new FailureHandler());
+ }
+ }
+ }
+ }
+}
Modified: trunk/tests/src/org/jboss/messaging/tests/integration/cluster/bridge/BridgeStartTest.java
===================================================================
--- trunk/tests/src/org/jboss/messaging/tests/integration/cluster/bridge/BridgeStartTest.java 2009-04-03 14:08:30 UTC (rev 6298)
+++ trunk/tests/src/org/jboss/messaging/tests/integration/cluster/bridge/BridgeStartTest.java 2009-04-03 14:12:53 UTC (rev 6299)
@@ -460,7 +460,7 @@
// Wait a bit
Thread.sleep(1000);
- // Bridge should be stopped since retries = 0
+ // JMSBridge should be stopped since retries = 0
server1.start();
Modified: trunk/tests/src/org/jboss/messaging/tests/integration/cluster/bridge/BridgeTest.java
===================================================================
--- trunk/tests/src/org/jboss/messaging/tests/integration/cluster/bridge/BridgeTest.java 2009-04-03 14:08:30 UTC (rev 6298)
+++ trunk/tests/src/org/jboss/messaging/tests/integration/cluster/bridge/BridgeTest.java 2009-04-03 14:12:53 UTC (rev 6299)
@@ -45,7 +45,7 @@
import org.jboss.messaging.utils.SimpleString;
/**
- * A BridgeTest
+ * A JMSBridgeTest
*
* @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
*
Deleted: trunk/tests/src/org/jboss/messaging/tests/integration/jms/bridge/BridgeReconnectionTest.java
===================================================================
--- trunk/tests/src/org/jboss/messaging/tests/integration/jms/bridge/BridgeReconnectionTest.java 2009-04-03 14:08:30 UTC (rev 6298)
+++ trunk/tests/src/org/jboss/messaging/tests/integration/jms/bridge/BridgeReconnectionTest.java 2009-04-03 14:12:53 UTC (rev 6299)
@@ -1,302 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.messaging.tests.integration.jms.bridge;
-
-import org.jboss.messaging.core.logging.Logger;
-import org.jboss.messaging.jms.bridge.QualityOfServiceMode;
-import org.jboss.messaging.jms.bridge.impl.BridgeImpl;
-import org.jboss.messaging.jms.server.impl.JMSServerManagerImpl;
-import org.jboss.messaging.tests.unit.util.InVMContext;
-
-/**
- * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
- * @version <tt>$Revision: 1.1 $</tt>
- *
- * $Id$
- *
- */
-public class BridgeReconnectionTest extends BridgeTestBase
-{
- private static final Logger log = Logger.getLogger(BridgeReconnectionTest.class);
-
- // Crash and reconnect
-
- // Once and only once
-
- public void testCrashAndReconnectDestBasic_OnceAndOnlyOnce_P() throws Exception
- {
- testCrashAndReconnectDestBasic(QualityOfServiceMode.ONCE_AND_ONLY_ONCE, true);
- }
-
- public void testCrashAndReconnectDestBasic_OnceAndOnlyOnce_NP() throws Exception
- {
- testCrashAndReconnectDestBasic(QualityOfServiceMode.ONCE_AND_ONLY_ONCE, false);
- }
-
- // dups ok
-
- public void testCrashAndReconnectDestBasic_DuplicatesOk_P() throws Exception
- {
- testCrashAndReconnectDestBasic(QualityOfServiceMode.DUPLICATES_OK, true);
- }
-
- public void testCrashAndReconnectDestBasic_DuplicatesOk_NP() throws Exception
- {
- testCrashAndReconnectDestBasic(QualityOfServiceMode.DUPLICATES_OK, false);
- }
-
- // At most once
-
- public void testCrashAndReconnectDestBasic_AtMostOnce_P() throws Exception
- {
- testCrashAndReconnectDestBasic(QualityOfServiceMode.AT_MOST_ONCE, true);
- }
-
- public void testCrashAndReconnectDestBasic_AtMostOnce_NP() throws Exception
- {
- testCrashAndReconnectDestBasic(QualityOfServiceMode.AT_MOST_ONCE, false);
- }
-
- // Crash tests specific to XA transactions
-
- public void testCrashAndReconnectDestCrashBeforePrepare_P() throws Exception
- {
- testCrashAndReconnectDestCrashBeforePrepare(true);
- }
-
- public void testCrashAndReconnectDestCrashBeforePrepare_NP() throws Exception
- {
- testCrashAndReconnectDestCrashBeforePrepare(false);
- }
-
- // Crash before bridge is started
-
- public void testRetryConnectionOnStartup() throws Exception
- {
- server1.stop();
-
- BridgeImpl bridge = new BridgeImpl(cff0, cff1, sourceQueueFactory, targetQueueFactory,
- null, null, null, null,
- null, 1000, -1, QualityOfServiceMode.DUPLICATES_OK,
- 10, -1,
- null, null, false);
- bridge.setTransactionManager(newTransactionManager());
-
- try
- {
- bridge.start();
- assertFalse(bridge.isStarted());
- assertTrue(bridge.isFailed());
-
- //Restart the server
- server1.start();
-
- context1 = new InVMContext();
- jmsServer1 = JMSServerManagerImpl.newJMSServerManagerImpl(server1);
- jmsServer1.start();
- jmsServer1.setContext(context1);
-
- createQueue("targetQueue", 1);
- setUpAdministeredObjects();
-
- Thread.sleep(3000);
-
- assertTrue(bridge.isStarted());
- assertFalse(bridge.isFailed());
- }
- finally
- {
- try
- {
- bridge.stop();
- }
- catch (Exception e)
- {
- log.error("Failed to stop bridge", e);
- }
- }
- }
-
- /*
- * Send some messages
- * Crash the destination server
- * Bring the destination server back up
- * Send some more messages
- * Verify all messages are received
- */
- private void testCrashAndReconnectDestBasic(QualityOfServiceMode qosMode, boolean persistent) throws Exception
- {
- BridgeImpl bridge = null;
-
- try
- {
- bridge = new BridgeImpl(cff0, cff1, sourceQueueFactory, targetQueueFactory,
- null, null, null, null,
- null, 1000, -1, qosMode,
- 10, -1,
- null, null, false);
- bridge.setTransactionManager(newTransactionManager());
- bridge.start();
-
- final int NUM_MESSAGES = 10;
-
- //Send some messages
-
- sendMessages(cf0, sourceQueue, 0, NUM_MESSAGES / 2 , persistent);
-
- //Verify none are received
-
- checkEmpty(targetQueue, 1);
-
- //Now crash the dest server
-
- log.info("About to crash server");
-
- server1.stop();
-
- //Wait a while before starting up to simulate the dest being down for a while
- log.info("Waiting 5 secs before bringing server back up");
- Thread.sleep(10000);
- log.info("Done wait");
-
- //Restart the server
-
- log.info("Restarting server");
-
- server1.start();
-
- context1 = new InVMContext();
- jmsServer1 = JMSServerManagerImpl.newJMSServerManagerImpl(server1);
- jmsServer1.start();
- jmsServer1.setContext(context1);
-
- createQueue("targetQueue", 1);
-
- setUpAdministeredObjects();
-
- //Send some more messages
-
- log.info("Sending more messages");
-
- sendMessages(cf0, sourceQueue, NUM_MESSAGES / 2, NUM_MESSAGES / 2, persistent);
-
- log.info("Sent messages");
-
- checkMessagesReceived(cf1, targetQueue, qosMode, NUM_MESSAGES, false);
- }
- finally
- {
-
- if (bridge != null)
- {
- try
- {
- bridge.stop();
- }
- catch (Exception e)
- {
- log.error("Failed to stop bridge", e);
- }
- }
- }
- }
-
- /*
- * Send some messages
- * Crash the destination server
- * Set the max batch time such that it will attempt to send the batch while the dest server is down
- * Bring up the destination server
- * Send some more messages
- * Verify all messages are received
- */
- private void testCrashAndReconnectDestCrashBeforePrepare(boolean persistent) throws Exception
- {
- BridgeImpl bridge = null;
-
- try
- {
- bridge = new BridgeImpl(cff0, cff1, sourceQueueFactory, targetQueueFactory,
- null, null, null, null,
- null, 1000, -1, QualityOfServiceMode.ONCE_AND_ONLY_ONCE,
- 10, 5000,
- null, null, false);
- bridge.setTransactionManager(newTransactionManager());
-
- bridge.start();
-
- final int NUM_MESSAGES = 10;
- //Send some messages
-
- this.sendMessages(cf0, sourceQueue, 0, NUM_MESSAGES / 2, persistent);
-
- //verify none are received
-
- checkEmpty(targetQueue, 1);
-
- //Now crash the dest server
-
- log.info("About to crash server");
-
- server1.stop();
-
- //Wait a while before starting up to simulate the dest being down for a while
- log.info("Waiting 5 secs before bringing server back up");
- Thread.sleep(10000);
- log.info("Done wait");
-
- //Restart the server
- server1.start();
-
- context1 = new InVMContext();
- jmsServer1 = JMSServerManagerImpl.newJMSServerManagerImpl(server1);
- jmsServer1.start();
- jmsServer1.setContext(context1);
-
- createQueue("targetQueue", 1);
-
- setUpAdministeredObjects();
-
- sendMessages(cf0, sourceQueue, NUM_MESSAGES / 2, NUM_MESSAGES / 2, persistent);
-
- checkMessagesReceived(cf1, targetQueue, QualityOfServiceMode.ONCE_AND_ONLY_ONCE, NUM_MESSAGES, false);
- }
- finally
- {
-
- if (bridge != null)
- {
- try
- {
- bridge.stop();
- }
- catch (Exception e)
- {
- log.error("Failed to stop bridge", e);
- }
- }
-
- }
- }
-
- // Inner classes -------------------------------------------------------------------
-
-}
Deleted: trunk/tests/src/org/jboss/messaging/tests/integration/jms/bridge/BridgeTest.java
===================================================================
--- trunk/tests/src/org/jboss/messaging/tests/integration/jms/bridge/BridgeTest.java 2009-04-03 14:08:30 UTC (rev 6298)
+++ trunk/tests/src/org/jboss/messaging/tests/integration/jms/bridge/BridgeTest.java 2009-04-03 14:12:53 UTC (rev 6299)
@@ -1,1590 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.messaging.tests.integration.jms.bridge;
-
-import org.jboss.messaging.core.logging.Logger;
-import org.jboss.messaging.jms.bridge.QualityOfServiceMode;
-import org.jboss.messaging.jms.bridge.impl.BridgeImpl;
-import org.jboss.messaging.jms.client.JBossMessage;
-
-import javax.jms.Connection;
-import javax.jms.DeliveryMode;
-import javax.jms.Message;
-import javax.jms.MessageConsumer;
-import javax.jms.MessageProducer;
-import javax.jms.Session;
-import javax.jms.TextMessage;
-import javax.transaction.Transaction;
-import javax.transaction.TransactionManager;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-/**
- * A BridgeTest
- *
- * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
- * @version <tt>$Revision$</tt>
- *
- * $Id$
- *
- */
-public class BridgeTest extends BridgeTestBase
-{
- private static final Logger log = Logger.getLogger(BridgeTest.class);
-
- // MaxBatchSize but no MaxBatchTime
-
- public void testNoMaxBatchTime_AtMostOnce_P() throws Exception
- {
- testNoMaxBatchTime(QualityOfServiceMode.AT_MOST_ONCE, true);
- }
-
- public void testNoMaxBatchTime_DuplicatesOk_P() throws Exception
- {
- testNoMaxBatchTime(QualityOfServiceMode.DUPLICATES_OK, true);
- }
-
- public void testNoMaxBatchTime_OnceAndOnlyOnce_P() throws Exception
- {
- testNoMaxBatchTime(QualityOfServiceMode.ONCE_AND_ONLY_ONCE, true);
- }
-
- public void testNoMaxBatchTime_AtMostOnce_NP() throws Exception
- {
- testNoMaxBatchTime(QualityOfServiceMode.AT_MOST_ONCE, false);
- }
-
- public void testNoMaxBatchTime_DuplicatesOk_NP() throws Exception
- {
- testNoMaxBatchTime(QualityOfServiceMode.DUPLICATES_OK, false);
- }
-
- public void testNoMaxBatchTime_OnceAndOnlyOnce_NP() throws Exception
- {
- testNoMaxBatchTime(QualityOfServiceMode.ONCE_AND_ONLY_ONCE, false);
- }
-
- //Same server
-
- // MaxBatchSize but no MaxBatchTime
-
- public void testNoMaxBatchTimeSameServer_AtMostOnce_P() throws Exception
- {
- testNoMaxBatchTimeSameServer(QualityOfServiceMode.AT_MOST_ONCE, true);
- }
-
- public void testNoMaxBatchTimeSameServer_DuplicatesOk_P() throws Exception
- {
- testNoMaxBatchTimeSameServer(QualityOfServiceMode.DUPLICATES_OK, true);
- }
-
- public void testNoMaxBatchTimeSameServer_OnceAndOnlyOnce_P() throws Exception
- {
- testNoMaxBatchTimeSameServer(QualityOfServiceMode.ONCE_AND_ONLY_ONCE, true);
- }
-
- public void testNoMaxBatchTimeSameServer_AtMostOnce_NP() throws Exception
- {
- testNoMaxBatchTimeSameServer(QualityOfServiceMode.AT_MOST_ONCE, false);
- }
-
- public void testNoMaxBatchTimeSameServer_DuplicatesOk_NP() throws Exception
- {
- testNoMaxBatchTimeSameServer(QualityOfServiceMode.DUPLICATES_OK, false);
- }
-
- public void testNoMaxBatchTimeSameServer_OnceAndOnlyOnce_NP() throws Exception
- {
- testNoMaxBatchTimeSameServer(QualityOfServiceMode.ONCE_AND_ONLY_ONCE, false);
- }
-
-
- // MaxBatchTime but no MaxBatchSize
-
- public void testMaxBatchTime_AtMostOnce_P() throws Exception
- {
- this.testMaxBatchTime(QualityOfServiceMode.AT_MOST_ONCE, true);
- }
-
- public void testMaxBatchTime_DuplicatesOk_P() throws Exception
- {
- this.testMaxBatchTime(QualityOfServiceMode.DUPLICATES_OK, true);
- }
-
- public void testMaxBatchTime_OnceAndOnlyOnce_P() throws Exception
- {
- testMaxBatchTime(QualityOfServiceMode.ONCE_AND_ONLY_ONCE, true);
- }
-
- public void testMaxBatchTime_AtMostOnce_NP() throws Exception
- {
- this.testMaxBatchTime(QualityOfServiceMode.AT_MOST_ONCE, false);
- }
-
- public void testMaxBatchTime_DuplicatesOk_NP() throws Exception
- {
- this.testMaxBatchTime(QualityOfServiceMode.DUPLICATES_OK, false);
- }
-
- public void testMaxBatchTime_OnceAndOnlyOnce_NP() throws Exception
- {
- testMaxBatchTime(QualityOfServiceMode.ONCE_AND_ONLY_ONCE, false);
- }
-
- // Same server
-
- // MaxBatchTime but no MaxBatchSize
-
- public void testMaxBatchTimeSameServer_AtMostOnce_P() throws Exception
- {
- this.testMaxBatchTimeSameServer(QualityOfServiceMode.AT_MOST_ONCE, true);
- }
-
- public void testMaxBatchTimeSameServer_DuplicatesOk_P() throws Exception
- {
- this.testMaxBatchTimeSameServer(QualityOfServiceMode.DUPLICATES_OK, true);
- }
-
- public void testMaxBatchTimeSameServer_OnceAndOnlyOnce_P() throws Exception
- {
- testMaxBatchTimeSameServer(QualityOfServiceMode.ONCE_AND_ONLY_ONCE, true);
- }
-
- public void testMaxBatchTimeSameServer_AtMostOnce_NP() throws Exception
- {
- this.testMaxBatchTimeSameServer(QualityOfServiceMode.AT_MOST_ONCE, false);
- }
-
- public void testMaxBatchTimeSameServer_DuplicatesOk_NP() throws Exception
- {
- this.testMaxBatchTimeSameServer(QualityOfServiceMode.DUPLICATES_OK, false);
- }
-
- public void testMaxBatchTimeSameServer_OnceAndOnlyOnce_NP() throws Exception
- {
- testMaxBatchTimeSameServer(QualityOfServiceMode.ONCE_AND_ONLY_ONCE, false);
- }
-
- // Stress with batch size of 50
-
- public void testStress_AtMostOnce_P_50() throws Exception
- {
- testStress(QualityOfServiceMode.AT_MOST_ONCE, true, 50);
- }
-
- public void testStress_DuplicatesOk_P_50() throws Exception
- {
- testStress(QualityOfServiceMode.DUPLICATES_OK, true, 50);
- }
-
- public void testStress_OnceAndOnlyOnce_P_50() throws Exception
- {
- testStress(QualityOfServiceMode.ONCE_AND_ONLY_ONCE, true, 50);
- }
-
- public void testStress_AtMostOnce_NP_50() throws Exception
- {
- testStress(QualityOfServiceMode.AT_MOST_ONCE, false, 50);
- }
-
- public void testStress_DuplicatesOk_NP_50() throws Exception
- {
- testStress(QualityOfServiceMode.DUPLICATES_OK, false, 50);
- }
-
- public void testStress_OnceAndOnlyOnce_NP_50() throws Exception
- {
- testStress(QualityOfServiceMode.ONCE_AND_ONLY_ONCE, false, 50);
- }
-
- // Stress with batch size of 1
-
- public void testStress_AtMostOnce_P_1() throws Exception
- {
- testStress(QualityOfServiceMode.AT_MOST_ONCE, true, 1);
- }
-
- public void testStress_DuplicatesOk_P_1() throws Exception
- {
- testStress(QualityOfServiceMode.DUPLICATES_OK, true, 1);
- }
-
- public void testStress_OnceAndOnlyOnce_P_1() throws Exception
- {
- testStress(QualityOfServiceMode.ONCE_AND_ONLY_ONCE, true, 1);
- }
-
- public void testStress_AtMostOnce_NP_1() throws Exception
- {
- testStress(QualityOfServiceMode.AT_MOST_ONCE, false, 1);
- }
-
- public void testStress_DuplicatesOk_NP_1() throws Exception
- {
- testStress(QualityOfServiceMode.DUPLICATES_OK, false, 1);
- }
-
- public void testStress_OnceAndOnlyOnce_NP_1() throws Exception
- {
- testStress(QualityOfServiceMode.ONCE_AND_ONLY_ONCE, false, 1);
- }
-
- // Max batch time
-
- public void testStressMaxBatchTime_OnceAndOnlyOnce_NP() throws Exception
- {
- this.testStressBatchTime(QualityOfServiceMode.ONCE_AND_ONLY_ONCE, false, 200);
- }
-
- public void testStressMaxBatchTime_OnceAndOnlyOnce_P() throws Exception
- {
- this.testStressBatchTime(QualityOfServiceMode.ONCE_AND_ONLY_ONCE, true, 200);
- }
-
-
- // Stress on same server
-
- // Stress with batch size of 50
-
- public void testStressSameServer_AtMostOnce_P_50() throws Exception
- {
- testStressSameServer(QualityOfServiceMode.AT_MOST_ONCE, true, 50);
- }
-
- public void testStressSameServer_DuplicatesOk_P_50() throws Exception
- {
- testStressSameServer(QualityOfServiceMode.DUPLICATES_OK, true, 50);
- }
-
- public void testStressSameServer_OnceAndOnlyOnce_P_50() throws Exception
- {
- testStress(QualityOfServiceMode.ONCE_AND_ONLY_ONCE, true, 50);
- }
-
- public void testStressSameServer_AtMostOnce_NP_50() throws Exception
- {
- testStressSameServer(QualityOfServiceMode.AT_MOST_ONCE, false, 50);
- }
-
- public void testStressSameServer_DuplicatesOk_NP_50() throws Exception
- {
- testStressSameServer(QualityOfServiceMode.DUPLICATES_OK, false, 50);
- }
-
- public void testStressSameServer_OnceAndOnlyOnce_NP_50() throws Exception
- {
- testStressSameServer(QualityOfServiceMode.ONCE_AND_ONLY_ONCE, false, 50);
- }
-
- // Stress with batch size of 1
-
- public void testStressSameServer_AtMostOnce_P_1() throws Exception
- {
- testStressSameServer(QualityOfServiceMode.AT_MOST_ONCE, true, 1);
- }
-
- public void testStressSameServer_DuplicatesOk_P_1() throws Exception
- {
- testStressSameServer(QualityOfServiceMode.DUPLICATES_OK, true, 1);
- }
-
- public void testStressSameServer_OnceAndOnlyOnce_P_1() throws Exception
- {
- testStressSameServer(QualityOfServiceMode.ONCE_AND_ONLY_ONCE, true, 1);
- }
-
- public void testStressSameServer_AtMostOnce_NP_1() throws Exception
- {
- testStressSameServer(QualityOfServiceMode.AT_MOST_ONCE, false, 1);
- }
-
- public void testStressSameServer_DuplicatesOk_NP_1() throws Exception
- {
- testStressSameServer(QualityOfServiceMode.DUPLICATES_OK, false, 1);
- }
-
- public void testStressSameServer_OnceAndOnlyOnce_NP_1() throws Exception
- {
- testStressSameServer(QualityOfServiceMode.ONCE_AND_ONLY_ONCE, false, 1);
- }
-
- public void testParams() throws Exception
- {
- BridgeImpl bridge = null;
-
- try
- {
- QualityOfServiceMode qosMode = QualityOfServiceMode.AT_MOST_ONCE;
-
- int batchSize = 10;
-
- int maxBatchTime = -1;
-
- String sourceUsername = null;
-
- String sourcePassword = null;
-
- String destUsername = null;
-
- String destPassword = null;
-
- String selector = null;
-
- long failureRetryInterval = 5000;
-
- int maxRetries = 10;
-
- String subName = null;
-
- String clientID = null;
-
- try
- {
- bridge= new BridgeImpl(null, cff1, sourceQueueFactory, targetQueueFactory,
- sourceUsername, sourcePassword, destUsername, destPassword,
- selector, failureRetryInterval, maxRetries, qosMode,
- batchSize, maxBatchTime,
- subName, clientID, false);
- }
- catch (IllegalArgumentException e)
- {
- //Ok
- }
-
- try
- {
- bridge= new BridgeImpl(cff0, null, sourceQueueFactory, targetQueueFactory,
- sourceUsername, sourcePassword, destUsername, destPassword,
- selector, failureRetryInterval, maxRetries, qosMode,
- batchSize, maxBatchTime,
- subName, clientID, false);
- }
- catch (IllegalArgumentException e)
- {
- //Ok
- }
-
- try
- {
- bridge= new BridgeImpl(cff0, cff1, null, targetQueueFactory,
- sourceUsername, sourcePassword, destUsername, destPassword,
- selector, failureRetryInterval, maxRetries, qosMode,
- batchSize, maxBatchTime,
- subName, clientID, false);
- }
- catch (IllegalArgumentException e)
- {
- //Ok
- }
-
- try
- {
- bridge= new BridgeImpl(cff0, cff1, sourceQueueFactory, null,
- sourceUsername, sourcePassword, destUsername, destPassword,
- selector, failureRetryInterval, maxRetries, qosMode,
- batchSize, maxBatchTime,
- subName, clientID, false);
- }
- catch (IllegalArgumentException e)
- {
- //Ok
- }
-
- try
- {
- bridge= new BridgeImpl(cff0, cff1, sourceQueueFactory, targetQueueFactory,
- sourceUsername, sourcePassword, destUsername, destPassword,
- selector, -2, maxRetries, qosMode,
- batchSize, maxBatchTime,
- subName, clientID, false);
- }
- catch (IllegalArgumentException e)
- {
- //Ok
- }
-
- try
- {
- bridge= new BridgeImpl(cff0, cff1, sourceQueueFactory, targetQueueFactory,
- sourceUsername, sourcePassword, destUsername, destPassword,
- selector, -1, 10, qosMode,
- batchSize, maxBatchTime,
- subName, clientID, false);
- }
- catch (IllegalArgumentException e)
- {
- //Ok
- }
-
- try
- {
- bridge= new BridgeImpl(cff0, cff1, sourceQueueFactory, null,
- sourceUsername, sourcePassword, destUsername, destPassword,
- selector, failureRetryInterval, maxRetries, qosMode,
- 0, maxBatchTime,
- subName, clientID, false);
- }
- catch (IllegalArgumentException e)
- {
- //Ok
- }
-
- try
- {
- bridge= new BridgeImpl(cff0, cff1, sourceQueueFactory, null,
- sourceUsername, sourcePassword, destUsername, destPassword,
- selector, failureRetryInterval, maxRetries, qosMode,
- batchSize, -2,
- subName, clientID, false);
- }
- catch (IllegalArgumentException e)
- {
- //Ok
- }
- }
- finally
- {
- if (bridge != null)
- {
- bridge.stop();
- }
- }
- }
-
- public void testSelector() throws Exception
- {
- BridgeImpl bridge = null;
-
- Connection connSource = null;
-
- Connection connTarget = null;
-
- try
- {
- final int NUM_MESSAGES = 10;
-
- String selector = "vegetable='radish'";
-
- bridge = new BridgeImpl(cff0, cff1, sourceQueueFactory, targetQueueFactory,
- null, null, null, null,
- selector, 5000, 10, QualityOfServiceMode.AT_MOST_ONCE,
- 1, -1,
- null, null, false);
- bridge.setTransactionManager(newTransactionManager());
-
- bridge.start();
-
- connSource = cf0.createConnection();
-
- Session sessSend = connSource.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- MessageProducer prod = sessSend.createProducer(sourceQueue);
-
- for (int i = 0; i < NUM_MESSAGES; i++)
- {
- TextMessage tm = sessSend.createTextMessage("message" + i);
-
- if (i >= NUM_MESSAGES / 2)
- {
- tm.setStringProperty("vegetable", "radish");
- }
- else
- {
- tm.setStringProperty("vegetable", "cauliflower");
- }
-
- prod.send(tm);
- }
-
- connTarget = cf1.createConnection();
-
- Session sessRec = connTarget.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- MessageConsumer cons = sessRec.createConsumer(targetQueue);
-
- connTarget.start();
-
- for (int i = NUM_MESSAGES / 2 ; i < NUM_MESSAGES; i++)
- {
- TextMessage tm = (TextMessage)cons.receive(1000);
-
- assertNotNull(tm);
-
- assertEquals("message" + i, tm.getText());
- }
-
- Message m = cons.receive(1000);
-
- assertNull(m);
-
- }
- finally
- {
- if (connSource != null)
- {
- connSource.close();
- }
-
- if (connTarget != null)
- {
- connTarget.close();
- }
-
- if (bridge != null)
- {
- bridge.stop();
- }
-
- removeAllMessages(sourceQueue.getQueueName(), 0);
- }
- }
-
- public void testStartBridgeWithJTATransactionAlreadyRunning() throws Exception
- {
- BridgeImpl bridge = null;
-
- Transaction toResume = null;
-
- Transaction started = null;
-
- TransactionManager mgr = newTransactionManager();
-
- try
- {
-
- toResume = mgr.suspend();
-
- mgr.begin();
-
- started = mgr.getTransaction();
-
- final int NUM_MESSAGES = 10;
-
- bridge = new BridgeImpl(cff0, cff1, sourceTopicFactory, targetQueueFactory,
- null, null, null, null,
- null, 5000, 10, QualityOfServiceMode.AT_MOST_ONCE,
- 1, -1,
- null, null, false);
- bridge.setTransactionManager(mgr);
- bridge.start();
-
- this.sendMessages(cf0, sourceTopic, 0, NUM_MESSAGES, false);
-
- this.checkAllMessageReceivedInOrder(cf1, targetQueue, 0, NUM_MESSAGES);
- }
- finally
- {
- if (started != null)
- {
- try
- {
- started.rollback();
- }
- catch (Exception e)
- {
- log.error("Failed to rollback", e);
- }
- }
-
- if (toResume != null)
- {
- try
- {
- mgr.resume(toResume);
- }
- catch (Exception e)
- {
- log.error("Failed to resume", e);
- }
- }
- if (bridge != null)
- {
- bridge.stop();
- }
- }
- }
-
- public void testNonDurableSubscriber() throws Exception
- {
- BridgeImpl bridge = null;
-
- try
- {
- final int NUM_MESSAGES = 10;
-
- bridge = new BridgeImpl(cff0, cff1, sourceTopicFactory, targetQueueFactory,
- null, null, null, null,
- null, 5000, 10, QualityOfServiceMode.AT_MOST_ONCE,
- 1, -1,
- null, null, false);
- bridge.setTransactionManager(newTransactionManager());
-
- bridge.start();
-
- sendMessages(cf0, sourceTopic, 0, NUM_MESSAGES, false);
-
- checkAllMessageReceivedInOrder(cf1, targetQueue, 0, NUM_MESSAGES);
- }
- finally
- {
- if (bridge != null)
- {
- bridge.stop();
- }
- }
- }
-
- public void testDurableSubscriber() throws Exception
- {
- BridgeImpl bridge = null;
-
- try
- {
- final int NUM_MESSAGES = 10;
-
- bridge = new BridgeImpl(cff0, cff1, sourceTopicFactory, targetQueueFactory,
- null, null, null, null,
- null, 5000, 10, QualityOfServiceMode.AT_MOST_ONCE,
- 1, -1,
- "subTest", "clientid123", false);
- bridge.setTransactionManager(newTransactionManager());
-
- bridge.start();
-
- sendMessages(cf0, sourceTopic, 0, NUM_MESSAGES, true);
-
- checkAllMessageReceivedInOrder(cf1, targetQueue, 0, NUM_MESSAGES);
- }
- finally
- {
- if (bridge != null)
- {
- bridge.stop();
- }
-
- //Now unsubscribe
- Connection conn = cf0.createConnection();
- conn.setClientID("clientid123");
- Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
- sess.unsubscribe("subTest");
- conn.close();
- }
- }
-
- public void testMessageIDInHeaderOn() throws Exception
- {
- messageIDInHeader(true);
- }
-
- public void testMessageIDInHeaderOff() throws Exception
- {
- messageIDInHeader(false);
- }
-
- private void messageIDInHeader(boolean on) throws Exception
- {
- BridgeImpl bridge = null;
-
- Connection connSource = null;
-
- Connection connTarget = null;
-
- try
- {
- final int NUM_MESSAGES = 10;
-
- bridge = new BridgeImpl(cff0, cff1, sourceQueueFactory, targetQueueFactory,
- null, null, null, null,
- null, 5000, 10, QualityOfServiceMode.AT_MOST_ONCE,
- 1, -1,
- null, null, on);
- bridge.setTransactionManager(newTransactionManager());
-
- bridge.start();
-
- connSource = cf0.createConnection();
-
- connTarget = cf1.createConnection();
-
- log.trace("Sending " + NUM_MESSAGES + " messages");
-
- List ids1 = new ArrayList();
-
- Session sessSource = connSource.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- MessageProducer prod = sessSource.createProducer(sourceQueue);
-
- for (int i = 0; i < NUM_MESSAGES; i++)
- {
- TextMessage tm = sessSource.createTextMessage("message" + i);
-
- //We add some headers to make sure they get passed through ok
- tm.setStringProperty("wib", "uhuh");
- tm.setBooleanProperty("cheese", true);
- tm.setIntProperty("Sausages", 23);
-
- //We add some JMSX ones too
-
- tm.setStringProperty("JMSXGroupID", "mygroup543");
- tm.setIntProperty("JMSXGroupSeq", 777);
-
- prod.send(tm);
-
- ids1.add(tm.getJMSMessageID());
- }
-
- log.trace("Sent the first messages");
-
- Session sessTarget = connTarget.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- MessageConsumer cons = sessTarget.createConsumer(targetQueue);
-
- connTarget.start();
-
- List msgs = new ArrayList();
-
- for (int i = 0; i < NUM_MESSAGES; i++)
- {
- TextMessage tm = (TextMessage)cons.receive(5000);
-
- assertNotNull(tm);
-
- assertEquals("message" + i, tm.getText());
-
- assertEquals("uhuh", tm.getStringProperty("wib"));
- assertTrue(tm.getBooleanProperty("cheese"));
- assertEquals(23, tm.getIntProperty("Sausages"));
-
- assertEquals("mygroup543", tm.getStringProperty("JMSXGroupID"));
- assertEquals(777, tm.getIntProperty("JMSXGroupSeq"));
-
- if (on)
- {
- String header = tm.getStringProperty(JBossMessage.JBOSS_MESSAGING_BRIDGE_MESSAGE_ID_LIST);
-
- assertNotNull(header);
-
- assertEquals(ids1.get(i), header);
-
- msgs.add(tm);
- }
- }
-
- if (on)
- {
- //Now we send them again back to the source
-
- Iterator iter = msgs.iterator();
-
- List ids2 = new ArrayList();
-
- while (iter.hasNext())
- {
- Message msg = (Message)iter.next();
-
- prod.send(msg);
-
- ids2.add(msg.getJMSMessageID());
- }
-
- //And consume them again
-
- for (int i = 0; i < NUM_MESSAGES; i++)
- {
- TextMessage tm = (TextMessage)cons.receive(5000);
-
- assertNotNull(tm);
-
- assertEquals("message" + i, tm.getText());
-
- assertEquals("uhuh", tm.getStringProperty("wib"));
- assertTrue(tm.getBooleanProperty("cheese"));
- assertEquals(23, tm.getIntProperty("Sausages"));
-
- assertEquals("mygroup543", tm.getStringProperty("JMSXGroupID"));
- assertEquals(777, tm.getIntProperty("JMSXGroupSeq"));
-
- String header = tm.getStringProperty(JBossMessage.JBOSS_MESSAGING_BRIDGE_MESSAGE_ID_LIST);
-
- assertNotNull(header);
-
- assertEquals(ids1.get(i) + "," + ids2.get(i), header);
- }
- }
-
- }
- finally
- {
- if (bridge != null)
- {
- bridge.stop();
- }
-
- if (connSource != null)
- {
- connSource.close();
- }
-
- if (connTarget != null)
- {
- connTarget.close();
- }
- }
- }
-
-
- public void testPropertiesPreservedPOn() throws Exception
- {
- propertiesPreserved(true, true);
- }
-
- public void testPropertiesPreservedNPoff() throws Exception
- {
- propertiesPreserved(false, true);
- }
-
- public void testPropertiesPreservedNPOn() throws Exception
- {
- propertiesPreserved(false, true);
- }
-
- public void testPropertiesPreservedPoff() throws Exception
- {
- propertiesPreserved(true, true);
- }
-
- private void propertiesPreserved(boolean persistent, boolean messageIDInHeader) throws Exception
- {
- BridgeImpl bridge = null;
-
- Connection connSource = null;
-
- Connection connTarget = null;
-
- try
- {
- final int NUM_MESSAGES = 10;
-
- bridge = new BridgeImpl(cff0, cff1, sourceQueueFactory, targetQueueFactory,
- null, null, null, null,
- null, 5000, 10, QualityOfServiceMode.AT_MOST_ONCE,
- 1, -1,
- null, null, messageIDInHeader);
- bridge.setTransactionManager(newTransactionManager());
-
- bridge.start();
-
- connSource = cf0.createConnection();
-
- connTarget = cf1.createConnection();
-
- log.trace("Sending " + NUM_MESSAGES + " messages");
-
- Session sessSource = connSource.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- Session sessTarget = connTarget.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- MessageConsumer cons = sessTarget.createConsumer(targetQueue);
-
- connTarget.start();
-
- MessageProducer prod = sessSource.createProducer(sourceQueue);
-
- prod.setDeliveryMode(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT);
-
-
-
- TextMessage tm = sessSource.createTextMessage("blahmessage");
-
- prod.setPriority(7);
-
- prod.setTimeToLive(1 * 60 * 60 * 1000);
-
- prod.send(tm);
-
- long expiration = tm.getJMSExpiration();
-
- assertEquals(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT, tm.getJMSDeliveryMode());
-
- tm = (TextMessage)cons.receive(1000);
-
- assertNotNull(tm);
-
- assertEquals("blahmessage", tm.getText());
-
- assertEquals(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT, tm.getJMSDeliveryMode());
-
- assertEquals(7, tm.getJMSPriority());
-
- assertTrue(Math.abs(expiration - tm.getJMSExpiration()) < 100);
-
- Message m = cons.receive(5000);
-
- assertNull(m);
-
-
- //Now do one with expiration = 0
-
-
- tm = sessSource.createTextMessage("blahmessage2");
-
- prod.setPriority(7);
-
- prod.setTimeToLive(0);
-
- prod.send(tm);
-
- assertEquals(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT, tm.getJMSDeliveryMode());
-
- tm = (TextMessage)cons.receive(1000);
-
- assertNotNull(tm);
-
- assertEquals("blahmessage2", tm.getText());
-
- assertEquals(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT, tm.getJMSDeliveryMode());
-
- assertEquals(7, tm.getJMSPriority());
-
- assertEquals(0, tm.getJMSExpiration());
-
- m = cons.receive(5000);
-
- assertNull(m);
-
- tm = sessSource.createTextMessage("blahmessage3");
-
- final boolean myBool = false;
- final byte myByte = (byte)23;
- final double myDouble = 17625765d;
- final float myFloat = 87127.23f;
- final int myInt = 123;
- final long myLong = 81728712;
- final short myShort = (short)88;
- final String myString = "ojweodewj";
- final String myJMSX = "aardvark";
-
- tm.setBooleanProperty("mybool", myBool);
- tm.setByteProperty("mybyte", myByte);
- tm.setDoubleProperty("mydouble", myDouble);
- tm.setFloatProperty("myfloat", myFloat);
- tm.setIntProperty("myint", myInt);
- tm.setLongProperty("mylong", myLong);
- tm.setShortProperty("myshort", myShort);
- tm.setStringProperty("mystring", myString);
-
- tm.setStringProperty("JMSXMyNaughtyJMSXProperty", myJMSX);
-
- prod.send(tm);
-
- tm = (TextMessage)cons.receive(5000);
-
- assertNotNull(tm);
-
- assertEquals("blahmessage3", tm.getText());
-
- assertEquals(myBool, tm.getBooleanProperty("mybool"));
- assertEquals(myByte, tm.getByteProperty("mybyte"));
- assertEquals(myDouble, tm.getDoubleProperty("mydouble"));
- assertEquals(myFloat, tm.getFloatProperty("myfloat"));
- assertEquals(myInt, tm.getIntProperty("myint"));
- assertEquals(myLong, tm.getLongProperty("mylong"));
- assertEquals(myShort, tm.getShortProperty("myshort"));
- assertEquals(myString, tm.getStringProperty("mystring"));
- assertEquals(myJMSX, tm.getStringProperty("JMSXMyNaughtyJMSXProperty"));
-
- m = cons.receive(5000);
-
- }
- finally
- {
- if (bridge != null)
- {
- bridge.stop();
- }
-
- if (connSource != null)
- {
- connSource.close();
- }
-
- if (connTarget != null)
- {
- connTarget.close();
- }
- }
- }
-
- public void testNoMessageIDInHeader() throws Exception
- {
- BridgeImpl bridge = null;
-
- Connection connSource = null;
-
- Connection connTarget = null;
-
- try
- {
- final int NUM_MESSAGES = 10;
-
- bridge = new BridgeImpl(cff0, cff1, sourceQueueFactory, targetQueueFactory,
- null, null, null, null,
- null, 5000, 10, QualityOfServiceMode.AT_MOST_ONCE,
- 1, -1,
- null, null, false);
- bridge.setTransactionManager(newTransactionManager());
-
- bridge.start();
-
- connSource = cf0.createConnection();
-
- connTarget = cf1.createConnection();
-
- log.trace("Sending " + NUM_MESSAGES + " messages");
-
- Session sessSource = connSource.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- MessageProducer prod = sessSource.createProducer(sourceQueue);
-
- for (int i = 0; i < NUM_MESSAGES; i++)
- {
- TextMessage tm = sessSource.createTextMessage("message" + i);
-
- //We add some headers to make sure they get passed through ok
- tm.setStringProperty("wib", "uhuh");
- tm.setBooleanProperty("cheese", true);
- tm.setIntProperty("Sausages", 23);
-
- prod.send(tm);
- }
-
- log.trace("Sent the first messages");
-
- Session sessTarget = connTarget.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- MessageConsumer cons = sessTarget.createConsumer(targetQueue);
-
- connTarget.start();
-
- for (int i = 0; i < NUM_MESSAGES; i++)
- {
- TextMessage tm = (TextMessage)cons.receive(5000);
-
- assertNotNull(tm);
-
- assertEquals("message" + i, tm.getText());
-
- assertEquals("uhuh", tm.getStringProperty("wib"));
- assertTrue(tm.getBooleanProperty("cheese"));
- assertEquals(23, tm.getIntProperty("Sausages"));
-
- String header = tm.getStringProperty(JBossMessage.JBOSS_MESSAGING_BRIDGE_MESSAGE_ID_LIST);
-
- assertNull(header);
- }
- }
- finally
- {
- if (bridge != null)
- {
- bridge.stop();
- }
-
- if (connSource != null)
- {
- connSource.close();
- }
-
- if (connTarget != null)
- {
- connTarget.close();
- }
- }
- }
-
-
- // Private -------------------------------------------------------------------------------
-
- private void testStress(QualityOfServiceMode qosMode, boolean persistent, int batchSize) throws Exception
- {
- Connection connSource = null;
-
- BridgeImpl bridge = null;
-
- Thread t = null;
-
- try
- {
- bridge = new BridgeImpl(cff0, cff1, sourceQueueFactory, targetQueueFactory,
- null, null, null, null,
- null, 5000, 10, qosMode,
- batchSize, -1,
- null, null, false);
- bridge.setTransactionManager(newTransactionManager());
-
- bridge.start();
-
- connSource = cf0.createConnection();
-
- Session sessSend = connSource.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- MessageProducer prod = sessSend.createProducer(sourceQueue);
-
- final int NUM_MESSAGES = 250;
-
- StressSender sender = new StressSender();
- sender.sess = sessSend;
- sender.prod = prod;
- sender.numMessages = NUM_MESSAGES;
- prod.setDeliveryMode(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT);
-
- t = new Thread(sender);
-
- t.start();
-
- this.checkAllMessageReceivedInOrder(cf1, targetQueue, 0, NUM_MESSAGES);
-
- t.join();
-
- if (sender.ex != null)
- {
- //An error occurred during the send
- throw sender.ex;
- }
-
- }
- finally
- {
- if (t != null)
- {
- t.join(10000);
- }
-
- if (connSource != null)
- {
- try
- {
- connSource.close();
- }
- catch (Exception e)
- {
- log.error("Failed to close connection", e);
- }
- }
-
- if (bridge != null)
- {
- bridge.stop();
- }
- }
- }
-
- private void testStressBatchTime(QualityOfServiceMode qosMode, boolean persistent, int maxBatchTime) throws Exception
- {
- Connection connSource = null;
-
- BridgeImpl bridge = null;
-
- Thread t = null;
-
- try
- {
- bridge = new BridgeImpl(cff0, cff1, sourceQueueFactory, targetQueueFactory,
- null, null, null, null,
- null, 5000, 10, qosMode,
- 2, maxBatchTime,
- null, null, false);
- bridge.setTransactionManager(newTransactionManager());
-
- bridge.start();
-
- connSource = cf0.createConnection();
-
- Session sessSend = connSource.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- MessageProducer prod = sessSend.createProducer(sourceQueue);
-
- final int NUM_MESSAGES = 5000;
-
- StressSender sender = new StressSender();
- sender.sess = sessSend;
- sender.prod = prod;
- sender.numMessages = NUM_MESSAGES;
- prod.setDeliveryMode(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT);
-
- t = new Thread(sender);
-
- t.start();
-
- this.checkAllMessageReceivedInOrder(cf1, targetQueue, 0, NUM_MESSAGES);
-
- t.join();
-
- if (sender.ex != null)
- {
- //An error occurred during the send
- throw sender.ex;
- }
-
- }
- finally
- {
- if (t != null)
- {
- t.join(10000);
- }
-
- if (connSource != null)
- {
- try
- {
- connSource.close();
- }
- catch (Exception e)
- {
- log.error("Failed to close connection", e);
- }
- }
-
- if (bridge != null)
- {
- bridge.stop();
- }
- }
- }
-
- //Both source and destination on same rm
- private void testStressSameServer(QualityOfServiceMode qosMode, boolean persistent, int batchSize) throws Exception
- {
- Connection connSource = null;
-
- BridgeImpl bridge = null;
-
- Thread t = null;
-
- try
- {
- bridge = new BridgeImpl(cff0, cff0, sourceQueueFactory, localTargetQueueFactory,
- null, null, null, null,
- null, 5000, 10, qosMode,
- batchSize, -1,
- null, null, false);
- bridge.setTransactionManager(newTransactionManager());
-
- bridge.start();
-
- connSource = cf0.createConnection();
-
- Session sessSend = connSource.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- MessageProducer prod = sessSend.createProducer(sourceQueue);
-
- final int NUM_MESSAGES = 2000;
-
- StressSender sender = new StressSender();
- sender.sess = sessSend;
- sender.prod = prod;
- sender.numMessages = NUM_MESSAGES;
- prod.setDeliveryMode(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT);
-
- t = new Thread(sender);
-
- t.start();
-
- this.checkAllMessageReceivedInOrder(cf0, localTargetQueue, 0, NUM_MESSAGES);
-
- t.join();
-
- if (sender.ex != null)
- {
- //An error occurred during the send
- throw sender.ex;
- }
-
- }
- finally
- {
- if (t != null)
- {
- t.join(10000);
- }
-
- if (connSource != null)
- {
- try
- {
- connSource.close();
- }
- catch (Exception e)
- {
- log.error("Failed to close connection", e);
- }
- }
-
- if (bridge != null)
- {
- bridge.stop();
- }
- }
- }
-
-
- private void testNoMaxBatchTime(QualityOfServiceMode qosMode, boolean persistent) throws Exception
- {
- BridgeImpl bridge = null;
-
- try
- {
- final int NUM_MESSAGES = 10;
-
- bridge = new BridgeImpl(cff0, cff1, sourceQueueFactory, targetQueueFactory,
- null, null, null, null,
- null, 5000, 10, qosMode,
- NUM_MESSAGES, -1,
- null, null, false);
- bridge.setTransactionManager(newTransactionManager());
-
- bridge.start();
-
- //Send half the messges
-
- this.sendMessages(cf0, sourceQueue, 0, NUM_MESSAGES / 2, persistent);
-
- //Verify none are received
-
- this.checkEmpty(targetQueue, 1);
-
- //Send the other half
-
- this.sendMessages(cf0, sourceQueue, NUM_MESSAGES / 2, NUM_MESSAGES / 2, persistent);
-
- //This should now be receivable
-
- this.checkAllMessageReceivedInOrder(cf1, targetQueue, 0, NUM_MESSAGES);
-
- //Send another batch with one more than batch size
-
- this.sendMessages(cf0, sourceQueue, 0, NUM_MESSAGES + 1, persistent);
-
- //Make sure only batch size are received
-
- this.checkAllMessageReceivedInOrder(cf1, targetQueue, 0, NUM_MESSAGES);
-
- //Final batch
-
- this.sendMessages(cf0, sourceQueue, 0, NUM_MESSAGES - 1, persistent);
-
- this.checkAllMessageReceivedInOrder(cf1, targetQueue, NUM_MESSAGES, 1);
-
- this.checkAllMessageReceivedInOrder(cf1, targetQueue, 0, NUM_MESSAGES - 1);
- }
- finally
- {
- if (bridge != null)
- {
- log.info("Stopping bridge");
- bridge.stop();
- }
- }
- }
-
- private void testNoMaxBatchTimeSameServer(QualityOfServiceMode qosMode, boolean persistent) throws Exception
- {
- BridgeImpl bridge = null;
-
- try
- {
- final int NUM_MESSAGES = 10;
-
- bridge = new BridgeImpl(cff0, cff0, sourceQueueFactory, localTargetQueueFactory,
- null, null, null, null,
- null, 5000, 10, qosMode,
- NUM_MESSAGES, -1,
- null, null, false);
- bridge.setTransactionManager(newTransactionManager());
-
- bridge.start();
-
- this.sendMessages(cf0, sourceQueue, 0, NUM_MESSAGES / 2, persistent);
-
- this.checkEmpty(targetQueue, 1);
-
- //Send the other half
-
- this.sendMessages(cf0, sourceQueue, NUM_MESSAGES / 2, NUM_MESSAGES /2, persistent);
-
-
- //This should now be receivable
-
- this.checkAllMessageReceivedInOrder(cf0, localTargetQueue, 0, NUM_MESSAGES);
-
- this.checkEmpty(localTargetQueue, 0);
-
- this.checkEmpty(sourceQueue, 0);
-
- //Send another batch with one more than batch size
-
- this.sendMessages(cf0, sourceQueue, 0, NUM_MESSAGES + 1, persistent);
-
- //Make sure only batch size are received
-
- this.checkAllMessageReceivedInOrder(cf0, localTargetQueue, 0, NUM_MESSAGES);
-
- //Final batch
-
- this.sendMessages(cf0, sourceQueue, 0, NUM_MESSAGES - 1, persistent);
-
- this.checkAllMessageReceivedInOrder(cf0, localTargetQueue, NUM_MESSAGES, 1);
-
- this.checkAllMessageReceivedInOrder(cf0, localTargetQueue, 0, NUM_MESSAGES - 1);
- }
- finally
- {
- if (bridge != null)
- {
- bridge.stop();
- }
- }
- }
-
- private void testMaxBatchTime(QualityOfServiceMode qosMode, boolean persistent) throws Exception
- {
- BridgeImpl bridge = null;
-
- try
- {
- final long MAX_BATCH_TIME = 3000;
-
- final int MAX_BATCH_SIZE = 100000; // something big so it won't reach it
-
- bridge = new BridgeImpl(cff0, cff1, sourceQueueFactory, targetQueueFactory,
- null, null, null, null,
- null, 3000, 10, qosMode,
- MAX_BATCH_SIZE, MAX_BATCH_TIME,
- null, null, false);
- bridge.setTransactionManager(newTransactionManager());
-
- bridge.start();
-
- final int NUM_MESSAGES = 10;
-
- //Send some message
-
- this.sendMessages(cf0, sourceQueue, 0, NUM_MESSAGES, persistent);
-
- //Verify none are received
-
- this.checkEmpty(targetQueue, 1);
-
- //Messages should now be receivable
-
- this.checkAllMessageReceivedInOrder(cf1, targetQueue, 0, NUM_MESSAGES);
- }
- finally
- {
- if (bridge != null)
- {
- bridge.stop();
- }
- }
- }
-
- private void testMaxBatchTimeSameServer(QualityOfServiceMode qosMode, boolean persistent) throws Exception
- {
- BridgeImpl bridge = null;
-
- try
- {
- final long MAX_BATCH_TIME = 3000;
-
- final int MAX_BATCH_SIZE = 100000; // something big so it won't reach it
-
- bridge = new BridgeImpl(cff0, cff0, sourceQueueFactory, localTargetQueueFactory,
- null, null, null, null,
- null, 3000, 10, qosMode,
- MAX_BATCH_SIZE, MAX_BATCH_TIME,
- null, null, false);
- bridge.setTransactionManager(newTransactionManager());
-
- bridge.start();
-
- final int NUM_MESSAGES = 10;
-
- //Send some message
-
- //Send some message
-
- this.sendMessages(cf0, sourceQueue, 0, NUM_MESSAGES, persistent);
-
- //Verify none are received
-
- this.checkEmpty(localTargetQueue, 0);;
-
- //Messages should now be receivable
-
- this.checkAllMessageReceivedInOrder(cf0, localTargetQueue, 0, NUM_MESSAGES);
- }
- finally
- {
- if (bridge != null)
- {
- bridge.stop();
- }
- }
- }
-
-
- // Inner classes -------------------------------------------------------------------
-
- private static class StressSender implements Runnable
- {
- int numMessages;
-
- Session sess;
-
- MessageProducer prod;
-
- Exception ex;
-
- public void run()
- {
- try
- {
- for (int i = 0; i < numMessages; i++)
- {
- TextMessage tm = sess.createTextMessage("message" + i);
-
- prod.send(tm);
-
- log.trace("Sent message " + i);
- }
- }
- catch (Exception e)
- {
- log.error("Failed to send", e);
- ex = e;
- }
- }
-
- }
-}
Copied: trunk/tests/src/org/jboss/messaging/tests/integration/jms/bridge/JMSBridgeReconnectionTest.java (from rev 6295, trunk/tests/src/org/jboss/messaging/tests/integration/jms/bridge/BridgeReconnectionTest.java)
===================================================================
--- trunk/tests/src/org/jboss/messaging/tests/integration/jms/bridge/JMSBridgeReconnectionTest.java (rev 0)
+++ trunk/tests/src/org/jboss/messaging/tests/integration/jms/bridge/JMSBridgeReconnectionTest.java 2009-04-03 14:12:53 UTC (rev 6299)
@@ -0,0 +1,302 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.messaging.tests.integration.jms.bridge;
+
+import org.jboss.messaging.core.logging.Logger;
+import org.jboss.messaging.jms.bridge.QualityOfServiceMode;
+import org.jboss.messaging.jms.bridge.impl.JMSBridgeImpl;
+import org.jboss.messaging.jms.server.impl.JMSServerManagerImpl;
+import org.jboss.messaging.tests.unit.util.InVMContext;
+
+/**
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+public class JMSBridgeReconnectionTest extends BridgeTestBase
+{
+ private static final Logger log = Logger.getLogger(JMSBridgeReconnectionTest.class);
+
+ // Crash and reconnect
+
+ // Once and only once
+
+ public void testCrashAndReconnectDestBasic_OnceAndOnlyOnce_P() throws Exception
+ {
+ testCrashAndReconnectDestBasic(QualityOfServiceMode.ONCE_AND_ONLY_ONCE, true);
+ }
+
+ public void testCrashAndReconnectDestBasic_OnceAndOnlyOnce_NP() throws Exception
+ {
+ testCrashAndReconnectDestBasic(QualityOfServiceMode.ONCE_AND_ONLY_ONCE, false);
+ }
+
+ // dups ok
+
+ public void testCrashAndReconnectDestBasic_DuplicatesOk_P() throws Exception
+ {
+ testCrashAndReconnectDestBasic(QualityOfServiceMode.DUPLICATES_OK, true);
+ }
+
+ public void testCrashAndReconnectDestBasic_DuplicatesOk_NP() throws Exception
+ {
+ testCrashAndReconnectDestBasic(QualityOfServiceMode.DUPLICATES_OK, false);
+ }
+
+ // At most once
+
+ public void testCrashAndReconnectDestBasic_AtMostOnce_P() throws Exception
+ {
+ testCrashAndReconnectDestBasic(QualityOfServiceMode.AT_MOST_ONCE, true);
+ }
+
+ public void testCrashAndReconnectDestBasic_AtMostOnce_NP() throws Exception
+ {
+ testCrashAndReconnectDestBasic(QualityOfServiceMode.AT_MOST_ONCE, false);
+ }
+
+ // Crash tests specific to XA transactions
+
+ public void testCrashAndReconnectDestCrashBeforePrepare_P() throws Exception
+ {
+ testCrashAndReconnectDestCrashBeforePrepare(true);
+ }
+
+ public void testCrashAndReconnectDestCrashBeforePrepare_NP() throws Exception
+ {
+ testCrashAndReconnectDestCrashBeforePrepare(false);
+ }
+
+ // Crash before bridge is started
+
+ public void testRetryConnectionOnStartup() throws Exception
+ {
+ server1.stop();
+
+ JMSBridgeImpl bridge = new JMSBridgeImpl(cff0, cff1, sourceQueueFactory, targetQueueFactory,
+ null, null, null, null,
+ null, 1000, -1, QualityOfServiceMode.DUPLICATES_OK,
+ 10, -1,
+ null, null, false);
+ bridge.setTransactionManager(newTransactionManager());
+
+ try
+ {
+ bridge.start();
+ assertFalse(bridge.isStarted());
+ assertTrue(bridge.isFailed());
+
+ //Restart the server
+ server1.start();
+
+ context1 = new InVMContext();
+ jmsServer1 = JMSServerManagerImpl.newJMSServerManagerImpl(server1);
+ jmsServer1.start();
+ jmsServer1.setContext(context1);
+
+ createQueue("targetQueue", 1);
+ setUpAdministeredObjects();
+
+ Thread.sleep(3000);
+
+ assertTrue(bridge.isStarted());
+ assertFalse(bridge.isFailed());
+ }
+ finally
+ {
+ try
+ {
+ bridge.stop();
+ }
+ catch (Exception e)
+ {
+ log.error("Failed to stop bridge", e);
+ }
+ }
+ }
+
+ /*
+ * Send some messages
+ * Crash the destination server
+ * Bring the destination server back up
+ * Send some more messages
+ * Verify all messages are received
+ */
+ private void testCrashAndReconnectDestBasic(QualityOfServiceMode qosMode, boolean persistent) throws Exception
+ {
+ JMSBridgeImpl bridge = null;
+
+ try
+ {
+ bridge = new JMSBridgeImpl(cff0, cff1, sourceQueueFactory, targetQueueFactory,
+ null, null, null, null,
+ null, 1000, -1, qosMode,
+ 10, -1,
+ null, null, false);
+ bridge.setTransactionManager(newTransactionManager());
+ bridge.start();
+
+ final int NUM_MESSAGES = 10;
+
+ //Send some messages
+
+ sendMessages(cf0, sourceQueue, 0, NUM_MESSAGES / 2 , persistent);
+
+ //Verify none are received
+
+ checkEmpty(targetQueue, 1);
+
+ //Now crash the dest server
+
+ log.info("About to crash server");
+
+ server1.stop();
+
+ //Wait a while before starting up to simulate the dest being down for a while
+ log.info("Waiting 5 secs before bringing server back up");
+ Thread.sleep(10000);
+ log.info("Done wait");
+
+ //Restart the server
+
+ log.info("Restarting server");
+
+ server1.start();
+
+ context1 = new InVMContext();
+ jmsServer1 = JMSServerManagerImpl.newJMSServerManagerImpl(server1);
+ jmsServer1.start();
+ jmsServer1.setContext(context1);
+
+ createQueue("targetQueue", 1);
+
+ setUpAdministeredObjects();
+
+ //Send some more messages
+
+ log.info("Sending more messages");
+
+ sendMessages(cf0, sourceQueue, NUM_MESSAGES / 2, NUM_MESSAGES / 2, persistent);
+
+ log.info("Sent messages");
+
+ checkMessagesReceived(cf1, targetQueue, qosMode, NUM_MESSAGES, false);
+ }
+ finally
+ {
+
+ if (bridge != null)
+ {
+ try
+ {
+ bridge.stop();
+ }
+ catch (Exception e)
+ {
+ log.error("Failed to stop bridge", e);
+ }
+ }
+ }
+ }
+
+ /*
+ * Send some messages
+ * Crash the destination server
+ * Set the max batch time such that it will attempt to send the batch while the dest server is down
+ * Bring up the destination server
+ * Send some more messages
+ * Verify all messages are received
+ */
+ private void testCrashAndReconnectDestCrashBeforePrepare(boolean persistent) throws Exception
+ {
+ JMSBridgeImpl bridge = null;
+
+ try
+ {
+ bridge = new JMSBridgeImpl(cff0, cff1, sourceQueueFactory, targetQueueFactory,
+ null, null, null, null,
+ null, 1000, -1, QualityOfServiceMode.ONCE_AND_ONLY_ONCE,
+ 10, 5000,
+ null, null, false);
+ bridge.setTransactionManager(newTransactionManager());
+
+ bridge.start();
+
+ final int NUM_MESSAGES = 10;
+ //Send some messages
+
+ this.sendMessages(cf0, sourceQueue, 0, NUM_MESSAGES / 2, persistent);
+
+ //verify none are received
+
+ checkEmpty(targetQueue, 1);
+
+ //Now crash the dest server
+
+ log.info("About to crash server");
+
+ server1.stop();
+
+ //Wait a while before starting up to simulate the dest being down for a while
+ log.info("Waiting 5 secs before bringing server back up");
+ Thread.sleep(10000);
+ log.info("Done wait");
+
+ //Restart the server
+ server1.start();
+
+ context1 = new InVMContext();
+ jmsServer1 = JMSServerManagerImpl.newJMSServerManagerImpl(server1);
+ jmsServer1.start();
+ jmsServer1.setContext(context1);
+
+ createQueue("targetQueue", 1);
+
+ setUpAdministeredObjects();
+
+ sendMessages(cf0, sourceQueue, NUM_MESSAGES / 2, NUM_MESSAGES / 2, persistent);
+
+ checkMessagesReceived(cf1, targetQueue, QualityOfServiceMode.ONCE_AND_ONLY_ONCE, NUM_MESSAGES, false);
+ }
+ finally
+ {
+
+ if (bridge != null)
+ {
+ try
+ {
+ bridge.stop();
+ }
+ catch (Exception e)
+ {
+ log.error("Failed to stop bridge", e);
+ }
+ }
+
+ }
+ }
+
+ // Inner classes -------------------------------------------------------------------
+
+}
Copied: trunk/tests/src/org/jboss/messaging/tests/integration/jms/bridge/JMSBridgeTest.java (from rev 6295, trunk/tests/src/org/jboss/messaging/tests/integration/jms/bridge/BridgeTest.java)
===================================================================
--- trunk/tests/src/org/jboss/messaging/tests/integration/jms/bridge/JMSBridgeTest.java (rev 0)
+++ trunk/tests/src/org/jboss/messaging/tests/integration/jms/bridge/JMSBridgeTest.java 2009-04-03 14:12:53 UTC (rev 6299)
@@ -0,0 +1,1590 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.messaging.tests.integration.jms.bridge;
+
+import org.jboss.messaging.core.logging.Logger;
+import org.jboss.messaging.jms.bridge.QualityOfServiceMode;
+import org.jboss.messaging.jms.bridge.impl.JMSBridgeImpl;
+import org.jboss.messaging.jms.client.JBossMessage;
+
+import javax.jms.Connection;
+import javax.jms.DeliveryMode;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * A JMSBridgeTest
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision$</tt>
+ *
+ * $Id$
+ *
+ */
+public class JMSBridgeTest extends BridgeTestBase
+{
+ private static final Logger log = Logger.getLogger(JMSBridgeTest.class);
+
+ // MaxBatchSize but no MaxBatchTime
+
+ public void testNoMaxBatchTime_AtMostOnce_P() throws Exception
+ {
+ testNoMaxBatchTime(QualityOfServiceMode.AT_MOST_ONCE, true);
+ }
+
+ public void testNoMaxBatchTime_DuplicatesOk_P() throws Exception
+ {
+ testNoMaxBatchTime(QualityOfServiceMode.DUPLICATES_OK, true);
+ }
+
+ public void testNoMaxBatchTime_OnceAndOnlyOnce_P() throws Exception
+ {
+ testNoMaxBatchTime(QualityOfServiceMode.ONCE_AND_ONLY_ONCE, true);
+ }
+
+ public void testNoMaxBatchTime_AtMostOnce_NP() throws Exception
+ {
+ testNoMaxBatchTime(QualityOfServiceMode.AT_MOST_ONCE, false);
+ }
+
+ public void testNoMaxBatchTime_DuplicatesOk_NP() throws Exception
+ {
+ testNoMaxBatchTime(QualityOfServiceMode.DUPLICATES_OK, false);
+ }
+
+ public void testNoMaxBatchTime_OnceAndOnlyOnce_NP() throws Exception
+ {
+ testNoMaxBatchTime(QualityOfServiceMode.ONCE_AND_ONLY_ONCE, false);
+ }
+
+ //Same server
+
+ // MaxBatchSize but no MaxBatchTime
+
+ public void testNoMaxBatchTimeSameServer_AtMostOnce_P() throws Exception
+ {
+ testNoMaxBatchTimeSameServer(QualityOfServiceMode.AT_MOST_ONCE, true);
+ }
+
+ public void testNoMaxBatchTimeSameServer_DuplicatesOk_P() throws Exception
+ {
+ testNoMaxBatchTimeSameServer(QualityOfServiceMode.DUPLICATES_OK, true);
+ }
+
+ public void testNoMaxBatchTimeSameServer_OnceAndOnlyOnce_P() throws Exception
+ {
+ testNoMaxBatchTimeSameServer(QualityOfServiceMode.ONCE_AND_ONLY_ONCE, true);
+ }
+
+ public void testNoMaxBatchTimeSameServer_AtMostOnce_NP() throws Exception
+ {
+ testNoMaxBatchTimeSameServer(QualityOfServiceMode.AT_MOST_ONCE, false);
+ }
+
+ public void testNoMaxBatchTimeSameServer_DuplicatesOk_NP() throws Exception
+ {
+ testNoMaxBatchTimeSameServer(QualityOfServiceMode.DUPLICATES_OK, false);
+ }
+
+ public void testNoMaxBatchTimeSameServer_OnceAndOnlyOnce_NP() throws Exception
+ {
+ testNoMaxBatchTimeSameServer(QualityOfServiceMode.ONCE_AND_ONLY_ONCE, false);
+ }
+
+
+ // MaxBatchTime but no MaxBatchSize
+
+ public void testMaxBatchTime_AtMostOnce_P() throws Exception
+ {
+ this.testMaxBatchTime(QualityOfServiceMode.AT_MOST_ONCE, true);
+ }
+
+ public void testMaxBatchTime_DuplicatesOk_P() throws Exception
+ {
+ this.testMaxBatchTime(QualityOfServiceMode.DUPLICATES_OK, true);
+ }
+
+ public void testMaxBatchTime_OnceAndOnlyOnce_P() throws Exception
+ {
+ testMaxBatchTime(QualityOfServiceMode.ONCE_AND_ONLY_ONCE, true);
+ }
+
+ public void testMaxBatchTime_AtMostOnce_NP() throws Exception
+ {
+ this.testMaxBatchTime(QualityOfServiceMode.AT_MOST_ONCE, false);
+ }
+
+ public void testMaxBatchTime_DuplicatesOk_NP() throws Exception
+ {
+ this.testMaxBatchTime(QualityOfServiceMode.DUPLICATES_OK, false);
+ }
+
+ public void testMaxBatchTime_OnceAndOnlyOnce_NP() throws Exception
+ {
+ testMaxBatchTime(QualityOfServiceMode.ONCE_AND_ONLY_ONCE, false);
+ }
+
+ // Same server
+
+ // MaxBatchTime but no MaxBatchSize
+
+ public void testMaxBatchTimeSameServer_AtMostOnce_P() throws Exception
+ {
+ this.testMaxBatchTimeSameServer(QualityOfServiceMode.AT_MOST_ONCE, true);
+ }
+
+ public void testMaxBatchTimeSameServer_DuplicatesOk_P() throws Exception
+ {
+ this.testMaxBatchTimeSameServer(QualityOfServiceMode.DUPLICATES_OK, true);
+ }
+
+ public void testMaxBatchTimeSameServer_OnceAndOnlyOnce_P() throws Exception
+ {
+ testMaxBatchTimeSameServer(QualityOfServiceMode.ONCE_AND_ONLY_ONCE, true);
+ }
+
+ public void testMaxBatchTimeSameServer_AtMostOnce_NP() throws Exception
+ {
+ this.testMaxBatchTimeSameServer(QualityOfServiceMode.AT_MOST_ONCE, false);
+ }
+
+ public void testMaxBatchTimeSameServer_DuplicatesOk_NP() throws Exception
+ {
+ this.testMaxBatchTimeSameServer(QualityOfServiceMode.DUPLICATES_OK, false);
+ }
+
+ public void testMaxBatchTimeSameServer_OnceAndOnlyOnce_NP() throws Exception
+ {
+ testMaxBatchTimeSameServer(QualityOfServiceMode.ONCE_AND_ONLY_ONCE, false);
+ }
+
+ // Stress with batch size of 50
+
+ public void testStress_AtMostOnce_P_50() throws Exception
+ {
+ testStress(QualityOfServiceMode.AT_MOST_ONCE, true, 50);
+ }
+
+ public void testStress_DuplicatesOk_P_50() throws Exception
+ {
+ testStress(QualityOfServiceMode.DUPLICATES_OK, true, 50);
+ }
+
+ public void testStress_OnceAndOnlyOnce_P_50() throws Exception
+ {
+ testStress(QualityOfServiceMode.ONCE_AND_ONLY_ONCE, true, 50);
+ }
+
+ public void testStress_AtMostOnce_NP_50() throws Exception
+ {
+ testStress(QualityOfServiceMode.AT_MOST_ONCE, false, 50);
+ }
+
+ public void testStress_DuplicatesOk_NP_50() throws Exception
+ {
+ testStress(QualityOfServiceMode.DUPLICATES_OK, false, 50);
+ }
+
+ public void testStress_OnceAndOnlyOnce_NP_50() throws Exception
+ {
+ testStress(QualityOfServiceMode.ONCE_AND_ONLY_ONCE, false, 50);
+ }
+
+ // Stress with batch size of 1
+
+ public void testStress_AtMostOnce_P_1() throws Exception
+ {
+ testStress(QualityOfServiceMode.AT_MOST_ONCE, true, 1);
+ }
+
+ public void testStress_DuplicatesOk_P_1() throws Exception
+ {
+ testStress(QualityOfServiceMode.DUPLICATES_OK, true, 1);
+ }
+
+ public void testStress_OnceAndOnlyOnce_P_1() throws Exception
+ {
+ testStress(QualityOfServiceMode.ONCE_AND_ONLY_ONCE, true, 1);
+ }
+
+ public void testStress_AtMostOnce_NP_1() throws Exception
+ {
+ testStress(QualityOfServiceMode.AT_MOST_ONCE, false, 1);
+ }
+
+ public void testStress_DuplicatesOk_NP_1() throws Exception
+ {
+ testStress(QualityOfServiceMode.DUPLICATES_OK, false, 1);
+ }
+
+ public void testStress_OnceAndOnlyOnce_NP_1() throws Exception
+ {
+ testStress(QualityOfServiceMode.ONCE_AND_ONLY_ONCE, false, 1);
+ }
+
+ // Max batch time
+
+ public void testStressMaxBatchTime_OnceAndOnlyOnce_NP() throws Exception
+ {
+ this.testStressBatchTime(QualityOfServiceMode.ONCE_AND_ONLY_ONCE, false, 200);
+ }
+
+ public void testStressMaxBatchTime_OnceAndOnlyOnce_P() throws Exception
+ {
+ this.testStressBatchTime(QualityOfServiceMode.ONCE_AND_ONLY_ONCE, true, 200);
+ }
+
+
+ // Stress on same server
+
+ // Stress with batch size of 50
+
+ public void testStressSameServer_AtMostOnce_P_50() throws Exception
+ {
+ testStressSameServer(QualityOfServiceMode.AT_MOST_ONCE, true, 50);
+ }
+
+ public void testStressSameServer_DuplicatesOk_P_50() throws Exception
+ {
+ testStressSameServer(QualityOfServiceMode.DUPLICATES_OK, true, 50);
+ }
+
+ public void testStressSameServer_OnceAndOnlyOnce_P_50() throws Exception
+ {
+ testStress(QualityOfServiceMode.ONCE_AND_ONLY_ONCE, true, 50);
+ }
+
+ public void testStressSameServer_AtMostOnce_NP_50() throws Exception
+ {
+ testStressSameServer(QualityOfServiceMode.AT_MOST_ONCE, false, 50);
+ }
+
+ public void testStressSameServer_DuplicatesOk_NP_50() throws Exception
+ {
+ testStressSameServer(QualityOfServiceMode.DUPLICATES_OK, false, 50);
+ }
+
+ public void testStressSameServer_OnceAndOnlyOnce_NP_50() throws Exception
+ {
+ testStressSameServer(QualityOfServiceMode.ONCE_AND_ONLY_ONCE, false, 50);
+ }
+
+ // Stress with batch size of 1
+
+ public void testStressSameServer_AtMostOnce_P_1() throws Exception
+ {
+ testStressSameServer(QualityOfServiceMode.AT_MOST_ONCE, true, 1);
+ }
+
+ public void testStressSameServer_DuplicatesOk_P_1() throws Exception
+ {
+ testStressSameServer(QualityOfServiceMode.DUPLICATES_OK, true, 1);
+ }
+
+ public void testStressSameServer_OnceAndOnlyOnce_P_1() throws Exception
+ {
+ testStressSameServer(QualityOfServiceMode.ONCE_AND_ONLY_ONCE, true, 1);
+ }
+
+ public void testStressSameServer_AtMostOnce_NP_1() throws Exception
+ {
+ testStressSameServer(QualityOfServiceMode.AT_MOST_ONCE, false, 1);
+ }
+
+ public void testStressSameServer_DuplicatesOk_NP_1() throws Exception
+ {
+ testStressSameServer(QualityOfServiceMode.DUPLICATES_OK, false, 1);
+ }
+
+ public void testStressSameServer_OnceAndOnlyOnce_NP_1() throws Exception
+ {
+ testStressSameServer(QualityOfServiceMode.ONCE_AND_ONLY_ONCE, false, 1);
+ }
+
+ public void testParams() throws Exception
+ {
+ JMSBridgeImpl bridge = null;
+
+ try
+ {
+ QualityOfServiceMode qosMode = QualityOfServiceMode.AT_MOST_ONCE;
+
+ int batchSize = 10;
+
+ int maxBatchTime = -1;
+
+ String sourceUsername = null;
+
+ String sourcePassword = null;
+
+ String destUsername = null;
+
+ String destPassword = null;
+
+ String selector = null;
+
+ long failureRetryInterval = 5000;
+
+ int maxRetries = 10;
+
+ String subName = null;
+
+ String clientID = null;
+
+ try
+ {
+ bridge= new JMSBridgeImpl(null, cff1, sourceQueueFactory, targetQueueFactory,
+ sourceUsername, sourcePassword, destUsername, destPassword,
+ selector, failureRetryInterval, maxRetries, qosMode,
+ batchSize, maxBatchTime,
+ subName, clientID, false);
+ }
+ catch (IllegalArgumentException e)
+ {
+ //Ok
+ }
+
+ try
+ {
+ bridge= new JMSBridgeImpl(cff0, null, sourceQueueFactory, targetQueueFactory,
+ sourceUsername, sourcePassword, destUsername, destPassword,
+ selector, failureRetryInterval, maxRetries, qosMode,
+ batchSize, maxBatchTime,
+ subName, clientID, false);
+ }
+ catch (IllegalArgumentException e)
+ {
+ //Ok
+ }
+
+ try
+ {
+ bridge= new JMSBridgeImpl(cff0, cff1, null, targetQueueFactory,
+ sourceUsername, sourcePassword, destUsername, destPassword,
+ selector, failureRetryInterval, maxRetries, qosMode,
+ batchSize, maxBatchTime,
+ subName, clientID, false);
+ }
+ catch (IllegalArgumentException e)
+ {
+ //Ok
+ }
+
+ try
+ {
+ bridge= new JMSBridgeImpl(cff0, cff1, sourceQueueFactory, null,
+ sourceUsername, sourcePassword, destUsername, destPassword,
+ selector, failureRetryInterval, maxRetries, qosMode,
+ batchSize, maxBatchTime,
+ subName, clientID, false);
+ }
+ catch (IllegalArgumentException e)
+ {
+ //Ok
+ }
+
+ try
+ {
+ bridge= new JMSBridgeImpl(cff0, cff1, sourceQueueFactory, targetQueueFactory,
+ sourceUsername, sourcePassword, destUsername, destPassword,
+ selector, -2, maxRetries, qosMode,
+ batchSize, maxBatchTime,
+ subName, clientID, false);
+ }
+ catch (IllegalArgumentException e)
+ {
+ //Ok
+ }
+
+ try
+ {
+ bridge= new JMSBridgeImpl(cff0, cff1, sourceQueueFactory, targetQueueFactory,
+ sourceUsername, sourcePassword, destUsername, destPassword,
+ selector, -1, 10, qosMode,
+ batchSize, maxBatchTime,
+ subName, clientID, false);
+ }
+ catch (IllegalArgumentException e)
+ {
+ //Ok
+ }
+
+ try
+ {
+ bridge= new JMSBridgeImpl(cff0, cff1, sourceQueueFactory, null,
+ sourceUsername, sourcePassword, destUsername, destPassword,
+ selector, failureRetryInterval, maxRetries, qosMode,
+ 0, maxBatchTime,
+ subName, clientID, false);
+ }
+ catch (IllegalArgumentException e)
+ {
+ //Ok
+ }
+
+ try
+ {
+ bridge= new JMSBridgeImpl(cff0, cff1, sourceQueueFactory, null,
+ sourceUsername, sourcePassword, destUsername, destPassword,
+ selector, failureRetryInterval, maxRetries, qosMode,
+ batchSize, -2,
+ subName, clientID, false);
+ }
+ catch (IllegalArgumentException e)
+ {
+ //Ok
+ }
+ }
+ finally
+ {
+ if (bridge != null)
+ {
+ bridge.stop();
+ }
+ }
+ }
+
+ public void testSelector() throws Exception
+ {
+ JMSBridgeImpl bridge = null;
+
+ Connection connSource = null;
+
+ Connection connTarget = null;
+
+ try
+ {
+ final int NUM_MESSAGES = 10;
+
+ String selector = "vegetable='radish'";
+
+ bridge = new JMSBridgeImpl(cff0, cff1, sourceQueueFactory, targetQueueFactory,
+ null, null, null, null,
+ selector, 5000, 10, QualityOfServiceMode.AT_MOST_ONCE,
+ 1, -1,
+ null, null, false);
+ bridge.setTransactionManager(newTransactionManager());
+
+ bridge.start();
+
+ connSource = cf0.createConnection();
+
+ Session sessSend = connSource.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ MessageProducer prod = sessSend.createProducer(sourceQueue);
+
+ for (int i = 0; i < NUM_MESSAGES; i++)
+ {
+ TextMessage tm = sessSend.createTextMessage("message" + i);
+
+ if (i >= NUM_MESSAGES / 2)
+ {
+ tm.setStringProperty("vegetable", "radish");
+ }
+ else
+ {
+ tm.setStringProperty("vegetable", "cauliflower");
+ }
+
+ prod.send(tm);
+ }
+
+ connTarget = cf1.createConnection();
+
+ Session sessRec = connTarget.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ MessageConsumer cons = sessRec.createConsumer(targetQueue);
+
+ connTarget.start();
+
+ for (int i = NUM_MESSAGES / 2 ; i < NUM_MESSAGES; i++)
+ {
+ TextMessage tm = (TextMessage)cons.receive(1000);
+
+ assertNotNull(tm);
+
+ assertEquals("message" + i, tm.getText());
+ }
+
+ Message m = cons.receive(1000);
+
+ assertNull(m);
+
+ }
+ finally
+ {
+ if (connSource != null)
+ {
+ connSource.close();
+ }
+
+ if (connTarget != null)
+ {
+ connTarget.close();
+ }
+
+ if (bridge != null)
+ {
+ bridge.stop();
+ }
+
+ removeAllMessages(sourceQueue.getQueueName(), 0);
+ }
+ }
+
+ public void testStartBridgeWithJTATransactionAlreadyRunning() throws Exception
+ {
+ JMSBridgeImpl bridge = null;
+
+ Transaction toResume = null;
+
+ Transaction started = null;
+
+ TransactionManager mgr = newTransactionManager();
+
+ try
+ {
+
+ toResume = mgr.suspend();
+
+ mgr.begin();
+
+ started = mgr.getTransaction();
+
+ final int NUM_MESSAGES = 10;
+
+ bridge = new JMSBridgeImpl(cff0, cff1, sourceTopicFactory, targetQueueFactory,
+ null, null, null, null,
+ null, 5000, 10, QualityOfServiceMode.AT_MOST_ONCE,
+ 1, -1,
+ null, null, false);
+ bridge.setTransactionManager(mgr);
+ bridge.start();
+
+ this.sendMessages(cf0, sourceTopic, 0, NUM_MESSAGES, false);
+
+ this.checkAllMessageReceivedInOrder(cf1, targetQueue, 0, NUM_MESSAGES);
+ }
+ finally
+ {
+ if (started != null)
+ {
+ try
+ {
+ started.rollback();
+ }
+ catch (Exception e)
+ {
+ log.error("Failed to rollback", e);
+ }
+ }
+
+ if (toResume != null)
+ {
+ try
+ {
+ mgr.resume(toResume);
+ }
+ catch (Exception e)
+ {
+ log.error("Failed to resume", e);
+ }
+ }
+ if (bridge != null)
+ {
+ bridge.stop();
+ }
+ }
+ }
+
+ public void testNonDurableSubscriber() throws Exception
+ {
+ JMSBridgeImpl bridge = null;
+
+ try
+ {
+ final int NUM_MESSAGES = 10;
+
+ bridge = new JMSBridgeImpl(cff0, cff1, sourceTopicFactory, targetQueueFactory,
+ null, null, null, null,
+ null, 5000, 10, QualityOfServiceMode.AT_MOST_ONCE,
+ 1, -1,
+ null, null, false);
+ bridge.setTransactionManager(newTransactionManager());
+
+ bridge.start();
+
+ sendMessages(cf0, sourceTopic, 0, NUM_MESSAGES, false);
+
+ checkAllMessageReceivedInOrder(cf1, targetQueue, 0, NUM_MESSAGES);
+ }
+ finally
+ {
+ if (bridge != null)
+ {
+ bridge.stop();
+ }
+ }
+ }
+
+ public void testDurableSubscriber() throws Exception
+ {
+ JMSBridgeImpl bridge = null;
+
+ try
+ {
+ final int NUM_MESSAGES = 10;
+
+ bridge = new JMSBridgeImpl(cff0, cff1, sourceTopicFactory, targetQueueFactory,
+ null, null, null, null,
+ null, 5000, 10, QualityOfServiceMode.AT_MOST_ONCE,
+ 1, -1,
+ "subTest", "clientid123", false);
+ bridge.setTransactionManager(newTransactionManager());
+
+ bridge.start();
+
+ sendMessages(cf0, sourceTopic, 0, NUM_MESSAGES, true);
+
+ checkAllMessageReceivedInOrder(cf1, targetQueue, 0, NUM_MESSAGES);
+ }
+ finally
+ {
+ if (bridge != null)
+ {
+ bridge.stop();
+ }
+
+ //Now unsubscribe
+ Connection conn = cf0.createConnection();
+ conn.setClientID("clientid123");
+ Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ sess.unsubscribe("subTest");
+ conn.close();
+ }
+ }
+
+ public void testMessageIDInHeaderOn() throws Exception
+ {
+ messageIDInHeader(true);
+ }
+
+ public void testMessageIDInHeaderOff() throws Exception
+ {
+ messageIDInHeader(false);
+ }
+
+ private void messageIDInHeader(boolean on) throws Exception
+ {
+ JMSBridgeImpl bridge = null;
+
+ Connection connSource = null;
+
+ Connection connTarget = null;
+
+ try
+ {
+ final int NUM_MESSAGES = 10;
+
+ bridge = new JMSBridgeImpl(cff0, cff1, sourceQueueFactory, targetQueueFactory,
+ null, null, null, null,
+ null, 5000, 10, QualityOfServiceMode.AT_MOST_ONCE,
+ 1, -1,
+ null, null, on);
+ bridge.setTransactionManager(newTransactionManager());
+
+ bridge.start();
+
+ connSource = cf0.createConnection();
+
+ connTarget = cf1.createConnection();
+
+ log.trace("Sending " + NUM_MESSAGES + " messages");
+
+ List ids1 = new ArrayList();
+
+ Session sessSource = connSource.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ MessageProducer prod = sessSource.createProducer(sourceQueue);
+
+ for (int i = 0; i < NUM_MESSAGES; i++)
+ {
+ TextMessage tm = sessSource.createTextMessage("message" + i);
+
+ //We add some headers to make sure they get passed through ok
+ tm.setStringProperty("wib", "uhuh");
+ tm.setBooleanProperty("cheese", true);
+ tm.setIntProperty("Sausages", 23);
+
+ //We add some JMSX ones too
+
+ tm.setStringProperty("JMSXGroupID", "mygroup543");
+ tm.setIntProperty("JMSXGroupSeq", 777);
+
+ prod.send(tm);
+
+ ids1.add(tm.getJMSMessageID());
+ }
+
+ log.trace("Sent the first messages");
+
+ Session sessTarget = connTarget.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ MessageConsumer cons = sessTarget.createConsumer(targetQueue);
+
+ connTarget.start();
+
+ List msgs = new ArrayList();
+
+ for (int i = 0; i < NUM_MESSAGES; i++)
+ {
+ TextMessage tm = (TextMessage)cons.receive(5000);
+
+ assertNotNull(tm);
+
+ assertEquals("message" + i, tm.getText());
+
+ assertEquals("uhuh", tm.getStringProperty("wib"));
+ assertTrue(tm.getBooleanProperty("cheese"));
+ assertEquals(23, tm.getIntProperty("Sausages"));
+
+ assertEquals("mygroup543", tm.getStringProperty("JMSXGroupID"));
+ assertEquals(777, tm.getIntProperty("JMSXGroupSeq"));
+
+ if (on)
+ {
+ String header = tm.getStringProperty(JBossMessage.JBOSS_MESSAGING_BRIDGE_MESSAGE_ID_LIST);
+
+ assertNotNull(header);
+
+ assertEquals(ids1.get(i), header);
+
+ msgs.add(tm);
+ }
+ }
+
+ if (on)
+ {
+ //Now we send them again back to the source
+
+ Iterator iter = msgs.iterator();
+
+ List ids2 = new ArrayList();
+
+ while (iter.hasNext())
+ {
+ Message msg = (Message)iter.next();
+
+ prod.send(msg);
+
+ ids2.add(msg.getJMSMessageID());
+ }
+
+ //And consume them again
+
+ for (int i = 0; i < NUM_MESSAGES; i++)
+ {
+ TextMessage tm = (TextMessage)cons.receive(5000);
+
+ assertNotNull(tm);
+
+ assertEquals("message" + i, tm.getText());
+
+ assertEquals("uhuh", tm.getStringProperty("wib"));
+ assertTrue(tm.getBooleanProperty("cheese"));
+ assertEquals(23, tm.getIntProperty("Sausages"));
+
+ assertEquals("mygroup543", tm.getStringProperty("JMSXGroupID"));
+ assertEquals(777, tm.getIntProperty("JMSXGroupSeq"));
+
+ String header = tm.getStringProperty(JBossMessage.JBOSS_MESSAGING_BRIDGE_MESSAGE_ID_LIST);
+
+ assertNotNull(header);
+
+ assertEquals(ids1.get(i) + "," + ids2.get(i), header);
+ }
+ }
+
+ }
+ finally
+ {
+ if (bridge != null)
+ {
+ bridge.stop();
+ }
+
+ if (connSource != null)
+ {
+ connSource.close();
+ }
+
+ if (connTarget != null)
+ {
+ connTarget.close();
+ }
+ }
+ }
+
+
+ public void testPropertiesPreservedPOn() throws Exception
+ {
+ propertiesPreserved(true, true);
+ }
+
+ public void testPropertiesPreservedNPoff() throws Exception
+ {
+ propertiesPreserved(false, true);
+ }
+
+ public void testPropertiesPreservedNPOn() throws Exception
+ {
+ propertiesPreserved(false, true);
+ }
+
+ public void testPropertiesPreservedPoff() throws Exception
+ {
+ propertiesPreserved(true, true);
+ }
+
+ private void propertiesPreserved(boolean persistent, boolean messageIDInHeader) throws Exception
+ {
+ JMSBridgeImpl bridge = null;
+
+ Connection connSource = null;
+
+ Connection connTarget = null;
+
+ try
+ {
+ final int NUM_MESSAGES = 10;
+
+ bridge = new JMSBridgeImpl(cff0, cff1, sourceQueueFactory, targetQueueFactory,
+ null, null, null, null,
+ null, 5000, 10, QualityOfServiceMode.AT_MOST_ONCE,
+ 1, -1,
+ null, null, messageIDInHeader);
+ bridge.setTransactionManager(newTransactionManager());
+
+ bridge.start();
+
+ connSource = cf0.createConnection();
+
+ connTarget = cf1.createConnection();
+
+ log.trace("Sending " + NUM_MESSAGES + " messages");
+
+ Session sessSource = connSource.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ Session sessTarget = connTarget.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ MessageConsumer cons = sessTarget.createConsumer(targetQueue);
+
+ connTarget.start();
+
+ MessageProducer prod = sessSource.createProducer(sourceQueue);
+
+ prod.setDeliveryMode(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT);
+
+
+
+ TextMessage tm = sessSource.createTextMessage("blahmessage");
+
+ prod.setPriority(7);
+
+ prod.setTimeToLive(1 * 60 * 60 * 1000);
+
+ prod.send(tm);
+
+ long expiration = tm.getJMSExpiration();
+
+ assertEquals(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT, tm.getJMSDeliveryMode());
+
+ tm = (TextMessage)cons.receive(1000);
+
+ assertNotNull(tm);
+
+ assertEquals("blahmessage", tm.getText());
+
+ assertEquals(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT, tm.getJMSDeliveryMode());
+
+ assertEquals(7, tm.getJMSPriority());
+
+ assertTrue(Math.abs(expiration - tm.getJMSExpiration()) < 100);
+
+ Message m = cons.receive(5000);
+
+ assertNull(m);
+
+
+ //Now do one with expiration = 0
+
+
+ tm = sessSource.createTextMessage("blahmessage2");
+
+ prod.setPriority(7);
+
+ prod.setTimeToLive(0);
+
+ prod.send(tm);
+
+ assertEquals(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT, tm.getJMSDeliveryMode());
+
+ tm = (TextMessage)cons.receive(1000);
+
+ assertNotNull(tm);
+
+ assertEquals("blahmessage2", tm.getText());
+
+ assertEquals(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT, tm.getJMSDeliveryMode());
+
+ assertEquals(7, tm.getJMSPriority());
+
+ assertEquals(0, tm.getJMSExpiration());
+
+ m = cons.receive(5000);
+
+ assertNull(m);
+
+ tm = sessSource.createTextMessage("blahmessage3");
+
+ final boolean myBool = false;
+ final byte myByte = (byte)23;
+ final double myDouble = 17625765d;
+ final float myFloat = 87127.23f;
+ final int myInt = 123;
+ final long myLong = 81728712;
+ final short myShort = (short)88;
+ final String myString = "ojweodewj";
+ final String myJMSX = "aardvark";
+
+ tm.setBooleanProperty("mybool", myBool);
+ tm.setByteProperty("mybyte", myByte);
+ tm.setDoubleProperty("mydouble", myDouble);
+ tm.setFloatProperty("myfloat", myFloat);
+ tm.setIntProperty("myint", myInt);
+ tm.setLongProperty("mylong", myLong);
+ tm.setShortProperty("myshort", myShort);
+ tm.setStringProperty("mystring", myString);
+
+ tm.setStringProperty("JMSXMyNaughtyJMSXProperty", myJMSX);
+
+ prod.send(tm);
+
+ tm = (TextMessage)cons.receive(5000);
+
+ assertNotNull(tm);
+
+ assertEquals("blahmessage3", tm.getText());
+
+ assertEquals(myBool, tm.getBooleanProperty("mybool"));
+ assertEquals(myByte, tm.getByteProperty("mybyte"));
+ assertEquals(myDouble, tm.getDoubleProperty("mydouble"));
+ assertEquals(myFloat, tm.getFloatProperty("myfloat"));
+ assertEquals(myInt, tm.getIntProperty("myint"));
+ assertEquals(myLong, tm.getLongProperty("mylong"));
+ assertEquals(myShort, tm.getShortProperty("myshort"));
+ assertEquals(myString, tm.getStringProperty("mystring"));
+ assertEquals(myJMSX, tm.getStringProperty("JMSXMyNaughtyJMSXProperty"));
+
+ m = cons.receive(5000);
+
+ }
+ finally
+ {
+ if (bridge != null)
+ {
+ bridge.stop();
+ }
+
+ if (connSource != null)
+ {
+ connSource.close();
+ }
+
+ if (connTarget != null)
+ {
+ connTarget.close();
+ }
+ }
+ }
+
+ public void testNoMessageIDInHeader() throws Exception
+ {
+ JMSBridgeImpl bridge = null;
+
+ Connection connSource = null;
+
+ Connection connTarget = null;
+
+ try
+ {
+ final int NUM_MESSAGES = 10;
+
+ bridge = new JMSBridgeImpl(cff0, cff1, sourceQueueFactory, targetQueueFactory,
+ null, null, null, null,
+ null, 5000, 10, QualityOfServiceMode.AT_MOST_ONCE,
+ 1, -1,
+ null, null, false);
+ bridge.setTransactionManager(newTransactionManager());
+
+ bridge.start();
+
+ connSource = cf0.createConnection();
+
+ connTarget = cf1.createConnection();
+
+ log.trace("Sending " + NUM_MESSAGES + " messages");
+
+ Session sessSource = connSource.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ MessageProducer prod = sessSource.createProducer(sourceQueue);
+
+ for (int i = 0; i < NUM_MESSAGES; i++)
+ {
+ TextMessage tm = sessSource.createTextMessage("message" + i);
+
+ //We add some headers to make sure they get passed through ok
+ tm.setStringProperty("wib", "uhuh");
+ tm.setBooleanProperty("cheese", true);
+ tm.setIntProperty("Sausages", 23);
+
+ prod.send(tm);
+ }
+
+ log.trace("Sent the first messages");
+
+ Session sessTarget = connTarget.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ MessageConsumer cons = sessTarget.createConsumer(targetQueue);
+
+ connTarget.start();
+
+ for (int i = 0; i < NUM_MESSAGES; i++)
+ {
+ TextMessage tm = (TextMessage)cons.receive(5000);
+
+ assertNotNull(tm);
+
+ assertEquals("message" + i, tm.getText());
+
+ assertEquals("uhuh", tm.getStringProperty("wib"));
+ assertTrue(tm.getBooleanProperty("cheese"));
+ assertEquals(23, tm.getIntProperty("Sausages"));
+
+ String header = tm.getStringProperty(JBossMessage.JBOSS_MESSAGING_BRIDGE_MESSAGE_ID_LIST);
+
+ assertNull(header);
+ }
+ }
+ finally
+ {
+ if (bridge != null)
+ {
+ bridge.stop();
+ }
+
+ if (connSource != null)
+ {
+ connSource.close();
+ }
+
+ if (connTarget != null)
+ {
+ connTarget.close();
+ }
+ }
+ }
+
+
+ // Private -------------------------------------------------------------------------------
+
+ private void testStress(QualityOfServiceMode qosMode, boolean persistent, int batchSize) throws Exception
+ {
+ Connection connSource = null;
+
+ JMSBridgeImpl bridge = null;
+
+ Thread t = null;
+
+ try
+ {
+ bridge = new JMSBridgeImpl(cff0, cff1, sourceQueueFactory, targetQueueFactory,
+ null, null, null, null,
+ null, 5000, 10, qosMode,
+ batchSize, -1,
+ null, null, false);
+ bridge.setTransactionManager(newTransactionManager());
+
+ bridge.start();
+
+ connSource = cf0.createConnection();
+
+ Session sessSend = connSource.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ MessageProducer prod = sessSend.createProducer(sourceQueue);
+
+ final int NUM_MESSAGES = 250;
+
+ StressSender sender = new StressSender();
+ sender.sess = sessSend;
+ sender.prod = prod;
+ sender.numMessages = NUM_MESSAGES;
+ prod.setDeliveryMode(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT);
+
+ t = new Thread(sender);
+
+ t.start();
+
+ this.checkAllMessageReceivedInOrder(cf1, targetQueue, 0, NUM_MESSAGES);
+
+ t.join();
+
+ if (sender.ex != null)
+ {
+ //An error occurred during the send
+ throw sender.ex;
+ }
+
+ }
+ finally
+ {
+ if (t != null)
+ {
+ t.join(10000);
+ }
+
+ if (connSource != null)
+ {
+ try
+ {
+ connSource.close();
+ }
+ catch (Exception e)
+ {
+ log.error("Failed to close connection", e);
+ }
+ }
+
+ if (bridge != null)
+ {
+ bridge.stop();
+ }
+ }
+ }
+
+ private void testStressBatchTime(QualityOfServiceMode qosMode, boolean persistent, int maxBatchTime) throws Exception
+ {
+ Connection connSource = null;
+
+ JMSBridgeImpl bridge = null;
+
+ Thread t = null;
+
+ try
+ {
+ bridge = new JMSBridgeImpl(cff0, cff1, sourceQueueFactory, targetQueueFactory,
+ null, null, null, null,
+ null, 5000, 10, qosMode,
+ 2, maxBatchTime,
+ null, null, false);
+ bridge.setTransactionManager(newTransactionManager());
+
+ bridge.start();
+
+ connSource = cf0.createConnection();
+
+ Session sessSend = connSource.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ MessageProducer prod = sessSend.createProducer(sourceQueue);
+
+ final int NUM_MESSAGES = 5000;
+
+ StressSender sender = new StressSender();
+ sender.sess = sessSend;
+ sender.prod = prod;
+ sender.numMessages = NUM_MESSAGES;
+ prod.setDeliveryMode(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT);
+
+ t = new Thread(sender);
+
+ t.start();
+
+ this.checkAllMessageReceivedInOrder(cf1, targetQueue, 0, NUM_MESSAGES);
+
+ t.join();
+
+ if (sender.ex != null)
+ {
+ //An error occurred during the send
+ throw sender.ex;
+ }
+
+ }
+ finally
+ {
+ if (t != null)
+ {
+ t.join(10000);
+ }
+
+ if (connSource != null)
+ {
+ try
+ {
+ connSource.close();
+ }
+ catch (Exception e)
+ {
+ log.error("Failed to close connection", e);
+ }
+ }
+
+ if (bridge != null)
+ {
+ bridge.stop();
+ }
+ }
+ }
+
+ //Both source and destination on same rm
+ private void testStressSameServer(QualityOfServiceMode qosMode, boolean persistent, int batchSize) throws Exception
+ {
+ Connection connSource = null;
+
+ JMSBridgeImpl bridge = null;
+
+ Thread t = null;
+
+ try
+ {
+ bridge = new JMSBridgeImpl(cff0, cff0, sourceQueueFactory, localTargetQueueFactory,
+ null, null, null, null,
+ null, 5000, 10, qosMode,
+ batchSize, -1,
+ null, null, false);
+ bridge.setTransactionManager(newTransactionManager());
+
+ bridge.start();
+
+ connSource = cf0.createConnection();
+
+ Session sessSend = connSource.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ MessageProducer prod = sessSend.createProducer(sourceQueue);
+
+ final int NUM_MESSAGES = 2000;
+
+ StressSender sender = new StressSender();
+ sender.sess = sessSend;
+ sender.prod = prod;
+ sender.numMessages = NUM_MESSAGES;
+ prod.setDeliveryMode(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT);
+
+ t = new Thread(sender);
+
+ t.start();
+
+ this.checkAllMessageReceivedInOrder(cf0, localTargetQueue, 0, NUM_MESSAGES);
+
+ t.join();
+
+ if (sender.ex != null)
+ {
+ //An error occurred during the send
+ throw sender.ex;
+ }
+
+ }
+ finally
+ {
+ if (t != null)
+ {
+ t.join(10000);
+ }
+
+ if (connSource != null)
+ {
+ try
+ {
+ connSource.close();
+ }
+ catch (Exception e)
+ {
+ log.error("Failed to close connection", e);
+ }
+ }
+
+ if (bridge != null)
+ {
+ bridge.stop();
+ }
+ }
+ }
+
+
+ private void testNoMaxBatchTime(QualityOfServiceMode qosMode, boolean persistent) throws Exception
+ {
+ JMSBridgeImpl bridge = null;
+
+ try
+ {
+ final int NUM_MESSAGES = 10;
+
+ bridge = new JMSBridgeImpl(cff0, cff1, sourceQueueFactory, targetQueueFactory,
+ null, null, null, null,
+ null, 5000, 10, qosMode,
+ NUM_MESSAGES, -1,
+ null, null, false);
+ bridge.setTransactionManager(newTransactionManager());
+
+ bridge.start();
+
+ //Send half the messges
+
+ this.sendMessages(cf0, sourceQueue, 0, NUM_MESSAGES / 2, persistent);
+
+ //Verify none are received
+
+ this.checkEmpty(targetQueue, 1);
+
+ //Send the other half
+
+ this.sendMessages(cf0, sourceQueue, NUM_MESSAGES / 2, NUM_MESSAGES / 2, persistent);
+
+ //This should now be receivable
+
+ this.checkAllMessageReceivedInOrder(cf1, targetQueue, 0, NUM_MESSAGES);
+
+ //Send another batch with one more than batch size
+
+ this.sendMessages(cf0, sourceQueue, 0, NUM_MESSAGES + 1, persistent);
+
+ //Make sure only batch size are received
+
+ this.checkAllMessageReceivedInOrder(cf1, targetQueue, 0, NUM_MESSAGES);
+
+ //Final batch
+
+ this.sendMessages(cf0, sourceQueue, 0, NUM_MESSAGES - 1, persistent);
+
+ this.checkAllMessageReceivedInOrder(cf1, targetQueue, NUM_MESSAGES, 1);
+
+ this.checkAllMessageReceivedInOrder(cf1, targetQueue, 0, NUM_MESSAGES - 1);
+ }
+ finally
+ {
+ if (bridge != null)
+ {
+ log.info("Stopping bridge");
+ bridge.stop();
+ }
+ }
+ }
+
+ private void testNoMaxBatchTimeSameServer(QualityOfServiceMode qosMode, boolean persistent) throws Exception
+ {
+ JMSBridgeImpl bridge = null;
+
+ try
+ {
+ final int NUM_MESSAGES = 10;
+
+ bridge = new JMSBridgeImpl(cff0, cff0, sourceQueueFactory, localTargetQueueFactory,
+ null, null, null, null,
+ null, 5000, 10, qosMode,
+ NUM_MESSAGES, -1,
+ null, null, false);
+ bridge.setTransactionManager(newTransactionManager());
+
+ bridge.start();
+
+ this.sendMessages(cf0, sourceQueue, 0, NUM_MESSAGES / 2, persistent);
+
+ this.checkEmpty(targetQueue, 1);
+
+ //Send the other half
+
+ this.sendMessages(cf0, sourceQueue, NUM_MESSAGES / 2, NUM_MESSAGES /2, persistent);
+
+
+ //This should now be receivable
+
+ this.checkAllMessageReceivedInOrder(cf0, localTargetQueue, 0, NUM_MESSAGES);
+
+ this.checkEmpty(localTargetQueue, 0);
+
+ this.checkEmpty(sourceQueue, 0);
+
+ //Send another batch with one more than batch size
+
+ this.sendMessages(cf0, sourceQueue, 0, NUM_MESSAGES + 1, persistent);
+
+ //Make sure only batch size are received
+
+ this.checkAllMessageReceivedInOrder(cf0, localTargetQueue, 0, NUM_MESSAGES);
+
+ //Final batch
+
+ this.sendMessages(cf0, sourceQueue, 0, NUM_MESSAGES - 1, persistent);
+
+ this.checkAllMessageReceivedInOrder(cf0, localTargetQueue, NUM_MESSAGES, 1);
+
+ this.checkAllMessageReceivedInOrder(cf0, localTargetQueue, 0, NUM_MESSAGES - 1);
+ }
+ finally
+ {
+ if (bridge != null)
+ {
+ bridge.stop();
+ }
+ }
+ }
+
+ private void testMaxBatchTime(QualityOfServiceMode qosMode, boolean persistent) throws Exception
+ {
+ JMSBridgeImpl bridge = null;
+
+ try
+ {
+ final long MAX_BATCH_TIME = 3000;
+
+ final int MAX_BATCH_SIZE = 100000; // something big so it won't reach it
+
+ bridge = new JMSBridgeImpl(cff0, cff1, sourceQueueFactory, targetQueueFactory,
+ null, null, null, null,
+ null, 3000, 10, qosMode,
+ MAX_BATCH_SIZE, MAX_BATCH_TIME,
+ null, null, false);
+ bridge.setTransactionManager(newTransactionManager());
+
+ bridge.start();
+
+ final int NUM_MESSAGES = 10;
+
+ //Send some message
+
+ this.sendMessages(cf0, sourceQueue, 0, NUM_MESSAGES, persistent);
+
+ //Verify none are received
+
+ this.checkEmpty(targetQueue, 1);
+
+ //Messages should now be receivable
+
+ this.checkAllMessageReceivedInOrder(cf1, targetQueue, 0, NUM_MESSAGES);
+ }
+ finally
+ {
+ if (bridge != null)
+ {
+ bridge.stop();
+ }
+ }
+ }
+
+ private void testMaxBatchTimeSameServer(QualityOfServiceMode qosMode, boolean persistent) throws Exception
+ {
+ JMSBridgeImpl bridge = null;
+
+ try
+ {
+ final long MAX_BATCH_TIME = 3000;
+
+ final int MAX_BATCH_SIZE = 100000; // something big so it won't reach it
+
+ bridge = new JMSBridgeImpl(cff0, cff0, sourceQueueFactory, localTargetQueueFactory,
+ null, null, null, null,
+ null, 3000, 10, qosMode,
+ MAX_BATCH_SIZE, MAX_BATCH_TIME,
+ null, null, false);
+ bridge.setTransactionManager(newTransactionManager());
+
+ bridge.start();
+
+ final int NUM_MESSAGES = 10;
+
+ //Send some message
+
+ //Send some message
+
+ this.sendMessages(cf0, sourceQueue, 0, NUM_MESSAGES, persistent);
+
+ //Verify none are received
+
+ this.checkEmpty(localTargetQueue, 0);;
+
+ //Messages should now be receivable
+
+ this.checkAllMessageReceivedInOrder(cf0, localTargetQueue, 0, NUM_MESSAGES);
+ }
+ finally
+ {
+ if (bridge != null)
+ {
+ bridge.stop();
+ }
+ }
+ }
+
+
+ // Inner classes -------------------------------------------------------------------
+
+ private static class StressSender implements Runnable
+ {
+ int numMessages;
+
+ Session sess;
+
+ MessageProducer prod;
+
+ Exception ex;
+
+ public void run()
+ {
+ try
+ {
+ for (int i = 0; i < numMessages; i++)
+ {
+ TextMessage tm = sess.createTextMessage("message" + i);
+
+ prod.send(tm);
+
+ log.trace("Sent message " + i);
+ }
+ }
+ catch (Exception e)
+ {
+ log.error("Failed to send", e);
+ ex = e;
+ }
+ }
+
+ }
+}
Deleted: trunk/tests/src/org/jboss/messaging/tests/timing/jms/bridge/impl/BridgeImplTest.java
===================================================================
--- trunk/tests/src/org/jboss/messaging/tests/timing/jms/bridge/impl/BridgeImplTest.java 2009-04-03 14:08:30 UTC (rev 6298)
+++ trunk/tests/src/org/jboss/messaging/tests/timing/jms/bridge/impl/BridgeImplTest.java 2009-04-03 14:12:53 UTC (rev 6299)
@@ -1,519 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2008, Red Hat Middleware LLC, and individual contributors
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-
-package org.jboss.messaging.tests.timing.jms.bridge.impl;
-
-import static org.easymock.EasyMock.anyBoolean;
-import static org.easymock.EasyMock.anyInt;
-import static org.easymock.EasyMock.createNiceMock;
-import static org.easymock.EasyMock.createStrictMock;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.expectLastCall;
-import static org.easymock.EasyMock.getCurrentArguments;
-import static org.easymock.EasyMock.isA;
-import static org.easymock.EasyMock.replay;
-import static org.easymock.EasyMock.verify;
-
-import javax.jms.Connection;
-import javax.jms.ConnectionFactory;
-import javax.jms.Destination;
-import javax.jms.ExceptionListener;
-import javax.jms.JMSException;
-import javax.jms.Message;
-import javax.jms.MessageConsumer;
-import javax.jms.MessageListener;
-import javax.jms.MessageProducer;
-import javax.jms.Session;
-import javax.transaction.TransactionManager;
-
-import org.easymock.IAnswer;
-import org.jboss.messaging.jms.bridge.ConnectionFactoryFactory;
-import org.jboss.messaging.jms.bridge.DestinationFactory;
-import org.jboss.messaging.jms.bridge.QualityOfServiceMode;
-import org.jboss.messaging.jms.bridge.impl.BridgeImpl;
-import org.jboss.messaging.tests.util.UnitTestCase;
-
-/**
- * @author <a href="mailto:jmesnil at redhat.com">Jeff Mesnil</a>
- *
- * @version <tt>$Revision$</tt>
- *
- */
-public class BridgeImplTest extends UnitTestCase
-{
- // Constants -----------------------------------------------------
-
- // Attributes ----------------------------------------------------
-
- // Static --------------------------------------------------------
-
- // Constructors --------------------------------------------------
-
- // Public --------------------------------------------------------
-
- public void testStartWithRepeatedFailure() throws Exception
- {
- ConnectionFactoryFactory sourceCFF = createStrictMock(ConnectionFactoryFactory.class);
- ConnectionFactory sourceCF = createStrictMock(ConnectionFactory.class);
- Connection sourceConn = createStrictMock(Connection.class);
- Session sourceSession = createStrictMock(Session.class);
- MessageConsumer sourceConsumer = createStrictMock(MessageConsumer.class);
- DestinationFactory sourceDF = createStrictMock(DestinationFactory.class);
- Destination sourceDest = createStrictMock(Destination.class);
- ConnectionFactoryFactory targetCFF = createStrictMock(ConnectionFactoryFactory.class);
- ConnectionFactory targetCF = createStrictMock(ConnectionFactory.class);
- Connection targetConn = createStrictMock(Connection.class);
- Session targetSession = createStrictMock(Session.class);
- MessageProducer targetProducer = createStrictMock(MessageProducer.class);
- DestinationFactory targetDF = createStrictMock(DestinationFactory.class);
- Destination targetDest = createStrictMock(Destination.class);
- TransactionManager tm = createStrictMock(TransactionManager.class);
-
- expect(tm.suspend()).andReturn(null);
- expect(sourceDF.createDestination()).andStubReturn(sourceDest);
- expect(targetDF.createDestination()).andStubReturn(targetDest);
- expect(sourceCFF.createConnectionFactory()).andStubReturn(sourceCF);
- // the source connection can not be created
- expect(sourceCF.createConnection()).andStubThrow(
- new JMSException("unable to create a conn"));
-
- replay(sourceCFF, sourceCF, sourceConn, sourceSession, sourceConsumer,
- sourceDF, sourceDest);
- replay(targetCFF, targetCF, targetConn, targetSession, targetProducer,
- targetDF, targetDest);
- replay(tm);
-
- BridgeImpl bridge = new BridgeImpl();
-
- bridge.setSourceConnectionFactoryFactory(sourceCFF);
- bridge.setSourceDestinationFactory(sourceDF);
- bridge.setTargetConnectionFactoryFactory(targetCFF);
- bridge.setTargetDestinationFactory(targetDF);
- // retry after 10 ms
- bridge.setFailureRetryInterval(10);
- // retry only once
- bridge.setMaxRetries(1);
- bridge.setMaxBatchSize(1);
- bridge.setMaxBatchTime(-1);
- bridge.setTransactionManager(tm);
- bridge.setQualityOfServiceMode(QualityOfServiceMode.AT_MOST_ONCE);
-
- assertFalse(bridge.isStarted());
- bridge.start();
-
- Thread.sleep(50);
- assertFalse(bridge.isStarted());
- assertTrue(bridge.isFailed());
-
- verify(sourceCFF, sourceCF, sourceConn, sourceSession, sourceConsumer,
- sourceDF, sourceDest);
- verify(targetCFF, targetCF, targetConn, targetSession, targetProducer,
- targetDF, targetDest);
- verify(tm);
- }
-
- public void testStartWithFailureThenSuccess() throws Exception
- {
- ConnectionFactoryFactory sourceCFF = createStrictMock(ConnectionFactoryFactory.class);
- ConnectionFactory sourceCF = createStrictMock(ConnectionFactory.class);
- Connection sourceConn = createStrictMock(Connection.class);
- Session sourceSession = createStrictMock(Session.class);
- MessageConsumer sourceConsumer = createStrictMock(MessageConsumer.class);
- DestinationFactory sourceDF = createStrictMock(DestinationFactory.class);
- Destination sourceDest = createStrictMock(Destination.class);
- ConnectionFactoryFactory targetCFF = createStrictMock(ConnectionFactoryFactory.class);
- ConnectionFactory targetCF = createStrictMock(ConnectionFactory.class);
- Connection targetConn = createStrictMock(Connection.class);
- Session targetSession = createStrictMock(Session.class);
- MessageProducer targetProducer = createStrictMock(MessageProducer.class);
- DestinationFactory targetDF = createStrictMock(DestinationFactory.class);
- Destination targetDest = createStrictMock(Destination.class);
- TransactionManager tm = createStrictMock(TransactionManager.class);
-
- expect(tm.suspend()).andReturn(null);
- expect(sourceDF.createDestination()).andStubReturn(sourceDest);
- expect(targetDF.createDestination()).andStubReturn(targetDest);
- expect(sourceCFF.createConnectionFactory()).andStubReturn(sourceCF);
- // the source connection can not be created the 1st time...
- expect(sourceCF.createConnection()).andThrow(
- new JMSException("unable to create a conn"));
- // ... and it succeeds the 2nd time
- expect(sourceCF.createConnection()).andReturn(sourceConn);
- sourceConn.setExceptionListener(isA(ExceptionListener.class));
- expect(sourceConn.createSession(anyBoolean(), anyInt())).andReturn(
- sourceSession);
- expect(sourceSession.createConsumer(sourceDest))
- .andReturn(sourceConsumer);
- sourceConsumer.setMessageListener(isA(MessageListener.class));
- expect(targetCFF.createConnectionFactory()).andReturn(targetCF);
- expect(targetCF.createConnection()).andReturn(targetConn);
- targetConn.setExceptionListener(isA(ExceptionListener.class));
- expect(targetConn.createSession(anyBoolean(), anyInt())).andReturn(
- targetSession);
- expect(targetSession.createProducer(null)).andReturn(targetProducer);
- sourceConn.start();
-
- replay(sourceCFF, sourceCF, sourceConn, sourceSession, sourceConsumer,
- sourceDF, sourceDest);
- replay(targetCFF, targetCF, targetConn, targetSession, targetProducer,
- targetDF, targetDest);
- replay(tm);
-
- BridgeImpl bridge = new BridgeImpl();
-
- bridge.setSourceConnectionFactoryFactory(sourceCFF);
- bridge.setSourceDestinationFactory(sourceDF);
- bridge.setTargetConnectionFactoryFactory(targetCFF);
- bridge.setTargetDestinationFactory(targetDF);
- // retry after 10 ms
- bridge.setFailureRetryInterval(10);
- // retry only once
- bridge.setMaxRetries(1);
- bridge.setMaxBatchSize(1);
- bridge.setMaxBatchTime(-1);
- bridge.setTransactionManager(tm);
- bridge.setQualityOfServiceMode(QualityOfServiceMode.AT_MOST_ONCE);
-
- assertFalse(bridge.isStarted());
- bridge.start();
-
- Thread.sleep(50);
- assertTrue(bridge.isStarted());
- assertFalse(bridge.isFailed());
-
- verify(sourceCFF, sourceCF, sourceConn, sourceSession, sourceConsumer,
- sourceDF, sourceDest);
- verify(targetCFF, targetCF, targetConn, targetSession, targetProducer,
- targetDF, targetDest);
- verify(tm);
- }
-
- /*
- * we receive only 1 message. The message is sent when the maxBatchTime
- * expires even if the maxBatchSize is not reached
- */
- public void testSendMessagesWhenMaxBatchTimeExpires() throws Exception
- {
- int maxBatchSize = 2;
- long maxBatchTime = 500;
-
- ConnectionFactoryFactory sourceCFF = createStrictMock(ConnectionFactoryFactory.class);
- ConnectionFactory sourceCF = createStrictMock(ConnectionFactory.class);
- Connection sourceConn = createStrictMock(Connection.class);
- Session sourceSession = createStrictMock(Session.class);
- MessageConsumer sourceConsumer = createStrictMock(MessageConsumer.class);
- DestinationFactory sourceDF = createStrictMock(DestinationFactory.class);
- Destination sourceDest = createStrictMock(Destination.class);
- ConnectionFactoryFactory targetCFF = createStrictMock(ConnectionFactoryFactory.class);
- ConnectionFactory targetCF = createStrictMock(ConnectionFactory.class);
- Connection targetConn = createStrictMock(Connection.class);
- Session targetSession = createStrictMock(Session.class);
- MessageProducer targetProducer = createStrictMock(MessageProducer.class);
- DestinationFactory targetDF = createStrictMock(DestinationFactory.class);
- Destination targetDest = createStrictMock(Destination.class);
- TransactionManager tm = createStrictMock(TransactionManager.class);
- Message message = createNiceMock(Message.class);
-
- expect(tm.suspend()).andReturn(null);
- expect(sourceDF.createDestination()).andReturn(sourceDest);
- expect(targetDF.createDestination()).andReturn(targetDest);
- expect(sourceCFF.createConnectionFactory()).andReturn(sourceCF);
- expect(sourceCF.createConnection()).andReturn(sourceConn);
- sourceConn.setExceptionListener(isA(ExceptionListener.class));
- expect(sourceConn.createSession(anyBoolean(), anyInt())).andReturn(
- sourceSession);
- expect(sourceSession.createConsumer(sourceDest))
- .andReturn(sourceConsumer);
- SetMessageListenerAnswer answer = new SetMessageListenerAnswer();
- sourceConsumer.setMessageListener(isA(MessageListener.class));
- expectLastCall().andAnswer(answer);
- expect(targetCFF.createConnectionFactory()).andReturn(targetCF);
- expect(targetCF.createConnection()).andReturn(targetConn);
- targetConn.setExceptionListener(isA(ExceptionListener.class));
- expect(targetConn.createSession(anyBoolean(), anyInt())).andReturn(
- targetSession);
- expect(targetSession.createProducer(null)).andReturn(targetProducer);
- sourceConn.start();
-
- targetProducer.send(targetDest, message, 0, 0, 0);
- targetSession.commit();
-
- replay(sourceCFF, sourceCF, sourceConn, sourceSession, sourceConsumer,
- sourceDF, sourceDest);
- replay(targetCFF, targetCF, targetConn, targetSession, targetProducer,
- targetDF, targetDest);
- replay(tm);
- replay(message);
-
- BridgeImpl bridge = new BridgeImpl();
- assertNotNull(bridge);
-
- bridge.setSourceConnectionFactoryFactory(sourceCFF);
- bridge.setSourceDestinationFactory(sourceDF);
- bridge.setTargetConnectionFactoryFactory(targetCFF);
- bridge.setTargetDestinationFactory(targetDF);
- bridge.setFailureRetryInterval(-1);
- bridge.setMaxRetries(-1);
- bridge.setMaxBatchSize(maxBatchSize);
- bridge.setMaxBatchTime(maxBatchTime);
- bridge.setTransactionManager(tm);
- bridge.setQualityOfServiceMode(QualityOfServiceMode.AT_MOST_ONCE);
-
- assertFalse(bridge.isStarted());
- bridge.start();
- assertTrue(bridge.isStarted());
-
- answer.listener.onMessage(message);
-
- Thread.sleep(3 * maxBatchTime);
-
- verify(sourceCFF, sourceCF, sourceConn, sourceSession, sourceConsumer,
- sourceDF, sourceDest);
- verify(targetCFF, targetCF, targetConn, targetSession, targetProducer,
- targetDF, targetDest);
- verify(tm);
- verify(message);
- }
-
- public void testExceptionOnSourceAndRetrySucceeds() throws Exception
- {
- ConnectionFactoryFactory sourceCFF = createStrictMock(ConnectionFactoryFactory.class);
- ConnectionFactory sourceCF = createStrictMock(ConnectionFactory.class);
- Connection sourceConn = createStrictMock(Connection.class);
- Session sourceSession = createStrictMock(Session.class);
- MessageConsumer sourceConsumer = createStrictMock(MessageConsumer.class);
- DestinationFactory sourceDF = createStrictMock(DestinationFactory.class);
- Destination sourceDest = createStrictMock(Destination.class);
- ConnectionFactoryFactory targetCFF = createStrictMock(ConnectionFactoryFactory.class);
- ConnectionFactory targetCF = createStrictMock(ConnectionFactory.class);
- Connection targetConn = createStrictMock(Connection.class);
- Session targetSession = createStrictMock(Session.class);
- MessageProducer targetProducer = createStrictMock(MessageProducer.class);
- DestinationFactory targetDF = createStrictMock(DestinationFactory.class);
- Destination targetDest = createStrictMock(Destination.class);
- TransactionManager tm = createStrictMock(TransactionManager.class);
- Message message = createNiceMock(Message.class);
-
- expect(tm.suspend()).andReturn(null);
- expect(sourceDF.createDestination()).andReturn(sourceDest);
- expect(targetDF.createDestination()).andReturn(targetDest);
- expect(sourceCFF.createConnectionFactory()).andReturn(sourceCF);
- expect(sourceCF.createConnection()).andReturn(sourceConn);
- SetExceptionListenerAnswer exceptionListenerAnswer = new SetExceptionListenerAnswer();
- sourceConn.setExceptionListener(isA(ExceptionListener.class));
- expectLastCall().andAnswer(exceptionListenerAnswer);
- expect(sourceConn.createSession(anyBoolean(), anyInt())).andReturn(
- sourceSession);
- expect(sourceSession.createConsumer(sourceDest))
- .andReturn(sourceConsumer);
- sourceConsumer.setMessageListener(isA(MessageListener.class));
- expect(targetCFF.createConnectionFactory()).andReturn(targetCF);
- expect(targetCF.createConnection()).andReturn(targetConn);
- targetConn.setExceptionListener(isA(ExceptionListener.class));
- expect(targetConn.createSession(anyBoolean(), anyInt())).andReturn(
- targetSession);
- expect(targetSession.createProducer(null)).andReturn(targetProducer);
- sourceConn.start();
-
- //after failure detection, we retry to start the bridge:
- expect(sourceDF.createDestination()).andReturn(sourceDest);
- expect(targetDF.createDestination()).andReturn(targetDest);
- expect(sourceCFF.createConnectionFactory()).andReturn(sourceCF);
- expect(sourceCF.createConnection()).andReturn(sourceConn);
- sourceConn.setExceptionListener(isA(ExceptionListener.class));
- expectLastCall().andAnswer(exceptionListenerAnswer);
- expect(sourceConn.createSession(anyBoolean(), anyInt())).andReturn(
- sourceSession);
- expect(sourceSession.createConsumer(sourceDest))
- .andReturn(sourceConsumer);
- sourceConsumer.setMessageListener(isA(MessageListener.class));
- expect(targetCFF.createConnectionFactory()).andReturn(targetCF);
- expect(targetCF.createConnection()).andReturn(targetConn);
- targetConn.setExceptionListener(isA(ExceptionListener.class));
- expect(targetConn.createSession(anyBoolean(), anyInt())).andReturn(
- targetSession);
- expect(targetSession.createProducer(null)).andReturn(targetProducer);
- sourceConn.start();
-
-
- replay(sourceCFF, sourceCF, sourceConn, sourceSession, sourceConsumer,
- sourceDF, sourceDest);
- replay(targetCFF, targetCF, targetConn, targetSession, targetProducer,
- targetDF, targetDest);
- replay(tm);
- replay(message);
-
- BridgeImpl bridge = new BridgeImpl();
- assertNotNull(bridge);
-
- bridge.setSourceConnectionFactoryFactory(sourceCFF);
- bridge.setSourceDestinationFactory(sourceDF);
- bridge.setTargetConnectionFactoryFactory(targetCFF);
- bridge.setTargetDestinationFactory(targetDF);
- bridge.setFailureRetryInterval(10);
- bridge.setMaxRetries(2);
- bridge.setMaxBatchSize(1);
- bridge.setMaxBatchTime(-1);
- bridge.setTransactionManager(tm);
- bridge.setQualityOfServiceMode(QualityOfServiceMode.AT_MOST_ONCE);
-
- assertFalse(bridge.isStarted());
- bridge.start();
- assertTrue(bridge.isStarted());
-
- exceptionListenerAnswer.listener.onException(new JMSException("exception on the source"));
- Thread.sleep(4 * bridge.getFailureRetryInterval());
- // reconnection must have succeded
- assertTrue(bridge.isStarted());
-
- verify(sourceCFF, sourceCF, sourceConn, sourceSession, sourceConsumer,
- sourceDF, sourceDest);
- verify(targetCFF, targetCF, targetConn, targetSession, targetProducer,
- targetDF, targetDest);
- verify(tm);
- verify(message);
- }
-
- public void testExceptionOnSourceAndRetryFails() throws Exception
- {
- ConnectionFactoryFactory sourceCFF = createStrictMock(ConnectionFactoryFactory.class);
- ConnectionFactory sourceCF = createStrictMock(ConnectionFactory.class);
- Connection sourceConn = createStrictMock(Connection.class);
- Session sourceSession = createStrictMock(Session.class);
- MessageConsumer sourceConsumer = createStrictMock(MessageConsumer.class);
- DestinationFactory sourceDF = createStrictMock(DestinationFactory.class);
- Destination sourceDest = createStrictMock(Destination.class);
- ConnectionFactoryFactory targetCFF = createStrictMock(ConnectionFactoryFactory.class);
- ConnectionFactory targetCF = createStrictMock(ConnectionFactory.class);
- Connection targetConn = createStrictMock(Connection.class);
- Session targetSession = createStrictMock(Session.class);
- MessageProducer targetProducer = createStrictMock(MessageProducer.class);
- DestinationFactory targetDF = createStrictMock(DestinationFactory.class);
- Destination targetDest = createStrictMock(Destination.class);
- TransactionManager tm = createStrictMock(TransactionManager.class);
- Message message = createNiceMock(Message.class);
-
- expect(tm.suspend()).andReturn(null);
- expect(sourceDF.createDestination()).andReturn(sourceDest);
- expect(targetDF.createDestination()).andReturn(targetDest);
- expect(sourceCFF.createConnectionFactory()).andReturn(sourceCF);
- expect(sourceCF.createConnection()).andReturn(sourceConn);
- SetExceptionListenerAnswer exceptionListenerAnswer = new SetExceptionListenerAnswer();
- sourceConn.setExceptionListener(isA(ExceptionListener.class));
- expectLastCall().andAnswer(exceptionListenerAnswer);
- expect(sourceConn.createSession(anyBoolean(), anyInt())).andReturn(
- sourceSession);
- expect(sourceSession.createConsumer(sourceDest))
- .andReturn(sourceConsumer);
- sourceConsumer.setMessageListener(isA(MessageListener.class));
- expect(targetCFF.createConnectionFactory()).andReturn(targetCF);
- expect(targetCF.createConnection()).andReturn(targetConn);
- targetConn.setExceptionListener(isA(ExceptionListener.class));
- expect(targetConn.createSession(anyBoolean(), anyInt())).andReturn(
- targetSession);
- expect(targetSession.createProducer(null)).andReturn(targetProducer);
- sourceConn.start();
-
- //after failure detection, we clean up...
- // and it is stopped
- sourceConn.close();
- targetConn.close();
- // ...retry to start the bridge but it fails...
- expect(sourceDF.createDestination()).andReturn(sourceDest);
- expect(targetDF.createDestination()).andReturn(targetDest);
- expect(sourceCFF.createConnectionFactory()).andReturn(sourceCF);
- expect(sourceCF.createConnection()).andThrow(new JMSException("exception while retrying to connect"));
- // ... so we clean up again...
- sourceConn.close();
- targetConn.close();
- // ... and finally stop the bridge
- sourceConn.close();
- targetConn.close();
-
- replay(sourceCFF, sourceCF, sourceConn, sourceSession, sourceConsumer,
- sourceDF, sourceDest);
- replay(targetCFF, targetCF, targetConn, targetSession, targetProducer,
- targetDF, targetDest);
- replay(tm);
- replay(message);
-
- BridgeImpl bridge = new BridgeImpl();
- assertNotNull(bridge);
-
- bridge.setSourceConnectionFactoryFactory(sourceCFF);
- bridge.setSourceDestinationFactory(sourceDF);
- bridge.setTargetConnectionFactoryFactory(targetCFF);
- bridge.setTargetDestinationFactory(targetDF);
- bridge.setFailureRetryInterval(10);
- bridge.setMaxRetries(1);
- bridge.setMaxBatchSize(1);
- bridge.setMaxBatchTime(-1);
- bridge.setTransactionManager(tm);
- bridge.setQualityOfServiceMode(QualityOfServiceMode.AT_MOST_ONCE);
-
- assertFalse(bridge.isStarted());
- bridge.start();
- assertTrue(bridge.isStarted());
-
- exceptionListenerAnswer.listener.onException(new JMSException("exception on the source"));
- Thread.sleep(4 * bridge.getFailureRetryInterval());
- // reconnection must have failed
- assertFalse(bridge.isStarted());
-
- verify(sourceCFF, sourceCF, sourceConn, sourceSession, sourceConsumer,
- sourceDF, sourceDest);
- verify(targetCFF, targetCF, targetConn, targetSession, targetProducer,
- targetDF, targetDest);
- verify(tm);
- verify(message);
- }
-
- // Package protected ---------------------------------------------
-
- // Protected -----------------------------------------------------
-
- // Private -------------------------------------------------------
-
- // Inner classes -------------------------------------------------
-
- class SetExceptionListenerAnswer implements IAnswer
- {
- ExceptionListener listener = null;
-
- public Object answer() throws Throwable
- {
- listener = (ExceptionListener) getCurrentArguments()[0];
- return null;
- }
- }
-
- class SetMessageListenerAnswer implements IAnswer
- {
- MessageListener listener = null;
-
- public Object answer() throws Throwable
- {
- listener = (MessageListener) getCurrentArguments()[0];
- return null;
- }
- }
-}
Copied: trunk/tests/src/org/jboss/messaging/tests/timing/jms/bridge/impl/JMSBridgeImplTest.java (from rev 6295, trunk/tests/src/org/jboss/messaging/tests/timing/jms/bridge/impl/BridgeImplTest.java)
===================================================================
--- trunk/tests/src/org/jboss/messaging/tests/timing/jms/bridge/impl/JMSBridgeImplTest.java (rev 0)
+++ trunk/tests/src/org/jboss/messaging/tests/timing/jms/bridge/impl/JMSBridgeImplTest.java 2009-04-03 14:12:53 UTC (rev 6299)
@@ -0,0 +1,519 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.messaging.tests.timing.jms.bridge.impl;
+
+import static org.easymock.EasyMock.anyBoolean;
+import static org.easymock.EasyMock.anyInt;
+import static org.easymock.EasyMock.createNiceMock;
+import static org.easymock.EasyMock.createStrictMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.easymock.EasyMock.getCurrentArguments;
+import static org.easymock.EasyMock.isA;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.Destination;
+import javax.jms.ExceptionListener;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageListener;
+import javax.jms.MessageProducer;
+import javax.jms.Session;
+import javax.transaction.TransactionManager;
+
+import org.easymock.IAnswer;
+import org.jboss.messaging.jms.bridge.ConnectionFactoryFactory;
+import org.jboss.messaging.jms.bridge.DestinationFactory;
+import org.jboss.messaging.jms.bridge.QualityOfServiceMode;
+import org.jboss.messaging.jms.bridge.impl.JMSBridgeImpl;
+import org.jboss.messaging.tests.util.UnitTestCase;
+
+/**
+ * @author <a href="mailto:jmesnil at redhat.com">Jeff Mesnil</a>
+ *
+ * @version <tt>$Revision$</tt>
+ *
+ */
+public class JMSBridgeImplTest extends UnitTestCase
+{
+ // Constants -----------------------------------------------------
+
+ // Attributes ----------------------------------------------------
+
+ // Static --------------------------------------------------------
+
+ // Constructors --------------------------------------------------
+
+ // Public --------------------------------------------------------
+
+ public void testStartWithRepeatedFailure() throws Exception
+ {
+ ConnectionFactoryFactory sourceCFF = createStrictMock(ConnectionFactoryFactory.class);
+ ConnectionFactory sourceCF = createStrictMock(ConnectionFactory.class);
+ Connection sourceConn = createStrictMock(Connection.class);
+ Session sourceSession = createStrictMock(Session.class);
+ MessageConsumer sourceConsumer = createStrictMock(MessageConsumer.class);
+ DestinationFactory sourceDF = createStrictMock(DestinationFactory.class);
+ Destination sourceDest = createStrictMock(Destination.class);
+ ConnectionFactoryFactory targetCFF = createStrictMock(ConnectionFactoryFactory.class);
+ ConnectionFactory targetCF = createStrictMock(ConnectionFactory.class);
+ Connection targetConn = createStrictMock(Connection.class);
+ Session targetSession = createStrictMock(Session.class);
+ MessageProducer targetProducer = createStrictMock(MessageProducer.class);
+ DestinationFactory targetDF = createStrictMock(DestinationFactory.class);
+ Destination targetDest = createStrictMock(Destination.class);
+ TransactionManager tm = createStrictMock(TransactionManager.class);
+
+ expect(tm.suspend()).andReturn(null);
+ expect(sourceDF.createDestination()).andStubReturn(sourceDest);
+ expect(targetDF.createDestination()).andStubReturn(targetDest);
+ expect(sourceCFF.createConnectionFactory()).andStubReturn(sourceCF);
+ // the source connection can not be created
+ expect(sourceCF.createConnection()).andStubThrow(
+ new JMSException("unable to create a conn"));
+
+ replay(sourceCFF, sourceCF, sourceConn, sourceSession, sourceConsumer,
+ sourceDF, sourceDest);
+ replay(targetCFF, targetCF, targetConn, targetSession, targetProducer,
+ targetDF, targetDest);
+ replay(tm);
+
+ JMSBridgeImpl bridge = new JMSBridgeImpl();
+
+ bridge.setSourceConnectionFactoryFactory(sourceCFF);
+ bridge.setSourceDestinationFactory(sourceDF);
+ bridge.setTargetConnectionFactoryFactory(targetCFF);
+ bridge.setTargetDestinationFactory(targetDF);
+ // retry after 10 ms
+ bridge.setFailureRetryInterval(10);
+ // retry only once
+ bridge.setMaxRetries(1);
+ bridge.setMaxBatchSize(1);
+ bridge.setMaxBatchTime(-1);
+ bridge.setTransactionManager(tm);
+ bridge.setQualityOfServiceMode(QualityOfServiceMode.AT_MOST_ONCE);
+
+ assertFalse(bridge.isStarted());
+ bridge.start();
+
+ Thread.sleep(50);
+ assertFalse(bridge.isStarted());
+ assertTrue(bridge.isFailed());
+
+ verify(sourceCFF, sourceCF, sourceConn, sourceSession, sourceConsumer,
+ sourceDF, sourceDest);
+ verify(targetCFF, targetCF, targetConn, targetSession, targetProducer,
+ targetDF, targetDest);
+ verify(tm);
+ }
+
+ public void testStartWithFailureThenSuccess() throws Exception
+ {
+ ConnectionFactoryFactory sourceCFF = createStrictMock(ConnectionFactoryFactory.class);
+ ConnectionFactory sourceCF = createStrictMock(ConnectionFactory.class);
+ Connection sourceConn = createStrictMock(Connection.class);
+ Session sourceSession = createStrictMock(Session.class);
+ MessageConsumer sourceConsumer = createStrictMock(MessageConsumer.class);
+ DestinationFactory sourceDF = createStrictMock(DestinationFactory.class);
+ Destination sourceDest = createStrictMock(Destination.class);
+ ConnectionFactoryFactory targetCFF = createStrictMock(ConnectionFactoryFactory.class);
+ ConnectionFactory targetCF = createStrictMock(ConnectionFactory.class);
+ Connection targetConn = createStrictMock(Connection.class);
+ Session targetSession = createStrictMock(Session.class);
+ MessageProducer targetProducer = createStrictMock(MessageProducer.class);
+ DestinationFactory targetDF = createStrictMock(DestinationFactory.class);
+ Destination targetDest = createStrictMock(Destination.class);
+ TransactionManager tm = createStrictMock(TransactionManager.class);
+
+ expect(tm.suspend()).andReturn(null);
+ expect(sourceDF.createDestination()).andStubReturn(sourceDest);
+ expect(targetDF.createDestination()).andStubReturn(targetDest);
+ expect(sourceCFF.createConnectionFactory()).andStubReturn(sourceCF);
+ // the source connection can not be created the 1st time...
+ expect(sourceCF.createConnection()).andThrow(
+ new JMSException("unable to create a conn"));
+ // ... and it succeeds the 2nd time
+ expect(sourceCF.createConnection()).andReturn(sourceConn);
+ sourceConn.setExceptionListener(isA(ExceptionListener.class));
+ expect(sourceConn.createSession(anyBoolean(), anyInt())).andReturn(
+ sourceSession);
+ expect(sourceSession.createConsumer(sourceDest))
+ .andReturn(sourceConsumer);
+ sourceConsumer.setMessageListener(isA(MessageListener.class));
+ expect(targetCFF.createConnectionFactory()).andReturn(targetCF);
+ expect(targetCF.createConnection()).andReturn(targetConn);
+ targetConn.setExceptionListener(isA(ExceptionListener.class));
+ expect(targetConn.createSession(anyBoolean(), anyInt())).andReturn(
+ targetSession);
+ expect(targetSession.createProducer(null)).andReturn(targetProducer);
+ sourceConn.start();
+
+ replay(sourceCFF, sourceCF, sourceConn, sourceSession, sourceConsumer,
+ sourceDF, sourceDest);
+ replay(targetCFF, targetCF, targetConn, targetSession, targetProducer,
+ targetDF, targetDest);
+ replay(tm);
+
+ JMSBridgeImpl bridge = new JMSBridgeImpl();
+
+ bridge.setSourceConnectionFactoryFactory(sourceCFF);
+ bridge.setSourceDestinationFactory(sourceDF);
+ bridge.setTargetConnectionFactoryFactory(targetCFF);
+ bridge.setTargetDestinationFactory(targetDF);
+ // retry after 10 ms
+ bridge.setFailureRetryInterval(10);
+ // retry only once
+ bridge.setMaxRetries(1);
+ bridge.setMaxBatchSize(1);
+ bridge.setMaxBatchTime(-1);
+ bridge.setTransactionManager(tm);
+ bridge.setQualityOfServiceMode(QualityOfServiceMode.AT_MOST_ONCE);
+
+ assertFalse(bridge.isStarted());
+ bridge.start();
+
+ Thread.sleep(50);
+ assertTrue(bridge.isStarted());
+ assertFalse(bridge.isFailed());
+
+ verify(sourceCFF, sourceCF, sourceConn, sourceSession, sourceConsumer,
+ sourceDF, sourceDest);
+ verify(targetCFF, targetCF, targetConn, targetSession, targetProducer,
+ targetDF, targetDest);
+ verify(tm);
+ }
+
+ /*
+ * we receive only 1 message. The message is sent when the maxBatchTime
+ * expires even if the maxBatchSize is not reached
+ */
+ public void testSendMessagesWhenMaxBatchTimeExpires() throws Exception
+ {
+ int maxBatchSize = 2;
+ long maxBatchTime = 500;
+
+ ConnectionFactoryFactory sourceCFF = createStrictMock(ConnectionFactoryFactory.class);
+ ConnectionFactory sourceCF = createStrictMock(ConnectionFactory.class);
+ Connection sourceConn = createStrictMock(Connection.class);
+ Session sourceSession = createStrictMock(Session.class);
+ MessageConsumer sourceConsumer = createStrictMock(MessageConsumer.class);
+ DestinationFactory sourceDF = createStrictMock(DestinationFactory.class);
+ Destination sourceDest = createStrictMock(Destination.class);
+ ConnectionFactoryFactory targetCFF = createStrictMock(ConnectionFactoryFactory.class);
+ ConnectionFactory targetCF = createStrictMock(ConnectionFactory.class);
+ Connection targetConn = createStrictMock(Connection.class);
+ Session targetSession = createStrictMock(Session.class);
+ MessageProducer targetProducer = createStrictMock(MessageProducer.class);
+ DestinationFactory targetDF = createStrictMock(DestinationFactory.class);
+ Destination targetDest = createStrictMock(Destination.class);
+ TransactionManager tm = createStrictMock(TransactionManager.class);
+ Message message = createNiceMock(Message.class);
+
+ expect(tm.suspend()).andReturn(null);
+ expect(sourceDF.createDestination()).andReturn(sourceDest);
+ expect(targetDF.createDestination()).andReturn(targetDest);
+ expect(sourceCFF.createConnectionFactory()).andReturn(sourceCF);
+ expect(sourceCF.createConnection()).andReturn(sourceConn);
+ sourceConn.setExceptionListener(isA(ExceptionListener.class));
+ expect(sourceConn.createSession(anyBoolean(), anyInt())).andReturn(
+ sourceSession);
+ expect(sourceSession.createConsumer(sourceDest))
+ .andReturn(sourceConsumer);
+ SetMessageListenerAnswer answer = new SetMessageListenerAnswer();
+ sourceConsumer.setMessageListener(isA(MessageListener.class));
+ expectLastCall().andAnswer(answer);
+ expect(targetCFF.createConnectionFactory()).andReturn(targetCF);
+ expect(targetCF.createConnection()).andReturn(targetConn);
+ targetConn.setExceptionListener(isA(ExceptionListener.class));
+ expect(targetConn.createSession(anyBoolean(), anyInt())).andReturn(
+ targetSession);
+ expect(targetSession.createProducer(null)).andReturn(targetProducer);
+ sourceConn.start();
+
+ targetProducer.send(targetDest, message, 0, 0, 0);
+ targetSession.commit();
+
+ replay(sourceCFF, sourceCF, sourceConn, sourceSession, sourceConsumer,
+ sourceDF, sourceDest);
+ replay(targetCFF, targetCF, targetConn, targetSession, targetProducer,
+ targetDF, targetDest);
+ replay(tm);
+ replay(message);
+
+ JMSBridgeImpl bridge = new JMSBridgeImpl();
+ assertNotNull(bridge);
+
+ bridge.setSourceConnectionFactoryFactory(sourceCFF);
+ bridge.setSourceDestinationFactory(sourceDF);
+ bridge.setTargetConnectionFactoryFactory(targetCFF);
+ bridge.setTargetDestinationFactory(targetDF);
+ bridge.setFailureRetryInterval(-1);
+ bridge.setMaxRetries(-1);
+ bridge.setMaxBatchSize(maxBatchSize);
+ bridge.setMaxBatchTime(maxBatchTime);
+ bridge.setTransactionManager(tm);
+ bridge.setQualityOfServiceMode(QualityOfServiceMode.AT_MOST_ONCE);
+
+ assertFalse(bridge.isStarted());
+ bridge.start();
+ assertTrue(bridge.isStarted());
+
+ answer.listener.onMessage(message);
+
+ Thread.sleep(3 * maxBatchTime);
+
+ verify(sourceCFF, sourceCF, sourceConn, sourceSession, sourceConsumer,
+ sourceDF, sourceDest);
+ verify(targetCFF, targetCF, targetConn, targetSession, targetProducer,
+ targetDF, targetDest);
+ verify(tm);
+ verify(message);
+ }
+
+ public void testExceptionOnSourceAndRetrySucceeds() throws Exception
+ {
+ ConnectionFactoryFactory sourceCFF = createStrictMock(ConnectionFactoryFactory.class);
+ ConnectionFactory sourceCF = createStrictMock(ConnectionFactory.class);
+ Connection sourceConn = createStrictMock(Connection.class);
+ Session sourceSession = createStrictMock(Session.class);
+ MessageConsumer sourceConsumer = createStrictMock(MessageConsumer.class);
+ DestinationFactory sourceDF = createStrictMock(DestinationFactory.class);
+ Destination sourceDest = createStrictMock(Destination.class);
+ ConnectionFactoryFactory targetCFF = createStrictMock(ConnectionFactoryFactory.class);
+ ConnectionFactory targetCF = createStrictMock(ConnectionFactory.class);
+ Connection targetConn = createStrictMock(Connection.class);
+ Session targetSession = createStrictMock(Session.class);
+ MessageProducer targetProducer = createStrictMock(MessageProducer.class);
+ DestinationFactory targetDF = createStrictMock(DestinationFactory.class);
+ Destination targetDest = createStrictMock(Destination.class);
+ TransactionManager tm = createStrictMock(TransactionManager.class);
+ Message message = createNiceMock(Message.class);
+
+ expect(tm.suspend()).andReturn(null);
+ expect(sourceDF.createDestination()).andReturn(sourceDest);
+ expect(targetDF.createDestination()).andReturn(targetDest);
+ expect(sourceCFF.createConnectionFactory()).andReturn(sourceCF);
+ expect(sourceCF.createConnection()).andReturn(sourceConn);
+ SetExceptionListenerAnswer exceptionListenerAnswer = new SetExceptionListenerAnswer();
+ sourceConn.setExceptionListener(isA(ExceptionListener.class));
+ expectLastCall().andAnswer(exceptionListenerAnswer);
+ expect(sourceConn.createSession(anyBoolean(), anyInt())).andReturn(
+ sourceSession);
+ expect(sourceSession.createConsumer(sourceDest))
+ .andReturn(sourceConsumer);
+ sourceConsumer.setMessageListener(isA(MessageListener.class));
+ expect(targetCFF.createConnectionFactory()).andReturn(targetCF);
+ expect(targetCF.createConnection()).andReturn(targetConn);
+ targetConn.setExceptionListener(isA(ExceptionListener.class));
+ expect(targetConn.createSession(anyBoolean(), anyInt())).andReturn(
+ targetSession);
+ expect(targetSession.createProducer(null)).andReturn(targetProducer);
+ sourceConn.start();
+
+ //after failure detection, we retry to start the bridge:
+ expect(sourceDF.createDestination()).andReturn(sourceDest);
+ expect(targetDF.createDestination()).andReturn(targetDest);
+ expect(sourceCFF.createConnectionFactory()).andReturn(sourceCF);
+ expect(sourceCF.createConnection()).andReturn(sourceConn);
+ sourceConn.setExceptionListener(isA(ExceptionListener.class));
+ expectLastCall().andAnswer(exceptionListenerAnswer);
+ expect(sourceConn.createSession(anyBoolean(), anyInt())).andReturn(
+ sourceSession);
+ expect(sourceSession.createConsumer(sourceDest))
+ .andReturn(sourceConsumer);
+ sourceConsumer.setMessageListener(isA(MessageListener.class));
+ expect(targetCFF.createConnectionFactory()).andReturn(targetCF);
+ expect(targetCF.createConnection()).andReturn(targetConn);
+ targetConn.setExceptionListener(isA(ExceptionListener.class));
+ expect(targetConn.createSession(anyBoolean(), anyInt())).andReturn(
+ targetSession);
+ expect(targetSession.createProducer(null)).andReturn(targetProducer);
+ sourceConn.start();
+
+
+ replay(sourceCFF, sourceCF, sourceConn, sourceSession, sourceConsumer,
+ sourceDF, sourceDest);
+ replay(targetCFF, targetCF, targetConn, targetSession, targetProducer,
+ targetDF, targetDest);
+ replay(tm);
+ replay(message);
+
+ JMSBridgeImpl bridge = new JMSBridgeImpl();
+ assertNotNull(bridge);
+
+ bridge.setSourceConnectionFactoryFactory(sourceCFF);
+ bridge.setSourceDestinationFactory(sourceDF);
+ bridge.setTargetConnectionFactoryFactory(targetCFF);
+ bridge.setTargetDestinationFactory(targetDF);
+ bridge.setFailureRetryInterval(10);
+ bridge.setMaxRetries(2);
+ bridge.setMaxBatchSize(1);
+ bridge.setMaxBatchTime(-1);
+ bridge.setTransactionManager(tm);
+ bridge.setQualityOfServiceMode(QualityOfServiceMode.AT_MOST_ONCE);
+
+ assertFalse(bridge.isStarted());
+ bridge.start();
+ assertTrue(bridge.isStarted());
+
+ exceptionListenerAnswer.listener.onException(new JMSException("exception on the source"));
+ Thread.sleep(4 * bridge.getFailureRetryInterval());
+ // reconnection must have succeded
+ assertTrue(bridge.isStarted());
+
+ verify(sourceCFF, sourceCF, sourceConn, sourceSession, sourceConsumer,
+ sourceDF, sourceDest);
+ verify(targetCFF, targetCF, targetConn, targetSession, targetProducer,
+ targetDF, targetDest);
+ verify(tm);
+ verify(message);
+ }
+
+ public void testExceptionOnSourceAndRetryFails() throws Exception
+ {
+ ConnectionFactoryFactory sourceCFF = createStrictMock(ConnectionFactoryFactory.class);
+ ConnectionFactory sourceCF = createStrictMock(ConnectionFactory.class);
+ Connection sourceConn = createStrictMock(Connection.class);
+ Session sourceSession = createStrictMock(Session.class);
+ MessageConsumer sourceConsumer = createStrictMock(MessageConsumer.class);
+ DestinationFactory sourceDF = createStrictMock(DestinationFactory.class);
+ Destination sourceDest = createStrictMock(Destination.class);
+ ConnectionFactoryFactory targetCFF = createStrictMock(ConnectionFactoryFactory.class);
+ ConnectionFactory targetCF = createStrictMock(ConnectionFactory.class);
+ Connection targetConn = createStrictMock(Connection.class);
+ Session targetSession = createStrictMock(Session.class);
+ MessageProducer targetProducer = createStrictMock(MessageProducer.class);
+ DestinationFactory targetDF = createStrictMock(DestinationFactory.class);
+ Destination targetDest = createStrictMock(Destination.class);
+ TransactionManager tm = createStrictMock(TransactionManager.class);
+ Message message = createNiceMock(Message.class);
+
+ expect(tm.suspend()).andReturn(null);
+ expect(sourceDF.createDestination()).andReturn(sourceDest);
+ expect(targetDF.createDestination()).andReturn(targetDest);
+ expect(sourceCFF.createConnectionFactory()).andReturn(sourceCF);
+ expect(sourceCF.createConnection()).andReturn(sourceConn);
+ SetExceptionListenerAnswer exceptionListenerAnswer = new SetExceptionListenerAnswer();
+ sourceConn.setExceptionListener(isA(ExceptionListener.class));
+ expectLastCall().andAnswer(exceptionListenerAnswer);
+ expect(sourceConn.createSession(anyBoolean(), anyInt())).andReturn(
+ sourceSession);
+ expect(sourceSession.createConsumer(sourceDest))
+ .andReturn(sourceConsumer);
+ sourceConsumer.setMessageListener(isA(MessageListener.class));
+ expect(targetCFF.createConnectionFactory()).andReturn(targetCF);
+ expect(targetCF.createConnection()).andReturn(targetConn);
+ targetConn.setExceptionListener(isA(ExceptionListener.class));
+ expect(targetConn.createSession(anyBoolean(), anyInt())).andReturn(
+ targetSession);
+ expect(targetSession.createProducer(null)).andReturn(targetProducer);
+ sourceConn.start();
+
+ //after failure detection, we clean up...
+ // and it is stopped
+ sourceConn.close();
+ targetConn.close();
+ // ...retry to start the bridge but it fails...
+ expect(sourceDF.createDestination()).andReturn(sourceDest);
+ expect(targetDF.createDestination()).andReturn(targetDest);
+ expect(sourceCFF.createConnectionFactory()).andReturn(sourceCF);
+ expect(sourceCF.createConnection()).andThrow(new JMSException("exception while retrying to connect"));
+ // ... so we clean up again...
+ sourceConn.close();
+ targetConn.close();
+ // ... and finally stop the bridge
+ sourceConn.close();
+ targetConn.close();
+
+ replay(sourceCFF, sourceCF, sourceConn, sourceSession, sourceConsumer,
+ sourceDF, sourceDest);
+ replay(targetCFF, targetCF, targetConn, targetSession, targetProducer,
+ targetDF, targetDest);
+ replay(tm);
+ replay(message);
+
+ JMSBridgeImpl bridge = new JMSBridgeImpl();
+ assertNotNull(bridge);
+
+ bridge.setSourceConnectionFactoryFactory(sourceCFF);
+ bridge.setSourceDestinationFactory(sourceDF);
+ bridge.setTargetConnectionFactoryFactory(targetCFF);
+ bridge.setTargetDestinationFactory(targetDF);
+ bridge.setFailureRetryInterval(10);
+ bridge.setMaxRetries(1);
+ bridge.setMaxBatchSize(1);
+ bridge.setMaxBatchTime(-1);
+ bridge.setTransactionManager(tm);
+ bridge.setQualityOfServiceMode(QualityOfServiceMode.AT_MOST_ONCE);
+
+ assertFalse(bridge.isStarted());
+ bridge.start();
+ assertTrue(bridge.isStarted());
+
+ exceptionListenerAnswer.listener.onException(new JMSException("exception on the source"));
+ Thread.sleep(4 * bridge.getFailureRetryInterval());
+ // reconnection must have failed
+ assertFalse(bridge.isStarted());
+
+ verify(sourceCFF, sourceCF, sourceConn, sourceSession, sourceConsumer,
+ sourceDF, sourceDest);
+ verify(targetCFF, targetCF, targetConn, targetSession, targetProducer,
+ targetDF, targetDest);
+ verify(tm);
+ verify(message);
+ }
+
+ // Package protected ---------------------------------------------
+
+ // Protected -----------------------------------------------------
+
+ // Private -------------------------------------------------------
+
+ // Inner classes -------------------------------------------------
+
+ class SetExceptionListenerAnswer implements IAnswer
+ {
+ ExceptionListener listener = null;
+
+ public Object answer() throws Throwable
+ {
+ listener = (ExceptionListener) getCurrentArguments()[0];
+ return null;
+ }
+ }
+
+ class SetMessageListenerAnswer implements IAnswer
+ {
+ MessageListener listener = null;
+
+ public Object answer() throws Throwable
+ {
+ listener = (MessageListener) getCurrentArguments()[0];
+ return null;
+ }
+ }
+}
More information about the jboss-cvs-commits
mailing list