/** * 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.broker; import javax.jms.DeliveryMode; import java.util.ArrayList; import junit.framework.Test; import org.apache.activemq.command.ActiveMQDestination; import org.apache.activemq.command.ActiveMQQueue; import org.apache.activemq.command.ActiveMQTopic; import org.apache.activemq.command.ConnectionInfo; import org.apache.activemq.command.ConsumerInfo; import org.apache.activemq.command.LocalTransactionId; import org.apache.activemq.command.Message; import org.apache.activemq.command.MessageAck; import org.apache.activemq.command.MessageId; import org.apache.activemq.command.ProducerInfo; import org.apache.activemq.command.SessionInfo; import org.apache.activemq.command.XATransactionId; /** * Used to simulate the recovery that occurs when a broker shuts down. */ public class RecoveryBrokerTest extends BrokerRestartTestSupport { /** * Used to verify that after a broker restart durable subscriptions that use * wild cards are still wild card subscription after broker restart. * * @throws Exception */ //need to revist!!! public void XtestWildCardSubscriptionPreservedOnRestart() throws Exception { ActiveMQDestination dest1 = new ActiveMQTopic("TEST.A"); ActiveMQDestination dest2 = new ActiveMQTopic("TEST.B"); ActiveMQDestination dest3 = new ActiveMQTopic("TEST.C"); ActiveMQDestination wildDest = new ActiveMQTopic("TEST.>"); ArrayList<MessageId> sentBeforeRestart = new ArrayList<>(); ArrayList<MessageId> sentBeforeCreateConsumer = new ArrayList<>(); ArrayList<MessageId> sentAfterCreateConsumer = new ArrayList<>(); // Setup a first connection { StubConnection connection1 = createConnection(); ConnectionInfo connectionInfo1 = createConnectionInfo(); connectionInfo1.setClientId("A"); SessionInfo sessionInfo1 = createSessionInfo(connectionInfo1); ProducerInfo producerInfo1 = createProducerInfo(sessionInfo1); connection1.send(connectionInfo1); connection1.send(sessionInfo1); connection1.send(producerInfo1); // Create the durable subscription. ConsumerInfo consumerInfo1 = createConsumerInfo(sessionInfo1, wildDest); consumerInfo1.setSubscriptionName("test"); consumerInfo1.setPrefetchSize(100); connection1.send(consumerInfo1); // Close the subscription. connection1.send(closeConsumerInfo(consumerInfo1)); // Send the messages for (int i = 0; i < 4; i++) { Message m = createMessage(producerInfo1, dest1, DeliveryMode.PERSISTENT); connection1.send(m); sentBeforeRestart.add(m.getMessageId()); } connection1.request(closeConnectionInfo(connectionInfo1)); connection1.stop(); } // Restart the broker. restartBroker(); // Get a connection to the new broker. { StubConnection connection2 = createConnection(); ConnectionInfo connectionInfo2 = createConnectionInfo(); connectionInfo2.setClientId("A"); SessionInfo sessionInfo2 = createSessionInfo(connectionInfo2); connection2.send(connectionInfo2); connection2.send(sessionInfo2); ProducerInfo producerInfo2 = createProducerInfo(sessionInfo2); connection2.send(producerInfo2); // Send messages before the durable subscription is re-activated. for (int i = 0; i < 4; i++) { Message m = createMessage(producerInfo2, dest2, DeliveryMode.PERSISTENT); connection2.send(m); sentBeforeCreateConsumer.add(m.getMessageId()); } // Re-open the subscription. ConsumerInfo consumerInfo2 = createConsumerInfo(sessionInfo2, wildDest); consumerInfo2.setSubscriptionName("test"); consumerInfo2.setPrefetchSize(100); connection2.send(consumerInfo2); // Send messages after the subscription is activated. for (int i = 0; i < 4; i++) { Message m = createMessage(producerInfo2, dest3, DeliveryMode.PERSISTENT); connection2.send(m); sentAfterCreateConsumer.add(m.getMessageId()); } // We should get the recovered messages... for (int i = 0; i < 4; i++) { Message m2 = receiveMessage(connection2); assertNotNull("Recovered message missing: " + i, m2); assertEquals(sentBeforeRestart.get(i), m2.getMessageId()); } // We should get get the messages that were sent before the sub was // reactivated. for (int i = 0; i < 4; i++) { Message m2 = receiveMessage(connection2); assertNotNull("Before activated message missing: " + i, m2); assertEquals(sentBeforeCreateConsumer.get(i), m2.getMessageId()); } // We should get get the messages that were sent after the sub was // reactivated. for (int i = 0; i < 4; i++) { Message m2 = receiveMessage(connection2); assertNotNull("After activated message missing: " + i, m2); assertEquals("" + i, sentAfterCreateConsumer.get(i), m2.getMessageId()); } assertNoMessagesLeft(connection2); } } public void testConsumedQueuePersistentMessagesLostOnRestart() throws Exception { ActiveMQDestination destination = new ActiveMQQueue("TEST"); // Setup the producer and send the message. StubConnection connection = createConnection(); ConnectionInfo connectionInfo = createConnectionInfo(); SessionInfo sessionInfo = createSessionInfo(connectionInfo); ProducerInfo producerInfo = createProducerInfo(sessionInfo); connection.send(connectionInfo); connection.send(sessionInfo); connection.send(producerInfo); for (int i = 0; i < 4; i++) { Message message = createMessage(producerInfo, destination); message.setPersistent(true); connection.send(message); } // Setup the consumer and receive the message. connection = createConnection(); connectionInfo = createConnectionInfo(); sessionInfo = createSessionInfo(connectionInfo); connection.send(connectionInfo); connection.send(sessionInfo); ConsumerInfo consumerInfo = createConsumerInfo(sessionInfo, destination); connection.send(consumerInfo); // The we should get the messages. for (int i = 0; i < 4; i++) { Message m2 = receiveMessage(connection); assertNotNull(m2); } // restart the broker. restartBroker(); // No messages should be delivered. Message m = receiveMessage(connection); assertNull(m); } public void testQueuePersistentUncommitedMessagesLostOnRestart() throws Exception { ActiveMQDestination destination = new ActiveMQQueue("TEST"); // Setup the producer and send the message. StubConnection connection = createConnection(); ConnectionInfo connectionInfo = createConnectionInfo(); SessionInfo sessionInfo = createSessionInfo(connectionInfo); ProducerInfo producerInfo = createProducerInfo(sessionInfo); connection.send(connectionInfo); connection.send(sessionInfo); connection.send(producerInfo); // Begin the transaction. LocalTransactionId txid = createLocalTransaction(sessionInfo); connection.send(createBeginTransaction(connectionInfo, txid)); for (int i = 0; i < 4; i++) { Message message = createMessage(producerInfo, destination); message.setPersistent(true); message.setTransactionId(txid); connection.send(message); } // Don't commit // restart the broker. restartBroker(); // Setup the consumer and receive the message. connection = createConnection(); connectionInfo = createConnectionInfo(); sessionInfo = createSessionInfo(connectionInfo); connection.send(connectionInfo); connection.send(sessionInfo); ConsumerInfo consumerInfo = createConsumerInfo(sessionInfo, destination); connection.send(consumerInfo); // No messages should be delivered. Message m = receiveMessage(connection); assertNull(m); } public void testTopicDurableConsumerHoldsPersistentMessageAfterRestart() throws Exception { ActiveMQDestination destination = new ActiveMQTopic("TEST"); // Setup a first connection StubConnection connection1 = createConnection(); ConnectionInfo connectionInfo1 = createConnectionInfo(); connectionInfo1.setClientId("A"); SessionInfo sessionInfo1 = createSessionInfo(connectionInfo1); ProducerInfo producerInfo1 = createProducerInfo(sessionInfo1); connection1.send(connectionInfo1); connection1.send(sessionInfo1); connection1.send(producerInfo1); // Create the durable subscription. ConsumerInfo consumerInfo1 = createConsumerInfo(sessionInfo1, destination); consumerInfo1.setSubscriptionName("test"); consumerInfo1.setPrefetchSize(100); connection1.send(consumerInfo1); // Close the subscription. connection1.send(closeConsumerInfo(consumerInfo1)); // Send the messages connection1.send(createMessage(producerInfo1, destination, DeliveryMode.PERSISTENT)); connection1.send(createMessage(producerInfo1, destination, DeliveryMode.PERSISTENT)); connection1.send(createMessage(producerInfo1, destination, DeliveryMode.PERSISTENT)); connection1.send(createMessage(producerInfo1, destination, DeliveryMode.PERSISTENT)); connection1.request(closeConnectionInfo(connectionInfo1)); // Restart the broker. restartBroker(); // Get a connection to the new broker. StubConnection connection2 = createConnection(); ConnectionInfo connectionInfo2 = createConnectionInfo(); connectionInfo2.setClientId("A"); SessionInfo sessionInfo2 = createSessionInfo(connectionInfo2); connection2.send(connectionInfo2); connection2.send(sessionInfo2); // Re-open the subscription. ConsumerInfo consumerInfo2 = createConsumerInfo(sessionInfo2, destination); consumerInfo2.setSubscriptionName("test"); consumerInfo2.setPrefetchSize(100); connection2.send(consumerInfo2); // The we should get the messages. for (int i = 0; i < 4; i++) { Message m2 = receiveMessage(connection2); assertNotNull("Did not get message " + i, m2); } assertNoMessagesLeft(connection2); } public void testQueuePersistentMessagesNotLostOnRestart() throws Exception { ActiveMQDestination destination = new ActiveMQQueue("TEST"); // Setup the producer and send the message. StubConnection connection = createConnection(); ConnectionInfo connectionInfo = createConnectionInfo(); SessionInfo sessionInfo = createSessionInfo(connectionInfo); ProducerInfo producerInfo = createProducerInfo(sessionInfo); connection.send(connectionInfo); connection.send(sessionInfo); connection.send(producerInfo); Message message = createMessage(producerInfo, destination); message.setPersistent(true); connection.send(message); connection.request(closeConnectionInfo(connectionInfo)); // restart the broker. restartBroker(); // Setup the consumer and receive the message. connection = createConnection(); connectionInfo = createConnectionInfo(); sessionInfo = createSessionInfo(connectionInfo); connection.send(connectionInfo); connection.send(sessionInfo); ConsumerInfo consumerInfo = createConsumerInfo(sessionInfo, destination); connection.send(consumerInfo); // Message should have been dropped due to broker restart. Message m = receiveMessage(connection); assertNotNull("Should have received a message by now!", m); assertEquals(m.getMessageId(), message.getMessageId()); } public void testQueueNonPersistentMessagesLostOnRestart() throws Exception { ActiveMQDestination destination = new ActiveMQQueue("TEST"); // Setup the producer and send the message. StubConnection connection = createConnection(); ConnectionInfo connectionInfo = createConnectionInfo(); SessionInfo sessionInfo = createSessionInfo(connectionInfo); ProducerInfo producerInfo = createProducerInfo(sessionInfo); connection.send(connectionInfo); connection.send(sessionInfo); connection.send(producerInfo); Message message = createMessage(producerInfo, destination); message.setPersistent(false); connection.send(message); // restart the broker. restartBroker(); // Setup the consumer and receive the message. connection = createConnection(); connectionInfo = createConnectionInfo(); sessionInfo = createSessionInfo(connectionInfo); connection.send(connectionInfo); connection.send(sessionInfo); ConsumerInfo consumerInfo = createConsumerInfo(sessionInfo, destination); connection.send(consumerInfo); // Message should have been dropped due to broker restart. assertNoMessagesLeft(connection); } public void testQueuePersistentCommittedMessagesNotLostOnRestart() throws Exception { ActiveMQDestination destination = new ActiveMQQueue("TEST"); // Setup the producer and send the message. StubConnection connection = createConnection(); ConnectionInfo connectionInfo = createConnectionInfo(); SessionInfo sessionInfo = createSessionInfo(connectionInfo); ProducerInfo producerInfo = createProducerInfo(sessionInfo); connection.send(connectionInfo); connection.send(sessionInfo); connection.send(producerInfo); // Begin the transaction. LocalTransactionId txid = createLocalTransaction(sessionInfo); connection.send(createBeginTransaction(connectionInfo, txid)); for (int i = 0; i < 4; i++) { Message message = createMessage(producerInfo, destination); message.setPersistent(true); message.setTransactionId(txid); connection.send(message); } // Commit connection.send(createCommitTransaction1Phase(connectionInfo, txid)); connection.request(closeConnectionInfo(connectionInfo)); // restart the broker. restartBroker(); // Setup the consumer and receive the message. connection = createConnection(); connectionInfo = createConnectionInfo(); sessionInfo = createSessionInfo(connectionInfo); connection.send(connectionInfo); connection.send(sessionInfo); ConsumerInfo consumerInfo = createConsumerInfo(sessionInfo, destination); connection.send(consumerInfo); for (int i = 0; i < 4; i++) { Message m = receiveMessage(connection); assertNotNull(m); } assertNoMessagesLeft(connection); } public void testQueuePersistentCommittedAcksNotLostOnRestart() throws Exception { ActiveMQDestination destination = new ActiveMQQueue("TEST"); // Setup the producer and send the message. StubConnection connection = createConnection(); ConnectionInfo connectionInfo = createConnectionInfo(); SessionInfo sessionInfo = createSessionInfo(connectionInfo); ProducerInfo producerInfo = createProducerInfo(sessionInfo); connection.send(connectionInfo); connection.send(sessionInfo); connection.send(producerInfo); for (int i = 0; i < 4; i++) { Message message = createMessage(producerInfo, destination); message.setPersistent(true); connection.send(message); } // Setup the consumer and receive the message. ConsumerInfo consumerInfo = createConsumerInfo(sessionInfo, destination); connection.send(consumerInfo); // Begin the transaction. LocalTransactionId txid = createLocalTransaction(sessionInfo); connection.send(createBeginTransaction(connectionInfo, txid)); for (int i = 0; i < 4; i++) { Message m = receiveMessage(connection); assertNotNull(m); MessageAck ack = createAck(consumerInfo, m, 1, MessageAck.STANDARD_ACK_TYPE); ack.setTransactionId(txid); connection.send(ack); } // Commit connection.send(createCommitTransaction1Phase(connectionInfo, txid)); connection.request(closeConnectionInfo(connectionInfo)); // restart the broker. restartBroker(); // Setup the consumer and receive the message. connection = createConnection(); connectionInfo = createConnectionInfo(); sessionInfo = createSessionInfo(connectionInfo); connection.send(connectionInfo); connection.send(sessionInfo); consumerInfo = createConsumerInfo(sessionInfo, destination); connection.send(consumerInfo); // No messages should be delivered. Message m = receiveMessage(connection); assertNull(m); } public void testQueuePersistentUncommitedAcksLostOnRestart() throws Exception { ActiveMQDestination destination = new ActiveMQQueue("TEST"); // Setup the producer and send the message. StubConnection connection = createConnection(); ConnectionInfo connectionInfo = createConnectionInfo(); SessionInfo sessionInfo = createSessionInfo(connectionInfo); ProducerInfo producerInfo = createProducerInfo(sessionInfo); connection.send(connectionInfo); connection.send(sessionInfo); connection.send(producerInfo); for (int i = 0; i < 4; i++) { Message message = createMessage(producerInfo, destination); message.setPersistent(true); connection.send(message); } // Setup the consumer and receive the message. ConsumerInfo consumerInfo = createConsumerInfo(sessionInfo, destination); connection.send(consumerInfo); // Begin the transaction. LocalTransactionId txid = createLocalTransaction(sessionInfo); connection.send(createBeginTransaction(connectionInfo, txid)); for (int i = 0; i < 4; i++) { Message m = receiveMessage(connection); assertNotNull(m); MessageAck ack = createAck(consumerInfo, m, 1, MessageAck.STANDARD_ACK_TYPE); ack.setTransactionId(txid); connection.send(ack); } // Don't commit // restart the broker. restartBroker(); // Setup the consumer and receive the message. connection = createConnection(); connectionInfo = createConnectionInfo(); sessionInfo = createSessionInfo(connectionInfo); connection.send(connectionInfo); connection.send(sessionInfo); consumerInfo = createConsumerInfo(sessionInfo, destination); connection.send(consumerInfo); // All messages should be re-delivered. for (int i = 0; i < 4; i++) { Message m = receiveMessage(connection); assertNotNull(m); } assertNoMessagesLeft(connection); } public void testQueuePersistentXAUncommitedAcksLostOnRestart() throws Exception { int NUMBER = 100; ActiveMQDestination destination = new ActiveMQQueue("TEST"); // Setup the producer and send the message. StubConnection connection = createConnection(); ConnectionInfo connectionInfo = createConnectionInfo(); SessionInfo sessionInfo = createSessionInfo(connectionInfo); ProducerInfo producerInfo = createProducerInfo(sessionInfo); connection.send(connectionInfo); connection.send(sessionInfo); connection.send(producerInfo); for (int i = 0; i < NUMBER; i++) { Message message = createMessage(producerInfo, destination); message.setPersistent(true); connection.send(message); } // Setup the consumer and receive the message. ConsumerInfo consumerInfo = createConsumerInfo(sessionInfo, destination); connection.send(consumerInfo); // Begin the transaction. XATransactionId txid = createXATransaction(sessionInfo); connection.send(createBeginTransaction(connectionInfo, txid)); Message m = null; for (int i = 0; i < NUMBER; i++) { m = receiveMessage(connection); assertNotNull(m); } MessageAck ack = createAck(consumerInfo, m, NUMBER, MessageAck.STANDARD_ACK_TYPE); ack.setTransactionId(txid); connection.send(ack); // Don't commit // restart the broker. restartBroker(); // Setup the consumer and receive the message. connection = createConnection(); connectionInfo = createConnectionInfo(); sessionInfo = createSessionInfo(connectionInfo); connection.send(connectionInfo); connection.send(sessionInfo); consumerInfo = createConsumerInfo(sessionInfo, destination); connection.send(consumerInfo); // All messages should be re-delivered. for (int i = 0; i < NUMBER; i++) { m = receiveMessage(connection); assertNotNull(m); } assertNoMessagesLeft(connection); } public static Test suite() { return suite(RecoveryBrokerTest.class); } public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } }