/*
* 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);
}
}