/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.network;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.net.URI;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Session;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.advisory.AdvisoryBroker;
import org.apache.activemq.broker.BrokerPlugin;
import org.apache.activemq.broker.BrokerService;
import org.apache.activemq.broker.TransportConnector;
import org.apache.activemq.broker.region.DestinationStatistics;
import org.apache.activemq.broker.region.virtual.CompositeTopic;
import org.apache.activemq.broker.region.virtual.VirtualDestination;
import org.apache.activemq.command.ActiveMQDestination;
import org.apache.activemq.command.ActiveMQQueue;
import org.apache.activemq.command.ActiveMQTopic;
import org.apache.activemq.command.CommandTypes;
import org.apache.activemq.plugin.java.JavaRuntimeConfigurationBroker;
import org.apache.activemq.plugin.java.JavaRuntimeConfigurationPlugin;
import org.apache.activemq.store.kahadb.KahaDBPersistenceAdapter;
import org.apache.activemq.store.kahadb.disk.journal.Journal.JournalDiskSyncStrategy;
import org.apache.activemq.util.Wait;
import org.apache.activemq.util.Wait.Condition;
import org.junit.After;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.Timeout;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.Lists;
@RunWith(Parameterized.class)
public class DurableSyncNetworkBridgeTest extends DynamicNetworkTestSupport {
protected static final Logger LOG = LoggerFactory.getLogger(DurableSyncNetworkBridgeTest.class);
protected JavaRuntimeConfigurationBroker remoteRuntimeBroker;
protected String staticIncludeTopics = "include.static.test";
protected String includedTopics = "include.test.>";
protected String testTopicName2 = "include.test.bar2";
private boolean dynamicOnly = false;
private boolean forceDurable = false;
private boolean useVirtualDestSubs = false;
private byte remoteBrokerWireFormatVersion = CommandTypes.PROTOCOL_VERSION;
public static enum FLOW {FORWARD, REVERSE}
private BrokerService broker1;
private BrokerService broker2;
private Session session1;
private Session session2;
private final FLOW flow;
@Rule
public Timeout globalTimeout = new Timeout(30, TimeUnit.SECONDS);
@Parameters
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][] {
{FLOW.FORWARD},
{FLOW.REVERSE}
});
}
public static final String KEYSTORE_TYPE = "jks";
public static final String PASSWORD = "password";
public static final String SERVER_KEYSTORE = "src/test/resources/server.keystore";
public static final String TRUST_KEYSTORE = "src/test/resources/client.keystore";
static {
System.setProperty("javax.net.ssl.trustStore", TRUST_KEYSTORE);
System.setProperty("javax.net.ssl.trustStorePassword", PASSWORD);
System.setProperty("javax.net.ssl.trustStoreType", KEYSTORE_TYPE);
System.setProperty("javax.net.ssl.keyStore", SERVER_KEYSTORE);
System.setProperty("javax.net.ssl.keyStoreType", KEYSTORE_TYPE);
System.setProperty("javax.net.ssl.keyStorePassword", PASSWORD);
}
public DurableSyncNetworkBridgeTest(final FLOW flow) {
this.flow = flow;
}
@Before
public void setUp() throws Exception {
includedTopics = "include.test.>";
staticIncludeTopics = "include.static.test";
dynamicOnly = false;
forceDurable = false;
useVirtualDestSubs = false;
remoteBrokerWireFormatVersion = CommandTypes.PROTOCOL_VERSION;
doSetUp(true, true, tempFolder.newFolder(), tempFolder.newFolder());
}
@After
public void tearDown() throws Exception {
doTearDown();
}
@Test
public void testRemoveSubscriptionPropagate() throws Exception {
final ActiveMQTopic topic = new ActiveMQTopic(testTopicName);
MessageConsumer sub1 = session1.createDurableSubscriber(topic, subName);
sub1.close();
assertSubscriptionsCount(broker1, topic, 1);
assertNCDurableSubsCount(broker2, topic, 1);
removeSubscription(broker1, topic, subName);
assertSubscriptionsCount(broker1, topic, 0);
assertNCDurableSubsCount(broker2, topic, 0);
}
@Test
public void testRemoveSubscriptionPropegateAfterRestart() throws Exception {
final ActiveMQTopic topic = new ActiveMQTopic(testTopicName);
MessageConsumer sub1 = session1.createDurableSubscriber(topic, subName);
sub1.close();
assertSubscriptionsCount(broker1, topic, 1);
assertNCDurableSubsCount(broker2, topic, 1);
restartBrokers(true);
assertBridgeStarted();
assertSubscriptionsCount(broker1, topic, 1);
assertNCDurableSubsCount(broker2, topic, 1);
removeSubscription(broker1, topic, subName);
assertSubscriptionsCount(broker1, topic, 0);
assertNCDurableSubsCount(broker2, topic, 0);
}
@Test
public void testRemoveSubscriptionWithBridgeOffline() throws Exception {
final ActiveMQTopic topic = new ActiveMQTopic(testTopicName);
MessageConsumer sub1 = session1.createDurableSubscriber(topic, subName);
sub1.close();
assertSubscriptionsCount(broker1, topic, 1);
assertNCDurableSubsCount(broker2, topic, 1);
doTearDown();
restartBroker(broker1, false);
restartBroker(broker2, false);
//Send some messages to the NC sub and make sure it can still be deleted
MessageProducer prod = session2.createProducer(topic);
for (int i = 0; i < 10; i++) {
prod.send(session2.createTextMessage("test"));
}
assertSubscriptionsCount(broker1, topic, 1);
removeSubscription(broker1, topic, subName);
assertSubscriptionsCount(broker1, topic, 0);
doTearDown();
//Test that on successful reconnection of the bridge that
//the NC sub will be removed
restartBroker(broker2, true);
assertNCDurableSubsCount(broker2, topic, 1);
restartBroker(broker1, true);
assertBridgeStarted();
assertNCDurableSubsCount(broker2, topic, 0);
}
@Test
public void testRemoveSubscriptionWithBridgeOfflineIncludedChanged() throws Exception {
final ActiveMQTopic topic = new ActiveMQTopic(testTopicName);
MessageConsumer sub1 = session1.createDurableSubscriber(topic, subName);
sub1.close();
assertSubscriptionsCount(broker1, topic, 1);
assertNCDurableSubsCount(broker2, topic, 1);
doTearDown();
//change the included topics to make sure we still cleanup non-matching NC durables
includedTopics = "different.topic";
restartBroker(broker1, false);
assertSubscriptionsCount(broker1, topic, 1);
removeSubscription(broker1, topic, subName);
assertSubscriptionsCount(broker1, topic, 0);
//Test that on successful reconnection of the bridge that
//the NC sub will be removed
restartBroker(broker2, true);
assertNCDurableSubsCount(broker2, topic, 1);
restartBroker(broker1, true);
assertBridgeStarted();
assertNCDurableSubsCount(broker2, topic, 0);
}
@Test
public void testSubscriptionRemovedAfterIncludedChanged() throws Exception {
final ActiveMQTopic topic = new ActiveMQTopic(testTopicName);
MessageConsumer sub1 = session1.createDurableSubscriber(topic, subName);
sub1.close();
assertSubscriptionsCount(broker1, topic, 1);
assertNCDurableSubsCount(broker2, topic, 1);
doTearDown();
//change the included topics to make sure we still cleanup non-matching NC durables
includedTopics = "different.topic";
restartBroker(broker1, false);
assertSubscriptionsCount(broker1, topic, 1);
//Test that on successful reconnection of the bridge that
//the NC sub will be removed because even though the local subscription exists,
//it no longer matches the included filter
restartBroker(broker2, true);
assertNCDurableSubsCount(broker2, topic, 1);
restartBroker(broker1, true);
assertBridgeStarted();
assertNCDurableSubsCount(broker2, topic, 0);
assertSubscriptionsCount(broker1, topic, 1);
}
@Test
public void testSubscriptionRemovedAfterStaticChanged() throws Exception {
forceDurable = true;
this.restartBrokers(true);
final ActiveMQTopic topic = new ActiveMQTopic(this.staticIncludeTopics);
MessageConsumer sub1 = session1.createDurableSubscriber(topic, subName);
sub1.close();
assertSubscriptionsCount(broker1, topic, 1);
assertNCDurableSubsCount(broker2, topic, 1);
doTearDown();
//change the included topics to make sure we still cleanup non-matching NC durables
staticIncludeTopics = "different.topic";
this.restartBrokers(false);
assertSubscriptionsCount(broker1, topic, 1);
assertNCDurableSubsCount(broker2, topic, 1);
//Send some messages to the NC sub and make sure it can still be deleted
MessageProducer prod = session2.createProducer(topic);
for (int i = 0; i < 10; i++) {
prod.send(session2.createTextMessage("test"));
}
//Test that on successful reconnection of the bridge that
//the NC sub will be removed because even though the local subscription exists,
//it no longer matches the included static filter
restartBroker(broker2, true);
assertNCDurableSubsCount(broker2, topic, 1);
restartBroker(broker1, true);
assertBridgeStarted();
assertNCDurableSubsCount(broker2, topic, 0);
assertSubscriptionsCount(broker1, topic, 1);
}
@Test
public void testAddAndRemoveSubscriptionWithBridgeOfflineMultiTopics() throws Exception {
final ActiveMQTopic topic = new ActiveMQTopic(testTopicName);
final ActiveMQTopic topic2 = new ActiveMQTopic(testTopicName2);
MessageConsumer sub1 = session1.createDurableSubscriber(topic, subName);
sub1.close();
assertSubscriptionsCount(broker1, topic, 1);
assertNCDurableSubsCount(broker2, topic, 1);
doTearDown();
restartBroker(broker1, false);
assertSubscriptionsCount(broker1, topic, 1);
session1.createDurableSubscriber(topic2, "sub2");
removeSubscription(broker1, topic, subName);
assertSubscriptionsCount(broker1, topic, 0);
assertSubscriptionsCount(broker1, topic2, 1);
//Test that on successful reconnection of the bridge that
//the NC sub will be removed for topic1 but will stay for topic2
//before sync, the old NC should exist
restartBroker(broker2, true);
assertNCDurableSubsCount(broker2, topic, 1);
assertNCDurableSubsCount(broker2, topic2, 0);
//After sync, remove old NC and create one for topic 2
restartBroker(broker1, true);
assertBridgeStarted();
assertNCDurableSubsCount(broker2, topic, 0);
assertNCDurableSubsCount(broker2, topic2, 1);
}
@Test
public void testAddSubscriptionsWithBridgeOffline() throws Exception {
final ActiveMQTopic topic = new ActiveMQTopic(testTopicName);
final ActiveMQTopic topic2 = new ActiveMQTopic(testTopicName2);
final ActiveMQTopic excludeTopic = new ActiveMQTopic(excludeTopicName);
assertSubscriptionsCount(broker1, topic, 0);
assertNCDurableSubsCount(broker2, topic, 0);
doTearDown();
restartBroker(broker1, false);
assertSubscriptionsCount(broker1, topic, 0);
//add three subs, should only create 2 NC subs because of conduit
session1.createDurableSubscriber(topic, subName).close();
session1.createDurableSubscriber(topic, "sub2").close();
session1.createDurableSubscriber(topic2, "sub3").close();
assertSubscriptionsCount(broker1, topic, 2);
assertSubscriptionsCount(broker1, topic2, 1);
restartBrokers(true);
assertBridgeStarted();
assertNCDurableSubsCount(broker2, topic, 1);
assertNCDurableSubsCount(broker2, topic2, 1);
assertNCDurableSubsCount(broker2, excludeTopic, 0);
}
@Test
public void testSyncLoadTest() throws Exception {
String subName = this.subName;
//Create 1000 subs
for (int i = 0; i < 100; i++) {
for (int j = 0; j < 10; j++) {
session1.createDurableSubscriber(new ActiveMQTopic("include.test." + i), subName + i + j).close();
}
}
for (int i = 0; i < 100; i++) {
assertNCDurableSubsCount(broker2, new ActiveMQTopic("include.test." + i), 1);
}
doTearDown();
restartBroker(broker1, false);
//with bridge off, remove 100 subs
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
removeSubscription(broker1, new ActiveMQTopic("include.test." + i), subName + i + j);
}
}
//restart test that 900 are resynced and 100 are deleted
restartBrokers(true);
for (int i = 0; i < 10; i++) {
assertNCDurableSubsCount(broker2, new ActiveMQTopic("include.test." + i), 0);
}
for (int i = 10; i < 100; i++) {
assertNCDurableSubsCount(broker2, new ActiveMQTopic("include.test." + i), 1);
}
assertBridgeStarted();
}
/**
* Using an older version of openwire should not sync but the network bridge
* should still start without error
*/
@Test
public void testAddSubscriptionsWithBridgeOfflineOpenWire11() throws Exception {
this.remoteBrokerWireFormatVersion = CommandTypes.PROTOCOL_VERSION_DURABLE_SYNC - 1;
final ActiveMQTopic topic = new ActiveMQTopic(testTopicName);
assertSubscriptionsCount(broker1, topic, 0);
assertNCDurableSubsCount(broker2, topic, 0);
doTearDown();
restartBroker(broker1, false);
assertSubscriptionsCount(broker1, topic, 0);
session1.createDurableSubscriber(topic, subName).close();
assertSubscriptionsCount(broker1, topic, 1);
//Since we are using an old version of openwire, the NC should
//not be added
restartBrokers(true);
assertNCDurableSubsCount(broker2, topic, 0);
assertBridgeStarted();
}
@Test
public void testAddOfflineSubscriptionWithBridgeOfflineDynamicTrue() throws Exception {
//set dynamicOnly to true
this.dynamicOnly = true;
final ActiveMQTopic topic = new ActiveMQTopic(testTopicName);
assertSubscriptionsCount(broker1, topic, 0);
assertNCDurableSubsCount(broker2, topic, 0);
doTearDown();
restartBroker(broker1, false);
assertSubscriptionsCount(broker1, topic, 0);
session1.createDurableSubscriber(topic, subName).close();
assertSubscriptionsCount(broker1, topic, 1);
restartBrokers(true);
assertNCDurableSubsCount(broker2, topic, 0);
assertBridgeStarted();
}
@Test
public void testAddOnlineSubscriptionWithBridgeOfflineDynamicTrue() throws Exception {
//set dynamicOnly to true
this.dynamicOnly = true;
final ActiveMQTopic topic = new ActiveMQTopic(testTopicName);
assertSubscriptionsCount(broker1, topic, 0);
assertNCDurableSubsCount(broker2, topic, 0);
doTearDown();
restartBroker(broker1, false);
assertSubscriptionsCount(broker1, topic, 0);
session1.createDurableSubscriber(topic, subName).close();
assertSubscriptionsCount(broker1, topic, 1);
restartBrokers(true);
assertNCDurableSubsCount(broker2, topic, 0);
//bring online again
session1.createDurableSubscriber(topic, subName);
assertNCDurableSubsCount(broker2, topic, 1);
assertBridgeStarted();
}
@Test
public void testAddAndRemoveSubscriptionsWithBridgeOffline() throws Exception {
final ActiveMQTopic topic = new ActiveMQTopic(testTopicName);
final ActiveMQTopic excludeTopic = new ActiveMQTopic(excludeTopicName);
session1.createDurableSubscriber(topic, subName).close();
assertSubscriptionsCount(broker1, topic, 1);
assertNCDurableSubsCount(broker2, topic, 1);
doTearDown();
restartBroker(broker1, false);
assertSubscriptionsCount(broker1, topic, 1);
removeSubscription(broker1, topic, subName);
session1.createDurableSubscriber(topic, "sub2").close();
assertSubscriptionsCount(broker1, topic, 1);
restartBrokers(true);
assertNCDurableSubsCount(broker2, topic, 1);
assertNCDurableSubsCount(broker2, excludeTopic, 0);
assertBridgeStarted();
}
@Test
public void testAddOnlineSubscriptionsWithBridgeOffline() throws Exception {
Assume.assumeTrue(flow == FLOW.FORWARD);
final ActiveMQTopic topic = new ActiveMQTopic(testTopicName);
final ActiveMQTopic excludeTopic = new ActiveMQTopic(excludeTopicName);
assertSubscriptionsCount(broker1, topic, 0);
assertNCDurableSubsCount(broker2, topic, 0);
doTearDown();
restartBrokers(false);
assertSubscriptionsCount(broker1, topic, 0);
//create durable that shouldn't be propagated
session1.createDurableSubscriber(excludeTopic, "sub-exclude");
//Add 3 online subs
session1.createDurableSubscriber(topic, subName);
session1.createDurableSubscriber(topic, "sub2");
session1.createDurableSubscriber(topic, "sub3");
assertSubscriptionsCount(broker1, topic, 3);
//Restart brokers and make sure we don't have duplicate NCs created
//between the sync command and the online durables that are added over
//the consumer advisory
restartBrokers(true);
assertBridgeStarted();
//Re-create
session1.createDurableSubscriber(topic, subName);
session1.createDurableSubscriber(topic, "sub2");
session1.createDurableSubscriber(topic, "sub3");
session1.createDurableSubscriber(excludeTopic, "sub-exclude");
Thread.sleep(1000);
assertNCDurableSubsCount(broker2, topic, 1);
assertNCDurableSubsCount(broker2, excludeTopic, 0);
}
//Test that durable sync works with more than one bridge
@Test
public void testAddOnlineSubscriptionsTwoBridges() throws Exception {
final ActiveMQTopic topic = new ActiveMQTopic(testTopicName);
final ActiveMQTopic excludeTopic = new ActiveMQTopic(excludeTopicName);
final ActiveMQTopic topic2 = new ActiveMQTopic("include.new.topic");
assertSubscriptionsCount(broker1, topic, 0);
assertNCDurableSubsCount(broker2, topic, 0);
//create durable that shouldn't be propagated
session1.createDurableSubscriber(excludeTopic, "sub-exclude");
//Add 3 online subs
session1.createDurableSubscriber(topic, subName);
session1.createDurableSubscriber(topic, "sub2");
session1.createDurableSubscriber(topic, "sub3");
//Add sub on second topic/bridge
session1.createDurableSubscriber(topic2, "secondTopicSubName");
assertSubscriptionsCount(broker1, topic, 3);
assertSubscriptionsCount(broker1, topic2, 1);
//Add the second network connector
NetworkConnector secondConnector = configureLocalNetworkConnector();
secondConnector.setName("networkConnector2");
secondConnector.setDynamicallyIncludedDestinations(
Lists.<ActiveMQDestination>newArrayList(
new ActiveMQTopic("include.new.topic?forceDurable=" + forceDurable)));
localBroker.addNetworkConnector(secondConnector);
secondConnector.start();
//Make sure both bridges are connected
assertTrue(Wait.waitFor(new Condition() {
@Override
public boolean isSatisified() throws Exception {
return localBroker.getNetworkConnectors().get(0).activeBridges().size() == 1 &&
localBroker.getNetworkConnectors().get(1).activeBridges().size() == 1;
}
}, 10000, 500));
//Make sure NC durables exist for both bridges
assertNCDurableSubsCount(broker2, topic2, 1);
assertNCDurableSubsCount(broker2, topic, 1);
assertNCDurableSubsCount(broker2, excludeTopic, 0);
//Make sure message can reach remote broker
MessageProducer producer = session2.createProducer(topic2);
producer.send(session2.createTextMessage("test"));
waitForDispatchFromLocalBroker(broker2.getDestination(topic2).getDestinationStatistics(), 1);
assertLocalBrokerStatistics(broker2.getDestination(topic2).getDestinationStatistics(), 1);
}
@Test(timeout = 60 * 1000)
public void testVirtualDestSubForceDurableSync() throws Exception {
Assume.assumeTrue(flow == FLOW.FORWARD);
forceDurable = true;
useVirtualDestSubs = true;
this.restartBrokers(true);
//configure a virtual destination that forwards messages from topic testQueueName
CompositeTopic compositeTopic = createCompositeTopic(testTopicName,
new ActiveMQQueue("include.test.bar.bridge"));
remoteRuntimeBroker.setVirtualDestinations(new VirtualDestination[] {compositeTopic}, true);
MessageProducer includedProducer = localSession.createProducer(included);
Message test = localSession.createTextMessage("test");
final DestinationStatistics destinationStatistics = localBroker.getDestination(included).getDestinationStatistics();
final DestinationStatistics remoteDestStatistics = remoteBroker.getDestination(
new ActiveMQQueue("include.test.bar.bridge")).getDestinationStatistics();
//Make sure that the NC durable is created because of the compositeTopic
waitForConsumerCount(destinationStatistics, 1);
assertNCDurableSubsCount(localBroker, included, 1);
//Send message and make sure it is dispatched across the bridge
includedProducer.send(test);
waitForDispatchFromLocalBroker(destinationStatistics, 1);
assertLocalBrokerStatistics(destinationStatistics, 1);
assertEquals("remote dest messages", 1, remoteDestStatistics.getMessages().getCount());
//Stop the remote broker so the bridge stops and then send 500 messages so
//the messages build up on the NC durable
this.stopRemoteBroker();
for (int i = 0; i < 500; i++) {
includedProducer.send(test);
}
this.stopLocalBroker();
//Restart the brokers
this.restartRemoteBroker();
remoteRuntimeBroker.setVirtualDestinations(new VirtualDestination[] {compositeTopic}, true);
this.restartLocalBroker(true);
//We now need to verify that 501 messages made it to the queue on the remote side
//which means that the NC durable was not deleted and recreated during the sync
final DestinationStatistics remoteDestStatistics2 = remoteBroker.getDestination(
new ActiveMQQueue("include.test.bar.bridge")).getDestinationStatistics();
assertTrue(Wait.waitFor(new Condition() {
@Override
public boolean isSatisified() throws Exception {
return remoteDestStatistics2.getMessages().getCount() == 501;
}
}));
}
@Test(timeout = 60 * 1000)
public void testForceDurableTopicSubSync() throws Exception {
Assume.assumeTrue(flow == FLOW.FORWARD);
forceDurable = true;
this.restartBrokers(true);
//configure a virtual destination that forwards messages from topic testQueueName
remoteSession.createConsumer(included);
MessageProducer includedProducer = localSession.createProducer(included);
Message test = localSession.createTextMessage("test");
final DestinationStatistics destinationStatistics = localBroker.getDestination(included).getDestinationStatistics();
//Make sure that the NC durable is created because of the compositeTopic
waitForConsumerCount(destinationStatistics, 1);
assertNCDurableSubsCount(localBroker, included, 1);
//Send message and make sure it is dispatched across the bridge
includedProducer.send(test);
waitForDispatchFromLocalBroker(destinationStatistics, 1);
assertLocalBrokerStatistics(destinationStatistics, 1);
//Stop the network connector and send messages to the local broker so they build
//up on the durable
this.localBroker.getNetworkConnectorByName("networkConnector").stop();
for (int i = 0; i < 500; i++) {
includedProducer.send(test);
}
//restart the local broker and bridge
this.stopLocalBroker();
this.restartLocalBroker(true);
//We now need to verify that the 500 messages on the NC durable are dispatched
//on bridge sync which shows that the durable wasn't destroyed/recreated
final DestinationStatistics destinationStatistics2 =
localBroker.getDestination(included).getDestinationStatistics();
waitForDispatchFromLocalBroker(destinationStatistics2, 500);
assertLocalBrokerStatistics(destinationStatistics2, 500);
}
protected CompositeTopic createCompositeTopic(String name, ActiveMQDestination...forwardTo) {
CompositeTopic compositeTopic = new CompositeTopic();
compositeTopic.setName(name);
compositeTopic.setForwardOnly(true);
compositeTopic.setForwardTo( Lists.newArrayList(forwardTo));
return compositeTopic;
}
protected void restartBroker(BrokerService broker, boolean startNetworkConnector) throws Exception {
if (broker.getBrokerName().equals("localBroker")) {
restartLocalBroker(startNetworkConnector);
} else {
restartRemoteBroker();
}
}
protected void restartBrokers(boolean startNetworkConnector) throws Exception {
doTearDown();
doSetUp(false, startNetworkConnector, localBroker.getDataDirectoryFile(),
remoteBroker.getDataDirectoryFile());
}
protected void doSetUp(boolean deleteAllMessages, boolean startNetworkConnector, File localDataDir,
File remoteDataDir) throws Exception {
included = new ActiveMQTopic(testTopicName);
doSetUpRemoteBroker(deleteAllMessages, remoteDataDir, 0);
doSetUpLocalBroker(deleteAllMessages, startNetworkConnector, localDataDir);
//Give time for advisories to propagate
Thread.sleep(1000);
}
protected void restartLocalBroker(boolean startNetworkConnector) throws Exception {
stopLocalBroker();
doSetUpLocalBroker(false, startNetworkConnector, localBroker.getDataDirectoryFile());
}
protected void restartRemoteBroker() throws Exception {
int port = 0;
if (remoteBroker != null) {
List<TransportConnector> transportConnectors = remoteBroker.getTransportConnectors();
port = transportConnectors.get(0).getConnectUri().getPort();
}
stopRemoteBroker();
doSetUpRemoteBroker(false, remoteBroker.getDataDirectoryFile(), port);
}
protected void doSetUpLocalBroker(boolean deleteAllMessages, boolean startNetworkConnector,
File dataDir) throws Exception {
localBroker = createLocalBroker(dataDir, startNetworkConnector);
localBroker.setDeleteAllMessagesOnStartup(deleteAllMessages);
localBroker.start();
localBroker.waitUntilStarted();
URI localURI = localBroker.getVmConnectorURI();
ActiveMQConnectionFactory fac = new ActiveMQConnectionFactory(localURI);
fac.setAlwaysSyncSend(true);
fac.setDispatchAsync(false);
localConnection = fac.createConnection();
localConnection.setClientID("clientId");
localConnection.start();
if (startNetworkConnector) {
Wait.waitFor(new Condition() {
@Override
public boolean isSatisified() throws Exception {
return localBroker.getNetworkConnectors().get(0).activeBridges().size() == 1;
}
}, 5000, 500);
}
localSession = localConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
if (flow.equals(FLOW.FORWARD)) {
broker1 = localBroker;
session1 = localSession;
} else {
broker2 = localBroker;
session2 = localSession;
}
}
protected void doSetUpRemoteBroker(boolean deleteAllMessages, File dataDir, int port) throws Exception {
remoteBroker = createRemoteBroker(dataDir, port);
remoteBroker.setDeleteAllMessagesOnStartup(deleteAllMessages);
remoteBroker.start();
remoteBroker.waitUntilStarted();
URI remoteURI = remoteBroker.getVmConnectorURI();
ActiveMQConnectionFactory fac = new ActiveMQConnectionFactory(remoteURI);
remoteConnection = fac.createConnection();
remoteConnection.setClientID("clientId");
remoteConnection.start();
remoteSession = remoteConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
if (flow.equals(FLOW.FORWARD)) {
broker2 = remoteBroker;
session2 = remoteSession;
remoteRuntimeBroker = (JavaRuntimeConfigurationBroker)
remoteBroker.getBroker().getAdaptor(JavaRuntimeConfigurationBroker.class);
} else {
broker1 = remoteBroker;
session1 = remoteSession;
}
}
protected BrokerService createLocalBroker(File dataDir, boolean startNetworkConnector) throws Exception {
BrokerService brokerService = new BrokerService();
brokerService.setMonitorConnectionSplits(true);
brokerService.setBrokerName("localBroker");
brokerService.setDataDirectoryFile(dataDir);
KahaDBPersistenceAdapter adapter = new KahaDBPersistenceAdapter();
adapter.setDirectory(dataDir);
adapter.setJournalDiskSyncStrategy(JournalDiskSyncStrategy.PERIODIC.name());
brokerService.setPersistenceAdapter(adapter);
brokerService.setUseVirtualDestSubs(useVirtualDestSubs);
brokerService.setUseVirtualDestSubsOnCreation(useVirtualDestSubs);
if (startNetworkConnector) {
brokerService.addNetworkConnector(configureLocalNetworkConnector());
}
//Use auto+nio+ssl to test out the transport works with bridging
brokerService.addConnector("auto+nio+ssl://localhost:0");
return brokerService;
}
protected NetworkConnector configureLocalNetworkConnector() throws Exception {
List<TransportConnector> transportConnectors = remoteBroker.getTransportConnectors();
URI remoteURI = transportConnectors.get(0).getConnectUri();
String uri = "static:(" + remoteURI + ")";
NetworkConnector connector = new DiscoveryNetworkConnector(new URI(uri));
connector.setName("networkConnector");
connector.setDynamicOnly(dynamicOnly);
connector.setDecreaseNetworkConsumerPriority(false);
connector.setConduitSubscriptions(true);
connector.setDuplex(true);
connector.setStaticBridge(false);
connector.setSyncDurableSubs(true);
connector.setUseVirtualDestSubs(useVirtualDestSubs);
connector.setStaticallyIncludedDestinations(
Lists.<ActiveMQDestination>newArrayList(new ActiveMQTopic(staticIncludeTopics + "?forceDurable=" + forceDurable)));
connector.setDynamicallyIncludedDestinations(
Lists.<ActiveMQDestination>newArrayList(new ActiveMQTopic(includedTopics + "?forceDurable=" + forceDurable)));
connector.setExcludedDestinations(
Lists.<ActiveMQDestination>newArrayList(new ActiveMQTopic(excludeTopicName)));
return connector;
}
protected AdvisoryBroker remoteAdvisoryBroker;
protected BrokerService createRemoteBroker(File dataDir, int port) throws Exception {
BrokerService brokerService = new BrokerService();
brokerService.setBrokerName("remoteBroker");
brokerService.setUseJmx(false);
brokerService.setDataDirectoryFile(dataDir);
KahaDBPersistenceAdapter adapter = new KahaDBPersistenceAdapter();
adapter.setDirectory(dataDir);
adapter.setJournalDiskSyncStrategy(JournalDiskSyncStrategy.PERIODIC.name());
brokerService.setPersistenceAdapter(adapter);
brokerService.setUseVirtualDestSubs(useVirtualDestSubs);
brokerService.setUseVirtualDestSubsOnCreation(useVirtualDestSubs);
if (useVirtualDestSubs) {
brokerService.setPlugins(new BrokerPlugin[] {new JavaRuntimeConfigurationPlugin()});
}
remoteAdvisoryBroker = (AdvisoryBroker) brokerService.getBroker().getAdaptor(AdvisoryBroker.class);
//Need a larger cache size in order to handle all of the durables
//Use auto+nio+ssl to test out the transport works with bridging
brokerService.addConnector("auto+nio+ssl://localhost:" + port + "?wireFormat.cacheSize=2048&wireFormat.version=" + remoteBrokerWireFormatVersion);
return brokerService;
}
}