/* * 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.artemis.tests.integration.jms.server.management; import javax.jms.BytesMessage; import javax.jms.Connection; import javax.jms.ConnectionFactory; import javax.jms.Destination; import javax.jms.JMSException; import javax.jms.Message; import javax.jms.MessageConsumer; import javax.jms.MessageProducer; import javax.jms.Session; import javax.jms.Topic; import javax.jms.TopicSubscriber; import javax.management.Notification; import javax.management.NotificationListener; import java.util.Collection; import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import org.apache.activemq.artemis.api.core.ActiveMQException; import org.apache.activemq.artemis.api.core.TransportConfiguration; import org.apache.activemq.artemis.api.core.client.ClientSession; import org.apache.activemq.artemis.api.core.client.ServerLocator; import org.apache.activemq.artemis.api.core.client.SessionFailureListener; import org.apache.activemq.artemis.api.jms.ActiveMQJMSClient; import org.apache.activemq.artemis.api.jms.JMSFactoryType; import org.apache.activemq.artemis.core.client.impl.Topology; import org.apache.activemq.artemis.core.client.impl.TopologyMemberImpl; import org.apache.activemq.artemis.core.remoting.impl.invm.InVMConnectorFactory; import org.apache.activemq.artemis.core.server.ActiveMQServer; import org.apache.activemq.artemis.core.server.cluster.ClusterConnection; import org.apache.activemq.artemis.core.server.cluster.ClusterManager; import org.apache.activemq.artemis.core.server.cluster.impl.ClusterConnectionImpl; import org.apache.activemq.artemis.jms.client.ActiveMQConnection; import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory; import org.apache.activemq.artemis.jms.client.ActiveMQJMSConnectionFactory; import org.apache.activemq.artemis.tests.integration.cluster.failover.FailoverTestBase; import org.apache.activemq.artemis.utils.RandomUtil; import org.junit.Assert; public class JMSUtil { // Constants ----------------------------------------------------- // Attributes ---------------------------------------------------- // Static -------------------------------------------------------- public static Connection createConnection(final String connectorFactory) throws JMSException { ActiveMQJMSConnectionFactory cf = (ActiveMQJMSConnectionFactory) ActiveMQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF, new TransportConfiguration(connectorFactory)); cf.setBlockOnNonDurableSend(true); cf.setBlockOnDurableSend(true); cf.setBlockOnAcknowledge(true); return cf.createConnection(); } public static ConnectionFactory createFactory(final String connectorFactory, final long connectionTTL, final long clientFailureCheckPeriod) throws JMSException { ActiveMQJMSConnectionFactory cf = (ActiveMQJMSConnectionFactory) ActiveMQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF, new TransportConfiguration(connectorFactory)); cf.setBlockOnNonDurableSend(true); cf.setBlockOnDurableSend(true); cf.setBlockOnAcknowledge(true); cf.setConnectionTTL(connectionTTL); cf.setClientFailureCheckPeriod(clientFailureCheckPeriod); return cf; } static MessageConsumer createConsumer(final Connection connection, final Destination destination) throws JMSException { return createConsumer(connection, destination, Session.AUTO_ACKNOWLEDGE); } static MessageConsumer createConsumer(final Connection connection, final Destination destination, int ackMode) throws JMSException { Session s = connection.createSession(false, ackMode); return s.createConsumer(destination); } static TopicSubscriber createDurableSubscriber(final Connection connection, final Topic topic, final String clientID, final String subscriptionName) throws JMSException { return createDurableSubscriber(connection, topic, clientID, subscriptionName, Session.AUTO_ACKNOWLEDGE); } static TopicSubscriber createDurableSubscriber(final Connection connection, final Topic topic, final String clientID, final String subscriptionName, final int ackMode) throws JMSException { connection.setClientID(clientID); Session s = connection.createSession(false, ackMode); return s.createDurableSubscriber(topic, subscriptionName); } public static String[] sendMessages(final Destination destination, final int messagesToSend) throws Exception { ActiveMQJMSConnectionFactory cf = (ActiveMQJMSConnectionFactory) ActiveMQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF, new TransportConfiguration(InVMConnectorFactory.class.getName())); return JMSUtil.sendMessages(cf, destination, messagesToSend); } public static String[] sendMessages(final ConnectionFactory cf, final Destination destination, final int messagesToSend) throws Exception { String[] messageIDs = new String[messagesToSend]; Connection conn = cf.createConnection(); Session s = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageProducer producer = s.createProducer(destination); for (int i = 0; i < messagesToSend; i++) { Message m = s.createTextMessage(RandomUtil.randomString()); producer.send(m); messageIDs[i] = m.getJMSMessageID(); } conn.close(); return messageIDs; } public static Message sendMessageWithProperty(final Session session, final Destination destination, final String key, final long value) throws JMSException { MessageProducer producer = session.createProducer(destination); Message message = session.createMessage(); message.setLongProperty(key, value); producer.send(message); return message; } public static BytesMessage sendByteMessage(final Session session, final Destination destination, final byte[] bytes) throws JMSException { MessageProducer producer = session.createProducer(destination); BytesMessage message = session.createBytesMessage(); message.writeBytes(bytes); producer.send(message); return message; } public static Message sendMessageWithProperty(final Session session, final Destination destination, final String key, final int value) throws JMSException { MessageProducer producer = session.createProducer(destination); Message message = session.createMessage(); message.setIntProperty(key, value); producer.send(message); return message; } public static Message sendMessageWithProperty(final Session session, final Destination destination, final String key, final String value) throws JMSException { MessageProducer producer = session.createProducer(destination); Message message = session.createMessage(); message.setStringProperty(key, value); producer.send(message); return message; } public static Message sendMessageWithReplyTo(final Session session, final Destination destination, final String replyTo) throws JMSException { MessageProducer producer = session.createProducer(destination); Message message = session.createMessage(); message.setJMSReplyTo(ActiveMQJMSClient.createQueue(replyTo)); producer.send(message); return message; } public static void consumeMessages(final int expected, final Destination dest) throws JMSException { Connection connection = JMSUtil.createConnection(InVMConnectorFactory.class.getName()); try { Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageConsumer consumer = session.createConsumer(dest); connection.start(); Message m = null; for (int i = 0; i < expected; i++) { m = consumer.receive(500); Assert.assertNotNull("expected to received " + expected + " messages, got only " + (i + 1), m); } m = consumer.receiveNoWait(); Assert.assertNull("received one more message than expected (" + expected + ")", m); } finally { if (connection != null) { connection.close(); } } } public static void waitForServer(ActiveMQServer server) throws InterruptedException { long timetowait = System.currentTimeMillis() + 5000; while (!server.isStarted()) { Thread.sleep(100); if (server.isStarted()) { break; } else if (System.currentTimeMillis() > timetowait) { throw new IllegalStateException("server didn't start"); } } } public static void crash(ActiveMQServer server, ClientSession... sessions) throws Exception { final CountDownLatch latch = new CountDownLatch(sessions.length); class MyListener implements SessionFailureListener { @Override public void connectionFailed(final ActiveMQException me, boolean failedOver) { latch.countDown(); } @Override public void connectionFailed(final ActiveMQException me, boolean failedOver, String scaleDownTargetNodeID) { connectionFailed(me, failedOver); } @Override public void beforeReconnect(ActiveMQException exception) { System.out.println("MyListener.beforeReconnect"); } } for (ClientSession session : sessions) { session.addFailureListener(new MyListener()); } ClusterManager clusterManager = server.getClusterManager(); clusterManager.clear(); server.stop(true); // Wait to be informed of failure boolean ok = latch.await(10000, TimeUnit.MILLISECONDS); Assert.assertTrue(ok); } // Constructors -------------------------------------------------- // Public -------------------------------------------------------- // Package protected --------------------------------------------- // Protected ----------------------------------------------------- // Private ------------------------------------------------------- // Inner classes ------------------------------------------------- public static ActiveMQConnection createConnectionAndWaitForTopology(ActiveMQConnectionFactory factory, int topologyMembers, int timeout) throws Exception { ActiveMQConnection conn; CountDownLatch countDownLatch = new CountDownLatch(topologyMembers); ServerLocator locator = factory.getServerLocator(); locator.addClusterTopologyListener(new FailoverTestBase.LatchClusterTopologyListener(countDownLatch)); conn = (ActiveMQConnection) factory.createConnection(); boolean ok = countDownLatch.await(timeout, TimeUnit.SECONDS); if (!ok) { throw new IllegalStateException("timed out waiting for topology"); } return conn; } public static void waitForFailoverTopology(final int timeToWait, final ActiveMQServer backupServer, final ActiveMQServer... liveServers) throws Exception { long start = System.currentTimeMillis(); final int waitMillis = 2000; final int sleepTime = 50; int nWaits = 0; while ((backupServer.getClusterManager() == null || backupServer.getClusterManager().getClusterConnections().size() != 1) && nWaits++ < waitMillis / sleepTime) { Thread.sleep(sleepTime); } Set<ClusterConnection> ccs = backupServer.getClusterManager().getClusterConnections(); if (ccs.size() != 1) { throw new IllegalStateException("You need a single cluster connection on this version of waitForTopology on ServiceTestBase"); } boolean exists = false; for (ActiveMQServer liveServer : liveServers) { ClusterConnectionImpl clusterConnection = (ClusterConnectionImpl) ccs.iterator().next(); Topology topology = clusterConnection.getTopology(); TransportConfiguration nodeConnector = liveServer.getClusterManager().getClusterConnections().iterator().next().getConnector(); do { Collection<TopologyMemberImpl> members = topology.getMembers(); for (TopologyMemberImpl member : members) { if (member.getConnector().getA() != null && member.getConnector().getA().equals(nodeConnector)) { exists = true; break; } } if (exists) { break; } Thread.sleep(10); } while (System.currentTimeMillis() - start < timeToWait); if (!exists) { String msg = "Timed out waiting for cluster topology of " + backupServer + " (received " + topology.getMembers().size() + ") topology = " + topology + ")"; //logTopologyDiagram(); throw new Exception(msg); } } } public static class JMXListener implements NotificationListener { private Notification notif; @Override public void handleNotification(Notification notification, Object handback) { notif = notification; } public Notification getNotification() { return notif; } } }