/*
* 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.stomp;
import javax.jms.BytesMessage;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.MessageProducer;
import javax.jms.TextMessage;
import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.client.ActiveMQClient;
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.ClientSessionFactory;
import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.api.core.management.ActiveMQServerControl;
import org.apache.activemq.artemis.api.core.management.ManagementHelper;
import org.apache.activemq.artemis.api.core.management.ResourceNames;
import org.apache.activemq.artemis.api.jms.ActiveMQJMSClient;
import org.apache.activemq.artemis.core.postoffice.impl.LocalQueueBinding;
import org.apache.activemq.artemis.core.protocol.stomp.Stomp;
import org.apache.activemq.artemis.core.protocol.stomp.StompProtocolManagerFactory;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.core.server.Queue;
import org.apache.activemq.artemis.core.server.impl.ActiveMQServerImpl;
import org.apache.activemq.artemis.core.server.impl.AddressInfo;
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
import org.apache.activemq.artemis.logs.AssertionLoggerHandler;
import org.apache.activemq.artemis.tests.integration.IntegrationTestLogger;
import org.apache.activemq.artemis.tests.integration.mqtt.imported.FuseMQTTClientProvider;
import org.apache.activemq.artemis.tests.integration.mqtt.imported.MQTTClientProvider;
import org.apache.activemq.artemis.tests.integration.stomp.util.ClientStompFrame;
import org.apache.activemq.artemis.tests.integration.stomp.util.StompClientConnection;
import org.apache.activemq.artemis.tests.integration.stomp.util.StompClientConnectionFactory;
import org.apache.activemq.artemis.tests.util.Wait;
import org.apache.activemq.artemis.utils.RandomUtil;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class StompTest extends StompTestBase {
private static final transient IntegrationTestLogger log = IntegrationTestLogger.LOGGER;
protected StompClientConnection conn;
@Override
@Before
public void setUp() throws Exception {
super.setUp();
conn = StompClientConnectionFactory.createClientConnection("1.0", hostname, port);
}
@Override
@After
public void tearDown() throws Exception {
try {
boolean connected = conn != null && conn.isConnected();
log.debug("Connection 1.0 connected: " + connected);
if (connected) {
try {
conn.disconnect();
} catch (Exception e) {
// ignore
}
}
} finally {
super.tearDown();
}
}
@Test
public void testConnectionTTL() throws Exception {
int port = 61614;
server.getActiveMQServer().getRemotingService().createAcceptor("test", "tcp://127.0.0.1:" + port + "?connectionTtl=1000").start();
conn = StompClientConnectionFactory.createClientConnection("1.0", hostname, port);
conn.connect("brianm", "wombats");
Thread.sleep(5000);
ClientStompFrame frame = conn.receiveFrame();
assertEquals(Stomp.Responses.ERROR, frame.getCommand());
assertFalse(conn.isConnected());
}
@Test
public void testSendManyMessages() throws Exception {
conn.connect(defUser, defPass);
MessageConsumer consumer = session.createConsumer(queue);
int count = 1000;
final CountDownLatch latch = new CountDownLatch(count);
consumer.setMessageListener(new MessageListener() {
@Override
public void onMessage(Message arg0) {
latch.countDown();
}
});
for (int i = 1; i <= count; i++) {
send(conn, getQueuePrefix() + getQueueName(), null, "Hello World!");
}
assertTrue(latch.await(60, TimeUnit.SECONDS));
}
@Test
public void testSendOverDiskFull() throws Exception {
AssertionLoggerHandler.startCapture();
try {
MessageConsumer consumer = session.createConsumer(queue);
conn.connect(defUser, defPass);
int count = 1000;
final CountDownLatch latch = new CountDownLatch(count);
consumer.setMessageListener(new MessageListener() {
@Override
public void onMessage(Message arg0) {
latch.countDown();
}
});
((ActiveMQServerImpl) server.getActiveMQServer()).getMonitor()
.setMaxUsage(0)
.tick();
for (int i = 1; i <= count; i++) {
// Thread.sleep(1);
// log.info(">>> " + i);
send(conn, getQueuePrefix() + getQueueName(), null, "Hello World!");
}
// It should encounter the exception on logs
AssertionLoggerHandler.findText("AMQ119119");
} finally {
AssertionLoggerHandler.clear();
AssertionLoggerHandler.stopCapture();
}
}
@Test
public void testConnect() throws Exception {
ClientStompFrame frame = conn.createFrame(Stomp.Commands.CONNECT)
.addHeader(Stomp.Headers.Connect.LOGIN, defUser)
.addHeader(Stomp.Headers.Connect.PASSCODE, defPass)
.addHeader(Stomp.Headers.Connect.REQUEST_ID, "1");
ClientStompFrame response = conn.sendFrame(frame);
Assert.assertTrue(response.getCommand()
.equals(Stomp.Responses.CONNECTED));
Assert.assertTrue(response.getHeader(Stomp.Headers.Connected.RESPONSE_ID)
.equals("1"));
}
@Test
public void testDisconnectAndError() throws Exception {
ClientStompFrame frame = conn.createFrame(Stomp.Commands.CONNECT)
.addHeader(Stomp.Headers.Connect.LOGIN, defUser)
.addHeader(Stomp.Headers.Connect.PASSCODE, defPass)
.addHeader(Stomp.Headers.Connect.REQUEST_ID, "1");
ClientStompFrame response = conn.sendFrame(frame);
Assert.assertTrue(response.getCommand()
.equals(Stomp.Responses.CONNECTED));
Assert.assertTrue(response.getHeader(Stomp.Headers.Connected.RESPONSE_ID)
.equals("1"));
conn.disconnect();
// sending a message will result in an error
try {
send(conn, getQueuePrefix() + getQueueName(), null, "Hello World!");
fail("Should have thrown an exception since connection is disconnected");
} catch (Exception e) {
// ignore
}
}
@Test
public void testSendMessage() throws Exception {
MessageConsumer consumer = session.createConsumer(queue);
conn.connect(defUser, defPass);
send(conn, getQueuePrefix() + getQueueName(), null, "Hello World");
TextMessage message = (TextMessage) consumer.receive(1000);
Assert.assertNotNull(message);
Assert.assertEquals("Hello World", message.getText());
// Assert default priority 4 is used when priority header is not set
Assert.assertEquals("getJMSPriority", 4, message.getJMSPriority());
// Make sure that the timestamp is valid - should
// be very close to the current time.
long tnow = System.currentTimeMillis();
long tmsg = message.getJMSTimestamp();
Assert.assertTrue(Math.abs(tnow - tmsg) < 1000);
}
@Test
public void sendSTOMPReceiveMQTT() throws Exception {
// Set up MQTT Subscription
MQTTClientProvider clientProvider = new FuseMQTTClientProvider();
clientProvider.connect("tcp://" + hostname + ":" + port);
clientProvider.subscribe(getTopicPrefix() + getTopicName(), 0);
String stompPayload = "This is a test message";
// Set up STOMP connection and send STOMP Message
conn.connect(defUser, defPass);
send(conn, getTopicPrefix() + getTopicName(), null, stompPayload);
// Receive MQTT Message
byte[] mqttPayload = clientProvider.receive(10000);
clientProvider.disconnect();
assertEquals(stompPayload, new String(mqttPayload, "UTF-8"));
clientProvider.disconnect();
}
@Test
public void sendMQTTReceiveSTOMP() throws Exception {
String payload = "This is a test message";
// Set up STOMP subscription
conn.connect(defUser, defPass);
subscribe(conn, null, Stomp.Headers.Subscribe.AckModeValues.AUTO);
// Send MQTT Message
MQTTClientProvider clientProvider = new FuseMQTTClientProvider();
clientProvider.connect("tcp://" + hostname + ":" + port);
clientProvider.publish(getQueuePrefix() + getQueueName(), payload.getBytes(), 0);
clientProvider.disconnect();
// Receive STOMP Message
ClientStompFrame frame = conn.receiveFrame();
assertTrue(frame.getBody()
.contains(payload));
}
@Test
public void testSendMessageToNonExistentQueue() throws Exception {
String nonExistentQueue = RandomUtil.randomString();
conn.connect(defUser, defPass);
send(conn, getQueuePrefix() + nonExistentQueue, null, "Hello World", true, RoutingType.ANYCAST);
MessageConsumer consumer = session.createConsumer(ActiveMQJMSClient.createQueue(nonExistentQueue));
TextMessage message = (TextMessage) consumer.receive(1000);
Assert.assertNotNull(message);
Assert.assertEquals("Hello World", message.getText());
// Assert default priority 4 is used when priority header is not set
Assert.assertEquals("getJMSPriority", 4, message.getJMSPriority());
// Make sure that the timestamp is valid - should
// be very close to the current time.
long tnow = System.currentTimeMillis();
long tmsg = message.getJMSTimestamp();
Assert.assertTrue(Math.abs(tnow - tmsg) < 1500);
// closing the consumer here should trigger auto-deletion
assertNotNull(server.getActiveMQServer()
.getPostOffice()
.getBinding(new SimpleString(nonExistentQueue)));
consumer.close();
assertNull(server.getActiveMQServer()
.getPostOffice()
.getBinding(new SimpleString(nonExistentQueue)));
}
@Test
public void testSendMessageToNonExistentTopic() throws Exception {
String nonExistentTopic = RandomUtil.randomString();
conn.connect(defUser, defPass);
// first send a message to ensure that sending to a non-existent topic won't throw an error
send(conn, getTopicPrefix() + nonExistentTopic, null, "Hello World", true, RoutingType.MULTICAST);
// create a subscription on the topic and send/receive another message
MessageConsumer consumer = session.createConsumer(ActiveMQJMSClient.createTopic(nonExistentTopic));
send(conn, getTopicPrefix() + nonExistentTopic, null, "Hello World", true);
TextMessage message = (TextMessage) consumer.receive(1000);
Assert.assertNotNull(message);
Assert.assertEquals("Hello World", message.getText());
// Assert default priority 4 is used when priority header is not set
Assert.assertEquals("getJMSPriority", 4, message.getJMSPriority());
// Make sure that the timestamp is valid - should
// be very close to the current time.
long tnow = System.currentTimeMillis();
long tmsg = message.getJMSTimestamp();
Assert.assertTrue(Math.abs(tnow - tmsg) < 1500);
assertNotNull(server.getActiveMQServer()
.getAddressInfo(new SimpleString(nonExistentTopic)));
// closing the consumer here should trigger auto-deletion of the subscription queue and address
consumer.close();
Thread.sleep(200);
assertNull(server.getActiveMQServer()
.getAddressInfo(new SimpleString(nonExistentTopic)));
}
/*
* Some STOMP clients erroneously put a new line \n *after* the terminating NUL char at the end of the frame
* This means next frame read might have a \n a the beginning.
* This is contrary to STOMP spec but we deal with it so we can work nicely with crappy STOMP clients
*/
@Test
public void testSendMessageWithLeadingNewLine() throws Exception {
conn.connect(defUser, defPass);
ClientStompFrame frame = conn.createFrame(Stomp.Commands.SEND)
.addHeader(Stomp.Headers.Send.DESTINATION, getQueuePrefix() + getQueueName())
.setBody("Hello World");
conn.sendWickedFrame(frame);
MessageConsumer consumer = session.createConsumer(queue);
TextMessage message = (TextMessage) consumer.receive(1000);
Assert.assertNotNull(message);
Assert.assertEquals("Hello World", message.getText());
send(conn, getQueuePrefix() + getQueueName(), null, "Hello World");
message = (TextMessage) consumer.receive(1000);
Assert.assertNotNull(message);
Assert.assertEquals("Hello World", message.getText());
// Make sure that the timestamp is valid - should
// be very close to the current time.
long tnow = System.currentTimeMillis();
long tmsg = message.getJMSTimestamp();
Assert.assertTrue(Math.abs(tnow - tmsg) < 1000);
}
@Test
public void testSendMessageWithReceipt() throws Exception {
MessageConsumer consumer = session.createConsumer(queue);
conn.connect(defUser, defPass);
send(conn, getQueuePrefix() + getQueueName(), null, "Hello World", true);
TextMessage message = (TextMessage) consumer.receive(1000);
Assert.assertNotNull(message);
Assert.assertEquals("Hello World", message.getText());
// Make sure that the timestamp is valid - should
// be very close to the current time.
long tnow = System.currentTimeMillis();
long tmsg = message.getJMSTimestamp();
Assert.assertTrue(Math.abs(tnow - tmsg) < 1000);
}
@Test
public void testSendMessageWithContentLength() throws Exception {
MessageConsumer consumer = session.createConsumer(queue);
conn.connect(defUser, defPass);
byte[] data = new byte[]{1, 0, 0, 4};
ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos.write(data);
baos.flush();
ClientStompFrame frame = conn.createFrame(Stomp.Commands.SEND)
.addHeader(Stomp.Headers.Send.DESTINATION, getQueuePrefix() + getQueueName())
.addHeader(Stomp.Headers.CONTENT_LENGTH, Integer.toString(data.length))
.setBody(new String(baos.toByteArray()));
conn.sendFrame(frame);
BytesMessage message = (BytesMessage) consumer.receive(10000);
Assert.assertNotNull(message);
assertEquals(data.length, message.getBodyLength());
assertEquals(data[0], message.readByte());
assertEquals(data[1], message.readByte());
assertEquals(data[2], message.readByte());
assertEquals(data[3], message.readByte());
}
@Test
public void testJMSXGroupIdCanBeSet() throws Exception {
final String jmsxGroupID = "JMSXGroupID";
MessageConsumer consumer = session.createConsumer(queue);
conn.connect(defUser, defPass);
ClientStompFrame frame = conn.createFrame(Stomp.Commands.SEND)
.addHeader(Stomp.Headers.Send.DESTINATION, getQueuePrefix() + getQueueName())
.addHeader("JMSXGroupID", jmsxGroupID)
.setBody("Hello World");
conn.sendFrame(frame);
TextMessage message = (TextMessage) consumer.receive(1000);
Assert.assertNotNull(message);
Assert.assertEquals("Hello World", message.getText());
// differ from StompConnect
Assert.assertEquals(jmsxGroupID, message.getStringProperty("JMSXGroupID"));
}
@Test
public void testSendMessageWithCustomHeadersAndSelector() throws Exception {
MessageConsumer consumer = session.createConsumer(queue, "foo = 'abc'");
conn.connect(defUser, defPass);
ClientStompFrame frame = conn.createFrame(Stomp.Commands.SEND)
.addHeader(Stomp.Headers.Send.DESTINATION, getQueuePrefix() + getQueueName())
.addHeader("foo", "abc")
.addHeader("bar", "123")
.setBody("Hello World");
conn.sendFrame(frame);
TextMessage message = (TextMessage) consumer.receive(1000);
Assert.assertNotNull(message);
Assert.assertEquals("Hello World", message.getText());
Assert.assertEquals("foo", "abc", message.getStringProperty("foo"));
Assert.assertEquals("bar", "123", message.getStringProperty("bar"));
}
@Test
public void testSendMessageWithCustomHeadersAndHyphenatedSelector() throws Exception {
MessageConsumer consumer = session.createConsumer(queue, "hyphenated_props:b-ar = '123'");
conn.connect(defUser, defPass);
ClientStompFrame frame = conn.createFrame(Stomp.Commands.SEND)
.addHeader(Stomp.Headers.Send.DESTINATION, getQueuePrefix() + getQueueName())
.addHeader("foo", "abc")
.addHeader("b-ar", "123")
.setBody("Hello World");
conn.sendFrame(frame);
TextMessage message = (TextMessage) consumer.receive(1000);
Assert.assertNotNull(message);
Assert.assertEquals("Hello World", message.getText());
Assert.assertEquals("foo", "abc", message.getStringProperty("foo"));
Assert.assertEquals("b-ar", "123", message.getStringProperty("b-ar"));
}
@Test
public void testSendMessageWithStandardHeaders() throws Exception {
MessageConsumer consumer = session.createConsumer(queue);
conn.connect(defUser, defPass);
ClientStompFrame frame = conn.createFrame(Stomp.Commands.SEND)
.addHeader(Stomp.Headers.Send.DESTINATION, getQueuePrefix() + getQueueName())
.addHeader("foo", "abc")
.addHeader("bar", "123")
.addHeader("correlation-id", "c123")
.addHeader("persistent", "true")
.addHeader("type", "t345")
.addHeader("JMSXGroupID", "abc")
.addHeader("priority", "3")
.setBody("Hello World");
conn.sendFrame(frame);
TextMessage message = (TextMessage) consumer.receive(1000);
Assert.assertNotNull(message);
Assert.assertEquals("Hello World", message.getText());
Assert.assertEquals("JMSCorrelationID", "c123", message.getJMSCorrelationID());
Assert.assertEquals("getJMSType", "t345", message.getJMSType());
Assert.assertEquals("getJMSPriority", 3, message.getJMSPriority());
Assert.assertEquals(javax.jms.DeliveryMode.PERSISTENT, message.getJMSDeliveryMode());
Assert.assertEquals("foo", "abc", message.getStringProperty("foo"));
Assert.assertEquals("bar", "123", message.getStringProperty("bar"));
Assert.assertEquals("JMSXGroupID", "abc", message.getStringProperty("JMSXGroupID"));
// FIXME do we support it?
// Assert.assertEquals("GroupID", "abc", amqMessage.getGroupID());
}
@Test
public void testSendMessageWithLongHeaders() throws Exception {
MessageConsumer consumer = session.createConsumer(queue);
conn.connect(defUser, defPass);
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < 1024; i++) {
buffer.append("a");
}
ClientStompFrame frame = conn.createFrame(Stomp.Commands.SEND)
.addHeader(Stomp.Headers.Send.DESTINATION, getQueuePrefix() + getQueueName())
.addHeader("foo", "abc")
.addHeader("bar", "123")
.addHeader("correlation-id", "c123")
.addHeader("persistent", "true")
.addHeader("type", "t345")
.addHeader("JMSXGroupID", "abc")
.addHeader("priority", "3")
.addHeader("longHeader", buffer.toString())
.setBody("Hello World");
conn.sendFrame(frame);
TextMessage message = (TextMessage) consumer.receive(1000);
Assert.assertNotNull(message);
Assert.assertEquals("Hello World", message.getText());
Assert.assertEquals("JMSCorrelationID", "c123", message.getJMSCorrelationID());
Assert.assertEquals("getJMSType", "t345", message.getJMSType());
Assert.assertEquals("getJMSPriority", 3, message.getJMSPriority());
Assert.assertEquals(javax.jms.DeliveryMode.PERSISTENT, message.getJMSDeliveryMode());
Assert.assertEquals("foo", "abc", message.getStringProperty("foo"));
Assert.assertEquals("longHeader", 1024, message.getStringProperty("longHeader")
.length());
Assert.assertEquals("JMSXGroupID", "abc", message.getStringProperty("JMSXGroupID"));
}
@Test
public void testSubscribeWithAutoAck() throws Exception {
conn.connect(defUser, defPass);
subscribe(conn, null, Stomp.Headers.Subscribe.AckModeValues.AUTO);
sendJmsMessage(getName());
ClientStompFrame frame = conn.receiveFrame(10000);
Assert.assertEquals(Stomp.Responses.MESSAGE, frame.getCommand());
Assert.assertEquals(getQueuePrefix() + getQueueName(), frame.getHeader(Stomp.Headers.Send.DESTINATION));
Assert.assertEquals(getName(), frame.getBody());
Pattern cl = Pattern.compile(Stomp.Headers.CONTENT_LENGTH + ":\\s*(\\d+)", Pattern.CASE_INSENSITIVE);
Matcher cl_matcher = cl.matcher(frame.toString());
Assert.assertFalse(cl_matcher.find());
conn.disconnect();
// message should not be received as it was auto-acked
MessageConsumer consumer = session.createConsumer(queue);
Message message = consumer.receive(1000);
Assert.assertNull(message);
}
@Test
public void testSubscribeWithAutoAckAndBytesMessage() throws Exception {
conn.connect(defUser, defPass);
subscribe(conn, null, Stomp.Headers.Subscribe.AckModeValues.AUTO);
byte[] payload = new byte[]{1, 2, 3, 4, 5};
sendJmsMessage(payload, queue);
ClientStompFrame frame = conn.receiveFrame(10000);
Assert.assertEquals(Stomp.Responses.MESSAGE, frame.getCommand());
Pattern cl = Pattern.compile(Stomp.Headers.CONTENT_LENGTH + ":\\s*(\\d+)", Pattern.CASE_INSENSITIVE);
Matcher cl_matcher = cl.matcher(frame.toString());
Assert.assertTrue(cl_matcher.find());
Assert.assertEquals("5", cl_matcher.group(1));
Assert.assertFalse(Pattern.compile("type:\\s*null", Pattern.CASE_INSENSITIVE).matcher(frame.toString()).find());
Assert.assertTrue(frame.getBody().toString().indexOf(new String(payload)) > -1);
conn.disconnect();
}
@Test
public void testSubscribeWithMessageSentWithProperties() throws Exception {
conn.connect(defUser, defPass);
subscribe(conn, null, Stomp.Headers.Subscribe.AckModeValues.AUTO);
MessageProducer producer = session.createProducer(queue);
BytesMessage message = session.createBytesMessage();
message.setStringProperty("S", "value");
message.setBooleanProperty("n", false);
message.setByteProperty("byte", (byte) 9);
message.setDoubleProperty("d", 2.0);
message.setFloatProperty("f", (float) 6.0);
message.setIntProperty("i", 10);
message.setLongProperty("l", 121);
message.setShortProperty("s", (short) 12);
message.writeBytes("Hello World".getBytes(StandardCharsets.UTF_8));
producer.send(message);
ClientStompFrame frame = conn.receiveFrame(10000);
Assert.assertNotNull(frame);
Assert.assertEquals(Stomp.Responses.MESSAGE, frame.getCommand());
Assert.assertEquals("value", frame.getHeader("S"));
Assert.assertEquals("false", frame.getHeader("n"));
Assert.assertEquals("9", frame.getHeader("byte"));
Assert.assertEquals("2.0", frame.getHeader("d"));
Assert.assertEquals("6.0", frame.getHeader("f"));
Assert.assertEquals("10", frame.getHeader("i"));
Assert.assertEquals("121", frame.getHeader("l"));
Assert.assertEquals("12", frame.getHeader("s"));
Assert.assertEquals("Hello World", frame.getBody());
conn.disconnect();
}
@Test
public void testSubscribeWithID() throws Exception {
conn.connect(defUser, defPass);
subscribe(conn, "mysubid", Stomp.Headers.Subscribe.AckModeValues.AUTO);
sendJmsMessage(getName());
ClientStompFrame frame = conn.receiveFrame(10000);
Assert.assertEquals(Stomp.Responses.MESSAGE, frame.getCommand());
Assert.assertEquals(getQueuePrefix() + getQueueName(), frame.getHeader(Stomp.Headers.Message.DESTINATION));
Assert.assertEquals("mysubid", frame.getHeader(Stomp.Headers.Message.SUBSCRIPTION));
Assert.assertEquals(getName(), frame.getBody());
conn.disconnect();
}
//
@Test
public void testBodyWithUTF8() throws Exception {
conn.connect(defUser, defPass);
subscribe(conn, null, Stomp.Headers.Subscribe.AckModeValues.AUTO);
String text = "A" + "\u00ea" + "\u00f1" + "\u00fc" + "C";
log.info(text);
sendJmsMessage(text);
ClientStompFrame frame = conn.receiveFrame(10000);
log.info(frame);
Assert.assertEquals(Stomp.Responses.MESSAGE, frame.getCommand());
Assert.assertEquals(getQueuePrefix() + getQueueName(), frame.getHeader(Stomp.Headers.Message.DESTINATION));
Assert.assertEquals(text, frame.getBody());
conn.disconnect();
}
@Test
public void testMessagesAreInOrder() throws Exception {
int ctr = 10;
String[] data = new String[ctr];
conn.connect(defUser, defPass);
subscribe(conn, null, Stomp.Headers.Subscribe.AckModeValues.AUTO);
for (int i = 0; i < ctr; ++i) {
data[i] = getName() + i;
sendJmsMessage(data[i]);
}
for (int i = 0; i < ctr; ++i) {
ClientStompFrame frame = conn.receiveFrame(1000);
Assert.assertTrue("Message not in order", frame.getBody().equals(data[i]));
}
// sleep a while before publishing another set of messages
Thread.sleep(200);
for (int i = 0; i < ctr; ++i) {
data[i] = getName() + Stomp.Headers.SEPARATOR + "second:" + i;
sendJmsMessage(data[i]);
}
for (int i = 0; i < ctr; ++i) {
ClientStompFrame frame = conn.receiveFrame(1000);
Assert.assertTrue("Message not in order", frame.getBody().equals(data[i]));
}
conn.disconnect();
}
@Test
public void testSubscribeWithAutoAckAndSelector() throws Exception {
conn.connect(defUser, defPass);
subscribe(conn, null, Stomp.Headers.Subscribe.AckModeValues.AUTO, null, "foo = 'zzz'");
sendJmsMessage("Ignored message", "foo", "1234");
sendJmsMessage("Real message", "foo", "zzz");
ClientStompFrame frame = conn.receiveFrame(10000);
Assert.assertEquals(Stomp.Responses.MESSAGE, frame.getCommand());
Assert.assertTrue("Should have received the real message but got: " + frame, frame.getBody().equals("Real message"));
conn.disconnect();
}
@Test
public void testSubscribeWithAutoAckAndHyphenatedSelector() throws Exception {
conn.connect(defUser, defPass);
subscribe(conn, null, Stomp.Headers.Subscribe.AckModeValues.AUTO, null, "hyphenated_props:foo-bar = 'zzz'");
ServerLocator serverLocator = addServerLocator(ActiveMQClient.createServerLocator("vm://0"));
ClientSessionFactory clientSessionFactory = serverLocator.createSessionFactory();
ClientSession clientSession = clientSessionFactory.createSession(true, true);
ClientProducer producer = clientSession.createProducer(getQueuePrefix() + getQueueName());
ClientMessage ignoredMessage = clientSession.createMessage(false);
ignoredMessage.putStringProperty("foo-bar", "1234");
ignoredMessage.getBodyBuffer().writeNullableSimpleString(SimpleString.toSimpleString("Ignored message"));
ClientMessage realMessage = clientSession.createMessage(false);
realMessage.putStringProperty("foo-bar", "zzz");
realMessage.getBodyBuffer().writeNullableSimpleString(SimpleString.toSimpleString("Real message"));
producer.send(ignoredMessage);
producer.send(realMessage);
ClientStompFrame frame = conn.receiveFrame(10000);
Assert.assertEquals(Stomp.Responses.MESSAGE, frame.getCommand());
Assert.assertTrue("Should have received the real message but got: " + frame, frame.getBody().equals("Real message"));
conn.disconnect();
}
@Test
public void testSubscribeWithClientAck() throws Exception {
conn.connect(defUser, defPass);
subscribe(conn, null, Stomp.Headers.Subscribe.AckModeValues.CLIENT);
sendJmsMessage(getName());
ClientStompFrame frame = conn.receiveFrame(10000);
Assert.assertEquals(Stomp.Responses.MESSAGE, frame.getCommand());
Assert.assertNotNull(frame.getHeader(Stomp.Headers.Message.MESSAGE_ID));
ack(conn, null, frame);
conn.disconnect();
// message should not be received since message was acknowledged by the client
MessageConsumer consumer = session.createConsumer(queue);
Message message = consumer.receive(1000);
Assert.assertNull(message);
}
@Test
public void testRedeliveryWithClientAck() throws Exception {
conn.connect(defUser, defPass);
subscribe(conn, null, Stomp.Headers.Subscribe.AckModeValues.CLIENT);
sendJmsMessage(getName());
ClientStompFrame frame = conn.receiveFrame(10000);
Assert.assertEquals(Stomp.Responses.MESSAGE, frame.getCommand());
conn.disconnect();
// message should be received since message was not acknowledged
MessageConsumer consumer = session.createConsumer(queue);
Message message = consumer.receive(1000);
Assert.assertNotNull(message);
Assert.assertTrue(message.getJMSRedelivered());
}
@Test
public void testSubscribeWithClientAckThenConsumingAgainWithAutoAckWithNoDisconnectFrame() throws Exception {
assertSubscribeWithClientAckThenConsumeWithAutoAck(false);
}
@Test
public void testSubscribeWithClientAckThenConsumingAgainWithAutoAckWithExplicitDisconnect() throws Exception {
assertSubscribeWithClientAckThenConsumeWithAutoAck(true);
}
protected void assertSubscribeWithClientAckThenConsumeWithAutoAck(boolean sendDisconnect) throws Exception {
conn.connect(defUser, defPass);
subscribe(conn, null, Stomp.Headers.Subscribe.AckModeValues.CLIENT);
sendJmsMessage(getName());
ClientStompFrame frame = conn.receiveFrame(10000);
Assert.assertEquals(Stomp.Responses.MESSAGE, frame.getCommand());
log.info("Reconnecting!");
if (sendDisconnect) {
conn.disconnect();
conn.destroy();
conn = StompClientConnectionFactory.createClientConnection("1.0", hostname, port);
} else {
conn.destroy();
conn = StompClientConnectionFactory.createClientConnection("1.0", hostname, port);
}
// message should be received since message was not acknowledged
conn.connect(defUser, defPass);
subscribe(conn, null);
frame = conn.receiveFrame(10000);
Assert.assertEquals(Stomp.Responses.MESSAGE, frame.getCommand());
conn.disconnect();
conn.destroy();
conn = StompClientConnectionFactory.createClientConnection("1.0", hostname, port);
// now let's make sure we don't see the message again
conn.connect(defUser, defPass);
subscribe(conn, null, Stomp.Headers.Subscribe.AckModeValues.AUTO, null, true);
sendJmsMessage("shouldBeNextMessage");
frame = conn.receiveFrame(10000);
Assert.assertEquals(Stomp.Responses.MESSAGE, frame.getCommand());
Assert.assertEquals("shouldBeNextMessage", frame.getBody());
}
@Test
public void testUnsubscribe() throws Exception {
conn.connect(defUser, defPass);
subscribe(conn, null, Stomp.Headers.Subscribe.AckModeValues.AUTO);
// send a message to our queue
sendJmsMessage("first message");
// receive message
ClientStompFrame frame = conn.receiveFrame(10000);
Assert.assertEquals(Stomp.Responses.MESSAGE, frame.getCommand());
// remove suscription
unsubscribe(conn, null, getQueuePrefix() + getQueueName(), true, false);
// send a message to our queue
sendJmsMessage("second message");
frame = conn.receiveFrame(1000);
log.info("Received frame: " + frame);
Assert.assertNull("No message should have been received since subscription was removed", frame);
}
@Test
public void testUnsubscribeWithID() throws Exception {
conn.connect(defUser, defPass);
subscribe(conn, "mysubid", Stomp.Headers.Subscribe.AckModeValues.AUTO);
// send a message to our queue
sendJmsMessage("first message");
// receive message from socket
ClientStompFrame frame = conn.receiveFrame(10000);
Assert.assertEquals(Stomp.Responses.MESSAGE, frame.getCommand());
// remove suscription
unsubscribe(conn, "mysubid", null, true, false);
// send a message to our queue
sendJmsMessage("second message");
frame = conn.receiveFrame(1000);
log.info("Received frame: " + frame);
Assert.assertNull("No message should have been received since subscription was removed", frame);
}
@Test
public void testTransactionCommit() throws Exception {
MessageConsumer consumer = session.createConsumer(queue);
conn.connect(defUser, defPass);
beginTransaction(conn, "tx1");
send(conn, getQueuePrefix() + getQueueName(), null, "Hello World", true, null, "tx1");
// check the message is not committed
assertNull(consumer.receive(100));
commitTransaction(conn, "tx1", true);
Message message = consumer.receive(1000);
Assert.assertNotNull("Should have received a message", message);
}
@Test
public void testSuccessiveTransactionsWithSameID() throws Exception {
MessageConsumer consumer = session.createConsumer(queue);
conn.connect(defUser, defPass);
// first tx
beginTransaction(conn, "tx1");
send(conn, getQueuePrefix() + getQueueName(), null, "Hello World", true, null, "tx1");
commitTransaction(conn, "tx1");
Message message = consumer.receive(1000);
Assert.assertNotNull("Should have received a message", message);
// 2nd tx with same tx ID
beginTransaction(conn, "tx1");
send(conn, getQueuePrefix() + getQueueName(), null, "Hello World", true, null, "tx1");
commitTransaction(conn, "tx1");
message = consumer.receive(1000);
Assert.assertNotNull("Should have received a message", message);
}
@Test
public void testBeginSameTransactionTwice() throws Exception {
conn.connect(defUser, defPass);
beginTransaction(conn, "tx1");
beginTransaction(conn, "tx1");
ClientStompFrame frame = conn.receiveFrame(1000);
Assert.assertEquals(Stomp.Responses.ERROR, frame.getCommand());
}
@Test
public void testTransactionRollback() throws Exception {
MessageConsumer consumer = session.createConsumer(queue);
String txId = "tx1";
conn.connect(defUser, defPass);
beginTransaction(conn, txId);
send(conn, getQueuePrefix() + getQueueName(), null, "first message", true, null, txId);
abortTransaction(conn, txId);
beginTransaction(conn, txId);
send(conn, getQueuePrefix() + getQueueName(), null, "second message", true, null, txId);
commitTransaction(conn, txId);
// only second msg should be received since first msg was rolled back
TextMessage message = (TextMessage) consumer.receive(1000);
Assert.assertNotNull(message);
Assert.assertEquals("second message", message.getText());
}
@Test
public void testSubscribeToTopic() throws Exception {
final int baselineQueueCount = server.getActiveMQServer().getActiveMQServerControl().getQueueNames().length;
conn.connect(defUser, defPass);
subscribeTopic(conn, null, null, null, true);
assertTrue("Subscription queue should be created here", Wait.waitFor(new Wait.Condition() {
@Override
public boolean isSatisfied() throws Exception {
int length = server.getActiveMQServer().getActiveMQServerControl().getQueueNames().length;
if (length - baselineQueueCount == 1) {
return true;
} else {
log.info("Queue count: " + (length - baselineQueueCount));
return false;
}
}
}, TimeUnit.SECONDS.toMillis(10), TimeUnit.MILLISECONDS.toMillis(100)));
sendJmsMessage(getName(), topic);
ClientStompFrame frame = conn.receiveFrame(1000);
Assert.assertEquals(Stomp.Responses.MESSAGE, frame.getCommand());
Assert.assertEquals(getTopicPrefix() + getTopicName(), frame.getHeader(Stomp.Headers.Send.DESTINATION));
Assert.assertEquals(getName(), frame.getBody());
unsubscribe(conn, null, getTopicPrefix() + getTopicName(), true, false);
sendJmsMessage(getName(), topic);
frame = conn.receiveFrame(1000);
log.info("Received frame: " + frame);
Assert.assertNull("No message should have been received since subscription was removed", frame);
assertEquals("Subscription queue should be deleted", 0, server.getActiveMQServer().getActiveMQServerControl().getQueueNames().length - baselineQueueCount);
conn.disconnect();
}
@Test
public void testSubscribeToQueue() throws Exception {
final int baselineQueueCount = server.getActiveMQServer().getActiveMQServerControl().getQueueNames().length;
conn.connect(defUser, defPass);
subscribe(conn, null, null, null, true);
assertFalse("Queue should not be created here", Wait.waitFor(new Wait.Condition() {
@Override
public boolean isSatisfied() throws Exception {
if (server.getActiveMQServer().getActiveMQServerControl().getQueueNames().length - baselineQueueCount == 1) {
return true;
} else {
return false;
}
}
}, TimeUnit.MILLISECONDS.toMillis(1000), TimeUnit.MILLISECONDS.toMillis(100)));
sendJmsMessage(getName(), queue);
ClientStompFrame frame = conn.receiveFrame(1000);
Assert.assertEquals(Stomp.Responses.MESSAGE, frame.getCommand());
Assert.assertEquals(getQueuePrefix() + getQueueName(), frame.getHeader(Stomp.Headers.Send.DESTINATION));
Assert.assertEquals(getName(), frame.getBody());
unsubscribe(conn, null, getQueuePrefix() + getQueueName(), true, false);
sendJmsMessage(getName(), queue);
frame = conn.receiveFrame(1000);
log.info("Received frame: " + frame);
Assert.assertNull("No message should have been received since subscription was removed", frame);
assertEquals("Subscription queue should not be deleted", baselineQueueCount, server.getActiveMQServer().getActiveMQServerControl().getQueueNames().length);
conn.disconnect();
}
@Test
public void testSubscribeToNonExistentQueue() throws Exception {
String nonExistentQueue = RandomUtil.randomString();
conn.connect(defUser, defPass);
subscribe(conn, null, null, null, null, getQueuePrefix() + nonExistentQueue, true);
sendJmsMessage(getName(), ActiveMQJMSClient.createQueue(nonExistentQueue));
ClientStompFrame frame = conn.receiveFrame(1000);
Assert.assertEquals(Stomp.Responses.MESSAGE, frame.getCommand());
Assert.assertEquals(getQueuePrefix() + nonExistentQueue, frame.getHeader(Stomp.Headers.Send.DESTINATION));
Assert.assertEquals(getName(), frame.getBody());
assertNotNull(server.getActiveMQServer().getPostOffice().getBinding(new SimpleString(nonExistentQueue)));
final Queue subscription = ((LocalQueueBinding) server.getActiveMQServer().getPostOffice().getBinding(new SimpleString(nonExistentQueue))).getQueue();
assertTrue(Wait.waitFor(new Wait.Condition() {
@Override
public boolean isSatisfied() throws Exception {
if (subscription.getMessageCount() == 0)
return true;
else
return false;
}
}, 1000, 50));
unsubscribe(conn, null, getQueuePrefix() + nonExistentQueue, true, false);
assertNull(server.getActiveMQServer().getPostOffice().getBinding(new SimpleString(nonExistentQueue)));
sendJmsMessage(getName(), ActiveMQJMSClient.createQueue(nonExistentQueue));
frame = conn.receiveFrame(1000);
log.info("Received frame: " + frame);
Assert.assertNull("No message should have been received since subscription was removed", frame);
conn.disconnect();
}
@Test
public void testDurableSubscriberWithReconnection() throws Exception {
conn.connect(defUser, defPass, "myclientid");
subscribeTopic(conn, null, null, getName());
conn.disconnect();
Thread.sleep(500);
// send the message when the durable subscriber is disconnected
sendJmsMessage(getName(), topic);
conn.destroy();
conn = StompClientConnectionFactory.createClientConnection("1.0", hostname, port);
conn.connect(defUser, defPass, "myclientid");
subscribeTopic(conn, null, null, getName());
ClientStompFrame frame = conn.receiveFrame(3000);
assertNotNull("Should have received a message from the durable subscription", frame);
Assert.assertEquals(Stomp.Responses.MESSAGE, frame.getCommand());
Assert.assertEquals(getTopicPrefix() + getTopicName(), frame.getHeader(Stomp.Headers.Send.DESTINATION));
Assert.assertEquals(getName(), frame.getBody());
unsubscribe(conn, null, getTopicPrefix() + getTopicName(), true, true);
conn.disconnect();
}
@Test
public void testDurableSubscriber() throws Exception {
conn.connect(defUser, defPass, "myclientid");
subscribeTopic(conn, null, null, getName(), true);
ClientStompFrame response = subscribeTopic(conn, null, null, getName(), true);
// creating a subscriber with the same durable-subscriber-name must fail
Assert.assertEquals(Stomp.Responses.ERROR, response.getCommand());
conn.disconnect();
}
@Test
public void testDurableUnSubscribe() throws Exception {
conn.connect(defUser, defPass, "myclientid");
subscribeTopic(conn, null, null, getName(), true);
conn.disconnect();
Thread.sleep(500);
assertNotNull(server.getActiveMQServer().locateQueue(SimpleString.toSimpleString("myclientid." + getName())));
conn.destroy();
conn = StompClientConnectionFactory.createClientConnection("1.0", hostname, port);
conn.connect(defUser, defPass, "myclientid");
unsubscribe(conn, getName(), getTopicPrefix() + getTopicName(), false, true);
conn.disconnect();
Thread.sleep(500);
assertNull(server.getActiveMQServer().locateQueue(SimpleString.toSimpleString("myclientid." + getName())));
}
@Test
public void testSubscribeToTopicWithNoLocal() throws Exception {
conn.connect(defUser, defPass);
subscribeTopic(conn, null, null, null, true, true);
// send a message on the same connection => it should not be received is noLocal = true on subscribe
send(conn, getTopicPrefix() + getTopicName(), null, "Hello World");
ClientStompFrame frame = conn.receiveFrame(2000);
log.info("Received frame: " + frame);
Assert.assertNull("No message should have been received since subscription was removed", frame);
// send message on another JMS connection => it should be received
sendJmsMessage(getName(), topic);
frame = conn.receiveFrame(10000);
Assert.assertEquals(Stomp.Responses.MESSAGE, frame.getCommand());
Assert.assertEquals(getTopicPrefix() + getTopicName(), frame.getHeader(Stomp.Headers.Send.DESTINATION));
Assert.assertEquals(getName(), frame.getBody());
conn.disconnect();
}
@Test
public void testTopicExistsAfterNoUnsubscribeDisconnect() throws Exception {
conn.connect(defUser, defPass);
subscribeTopic(conn, null, null, null, true);
// disconnect, _without unsubscribing_
conn.disconnect();
Thread.sleep(500);
conn.destroy();
// connect again
conn = StompClientConnectionFactory.createClientConnection("1.0", hostname, port);
conn.connect(defUser, defPass);
// send a receipted message to the topic
ClientStompFrame response = send(conn, getTopicPrefix() + getTopicName(), null, "Hello World", true);
assertEquals(Stomp.Responses.RECEIPT, response.getCommand());
// ...and nothing else
ClientStompFrame frame = conn.receiveFrame(2000);
log.info("Received frame: " + frame);
Assert.assertNull(frame);
conn.disconnect();
}
@Test
public void testClientAckNotPartOfTransaction() throws Exception {
conn.connect(defUser, defPass);
subscribe(conn, null, Stomp.Headers.Subscribe.AckModeValues.CLIENT);
sendJmsMessage(getName());
ClientStompFrame frame = conn.receiveFrame(10000);
Assert.assertEquals(Stomp.Responses.MESSAGE, frame.getCommand());
Assert.assertEquals(getQueuePrefix() + getQueueName(), frame.getHeader(Stomp.Headers.Send.DESTINATION));
String messageID = frame.getHeader(Stomp.Headers.Message.MESSAGE_ID);
Assert.assertNotNull(messageID);
Assert.assertEquals(getName(), frame.getBody());
beginTransaction(conn, "tx1");
ack(conn, null, messageID, "tx1");
abortTransaction(conn, "tx1");
frame = conn.receiveFrame(1000);
Assert.assertNull("No message should have been received as the message was acked even though the transaction has been aborted", frame);
unsubscribe(conn, null, getQueuePrefix() + getQueueName(), false, false);
conn.disconnect();
}
// HORNETQ-1007
@Test
public void testMultiProtocolConsumers() throws Exception {
final int TIME_OUT = 2000;
int count = 1000;
// Create 2 core consumers
MessageConsumer consumer1 = session.createConsumer(topic);
MessageConsumer consumer2 = session.createConsumer(topic);
// connect and subscribe STOMP consumer
conn.connect(defUser, defPass);
subscribeTopic(conn, null, null, null, true);
MessageProducer producer = session.createProducer(topic);
TextMessage message = session.createTextMessage(getName());
for (int i = 1; i <= count; i++) {
producer.send(message);
Assert.assertNotNull(consumer1.receive(TIME_OUT));
Assert.assertNotNull(consumer2.receive(TIME_OUT));
ClientStompFrame frame = conn.receiveFrame(TIME_OUT);
Assert.assertEquals(Stomp.Responses.MESSAGE, frame.getCommand());
Assert.assertEquals(getTopicPrefix() + getTopicName(), frame.getHeader(Stomp.Headers.Send.DESTINATION));
Assert.assertEquals(getName(), frame.getBody());
}
consumer1.close();
consumer2.close();
unsubscribe(conn, null, getTopicPrefix() + getTopicName(), true, false);
sendJmsMessage(getName(), topic);
ClientStompFrame frame = conn.receiveFrame(TIME_OUT);
log.info("Received frame: " + frame);
Assert.assertNull("No message should have been received since subscription was removed", frame);
conn.disconnect();
}
@Test
//stomp should return an ERROR when acking a non-existent message
public void testUnexpectedAck() throws Exception {
String messageID = "888888";
conn.connect(defUser, defPass);
ack(conn, null, messageID, null);
ClientStompFrame frame = conn.receiveFrame(1000);
assertNotNull(frame);
assertEquals(Stomp.Responses.ERROR, frame.getCommand());
conn.disconnect();
}
@Test
public void testDotAnycastPrefixOnSend() throws Exception {
testPrefix("jms.queue.", RoutingType.ANYCAST, true);
}
@Test
public void testDotMulticastPrefixOnSend() throws Exception {
testPrefix("jms.topic.", RoutingType.MULTICAST, true);
}
@Test
public void testDotAnycastPrefixOnSubscribe() throws Exception {
testPrefix("jms.queue.", RoutingType.ANYCAST, false);
}
@Test
public void testDotMulticastPrefixOnSubscribe() throws Exception {
testPrefix("jms.topic.", RoutingType.MULTICAST, false);
}
@Test
public void testSlashAnycastPrefixOnSend() throws Exception {
testPrefix("/queue/", RoutingType.ANYCAST, true);
}
@Test
public void testSlashMulticastPrefixOnSend() throws Exception {
testPrefix("/topic/", RoutingType.MULTICAST, true);
}
@Test
public void testSlashAnycastPrefixOnSubscribe() throws Exception {
testPrefix("/queue/", RoutingType.ANYCAST, false);
}
@Test
public void testSlashMulticastPrefixOnSubscribe() throws Exception {
testPrefix("/topic/", RoutingType.MULTICAST, false);
}
public void testPrefix(final String prefix, final RoutingType routingType, final boolean send) throws Exception {
int port = 61614;
final String ADDRESS = UUID.randomUUID().toString();
final String PREFIXED_ADDRESS = prefix + ADDRESS;
String param = routingType.toString();
String urlParam = param.toLowerCase() + "Prefix";
server.getActiveMQServer().getRemotingService().createAcceptor("test", "tcp://" + hostname + ":" + port + "?protocols=" + StompProtocolManagerFactory.STOMP_PROTOCOL_NAME + "&" + urlParam + "=" + prefix).start();
conn = StompClientConnectionFactory.createClientConnection("1.0", hostname, port);
conn.connect(defUser, defPass);
// since this queue doesn't exist the broker should create a new address using the routing type matching the prefix
if (send) {
send(conn, PREFIXED_ADDRESS, null, "Hello World", true);
} else {
String uuid = UUID.randomUUID().toString();
ClientStompFrame frame = conn.createFrame(Stomp.Commands.SUBSCRIBE)
.addHeader(Stomp.Headers.Subscribe.DESTINATION, PREFIXED_ADDRESS)
.addHeader(Stomp.Headers.RECEIPT_REQUESTED, uuid);
frame = conn.sendFrame(frame);
assertEquals(uuid, frame.getHeader(Stomp.Headers.Response.RECEIPT_ID));
}
AddressInfo addressInfo = server.getActiveMQServer().getAddressInfo(SimpleString.toSimpleString(ADDRESS));
assertNotNull("No address was created with the name " + ADDRESS, addressInfo);
Set<RoutingType> routingTypes = new HashSet<>();
routingTypes.add(RoutingType.valueOf(param));
assertEquals(routingTypes, addressInfo.getRoutingTypes());
conn.disconnect();
}
@Test
public void testDotPrefixedSendAndRecieveAnycast() throws Exception {
testPrefixedSendAndRecieve("jms.queue.", RoutingType.ANYCAST);
}
@Test
public void testDotPrefixedSendAndRecieveMulticast() throws Exception {
testPrefixedSendAndRecieve("jms.topic.", RoutingType.MULTICAST);
}
@Test
public void testSlashPrefixedSendAndRecieveAnycast() throws Exception {
testPrefixedSendAndRecieve("/queue/", RoutingType.ANYCAST);
}
@Test
public void testSlashPrefixedSendAndRecieveMulticast() throws Exception {
testPrefixedSendAndRecieve("/topic/", RoutingType.MULTICAST);
}
public void testPrefixedSendAndRecieve(final String prefix, RoutingType routingType) throws Exception {
int port = 61614;
final String ADDRESS = UUID.randomUUID().toString();
final String PREFIXED_ADDRESS = prefix + ADDRESS;
String urlParam = routingType.toString().toLowerCase() + "Prefix";
server.getActiveMQServer().getRemotingService().createAcceptor("test", "tcp://" + hostname + ":" + port + "?protocols=" + StompProtocolManagerFactory.STOMP_PROTOCOL_NAME + "&" + urlParam + "=" + prefix).start();
conn = StompClientConnectionFactory.createClientConnection("1.0", hostname, port);
conn.connect(defUser, defPass);
String uuid = UUID.randomUUID().toString();
ClientStompFrame frame = conn.createFrame(Stomp.Commands.SUBSCRIBE)
.addHeader(Stomp.Headers.Subscribe.DESTINATION, PREFIXED_ADDRESS)
.addHeader(Stomp.Headers.RECEIPT_REQUESTED, uuid);
frame = conn.sendFrame(frame);
assertEquals(uuid, frame.getHeader(Stomp.Headers.Response.RECEIPT_ID));
send(conn, ADDRESS, null, "Hello World", true);
frame = conn.receiveFrame(10000);
Assert.assertNotNull("Should have received a message", frame);
Assert.assertEquals(Stomp.Responses.MESSAGE, frame.getCommand());
Assert.assertEquals(ADDRESS, frame.getHeader(Stomp.Headers.Send.DESTINATION));
Assert.assertEquals("Hello World", frame.getBody());
conn.disconnect();
}
@Test
public void testMulticastOperationsOnAnycastAddress() throws Exception {
testRoutingSemantics(RoutingType.MULTICAST.toString(), getQueuePrefix() + getQueueName());
}
@Test
public void testAnycastOperationsOnMulticastAddress() throws Exception {
testRoutingSemantics(RoutingType.ANYCAST.toString(), getTopicPrefix() + getTopicName());
}
public void testRoutingSemantics(String routingType, String destination) throws Exception {
conn.connect(defUser, defPass);
String uuid = UUID.randomUUID().toString();
ClientStompFrame frame = conn.createFrame(Stomp.Commands.SUBSCRIBE)
.addHeader(Stomp.Headers.Subscribe.SUBSCRIPTION_TYPE, routingType)
.addHeader(Stomp.Headers.Subscribe.DESTINATION, destination)
.addHeader(Stomp.Headers.RECEIPT_REQUESTED, uuid);
frame = conn.sendFrame(frame);
assertEquals(Stomp.Responses.ERROR, frame.getCommand());
uuid = UUID.randomUUID().toString();
frame = conn.createFrame(Stomp.Commands.SEND)
.addHeader(Stomp.Headers.Send.DESTINATION_TYPE, RoutingType.MULTICAST.toString())
.addHeader(Stomp.Headers.Send.DESTINATION, getQueuePrefix() + getQueueName())
.addHeader(Stomp.Headers.RECEIPT_REQUESTED, uuid);
frame = conn.sendFrame(frame);
assertEquals(Stomp.Responses.ERROR, frame.getCommand());
}
@Test
public void testGetManagementAttributeFromStomp() throws Exception {
server.getActiveMQServer().getAddressSettingsRepository().addMatch("#", new AddressSettings().setAutoCreateAddresses(false).setAutoCreateQueues(false));
conn.connect(defUser, defPass);
subscribe(conn, null);
ClientStompFrame frame = conn.createFrame(Stomp.Commands.SEND)
.addHeader(Stomp.Headers.Send.DESTINATION, ActiveMQDefaultConfiguration.getDefaultManagementAddress().toString())
.addHeader(Stomp.Headers.Send.REPLY_TO, getQueuePrefix() + getQueueName())
.addHeader(ManagementHelper.HDR_RESOURCE_NAME.toString(), ResourceNames.QUEUE + getQueuePrefix() + getQueueName())
.addHeader(ManagementHelper.HDR_ATTRIBUTE.toString(), "Address");
conn.sendFrame(frame);
frame = conn.receiveFrame(10000);
IntegrationTestLogger.LOGGER.info("Received: " + frame);
Assert.assertEquals(Boolean.TRUE.toString(), frame.getHeader(ManagementHelper.HDR_OPERATION_SUCCEEDED.toString()));
// the address will be returned in the message body in a JSON array
Assert.assertEquals("[\"" + getQueuePrefix() + getQueueName() + "\"]", frame.getBody());
unsubscribe(conn, null);
conn.disconnect();
}
@Test
public void testInvokeOperationFromStomp() throws Exception {
conn.connect(defUser, defPass);
subscribe(conn, null);
ClientStompFrame frame = conn.createFrame(Stomp.Commands.SEND)
.addHeader(Stomp.Headers.Send.DESTINATION, ActiveMQDefaultConfiguration.getDefaultManagementAddress().toString())
.addHeader(Stomp.Headers.Send.REPLY_TO, getQueuePrefix() + getQueueName())
.addHeader(ManagementHelper.HDR_RESOURCE_NAME.toString(), ResourceNames.QUEUE + getQueuePrefix() + getQueueName())
.addHeader(ManagementHelper.HDR_OPERATION_NAME.toString(), "countMessages")
.setBody("[\"color = 'blue'\"]");
conn.sendFrame(frame);
frame = conn.receiveFrame(10000);
IntegrationTestLogger.LOGGER.info("Received: " + frame);
Assert.assertEquals(Boolean.TRUE.toString(), frame.getHeader(ManagementHelper.HDR_OPERATION_SUCCEEDED.toString()));
// there is no such messages => 0 returned in a JSON array
Assert.assertEquals("[0]", frame.getBody());
unsubscribe(conn, null);
conn.disconnect();
}
@Test
public void testAnycastMessageRoutingExclusivity() throws Exception {
conn.connect(defUser, defPass);
final String addressA = "addressA";
final String queueA = "queueA";
final String queueB = "queueB";
final String queueC = "queueC";
ActiveMQServer activeMQServer = server.getActiveMQServer();
ActiveMQServerControl serverControl = server.getActiveMQServer().getActiveMQServerControl();
serverControl.createAddress(addressA, RoutingType.ANYCAST.toString() + "," + RoutingType.MULTICAST.toString());
serverControl.createQueue(addressA, queueA, RoutingType.ANYCAST.toString());
serverControl.createQueue(addressA, queueB, RoutingType.ANYCAST.toString());
serverControl.createQueue(addressA, queueC, RoutingType.MULTICAST.toString());
send(conn, addressA, null, "Hello World!", true, RoutingType.ANYCAST);
assertEquals(1, activeMQServer.locateQueue(SimpleString.toSimpleString(queueA)).getMessageCount() + activeMQServer.locateQueue(SimpleString.toSimpleString(queueB)).getMessageCount());
assertEquals(0, activeMQServer.locateQueue(SimpleString.toSimpleString(queueC)).getMessageCount());
}
@Test
public void testMulticastMessageRoutingExclusivity() throws Exception {
conn.connect(defUser, defPass);
final String addressA = "addressA";
final String queueA = "queueA";
final String queueB = "queueB";
final String queueC = "queueC";
ActiveMQServer activeMQServer = server.getActiveMQServer();
ActiveMQServerControl serverControl = server.getActiveMQServer().getActiveMQServerControl();
serverControl.createAddress(addressA, RoutingType.ANYCAST.toString() + "," + RoutingType.MULTICAST.toString());
serverControl.createQueue(addressA, queueA, RoutingType.ANYCAST.toString());
serverControl.createQueue(addressA, queueB, RoutingType.MULTICAST.toString());
serverControl.createQueue(addressA, queueC, RoutingType.MULTICAST.toString());
send(conn, addressA, null, "Hello World!", true, RoutingType.MULTICAST);
assertEquals(0, activeMQServer.locateQueue(SimpleString.toSimpleString(queueA)).getMessageCount());
assertEquals(2, activeMQServer.locateQueue(SimpleString.toSimpleString(queueC)).getMessageCount() + activeMQServer.locateQueue(SimpleString.toSimpleString(queueB)).getMessageCount());
}
@Test
public void testAmbiguousMessageRouting() throws Exception {
conn.connect(defUser, defPass);
final String addressA = "addressA";
final String queueA = "queueA";
final String queueB = "queueB";
final String queueC = "queueC";
final String queueD = "queueD";
ActiveMQServer activeMQServer = server.getActiveMQServer();
ActiveMQServerControl serverControl = server.getActiveMQServer().getActiveMQServerControl();
serverControl.createAddress(addressA, RoutingType.ANYCAST.toString() + "," + RoutingType.MULTICAST.toString());
serverControl.createQueue(addressA, queueA, RoutingType.ANYCAST.toString());
serverControl.createQueue(addressA, queueB, RoutingType.ANYCAST.toString());
serverControl.createQueue(addressA, queueC, RoutingType.MULTICAST.toString());
serverControl.createQueue(addressA, queueD, RoutingType.MULTICAST.toString());
send(conn, addressA, null, "Hello World!", true);
assertEquals(1, activeMQServer.locateQueue(SimpleString.toSimpleString(queueA)).getMessageCount() + activeMQServer.locateQueue(SimpleString.toSimpleString(queueB)).getMessageCount());
assertEquals(2, activeMQServer.locateQueue(SimpleString.toSimpleString(queueC)).getMessageCount() + activeMQServer.locateQueue(SimpleString.toSimpleString(queueD)).getMessageCount());
}
}