/**
* 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.assertNotNull;
import java.net.URI;
import javax.jms.JMSException;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Session;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.broker.BrokerService;
import org.apache.activemq.broker.ConnectionContext;
import org.apache.activemq.broker.region.DestinationStatistics;
import org.apache.activemq.command.ActiveMQDestination;
import org.apache.activemq.command.ActiveMQTopic;
import org.apache.activemq.command.RemoveSubscriptionInfo;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.google.common.collect.Lists;
/**
* This test is to show that if a durable subscription over a network bridge is deleted and
* re-created, messages will flow properly again for dynamic subscriptions.
*
* AMQ-6050
*/
public class NetworkDurableRecreationTest extends DynamicNetworkTestSupport {
/**
* Test publisher on localBroker and durable on remoteBroker
* after durable deletion, recreate durable
*/
@Test(timeout = 30 * 1000)
public void testDurableConsumer() throws Exception {
testReceive(remoteBroker, remoteSession, localBroker, localSession, new ConsumerCreator() {
@Override
public MessageConsumer createConsumer() throws JMSException {
return remoteSession.createDurableSubscriber(included, subName);
}
});
}
/**
* Reverse and test publisher on remoteBroker and durable on localBroker
* after durable deletion, recreate durable
*/
@Test(timeout = 30 * 1000)
public void testDurableConsumerReverse() throws Exception {
testReceive(localBroker, localSession, remoteBroker, remoteSession, new ConsumerCreator() {
@Override
public MessageConsumer createConsumer() throws JMSException {
return localSession.createDurableSubscriber(included, subName);
}
});
}
/**
* Test publisher on localBroker and durable on remoteBroker
* after durable deletion, recreate with a non-durable consumer
*/
@Test(timeout = 30 * 1000)
public void testDurableAndTopicConsumer() throws Exception {
testReceive(remoteBroker, remoteSession, localBroker, localSession, new ConsumerCreator() {
@Override
public MessageConsumer createConsumer() throws JMSException {
return remoteSession.createConsumer(included);
}
});
}
/**
* Reverse and test publisher on remoteBroker and durable on localBroker
* after durable deletion, recreate with a non-durable consumer
*/
@Test(timeout = 30 * 1000)
public void testDurableAndTopicConsumerReverse() throws Exception {
testReceive(localBroker, localSession, remoteBroker, remoteSession, new ConsumerCreator() {
@Override
public MessageConsumer createConsumer() throws JMSException {
return localSession.createConsumer(included);
}
});
}
public void testReceive(BrokerService receiveBroker, Session receiveSession,
BrokerService publishBroker, Session publishSession, ConsumerCreator secondConsumerCreator) throws Exception {
final DestinationStatistics destinationStatistics =
publishBroker.getDestination(included).getDestinationStatistics();
MessageProducer includedProducer = publishSession.createProducer(included);
MessageConsumer bridgeConsumer = receiveSession.createDurableSubscriber(
included, subName);
waitForConsumerCount(destinationStatistics, 1);
//remove the durable
final ConnectionContext context = new ConnectionContext();
RemoveSubscriptionInfo info = getRemoveSubscriptionInfo(context, receiveBroker);
bridgeConsumer.close();
Thread.sleep(1000);
receiveBroker.getBroker().removeSubscription(context, info);
waitForConsumerCount(destinationStatistics, 0);
//re-create consumer
MessageConsumer bridgeConsumer2 = secondConsumerCreator.createConsumer();
waitForConsumerCount(destinationStatistics, 1);
//make sure message received
includedProducer.send(publishSession.createTextMessage("test"));
assertNotNull(bridgeConsumer2.receive(5000));
}
@Before
public void setUp() throws Exception {
doSetUp(true);
}
@After
public void tearDown() throws Exception {
doTearDown();
}
protected void doTearDown() throws Exception {
if (localConnection != null) {
localConnection.close();
}
if (remoteConnection != null) {
remoteConnection.close();
}
if (localBroker != null) {
localBroker.stop();
}
if (remoteBroker != null) {
remoteBroker.stop();
}
}
protected void doSetUp(boolean deleteAllMessages) throws Exception {
remoteBroker = createRemoteBroker();
remoteBroker.setDeleteAllMessagesOnStartup(deleteAllMessages);
remoteBroker.start();
remoteBroker.waitUntilStarted();
localBroker = createLocalBroker();
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();
URI remoteURI = remoteBroker.getVmConnectorURI();
fac = new ActiveMQConnectionFactory(remoteURI);
remoteConnection = fac.createConnection();
remoteConnection.setClientID(clientId);
remoteConnection.start();
included = new ActiveMQTopic(testTopicName);
localSession = localConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
remoteSession = remoteConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
}
protected NetworkConnector connector;
protected BrokerService createLocalBroker() throws Exception {
BrokerService brokerService = new BrokerService();
brokerService.setMonitorConnectionSplits(true);
brokerService.setDataDirectoryFile(tempFolder.newFolder());
brokerService.setBrokerName("localBroker");
connector = new DiscoveryNetworkConnector(new URI("static:(tcp://localhost:61617)"));
connector.setName("networkConnector");
connector.setDecreaseNetworkConsumerPriority(false);
connector.setConduitSubscriptions(true);
connector.setDuplex(true);
connector.setDynamicallyIncludedDestinations(Lists.<ActiveMQDestination>newArrayList(
new ActiveMQTopic(testTopicName)));
connector.setExcludedDestinations(Lists.<ActiveMQDestination>newArrayList(
new ActiveMQTopic(excludeTopicName)));
brokerService.addNetworkConnector(connector);
brokerService.addConnector("tcp://localhost:61616");
return brokerService;
}
protected BrokerService createRemoteBroker() throws Exception {
BrokerService brokerService = new BrokerService();
brokerService.setBrokerName("remoteBroker");
brokerService.setUseJmx(false);
brokerService.setDataDirectoryFile(tempFolder.newFolder());
brokerService.addConnector("tcp://localhost:61617");
return brokerService;
}
}