/**
* 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.transport.stomp;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.util.HashMap;
import java.util.List;
import javax.jms.Connection;
import javax.jms.Destination;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.Topic;
import javax.management.ObjectName;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.broker.BrokerPlugin;
import org.apache.activemq.broker.region.policy.ConstantPendingMessageLimitStrategy;
import org.apache.activemq.broker.region.policy.PolicyEntry;
import org.apache.activemq.broker.region.policy.PolicyMap;
import org.apache.activemq.command.ActiveMQQueue;
import org.apache.activemq.plugin.StatisticsBrokerPlugin;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class StompAdvisoryTest extends StompTestSupport {
static final String STATS_DESTINATION_PREFIX = "ActiveMQ.Statistics.Destination";
private static final Logger LOG = LoggerFactory.getLogger(StompAdvisoryTest.class);
protected ActiveMQConnection connection;
@Override
public void tearDown() throws Exception {
try {
connection.close();
} catch (Exception ex) {}
super.tearDown();
}
@Override
protected void addAdditionalPlugins(List<BrokerPlugin> plugins) throws Exception {
plugins.add(new StatisticsBrokerPlugin());
}
@Override
protected void applyBrokerPolicies() throws Exception {
PolicyEntry policy = new PolicyEntry();
policy.setAdvisoryForFastProducers(true);
policy.setAdvisoryForConsumed(true);
policy.setAdvisoryForDelivery(true);
policy.setAdvisoryForDiscardingMessages(true);
policy.setAdvisoryForSlowConsumers(true);
policy.setAdvisoryWhenFull(true);
policy.setProducerFlowControl(false);
ConstantPendingMessageLimitStrategy strategy = new ConstantPendingMessageLimitStrategy();
strategy.setLimit(10);
policy.setPendingMessageLimitStrategy(strategy);
PolicyMap pMap = new PolicyMap();
pMap.setDefaultEntry(policy);
brokerService.setDestinationPolicy(pMap);
brokerService.setAdvisorySupport(true);
}
@Test(timeout = 60000)
public void testConnectionAdvisory() throws Exception {
stompConnect();
HashMap<String, String> subheaders = new HashMap<String, String>(1);
subheaders.put("receipt", "id-1");
stompConnection.connect("system", "manager");
stompConnection.subscribe("/topic/ActiveMQ.Advisory.Connection",
Stomp.Headers.Subscribe.AckModeValues.AUTO, subheaders);
String frame = stompConnection.receiveFrame();
LOG.debug("Response to subscribe was: {}", frame);
assertTrue(frame.trim().startsWith("RECEIPT"));
// Now connect via openwire and check we get the advisory
Connection c = cf.createConnection("system", "manager");
c.start();
StompFrame f = stompConnection.receive();
LOG.debug(f.toString());
assertEquals(f.getAction(),"MESSAGE");
assertTrue("Should have a body", f.getBody().length() > 0);
assertTrue(f.getBody().startsWith("{\"ConnectionInfo\":"));
c.stop();
c.close();
f = stompConnection.receive();
LOG.debug(f.toString());
assertEquals(f.getAction(),"MESSAGE");
assertNotNull("Body is not null", f.getBody());
assertTrue("Body should have content", f.getBody().length() > 0);
assertTrue(f.getBody().startsWith("{\"ConnectionInfo\":"));
}
@Test(timeout = 60000)
public void testConnectionAdvisoryJSON() throws Exception {
stompConnect();
HashMap<String, String> subheaders = new HashMap<String, String>(1);
subheaders.put("transformation", Stomp.Transformations.JMS_JSON.toString());
subheaders.put("receipt", "id-1");
stompConnection.connect("system", "manager");
stompConnection.subscribe("/topic/ActiveMQ.Advisory.Connection",
Stomp.Headers.Subscribe.AckModeValues.AUTO, subheaders);
String frame = stompConnection.receiveFrame();
LOG.debug("Response to subscribe was: {}", frame);
assertTrue(frame.trim().startsWith("RECEIPT"));
// Now connect via openwire and check we get the advisory
Connection c = cf.createConnection("system", "manager");
c.start();
StompFrame f = stompConnection.receive();
LOG.debug(f.toString());
assertEquals(f.getAction(),"MESSAGE");
assertTrue("Should have a body", f.getBody().length() > 0);
assertTrue(f.getBody().startsWith("{\"ConnectionInfo\":"));
c.stop();
c.close();
f = stompConnection.receive();
LOG.debug(f.toString());
assertEquals(f.getAction(),"MESSAGE");
assertNotNull("Body is not null", f.getBody());
assertTrue("Body should have content", f.getBody().length() > 0);
assertTrue(f.getBody().startsWith("{\"ConnectionInfo\":"));
}
@Test(timeout = 60000)
public void testConnectionAdvisoryXML() throws Exception {
stompConnect();
HashMap<String, String> subheaders = new HashMap<String, String>(1);
subheaders.put("transformation", Stomp.Transformations.JMS_XML.toString());
subheaders.put("receipt", "id-1");
stompConnection.connect("system", "manager");
stompConnection.subscribe("/topic/ActiveMQ.Advisory.Connection",
Stomp.Headers.Subscribe.AckModeValues.AUTO, subheaders);
String frame = stompConnection.receiveFrame();
LOG.debug("Response to subscribe was: {}", frame);
assertTrue(frame.trim().startsWith("RECEIPT"));
// Now connect via openwire and check we get the advisory
Connection c = cf.createConnection("system", "manager");
c.start();
StompFrame f = stompConnection.receive();
LOG.debug(f.toString());
assertEquals(f.getAction(),"MESSAGE");
assertTrue("Should have a body", f.getBody().length() > 0);
assertTrue(f.getBody().startsWith("<ConnectionInfo>"));
c.stop();
c.close();
f = stompConnection.receive();
LOG.debug(f.toString());
assertEquals(f.getAction(),"MESSAGE");
assertNotNull("Body is not null", f.getBody());
assertTrue("Body should have content", f.getBody().length() > 0);
assertTrue(f.getBody().startsWith("<ConnectionInfo>"));
}
@Test(timeout = 60000)
public void testConsumerAdvisory() throws Exception {
stompConnect();
Destination dest = new ActiveMQQueue("testConsumerAdvisory");
HashMap<String, String> subheaders = new HashMap<String, String>(1);
subheaders.put("receipt", "id-1");
stompConnection.connect("system", "manager");
stompConnection.subscribe("/topic/ActiveMQ.Advisory.Consumer.>",
Stomp.Headers.Subscribe.AckModeValues.AUTO, subheaders);
String frame = stompConnection.receiveFrame();
LOG.debug("Response to subscribe was: {}", frame);
assertTrue(frame.trim().startsWith("RECEIPT"));
// Now connect via openwire and check we get the advisory
Connection c = cf.createConnection("system", "manager");
c.start();
Session session = c.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageConsumer consumer = session.createConsumer(dest);
assertNotNull(consumer);
StompFrame f = stompConnection.receive();
LOG.debug(f.toString());
assertEquals(f.getAction(),"MESSAGE");
assertTrue("Should have a body", f.getBody().length() > 0);
assertTrue(f.getBody().startsWith("{\"ConsumerInfo\":"));
c.stop();
c.close();
}
@Test(timeout = 60000)
public void testProducerAdvisory() throws Exception {
stompConnect();
Destination dest = new ActiveMQQueue("testProducerAdvisory");
HashMap<String, String> subheaders = new HashMap<String, String>(1);
subheaders.put("receipt", "id-1");
stompConnection.connect("system", "manager");
stompConnection.subscribe("/topic/ActiveMQ.Advisory.Producer.>",
Stomp.Headers.Subscribe.AckModeValues.AUTO, subheaders);
String frame = stompConnection.receiveFrame();
LOG.debug("Response to subscribe was: {}", frame);
assertTrue(frame.trim().startsWith("RECEIPT"));
// Now connect via openwire and check we get the advisory
Connection c = cf.createConnection("system", "manager");
c.start();
Session session = c.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer producer = session.createProducer(dest);
Message mess = session.createTextMessage("test");
producer.send(mess);
StompFrame f = stompConnection.receive();
LOG.debug(f.toString());
assertEquals(f.getAction(),"MESSAGE");
assertTrue("Should have a body", f.getBody().length() > 0);
assertTrue(f.getBody().startsWith("{\"ProducerInfo\":"));
c.stop();
c.close();
}
@Test(timeout = 60000)
public void testProducerAdvisoryXML() throws Exception {
stompConnect();
Destination dest = new ActiveMQQueue("testProducerAdvisoryXML");
HashMap<String, String> subheaders = new HashMap<String, String>(1);
subheaders.put("transformation", Stomp.Transformations.JMS_ADVISORY_XML.toString());
subheaders.put("receipt", "id-1");
stompConnection.connect("system", "manager");
stompConnection.subscribe("/topic/ActiveMQ.Advisory.Producer.>",
Stomp.Headers.Subscribe.AckModeValues.AUTO, subheaders);
String frame = stompConnection.receiveFrame();
LOG.debug("Response to subscribe was: {}", frame);
assertTrue(frame.trim().startsWith("RECEIPT"));
// Now connect via openwire and check we get the advisory
Connection c = cf.createConnection("system", "manager");
c.start();
Session session = c.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer producer = session.createProducer(dest);
Message mess = session.createTextMessage("test");
producer.send(mess);
StompFrame f = stompConnection.receive();
LOG.debug(f.toString());
assertEquals(f.getAction(),"MESSAGE");
assertTrue("Should have a body", f.getBody().length() > 0);
assertTrue(f.getBody().startsWith("<ProducerInfo>"));
c.stop();
c.close();
}
@Test(timeout = 60000)
public void testProducerAdvisoryJSON() throws Exception {
stompConnect();
Destination dest = new ActiveMQQueue("testProducerAdvisoryJSON");
HashMap<String, String> subheaders = new HashMap<String, String>(1);
subheaders.put("transformation", Stomp.Transformations.JMS_ADVISORY_JSON.toString());
subheaders.put("receipt", "id-1");
stompConnection.connect("system", "manager");
stompConnection.subscribe("/topic/ActiveMQ.Advisory.Producer.>",
Stomp.Headers.Subscribe.AckModeValues.AUTO, subheaders);
String frame = stompConnection.receiveFrame();
LOG.debug("Response to subscribe was: {}", frame);
assertTrue(frame.trim().startsWith("RECEIPT"));
// Now connect via openwire and check we get the advisory
Connection c = cf.createConnection("system", "manager");
c.start();
Session session = c.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer producer = session.createProducer(dest);
Message mess = session.createTextMessage("test");
producer.send(mess);
StompFrame f = stompConnection.receive();
LOG.debug(f.toString());
assertEquals(f.getAction(),"MESSAGE");
assertTrue("Should have a body", f.getBody().length() > 0);
assertTrue(f.getBody().startsWith("{\"ProducerInfo\":"));
c.stop();
c.close();
}
@Test(timeout = 60000)
public void testStatisticsAdvisory() throws Exception {
Connection c = cf.createConnection("system", "manager");
c.start();
final Session session = c.createSession(false, Session.AUTO_ACKNOWLEDGE);
final Topic replyTo = session.createTopic("stats");
// Dummy Queue used to later gather statistics.
final ActiveMQQueue testQueue = new ActiveMQQueue("queueToBeTestedForStats");
final MessageProducer producer = session.createProducer(null);
Message mess = session.createTextMessage("test");
producer.send(testQueue, mess);
// Create a request for Queue statistics
Thread child = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
Queue query = session.createQueue(STATS_DESTINATION_PREFIX + testQueue.getQueueName());
Message msg = session.createMessage();
msg.setJMSReplyTo(replyTo);
producer.send(query, msg);
} catch (Exception e) {
e.printStackTrace();
}
}
});
child.start();
stompConnect();
// Attempt to gather the statistics response from the previous request.
stompConnection.connect("system", "manager");
stompConnection.subscribe("/topic/" + replyTo.getTopicName(), Stomp.Headers.Subscribe.AckModeValues.AUTO);
stompConnection.begin("TX");
StompFrame f = stompConnection.receive(5000);
stompConnection.commit("TX");
LOG.debug(f.toString());
assertEquals(f.getAction(),"MESSAGE");
assertTrue("Should have a body", f.getBody().length() > 0);
assertTrue("Should contains memoryUsage stats", f.getBody().contains("memoryUsage"));
c.stop();
c.close();
}
@Test(timeout = 60000)
public void testDestinationAdvisoryTempQueue() throws Exception {
cf.setWatchTopicAdvisories(false);
stompConnect();
HashMap<String, String> subheaders = new HashMap<String, String>(1);
subheaders.put("receipt", "id-1");
stompConnection.connect("system", "manager");
stompConnection.subscribe("/topic/ActiveMQ.Advisory.TempQueue",
Stomp.Headers.Subscribe.AckModeValues.AUTO, subheaders);
String frame = stompConnection.receiveFrame();
LOG.debug("Response to subscribe was: {}", frame);
assertTrue(frame.trim().startsWith("RECEIPT"));
// Now connect via openwire and check we get the advisory
Connection connection = cf.createConnection("system", "manager");
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
session.createTemporaryQueue();
connection.close();
StompFrame f = stompConnection.receive();
LOG.debug(f.toString());
assertEquals(f.getAction(),"MESSAGE");
assertTrue("Should have a body", f.getBody().length() > 0);
assertTrue(f.getBody().startsWith("{\"DestinationInfo\":"));
}
@Test(timeout = 60000)
public void testDestinationAdvisoryTempTopic() throws Exception {
cf.setWatchTopicAdvisories(false);
stompConnect();
HashMap<String, String> subheaders = new HashMap<String, String>(1);
subheaders.put("receipt", "id-1");
stompConnection.connect("system", "manager");
stompConnection.subscribe("/topic/ActiveMQ.Advisory.TempTopic",
Stomp.Headers.Subscribe.AckModeValues.AUTO, subheaders);
String frame = stompConnection.receiveFrame();
LOG.debug("Response to subscribe was: {}", frame);
assertTrue(frame.trim().startsWith("RECEIPT"));
// Now connect via openwire and check we get the advisory
Connection connection = cf.createConnection("system", "manager");
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
session.createTemporaryTopic();
connection.close();
StompFrame f = stompConnection.receive();
LOG.debug(f.toString());
assertEquals(f.getAction(),"MESSAGE");
assertTrue("Should have a body", f.getBody().length() > 0);
assertTrue(f.getBody().startsWith("{\"DestinationInfo\":"));
}
@Test(timeout = 60000)
public void testDestinationAdvisoryCompositeTempDestinations() throws Exception {
cf.setWatchTopicAdvisories(true);
HashMap<String, String> subheaders = new HashMap<String, String>(1);
subheaders.put("receipt", "id-1");
stompConnect();
stompConnection.connect("system", "manager");
stompConnection.subscribe("/topic/ActiveMQ.Advisory.TempTopic,/topic/ActiveMQ.Advisory.TempQueue",
Stomp.Headers.Subscribe.AckModeValues.AUTO, subheaders);
String frame = stompConnection.receiveFrame();
LOG.debug("Response to subscribe was: {}", frame);
assertTrue(frame.trim().startsWith("RECEIPT"));
// Now connect via openwire and check we get the advisory
Connection connection = cf.createConnection("system", "manager");
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
session.createTemporaryTopic();
session.createTemporaryQueue();
ObjectName[] topicSubscribers = brokerService.getAdminView().getTopicSubscribers();
for (ObjectName subscription : topicSubscribers) {
LOG.info("Topic Subscription: {}", subscription);
}
connection.close();
StompFrame f = stompConnection.receive();
LOG.debug(f.toString());
assertEquals(f.getAction(),"MESSAGE");
assertTrue("Should have a body", f.getBody().length() > 0);
assertTrue(f.getBody().startsWith("{\"DestinationInfo\":"));
f = stompConnection.receive();
LOG.debug(f.toString());
assertEquals(f.getAction(),"MESSAGE");
assertTrue("Should have a body", f.getBody().length() > 0);
assertTrue(f.getBody().startsWith("{\"DestinationInfo\":"));
}
}