/* * Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. 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 io.ballerina.messaging.broker.integration.standalone.jms; import io.ballerina.messaging.broker.integration.util.ClientHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.Assert; import org.testng.annotations.Parameters; import org.testng.annotations.Test; import java.util.ArrayList; import java.util.List; import javax.jms.JMSException; import javax.jms.Session; import javax.jms.TextMessage; import javax.jms.Topic; import javax.jms.TopicConnection; import javax.jms.TopicConnectionFactory; import javax.jms.TopicPublisher; import javax.jms.TopicSession; import javax.jms.TopicSubscriber; import javax.naming.InitialContext; import javax.naming.NamingException; /** * Test class to validate message ordering in the durable topic. */ public class DurableTopicMessagesOrderTest { private static final Logger LOGGER = LoggerFactory.getLogger(DurableTopicMessagesOrderTest.class); @Parameters({"broker-port", "admin-username", "admin-password", "broker-hostname"}) @Test public void test1966DurableTopicMessagesOrderSingleSubscriber(String port, String adminUsername, String adminPassword, String brokerHostname) throws NamingException, JMSException { String topicName = "test1966DurableTopicMessagesOrderSingleSubscriber"; List<String> subscriberOneMessages = new ArrayList<>(); int numberOfMessages = 1966; InitialContext initialContext = ClientHelper .getInitialContextBuilder(adminUsername, adminPassword, brokerHostname, port) .withTopic(topicName) .build(); TopicConnectionFactory connectionFactory = (TopicConnectionFactory) initialContext.lookup(ClientHelper.CONNECTION_FACTORY); TopicConnection connection = connectionFactory.createTopicConnection(); connection.start(); // Initialize subscriber TopicSession subscriberSession = connection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); Topic subscriberDestination = (Topic) initialContext.lookup(topicName); TopicSubscriber subscriber = subscriberSession.createDurableSubscriber(subscriberDestination, "1966_1"); // publish 1966 messages TopicSession producerSession = connection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); TopicPublisher producer = producerSession.createPublisher(subscriberDestination); for (int i = 0; i < numberOfMessages; i++) { producer.publish(producerSession.createTextMessage(String.valueOf(i))); } producerSession.close(); for (int i = 0; i < numberOfMessages; i++) { TextMessage message = (TextMessage) subscriber.receive(5000); Assert.assertNotNull(message, "Message #" + i + " was not received"); subscriberOneMessages.add(message.getText()); } subscriberSession.close(); connection.close(); // verify order is preserved boolean isOrderPreserved = true; for (int i = 0; i < numberOfMessages; i++) { if (!(i == Integer.parseInt(subscriberOneMessages.get(i)))) { isOrderPreserved = false; break; } } Assert.assertTrue(isOrderPreserved, "Topic messages order not preserved for single subscriber."); } @Parameters({"broker-port", "admin-username", "admin-password", "broker-hostname"}) @Test public void test1571DurableTopicMessagesOrderTwoSequentialSubscribers(String port, String adminUsername, String adminPassword, String brokerHostname) throws NamingException, JMSException { String topicName = "test1571DurableTopicMessagesOrderTwoSequentialSubscribers"; List<String> subscriberOneMessages = new ArrayList<>(); List<String> subscriberTwoMessages = new ArrayList<>(); int numberOfMessages = 1571; InitialContext initialContext = ClientHelper .getInitialContextBuilder(adminUsername, adminPassword, brokerHostname, port) .withTopic(topicName) .build(); TopicConnectionFactory connectionFactory = (TopicConnectionFactory) initialContext.lookup(ClientHelper.CONNECTION_FACTORY); TopicConnection connection = connectionFactory.createTopicConnection(); connection.start(); // Initialize subscriber TopicSession subscriberSessionOne = connection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); TopicSession subscriberSessionTwo = connection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); Topic subscriberDestination = (Topic) initialContext.lookup(topicName); TopicSubscriber subscriberOne = subscriberSessionOne.createDurableSubscriber(subscriberDestination, "1571_1"); TopicSubscriber subscriberTwo = subscriberSessionTwo.createDurableSubscriber(subscriberDestination, "1571_2"); // publish 1571 messages TopicSession producerSession = connection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); TopicPublisher producer = producerSession.createPublisher(subscriberDestination); for (int i = 0; i < numberOfMessages; i++) { producer.publish(producerSession.createTextMessage(String.valueOf(i))); } producerSession.close(); for (int i = 0; i < numberOfMessages; i++) { TextMessage message = (TextMessage) subscriberOne.receive(5000); Assert.assertNotNull(message, "Message #" + i + " was not received"); subscriberOneMessages.add(message.getText()); } for (int i = 0; i < numberOfMessages; i++) { TextMessage message = (TextMessage) subscriberTwo.receive(5000); Assert.assertNotNull(message, "Message #" + i + " was not received"); subscriberTwoMessages.add(message.getText()); } subscriberSessionOne.close(); subscriberSessionTwo.close(); connection.close(); // verify order is preserved boolean isSubscriberOneOrderPreserved = true; boolean isSubscriberTwoOrderPreserved = true; for (int i = 0; i < numberOfMessages; i++) { if (!(i == Integer.parseInt(subscriberOneMessages.get(i)))) { isSubscriberOneOrderPreserved = false; break; } } for (int i = 0; i < numberOfMessages; i++) { if (!(i == Integer.parseInt(subscriberTwoMessages.get(i)))) { isSubscriberTwoOrderPreserved = false; break; } } Assert.assertTrue(isSubscriberOneOrderPreserved, "Topic messages order not preserved for sequential subscriber one."); Assert.assertTrue(isSubscriberTwoOrderPreserved, "Topic messages order not preserved for sequential subscriber two."); } @Parameters({"broker-port", "admin-username", "admin-password", "broker-hostname"}) @Test public void test1837DurableTopicMessagesOrderTwoParallelSubscribers(String port, String adminUsername, String adminPassword, String brokerHostname) throws NamingException, JMSException, InterruptedException { String topicName = "test1837DurableTopicMessagesOrderTwoParallelSubscribers"; List<String> subscriberOneMessages = new ArrayList<>(); List<String> subscriberTwoMessages = new ArrayList<>(); int numberOfMessages = 1837; InitialContext initialContext = ClientHelper .getInitialContextBuilder(adminUsername, adminPassword, brokerHostname, port) .withTopic(topicName) .build(); TopicConnectionFactory connectionFactory = (TopicConnectionFactory) initialContext.lookup(ClientHelper.CONNECTION_FACTORY); TopicConnection connection = connectionFactory.createTopicConnection(); connection.start(); // Initialize subscriber TopicSession subscriberSessionOne = connection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); TopicSession subscriberSessionTwo = connection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); Topic subscriberDestination = (Topic) initialContext.lookup(topicName); TopicSubscriber subscriberOne = subscriberSessionOne.createDurableSubscriber(subscriberDestination, "1837_1"); TopicSubscriber subscriberTwo = subscriberSessionTwo.createDurableSubscriber(subscriberDestination, "1837_2"); Thread subscriberOneThread = new Thread(() -> { try { for (int i = 0; i < numberOfMessages; i++) { TextMessage message = (TextMessage) subscriberOne.receive(5000); Assert.assertNotNull(message, "Message #" + i + " was not received"); subscriberOneMessages.add(message.getText()); } subscriberSessionOne.close(); } catch (JMSException e) { LOGGER.error("Error occurred while receiving messages consumer one thread.", e); } }); subscriberOneThread.start(); Thread subscriberTwoThread = new Thread(() -> { try { for (int i = 0; i < numberOfMessages; i++) { TextMessage message = (TextMessage) subscriberTwo.receive(5000); Assert.assertNotNull(message, "Message #" + i + " was not received"); subscriberTwoMessages.add(message.getText()); } subscriberSessionTwo.close(); } catch (JMSException e) { LOGGER.error("Error occurred while receiving messages consumer one thread.", e); } }); subscriberTwoThread.start(); // publish 1837 messages TopicSession producerSession = connection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); TopicPublisher producer = producerSession.createPublisher(subscriberDestination); for (int i = 0; i < numberOfMessages; i++) { producer.publish(producerSession.createTextMessage(String.valueOf(i))); } producerSession.close(); subscriberOneThread.join(); subscriberTwoThread.join(); connection.close(); // verify order is preserved boolean isSubscriberOneOrderPreserved = true; boolean isSubscriberTwoOrderPreserved = true; for (int i = 0; i < numberOfMessages; i++) { if (!(i == Integer.parseInt(subscriberOneMessages.get(i)))) { isSubscriberOneOrderPreserved = false; break; } } for (int i = 0; i < numberOfMessages; i++) { if (!(i == Integer.parseInt(subscriberTwoMessages.get(i)))) { isSubscriberTwoOrderPreserved = false; break; } } Assert.assertTrue(isSubscriberOneOrderPreserved, "Topic messages order not preserved for parallel subscriber one."); Assert.assertTrue(isSubscriberTwoOrderPreserved, "Topic messages order not preserved for parallel subscriber two."); } }