/* * 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.client; import java.util.List; import java.util.concurrent.TimeUnit; import org.apache.activemq.artemis.api.core.ActiveMQException; import org.apache.activemq.artemis.api.core.ActiveMQInternalErrorException; import org.apache.activemq.artemis.api.core.SimpleString; import org.apache.activemq.artemis.api.core.client.ClientConsumer; import org.apache.activemq.artemis.api.core.client.ClientMessage; import org.apache.activemq.artemis.api.core.client.ClientProducer; import org.apache.activemq.artemis.api.core.client.ClientSession; import org.apache.activemq.artemis.api.core.client.ClientSession.QueueQuery; import org.apache.activemq.artemis.api.core.client.ClientSessionFactory; import org.apache.activemq.artemis.api.core.client.ServerLocator; import org.apache.activemq.artemis.api.core.client.SessionFailureListener; import org.apache.activemq.artemis.core.client.impl.ClientSessionFactoryInternal; import org.apache.activemq.artemis.core.client.impl.ClientSessionInternal; import org.apache.activemq.artemis.core.server.ActiveMQServer; import org.apache.activemq.artemis.core.server.Queue; import org.apache.activemq.artemis.core.settings.impl.AddressSettings; import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection; import org.apache.activemq.artemis.tests.util.ActiveMQTestBase; import org.apache.activemq.artemis.tests.util.CountDownSessionFailureListener; import org.apache.activemq.artemis.tests.util.Wait; import org.junit.Assert; import org.junit.Before; import org.junit.Test; /** * This test covers the API for ClientSession although XA tests are tested separately. */ public class SessionTest extends ActiveMQTestBase { private final String queueName = "ClientSessionTestQ"; private ServerLocator locator; private ActiveMQServer server; private ClientSessionFactory cf; @Override @Before public void setUp() throws Exception { super.setUp(); locator = createInVMNonHALocator(); server = createServer(false); server.start(); waitForServerToStart(server); } @Test public void testFailureListener() throws Exception { cf = createSessionFactory(locator); ClientSession clientSession = addClientSession(cf.createSession(false, true, true)); CountDownSessionFailureListener listener = new CountDownSessionFailureListener(clientSession); clientSession.addFailureListener(listener); // Make sure failure listener is called if server is stopped without session being closed first server.stop(); Assert.assertTrue(listener.getLatch().await(5, TimeUnit.SECONDS)); } @Test public void testFailureListenerRemoved() throws Exception { cf = createSessionFactory(locator); try { ClientSession clientSession = cf.createSession(false, true, true); class MyFailureListener implements SessionFailureListener { boolean called = false; @Override public void connectionFailed(final ActiveMQException me, boolean failedOver) { called = true; } @Override public void connectionFailed(final ActiveMQException me, boolean failedOver, String scaleDownTargetNodeID) { connectionFailed(me, failedOver); } @Override public void beforeReconnect(final ActiveMQException me) { } } MyFailureListener listener = new MyFailureListener(); clientSession.addFailureListener(listener); Assert.assertTrue(clientSession.removeFailureListener(listener)); clientSession.close(); server.stop(); Assert.assertFalse(listener.called); } finally { ((ClientSessionFactoryInternal) cf).causeExit(); cf.close(); } } // Closing a session if the underlying remoting connection is dead should cleanly // release all resources @Test public void testCloseSessionOnDestroyedConnection() throws Exception { // Make sure we have a short connection TTL so sessions will be quickly closed on the server server.stop(); long ttl = 500; server.getConfiguration().setConnectionTTLOverride(ttl); server.start(); cf = createSessionFactory(locator); ClientSessionInternal clientSession = (ClientSessionInternal) cf.createSession(false, true, true); clientSession.createQueue(queueName, queueName, false); /** keep unused variables in order to maintain references to both objects */ @SuppressWarnings("unused") ClientProducer producer = clientSession.createProducer(); @SuppressWarnings("unused") ClientConsumer consumer = clientSession.createConsumer(queueName); Assert.assertEquals(1, server.getRemotingService().getConnections().size()); RemotingConnection rc = clientSession.getConnection(); rc.fail(new ActiveMQInternalErrorException()); clientSession.close(); long start = System.currentTimeMillis(); while (true) { int cons = server.getRemotingService().getConnections().size(); if (cons == 0) { break; } long now = System.currentTimeMillis(); if (now - start > 10000) { throw new Exception("Timed out waiting for connections to close"); } Thread.sleep(50); } } @Test public void testBindingQuery() throws Exception { cf = createSessionFactory(locator); ClientSession clientSession = cf.createSession(false, true, true); clientSession.createQueue("a1", "q1", false); clientSession.createQueue("a1", "q2", false); clientSession.createQueue("a2", "q3", false); clientSession.createQueue("a2", "q4", false); clientSession.createQueue("a2", "q5", false); ClientSession.AddressQuery resp = clientSession.addressQuery(new SimpleString("a")); List<SimpleString> queues = resp.getQueueNames(); Assert.assertTrue(queues.isEmpty()); resp = clientSession.addressQuery(new SimpleString("a1")); queues = resp.getQueueNames(); Assert.assertEquals(queues.size(), 2); Assert.assertTrue(queues.contains(new SimpleString("q1"))); Assert.assertTrue(queues.contains(new SimpleString("q2"))); resp = clientSession.addressQuery(new SimpleString("a2")); queues = resp.getQueueNames(); Assert.assertEquals(queues.size(), 3); Assert.assertTrue(queues.contains(new SimpleString("q3"))); Assert.assertTrue(queues.contains(new SimpleString("q4"))); Assert.assertTrue(queues.contains(new SimpleString("q5"))); clientSession.close(); } @Test public void testQueueQuery() throws Exception { cf = createSessionFactory(locator); ClientSession clientSession = cf.createSession(false, true, true); clientSession.createQueue("a1", queueName, false); clientSession.createConsumer(queueName); clientSession.createConsumer(queueName); ClientProducer cp = clientSession.createProducer("a1"); cp.send(clientSession.createMessage(true)); cp.send(clientSession.createMessage(true)); flushQueue(); QueueQuery resp = clientSession.queueQuery(new SimpleString(queueName)); Assert.assertEquals(new SimpleString("a1"), resp.getAddress()); Assert.assertEquals(2, resp.getConsumerCount()); Assert.assertEquals(2, resp.getMessageCount()); Assert.assertEquals(null, resp.getFilterString()); clientSession.close(); } private void flushQueue() throws Exception { Queue queue = server.locateQueue(SimpleString.toSimpleString(queueName)); assertNotNull(queue); queue.flushExecutor(); } @Test public void testQueueQueryWithFilter() throws Exception { cf = createSessionFactory(locator); ClientSession clientSession = cf.createSession(false, true, true); clientSession.createQueue("a1", queueName, "foo=bar", false); clientSession.createConsumer(queueName); clientSession.createConsumer(queueName); QueueQuery resp = clientSession.queueQuery(new SimpleString(queueName)); Assert.assertEquals(new SimpleString("a1"), resp.getAddress()); Assert.assertEquals(2, resp.getConsumerCount()); Assert.assertEquals(0, resp.getMessageCount()); Assert.assertEquals(new SimpleString("foo=bar"), resp.getFilterString()); clientSession.close(); } @Test public void testQueueQueryNoQ() throws Exception { server.getAddressSettingsRepository().addMatch("#", new AddressSettings().setAutoCreateQueues(false)); cf = createSessionFactory(locator); ClientSession clientSession = cf.createSession(false, true, true); QueueQuery resp = clientSession.queueQuery(new SimpleString(queueName)); Assert.assertFalse(resp.isExists()); Assert.assertFalse(resp.isAutoCreateQueues()); Assert.assertEquals(null, resp.getAddress()); clientSession.close(); } @Test public void testClose() throws Exception { cf = createSessionFactory(locator); ClientSession clientSession = cf.createSession(false, true, true); clientSession.createQueue(queueName, queueName, false); ClientProducer p = clientSession.createProducer(); ClientProducer p1 = clientSession.createProducer(queueName); ClientConsumer c = clientSession.createConsumer(queueName); ClientConsumer c1 = clientSession.createConsumer(queueName); clientSession.close(); Assert.assertTrue(clientSession.isClosed()); Assert.assertTrue(p.isClosed()); Assert.assertTrue(p1.isClosed()); Assert.assertTrue(c.isClosed()); Assert.assertTrue(c1.isClosed()); } @Test public void testCreateMessageNonDurable() throws Exception { cf = createSessionFactory(locator); ClientSession clientSession = cf.createSession(false, true, true); ClientMessage clientMessage = clientSession.createMessage(false); Assert.assertFalse(clientMessage.isDurable()); clientSession.close(); } @Test public void testCreateMessageDurable() throws Exception { cf = createSessionFactory(locator); ClientSession clientSession = cf.createSession(false, true, true); ClientMessage clientMessage = clientSession.createMessage(true); Assert.assertTrue(clientMessage.isDurable()); clientSession.close(); } @Test public void testCreateMessageType() throws Exception { cf = createSessionFactory(locator); ClientSession clientSession = cf.createSession(false, true, true); ClientMessage clientMessage = clientSession.createMessage((byte) 99, false); Assert.assertEquals((byte) 99, clientMessage.getType()); clientSession.close(); } @Test public void testCreateMessageOverrides() throws Exception { cf = createSessionFactory(locator); ClientSession clientSession = cf.createSession(false, true, true); ClientMessage clientMessage = clientSession.createMessage((byte) 88, false, 100L, 300L, (byte) 33); Assert.assertEquals((byte) 88, clientMessage.getType()); Assert.assertEquals(100L, clientMessage.getExpiration()); Assert.assertEquals(300L, clientMessage.getTimestamp()); Assert.assertEquals((byte) 33, clientMessage.getPriority()); clientSession.close(); } @Test public void testGetVersion() throws Exception { cf = createSessionFactory(locator); ClientSession clientSession = cf.createSession(false, true, true); Assert.assertEquals(server.getVersion().getIncrementingVersion(), clientSession.getVersion()); clientSession.close(); } @Test public void testStart() throws Exception { cf = createSessionFactory(locator); ClientSession clientSession = cf.createSession(false, true, true); clientSession.createQueue(queueName, queueName, false); clientSession.start(); clientSession.close(); } @Test public void testStop() throws Exception { cf = createSessionFactory(locator); ClientSession clientSession = cf.createSession(false, true, true); clientSession.createQueue(queueName, queueName, false); clientSession.start(); clientSession.stop(); clientSession.close(); } @Test public void testCommitWithSend() throws Exception { cf = createSessionFactory(locator); ClientSession clientSession = cf.createSession(false, false, true); clientSession.createQueue(queueName, queueName, false); ClientProducer cp = clientSession.createProducer(queueName); cp.send(clientSession.createMessage(false)); cp.send(clientSession.createMessage(false)); cp.send(clientSession.createMessage(false)); cp.send(clientSession.createMessage(false)); cp.send(clientSession.createMessage(false)); cp.send(clientSession.createMessage(false)); cp.send(clientSession.createMessage(false)); cp.send(clientSession.createMessage(false)); cp.send(clientSession.createMessage(false)); cp.send(clientSession.createMessage(false)); Queue q = (Queue) server.getPostOffice().getBinding(new SimpleString(queueName)).getBindable(); Assert.assertEquals(0, getMessageCount(q)); clientSession.commit(); Assert.assertEquals(10, getMessageCount(q)); clientSession.close(); } @Test public void testRollbackWithSend() throws Exception { cf = createSessionFactory(locator); ClientSession clientSession = cf.createSession(false, false, true); clientSession.createQueue(queueName, queueName, false); ClientProducer cp = clientSession.createProducer(queueName); cp.send(clientSession.createMessage(false)); cp.send(clientSession.createMessage(false)); cp.send(clientSession.createMessage(false)); cp.send(clientSession.createMessage(false)); cp.send(clientSession.createMessage(false)); cp.send(clientSession.createMessage(false)); cp.send(clientSession.createMessage(false)); cp.send(clientSession.createMessage(false)); cp.send(clientSession.createMessage(false)); cp.send(clientSession.createMessage(false)); Queue q = (Queue) server.getPostOffice().getBinding(new SimpleString(queueName)).getBindable(); Assert.assertEquals(0, getMessageCount(q)); clientSession.rollback(); cp.send(clientSession.createMessage(false)); cp.send(clientSession.createMessage(false)); clientSession.commit(); Assert.assertEquals(2, getMessageCount(q)); clientSession.close(); } @Test public void testCommitWithReceive() throws Exception { locator.setBlockOnNonDurableSend(true).setBlockOnDurableSend(true); cf = createSessionFactory(locator); ClientSession sendSession = cf.createSession(false, true, true); ClientProducer cp = sendSession.createProducer(queueName); ClientSession clientSession = cf.createSession(false, true, false); clientSession.createQueue(queueName, queueName, false); cp.send(clientSession.createMessage(false)); cp.send(clientSession.createMessage(false)); cp.send(clientSession.createMessage(false)); cp.send(clientSession.createMessage(false)); cp.send(clientSession.createMessage(false)); cp.send(clientSession.createMessage(false)); cp.send(clientSession.createMessage(false)); cp.send(clientSession.createMessage(false)); cp.send(clientSession.createMessage(false)); cp.send(clientSession.createMessage(false)); Queue q = (Queue) server.getPostOffice().getBinding(new SimpleString(queueName)).getBindable(); Assert.assertEquals(10, getMessageCount(q)); ClientConsumer cc = clientSession.createConsumer(queueName); clientSession.start(); ClientMessage m = cc.receive(5000); Assert.assertNotNull(m); m.acknowledge(); m = cc.receive(5000); Assert.assertNotNull(m); m.acknowledge(); m = cc.receive(5000); Assert.assertNotNull(m); m.acknowledge(); m = cc.receive(5000); Assert.assertNotNull(m); m.acknowledge(); m = cc.receive(5000); Assert.assertNotNull(m); m.acknowledge(); m = cc.receive(5000); Assert.assertNotNull(m); m.acknowledge(); m = cc.receive(5000); Assert.assertNotNull(m); m.acknowledge(); m = cc.receive(5000); Assert.assertNotNull(m); m.acknowledge(); m = cc.receive(5000); Assert.assertNotNull(m); m.acknowledge(); m = cc.receive(5000); Assert.assertNotNull(m); m.acknowledge(); clientSession.commit(); Assert.assertEquals(0, getMessageCount(q)); clientSession.close(); sendSession.close(); } @Test public void testRollbackWithReceive() throws Exception { locator.setBlockOnNonDurableSend(true).setBlockOnDurableSend(true); cf = createSessionFactory(locator); ClientSession sendSession = cf.createSession(false, true, true); ClientProducer cp = sendSession.createProducer(queueName); ClientSession clientSession = cf.createSession(false, true, false); clientSession.createQueue(queueName, queueName, false); cp.send(clientSession.createMessage(false)); cp.send(clientSession.createMessage(false)); cp.send(clientSession.createMessage(false)); cp.send(clientSession.createMessage(false)); cp.send(clientSession.createMessage(false)); cp.send(clientSession.createMessage(false)); cp.send(clientSession.createMessage(false)); cp.send(clientSession.createMessage(false)); cp.send(clientSession.createMessage(false)); cp.send(clientSession.createMessage(false)); Queue q = (Queue) server.getPostOffice().getBinding(new SimpleString(queueName)).getBindable(); Assert.assertEquals(10, getMessageCount(q)); ClientConsumer cc = clientSession.createConsumer(queueName); clientSession.start(); ClientMessage m = cc.receive(5000); Assert.assertNotNull(m); m.acknowledge(); m = cc.receive(5000); Assert.assertNotNull(m); m.acknowledge(); m = cc.receive(5000); Assert.assertNotNull(m); m.acknowledge(); m = cc.receive(5000); Assert.assertNotNull(m); m.acknowledge(); m = cc.receive(5000); Assert.assertNotNull(m); m.acknowledge(); m = cc.receive(5000); Assert.assertNotNull(m); m.acknowledge(); m = cc.receive(5000); Assert.assertNotNull(m); m.acknowledge(); m = cc.receive(5000); Assert.assertNotNull(m); m.acknowledge(); m = cc.receive(5000); Assert.assertNotNull(m); m.acknowledge(); m = cc.receive(5000); Assert.assertNotNull(m); m.acknowledge(); clientSession.rollback(); Wait.waitFor(() -> getMessageCount(q) == 10); Assert.assertEquals(10, getMessageCount(q)); clientSession.close(); sendSession.close(); } @Test public void testGetNodeId() throws Exception { cf = createSessionFactory(locator); ClientSession clientSession = addClientSession(cf.createSession(false, true, true)); String nodeId = ((ClientSessionInternal) clientSession).getNodeId(); assertNotNull(nodeId); } }