http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/standard/management-notifications/src/main/java/org/apache/activemq/artemis/jms/example/ManagementNotificationExample.java ---------------------------------------------------------------------- diff --git a/examples/features/standard/management-notifications/src/main/java/org/apache/activemq/artemis/jms/example/ManagementNotificationExample.java b/examples/features/standard/management-notifications/src/main/java/org/apache/activemq/artemis/jms/example/ManagementNotificationExample.java new file mode 100644 index 0000000..5fc00cf --- /dev/null +++ b/examples/features/standard/management-notifications/src/main/java/org/apache/activemq/artemis/jms/example/ManagementNotificationExample.java @@ -0,0 +1,109 @@ +/* + * 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.jms.example; + +import java.util.Enumeration; + +import javax.jms.Connection; +import javax.jms.ConnectionFactory; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.MessageListener; +import javax.jms.MessageProducer; +import javax.jms.Queue; +import javax.jms.Session; +import javax.jms.Topic; +import javax.naming.InitialContext; + +/** + * An example that shows how to receive management notifications using JMS messages. + */ +public class ManagementNotificationExample { + + public static void main(final String[] args) throws Exception { + Connection connection = null; + InitialContext initialContext = null; + try { + // Step 1. Create an initial context to perform the JNDI lookup. + initialContext = new InitialContext(); + + // Step 2. Perform a lookup on the queue + Queue queue = (Queue) initialContext.lookup("queue/exampleQueue"); + + // Step 3. Perform a lookup on the Connection Factory + ConnectionFactory cf = (ConnectionFactory) initialContext.lookup("ConnectionFactory"); + + // Step 4.Create a JMS connection, a session and a producer for the queue + connection = cf.createConnection(); + Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + MessageProducer producer = session.createProducer(queue); + + // Step 5. Perform a lookup on the notifications topic + Topic notificationsTopic = (Topic) initialContext.lookup("topic/notificationsTopic"); + + // Step 6. Create a JMS message consumer for the notification queue and set its message listener + // It will display all the properties of the JMS Message + MessageConsumer notificationConsumer = session.createConsumer(notificationsTopic); + notificationConsumer.setMessageListener(new MessageListener() { + public void onMessage(final Message notif) { + System.out.println("------------------------"); + System.out.println("Received notification:"); + try { + Enumeration propertyNames = notif.getPropertyNames(); + while (propertyNames.hasMoreElements()) { + String propertyName = (String) propertyNames.nextElement(); + System.out.format(" %s: %s%n", propertyName, notif.getObjectProperty(propertyName)); + } + } + catch (JMSException e) { + } + System.out.println("------------------------"); + } + }); + + // Step 7. Start the Connection to allow the consumers to receive messages + connection.start(); + + // Step 8. Create a JMS Message Consumer on the queue + MessageConsumer consumer = session.createConsumer(queue); + + // Step 9. Close the consumer + consumer.close(); + + // Step 10. Try to create a connection with unknown user + try { + cf.createConnection("not.a.valid.user", "not.a.valid.password"); + } + catch (JMSException e) { + } + + // sleep a little bit to be sure to receive the notification for the security + // authentication violation before leaving the example + Thread.sleep(2000); + } + finally { + // Step 11. Be sure to close the resources! + if (initialContext != null) { + initialContext.close(); + } + if (connection != null) { + connection.close(); + } + } + } +}
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/standard/management-notifications/src/main/resources/activemq/server0/artemis-roles.properties ---------------------------------------------------------------------- diff --git a/examples/features/standard/management-notifications/src/main/resources/activemq/server0/artemis-roles.properties b/examples/features/standard/management-notifications/src/main/resources/activemq/server0/artemis-roles.properties new file mode 100644 index 0000000..4e2d44c --- /dev/null +++ b/examples/features/standard/management-notifications/src/main/resources/activemq/server0/artemis-roles.properties @@ -0,0 +1,17 @@ +## --------------------------------------------------------------------------- +## 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. +## --------------------------------------------------------------------------- +guest=guest \ No newline at end of file http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/standard/management-notifications/src/main/resources/activemq/server0/artemis-users.properties ---------------------------------------------------------------------- diff --git a/examples/features/standard/management-notifications/src/main/resources/activemq/server0/artemis-users.properties b/examples/features/standard/management-notifications/src/main/resources/activemq/server0/artemis-users.properties new file mode 100644 index 0000000..4e2d44c --- /dev/null +++ b/examples/features/standard/management-notifications/src/main/resources/activemq/server0/artemis-users.properties @@ -0,0 +1,17 @@ +## --------------------------------------------------------------------------- +## 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. +## --------------------------------------------------------------------------- +guest=guest \ No newline at end of file http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/standard/management-notifications/src/main/resources/activemq/server0/broker.xml ---------------------------------------------------------------------- diff --git a/examples/features/standard/management-notifications/src/main/resources/activemq/server0/broker.xml b/examples/features/standard/management-notifications/src/main/resources/activemq/server0/broker.xml new file mode 100644 index 0000000..2c97901 --- /dev/null +++ b/examples/features/standard/management-notifications/src/main/resources/activemq/server0/broker.xml @@ -0,0 +1,81 @@ +<?xml version='1.0'?> +<!-- +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. +--> + +<configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="urn:activemq" + xsi:schemaLocation="urn:activemq ../../../../src/schema/artemis-server.xsd"> + + <jms xmlns="urn:activemq:jms"> + <!--the queue used by the example--> + <queue name="exampleQueue"/> + + <!--the notifications topic used by the example--> + <topic name="notificationsTopic"/> + </jms> + + <core xmlns="urn:activemq:core"> + + <bindings-directory>${data.dir}/server0/data/messaging/bindings</bindings-directory> + + <journal-directory>${data.dir}/server0/data/messaging/journal</journal-directory> + + <large-messages-directory>${data.dir}/server0/data/messaging/largemessages</large-messages-directory> + + <paging-directory>${data.dir}/server0/data/messaging/paging</paging-directory> + + + <management-notification-address>jms.topic.notificationsTopic</management-notification-address> + + <!-- Netty standard TCP acceptor --> + <acceptors> + <acceptor name="netty">tcp://localhost:61616</acceptor> + </acceptors> + + <!-- Other configs --> + + <security-settings> + <!--security for example queue--> + <security-setting match="jms.queue.exampleQueue"> + <permission type="createDurableQueue" roles="guest"/> + <permission type="deleteDurableQueue" roles="guest"/> + <permission type="createNonDurableQueue" roles="guest"/> + <permission type="deleteNonDurableQueue" roles="guest"/> + <permission type="consume" roles="guest"/> + <permission type="send" roles="guest"/> + </security-setting> + + <!--security for notification queue--> + <security-setting match="jms.topic.notificationsTopic"> + <permission type="consume" roles="guest"/> + <permission type="createNonDurableQueue" roles="guest"/> + <permission type="deleteNonDurableQueue" roles="guest"/> + </security-setting> + + <!-- security settings for JMS temporary queue --> + <security-setting match="queuetempjms.*"> + <permission type="createNonDurableQueue" roles="guest"/> + <permission type="deleteNonDurableQueue" roles="guest"/> + <permission type="consume" roles="guest"/> + <permission type="send" roles="guest"/> + </security-setting> + </security-settings> + + </core> +</configuration> http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/standard/management-notifications/src/main/resources/jndi.properties ---------------------------------------------------------------------- diff --git a/examples/features/standard/management-notifications/src/main/resources/jndi.properties b/examples/features/standard/management-notifications/src/main/resources/jndi.properties new file mode 100644 index 0000000..2582245 --- /dev/null +++ b/examples/features/standard/management-notifications/src/main/resources/jndi.properties @@ -0,0 +1,21 @@ +# 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. + +java.naming.factory.initial=org.apache.activemq.artemis.jndi.ActiveMQInitialContextFactory +connectionFactory.ConnectionFactory=tcp://localhost:61616 +queue.queue/exampleQueue=exampleQueue +topic.topic/notificationsTopic=notificationsTopic http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/standard/management/pom.xml ---------------------------------------------------------------------- diff --git a/examples/features/standard/management/pom.xml b/examples/features/standard/management/pom.xml new file mode 100644 index 0000000..cd006e5 --- /dev/null +++ b/examples/features/standard/management/pom.xml @@ -0,0 +1,109 @@ +<?xml version='1.0'?> +<!-- +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. +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.activemq.examples.broker</groupId> + <artifactId>jms-examples</artifactId> + <version>1.0.1-SNAPSHOT</version> + </parent> + + <artifactId>management</artifactId> + <packaging>jar</packaging> + <name>ActiveMQ Artemis JMS Management Example</name> + + <properties> + <activemq.basedir>${project.basedir}/../../../..</activemq.basedir> + </properties> + + <dependencies> + <dependency> + <groupId>org.apache.activemq</groupId> + <artifactId>artemis-jms-client</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.activemq</groupId> + <artifactId>artemis-maven-plugin</artifactId> + <executions> + <execution> + <id>create</id> + <goals> + <goal>create</goal> + </goals> + <configuration> + <ignore>${noServer}</ignore> + </configuration> + </execution> + <execution> + <id>start</id> + <goals> + <goal>cli</goal> + </goals> + <configuration> + <ignore>${noServer}</ignore> + <spawn>true</spawn> + <testURI>tcp://localhost:61616</testURI> + <args> + <param>run</param> + </args> + </configuration> + </execution> + <execution> + <id>runClient</id> + <goals> + <goal>runClient</goal> + </goals> + <configuration> + <clientClass>org.apache.activemq.artemis.jms.example.ManagementExample</clientClass> + </configuration> + </execution> + <execution> + <id>stop</id> + <goals> + <goal>cli</goal> + </goals> + <configuration> + <ignore>${noServer}</ignore> + <args> + <param>stop</param> + </args> + </configuration> + </execution> + </executions> + <dependencies> + <dependency> + <groupId>org.apache.activemq.examples.broker</groupId> + <artifactId>management</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> + </plugin> + </plugins> + </build> + +</project> http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/standard/management/readme.html ---------------------------------------------------------------------- diff --git a/examples/features/standard/management/readme.html b/examples/features/standard/management/readme.html new file mode 100644 index 0000000..30057ba --- /dev/null +++ b/examples/features/standard/management/readme.html @@ -0,0 +1,208 @@ +<!-- +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. +--> + +<html> + <head> + <title>ActiveMQ Artemis Management Example</title> + <link rel="stylesheet" type="text/css" href="../../../common/common.css" /> + <link rel="stylesheet" type="text/css" href="../../../common/prettify.css" /> + <script type="text/javascript" src="../../../common/prettify.js"></script> + </head> + <body onload="prettyPrint()"> + <h1>Management Example</h1> + <p>This example shows how to manage ActiveMQ Artemis using JMS Messages to invoke management operations on the server.</a></p> + <p>To manage ActiveMQ Artemis using JMX, see the <a href="../jmx/readme.html">JMX</a> example.</p> + + <h2>Example configuration</h2> + + <p>ActiveMQ Artemis can be managed by sending JMS messages with specific properties to its <em>management</em> queue.</p> + </p>By default, the management name is called <code>activemq.management</code> but this can be configured in <a href="server0/broker.xml">broker.xml</a> + <pre class="prettyprint"> + <code><management-address>activemq.management</management-address></code> + </pre> + + <p>The management queue requires a "special" user permission <code>manage</code> to be able to receive management messages. + This is also configured in <a href="server0/broker.xml">broker.xml</a></p> + <pre class="prettyprint"> + <code><security-setting match="activemq.management"> + <permission type="manage" roles="guest" /> + </security-setting></code> + </pre> + + <h2>Example step-by-step</h2> + <p><em>To run the example, simply type <code>mvn verify -Pexample</code> from this directory</em></p> + <ol> + <li>First we need to get an initial context so we can look-up the JMS connection factory and destination objects from JNDI. This initial context will get its properties from <a href="server0/client-jndi.properties">client-jndi.properties</a></li> + <pre class="prettyprint"> + <code>InitialContext initialContext = getContext(0);</code> + </pre> + + <li>We look up the JMS queue object from JNDI</li> + <pre class="prettyprint"> + <code>Queue queue = (Queue) initialContext.lookup("/queue/exampleQueue");</code> + </pre> + + <li>We look up the JMS connection factory object from JNDI</li> + <pre class="prettyprint"> + <code>ConnectionFactory cf = (ConnectionFactory) initialContext.lookup("/ConnectionFactory");</code> + </pre> + + <li>We create a JMS connection</li> + <pre class="prettyprint"> + <code>connection = cf.createConnection();</code> + </pre> + + <li>We create a JMS session. The session is created as non transacted and will auto acknowledge messages.</li> + <pre class="prettyprint"> + <code>Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);</code> + </pre> + + <li>We create a JMS message producer on the session. This will be used to send the messages.</li> + <pre class="prettyprint"> + <code>MessageProducer messageProducer = session.createProducer(topic);</code> + </pre> + + <li>We create a JMS text message that we are going to send.</li> + <pre class="prettyprint"> + <code>TextMessage message = session.createTextMessage("This is a text message");</code> + </pre> + + <li>We send message to the queue</li> + <pre class="prettyprint"> + <code>messageProducer.send(message);</code> + </pre> + + <p><em>Now that we have a message in the queue, we will manage the queue by retrieving the number of messages in the queue + (i.e. 1) and by removing the message which has been sent in step 8.</em></p> + + <li>We create the JMS management queue. This is a <em>special</em> queue which is not looked up from JNDI but instantiated directly</li> + <pre class="prettyprint"> + <code>Queue managementQueue = new ActiveMQQueue("activemq.management", "activemq.management");</code> + </pre> + + <li>We create a <code>QueueRequestor</code> to send messages to the management queue and receive replies (see <a href="../queue-requestor/readme.html">queue-requestor example</a>)</li> + <pre class="prettyprint"> + <code>QueueRequestor requestor = new QueueRequestor(session, managementQueue);</code> + </pre> + + <li>We start the connection to receive replies on the requestor</li> + <pre class="prettyprint"> + <code>connection.start()</code> + </pre> + + <li>We create a JMS message which will be used as a <em>management</em> message</li> + <pre class="prettyprint"> + <code>Message m = session.createMessage();</code> + </pre> + + <li>a <em>management</em> message has well-defined properties that ActiveMQ Artemis server needs to know to perform management operations.<br /> + We use a helper class <code>JMSManagementHelper</code> to fill these properties: + <ul> + <li>The name of the resource to manage <code>jms.queue.exampleQueue</code> + (i.e. <code>jms.queue</code> followed by the name of the queue as defined in <a href="server0/activemq-jms.xml">activemq-jms.xml</a>)</li> + <li>In our case, the name of the attribute to retrieve <code>MessageCount</code></li> + </ul> + </li> + <pre class="prettyprint"> + <code>JMSManagementHelper.putAttribute(m, "jms.queue.exampleQueue", "MessageCount");</code> + </pre> + + <li>We send the <em>management</em> message using the requestor and wait for a reply</li> + <pre class="prettyprint"> + <code>Message reply = requestor.request(m);</code> + </pre> + + <li>We use a helper class <code>JMSManagementHelper</code> to retrieve the result from the reply message: + <pre class="prettyprint"> + <code>int messageCount = (Integer)JMSManagementHelper.getResult(reply); + System.out.println(queue.getQueueName() + " contains " + messageCount + " messages");</code> + </pre> + + <li>We create another JMS message to use as a management message</li> + <pre class="prettyprint"> + <code>m = session.createMessage();</code> + </pre> + + <li>This time, we fill the <em>management</em> message with properties to <em>invoke</em> a management operation on the queue + <ul> + <li>the name of the resource <code>jms.queue.exampleQueue</code></li> + <li>the name of the management operation <code>removeMessage</code></li> + <li>any parameters required to invoke the management operations (in our case, the JMS Message ID of the message sent in step 8)</li> + </ul> + </li> + <pre class="prettyprint"> + <code>JMSManagementHelper.putOperationInvocation(m, "jms.queue.exampleQueue", "removeMessage", message.getJMSMessageID());</code> + </pre> + + <li>Again, we use the requestor to send the management message and wait for a reply</li> + <pre class="prettyprint"> + <code>reply = requestor.request(m);</code> + </pre> + + <li>We use the helper class to check that the operation was successfully invoked on the server</li> + <pre class="prettyprint"> + <code>boolean success = JMSManagementHelper.hasOperationSucceeded(reply); + System.out.println("operation invocation has succeeded: " + success);</code> + </pre> + + <li>We use a helper class <code>JMSManagementHelper</code> to retrieve the result from the reply message: + (in our case, the <code>removeMessage</code> method returns a boolean)</li> + <pre class="prettyprint"> + <code>boolean messageRemoved = (Boolean)JMSManagementHelper.getResult(reply); + System.out.println("message has been removed: " + messageRemoved);</code> + </pre> + + <p><em>We will now consume the message from the queue but there will be none: the message sent at step 8 was removed by the management operation</em></p> + + <li>We create a JMS message consumer on the queue</li> + <pre class="prettyprint"> + <code>MessageConsumer messageConsumer = session.createConsumer(queue);</code> + </pre> + + <li>We try to receive a message from the queue. Since there is none, the call will timeout after 5000ms and messageReceived will be null + </li> + <pre class="prettyprint"> + <code>TextMessage messageReceived = (TextMessage) messageConsumer.receive(5000); + System.out.println("Received message: " + messageReceived);</code> + </pre> + + <li>And finally, <b>always</b> remember to close your JMS connections and resources after use, in a <code>finally</code> block. Closing a JMS connection will automatically close all of its sessions, consumers, producer and browser objects</li> + + <pre class="prettyprint"> + <code>finally + { + if (initialContext != null) + { + initialContext.close(); + } + if (connection != null) + { + connection.close(); + } + }</code> + </pre> + </ol> + + <h2>More information</h2> + + <ul> + <li>User Manual's <a href="../../../docs/user-manual/en/html_single/index.html#management.jms">Using Management Via JMS chapter</a></li> + </ul> + </body> +</html> http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/standard/management/src/main/java/org/apache/activemq/artemis/jms/example/ManagementExample.java ---------------------------------------------------------------------- diff --git a/examples/features/standard/management/src/main/java/org/apache/activemq/artemis/jms/example/ManagementExample.java b/examples/features/standard/management/src/main/java/org/apache/activemq/artemis/jms/example/ManagementExample.java new file mode 100644 index 0000000..8c780c3 --- /dev/null +++ b/examples/features/standard/management/src/main/java/org/apache/activemq/artemis/jms/example/ManagementExample.java @@ -0,0 +1,133 @@ +/* + * 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.jms.example; + +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Queue; +import javax.jms.QueueConnection; +import javax.jms.QueueConnectionFactory; +import javax.jms.QueueRequestor; +import javax.jms.QueueSession; +import javax.jms.Session; +import javax.jms.TextMessage; +import javax.naming.InitialContext; + +import org.apache.activemq.artemis.api.jms.ActiveMQJMSClient; +import org.apache.activemq.artemis.api.jms.management.JMSManagementHelper; + +/** + * An example that shows how to manage ActiveMQ Artemis using JMS messages. + */ +public class ManagementExample { + + public static void main(final String[] args) throws Exception { + QueueConnection connection = null; + InitialContext initialContext = null; + try { + // Step 1. Create an initial context to perform the JNDI lookup. + initialContext = new InitialContext(); + + // Step 2. Perfom a lookup on the queue + Queue queue = (Queue) initialContext.lookup("queue/exampleQueue"); + + // Step 3. Perform a lookup on the Connection Factory + QueueConnectionFactory cf = (QueueConnectionFactory) initialContext.lookup("ConnectionFactory"); + + // Step 4.Create a JMS Connection + connection = cf.createQueueConnection(); + + // Step 5. Create a JMS Session + QueueSession session = connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); + + // Step 6. Create a JMS Message Producer + MessageProducer producer = session.createProducer(queue); + + // Step 7. Create a Text Message + TextMessage message = session.createTextMessage("This is a text message"); + System.out.println("Sent message: " + message.getText()); + + // Step 8. Send the Message + producer.send(message); + + // Step 9. create the JMS management queue. + // It is a "special" queue and it is not looked up from JNDI but constructed directly + Queue managementQueue = ActiveMQJMSClient.createQueue("activemq.management"); + + // Step 10. Create a QueueRequestor for the management queue (see queue-requestor example) + QueueRequestor requestor = new QueueRequestor(session, managementQueue); + + // Step 11. Start the Connection to allow the queue requestor to receive replies + connection.start(); + + // Step 12. Create a JMS message which is used to send a management message + Message m = session.createMessage(); + + // Step 13. Use a helper class to fill the JMS message with management information: + // * the name of the resource to manage + // * in this case, we want to retrieve the value of the messageCount of the queue + JMSManagementHelper.putAttribute(m, "jms.queue.exampleQueue", "messageCount"); + + // Step 14. Use the requestor to send the request and wait for the reply + Message reply = requestor.request(m); + + // Step 15. Use a helper class to retrieve the operation result + int messageCount = (Integer) JMSManagementHelper.getResult(reply); + System.out.println(queue.getQueueName() + " contains " + messageCount + " messages"); + + // Step 16. Create another JMS message to use as a management message + m = session.createMessage(); + + // Step 17. Use a helper class to fill the JMS message with management information: + // * the object name of the resource to manage (i.e. the queue) + // * in this case, we want to call the "removeMessage" operation with the JMS MessageID + // of the message sent to the queue in step 8. + JMSManagementHelper.putOperationInvocation(m, "jms.queue.exampleQueue", "removeMessage", message.getJMSMessageID()); + + // Step 18 Use the requestor to send the request and wait for the reply + reply = requestor.request(m); + + // Step 19. Use a helper class to check that the operation has succeeded + boolean success = JMSManagementHelper.hasOperationSucceeded(reply); + System.out.println("operation invocation has succeeded: " + success); + + // Step 20. Use a helper class to retrieve the operation result + // in that case, a boolean which is true if the message was removed, false else + boolean messageRemoved = (Boolean) JMSManagementHelper.getResult(reply); + System.out.println("message has been removed: " + messageRemoved); + + // Step 21. Create a JMS Message Consumer on the queue + MessageConsumer messageConsumer = session.createConsumer(queue); + + // Step 22. Trying to receive a message. Since the only message in the queue was removed by a management + // operation, + // there is none to consume. The call will timeout after 5000ms and messageReceived will be null + TextMessage messageReceived = (TextMessage) messageConsumer.receive(5000); + System.out.println("Received message: " + messageReceived); + } + finally { + // Step 23. Be sure to close the resources! + if (initialContext != null) { + initialContext.close(); + } + if (connection != null) { + connection.close(); + } + } + } +} http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/standard/management/src/main/resources/activemq/server0/artemis-roles.properties ---------------------------------------------------------------------- diff --git a/examples/features/standard/management/src/main/resources/activemq/server0/artemis-roles.properties b/examples/features/standard/management/src/main/resources/activemq/server0/artemis-roles.properties new file mode 100644 index 0000000..4e2d44c --- /dev/null +++ b/examples/features/standard/management/src/main/resources/activemq/server0/artemis-roles.properties @@ -0,0 +1,17 @@ +## --------------------------------------------------------------------------- +## 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. +## --------------------------------------------------------------------------- +guest=guest \ No newline at end of file http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/standard/management/src/main/resources/activemq/server0/artemis-users.properties ---------------------------------------------------------------------- diff --git a/examples/features/standard/management/src/main/resources/activemq/server0/artemis-users.properties b/examples/features/standard/management/src/main/resources/activemq/server0/artemis-users.properties new file mode 100644 index 0000000..4e2d44c --- /dev/null +++ b/examples/features/standard/management/src/main/resources/activemq/server0/artemis-users.properties @@ -0,0 +1,17 @@ +## --------------------------------------------------------------------------- +## 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. +## --------------------------------------------------------------------------- +guest=guest \ No newline at end of file http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/standard/management/src/main/resources/activemq/server0/broker.xml ---------------------------------------------------------------------- diff --git a/examples/features/standard/management/src/main/resources/activemq/server0/broker.xml b/examples/features/standard/management/src/main/resources/activemq/server0/broker.xml new file mode 100644 index 0000000..36eec30 --- /dev/null +++ b/examples/features/standard/management/src/main/resources/activemq/server0/broker.xml @@ -0,0 +1,76 @@ +<?xml version='1.0'?> +<!-- +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. +--> + +<configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="urn:activemq" + xsi:schemaLocation="urn:activemq /schema/artemis-server.xsd"> + + <jms xmlns="urn:activemq:jms"> + <!--the queue used by the example--> + <queue name="exampleQueue"/> + </jms> + + <core xmlns="urn:activemq:core"> + + <bindings-directory>${data.dir}/server0/data/messaging/bindings</bindings-directory> + + <journal-directory>${data.dir}/server0/data/messaging/journal</journal-directory> + + <large-messages-directory>${data.dir}/server0/data/messaging/largemessages</large-messages-directory> + + <paging-directory>${data.dir}/server0/data/messaging/paging</paging-directory> + + + <management-address>jms.queue.activemq.management</management-address> + + <!-- Netty standard TCP acceptor --> + <acceptors> + <acceptor name="netty">tcp://localhost:61616</acceptor> + </acceptors> + + <security-settings> + + <!--security for example queue--> + <security-setting match="jms.queue.exampleQueue"> + <permission type="createDurableQueue" roles="guest"/> + <permission type="deleteDurableQueue" roles="guest"/> + <permission type="createNonDurableQueue" roles="guest"/> + <permission type="deleteNonDurableQueue" roles="guest"/> + <permission type="consume" roles="guest"/> + <permission type="send" roles="guest"/> + </security-setting> + + <!--security for management queue--> + <security-setting match="jms.queue.activemq.management"> + <permission type="manage" roles="guest"/> + </security-setting> + + <!-- security settings for JMS temporary queue --> + <security-setting match="jms.tempqueue.#"> + <permission type="createNonDurableQueue" roles="guest"/> + <permission type="deleteNonDurableQueue" roles="guest"/> + <permission type="consume" roles="guest"/> + <permission type="send" roles="guest"/> + </security-setting> + + </security-settings> + + </core> +</configuration> http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/standard/management/src/main/resources/jndi.properties ---------------------------------------------------------------------- diff --git a/examples/features/standard/management/src/main/resources/jndi.properties b/examples/features/standard/management/src/main/resources/jndi.properties new file mode 100644 index 0000000..93537c4 --- /dev/null +++ b/examples/features/standard/management/src/main/resources/jndi.properties @@ -0,0 +1,20 @@ +# 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. + +java.naming.factory.initial=org.apache.activemq.artemis.jndi.ActiveMQInitialContextFactory +connectionFactory.ConnectionFactory=tcp://localhost:61616 +queue.queue/exampleQueue=exampleQueue http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/standard/message-counters/pom.xml ---------------------------------------------------------------------- diff --git a/examples/features/standard/message-counters/pom.xml b/examples/features/standard/message-counters/pom.xml new file mode 100644 index 0000000..e2db0ac --- /dev/null +++ b/examples/features/standard/message-counters/pom.xml @@ -0,0 +1,116 @@ +<?xml version='1.0'?> +<!-- +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. +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.activemq.examples.broker</groupId> + <artifactId>jms-examples</artifactId> + <version>1.0.1-SNAPSHOT</version> + </parent> + + <artifactId>message-counters</artifactId> + <packaging>jar</packaging> + <name>ActiveMQ Artemis JMS Message Counter Example</name> + + <properties> + <activemq.basedir>${project.basedir}/../../../..</activemq.basedir> + </properties> + + <dependencies> + <dependency> + <groupId>org.apache.activemq</groupId> + <artifactId>artemis-server</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.apache.activemq</groupId> + <artifactId>artemis-jms-client</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.activemq</groupId> + <artifactId>artemis-maven-plugin</artifactId> + <executions> + <execution> + <id>create</id> + <goals> + <goal>create</goal> + </goals> + <configuration> + <ignore>${noServer}</ignore> + <javaOptions>-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=3001 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false + </javaOptions> + </configuration> + </execution> + <execution> + <id>start</id> + <goals> + <goal>cli</goal> + </goals> + <configuration> + <ignore>${noServer}</ignore> + <spawn>true</spawn> + <testURI>tcp://localhost:61616</testURI> + <args> + <param>run</param> + </args> + </configuration> + </execution> + <execution> + <id>runClient</id> + <goals> + <goal>runClient</goal> + </goals> + <configuration> + <clientClass>org.apache.activemq.artemis.jms.example.MessageCounterExample</clientClass> + </configuration> + </execution> + <execution> + <id>stop</id> + <goals> + <goal>cli</goal> + </goals> + <configuration> + <ignore>${noServer}</ignore> + <args> + <param>stop</param> + </args> + </configuration> + </execution> + </executions> + <dependencies> + <dependency> + <groupId>org.apache.activemq.examples.broker</groupId> + <artifactId>message-counters</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> + </plugin> + </plugins> + </build> + +</project> http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/standard/message-counters/readme.html ---------------------------------------------------------------------- diff --git a/examples/features/standard/message-counters/readme.html b/examples/features/standard/message-counters/readme.html new file mode 100644 index 0000000..40e247a --- /dev/null +++ b/examples/features/standard/message-counters/readme.html @@ -0,0 +1,197 @@ +<!-- +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. +--> + +<html> + <head> + <title>ActiveMQ Artemis Message Counter Example</title> + <link rel="stylesheet" type="text/css" href="../../../common/common.css" /> + <link rel="stylesheet" type="text/css" href="../../../common/prettify.css" /> + <script type="text/javascript" src="../../../common/prettify.js"></script> + </head> + <body onload="prettyPrint()"> + <h1>JMS Message Counter Example</h1> + + <pre>To run the example, simply type <b>mvn verify</b> from this directory, <br>or <b>mvn -PnoServer verify</b> if you want to start and create the server manually.</pre> + + <p>This example shows you how to use message counters to obtain message information for a JMS queue.</p> + <p>The example will show how to configure sampling of message counters.<br /> + We will produce and consume 1 message from a queue. Interleaved with the JMS operation, we will retrieve the queue's message counters + at different times to display the metrics on the queue. + </p> + <h2>Example setup</h2> + <p>Message counter is configured in the server configuration file <a href="server0/broker.xml">broker.xml</a>:</p> + <pre class="prettyprint"> + <code><message-counter-enabled>true</message-counter-enabled> + <message-counter-sample-period>2000</message-counter-sample-period> + <message-counter-max-day-history>2</message-counter-max-day-history></code> + </pre> + <p>By default, Message counter is not enabled (for performance reason). To enable them, set <code>message-counter-enabled</code> to <code>true</code>.<br /> + Queues are sampled every 10 seconds by default. For this example we will reduce it to 2 seconds by setting <code>message-counter-sample-period</code> to <code>2000</code>.<br /> + ActiveMQ Artemis holds in memory the message counters' history for a maximum number of days (10 by default). We can change the number of days the history is kept by setting + the <code>message-counter-max-day-history</code> parameter.</p> + <p>The sample period and the max day history parameters have a small impact on the performance of ActiveMQ Artemis (the resources taken to sample a queue are not available to the system's + normal use). You should set these parameters accordingly to the use and throughput of your messages.</p> + + <h2>Example step-by-step</h2> + <ol> + <li>First we need to get an initial context so we can look-up the JMS connection factory and destination objects from JNDI. This initial context will get it's properties from the <code>client-jndi.properties</code> file in the directory <code>../common/config</code></li> + <pre class="prettyprint"> + <code>InitialContext initialContext = getContext();</code> + </pre> + + <li>We look up the JMS queue object from JNDI</li> + <pre class="prettyprint"> + <code>Queue queue = (Queue) initialContext.lookup("/queue/exampleQueue");</code> + </pre> + + <li>We look up the JMS connection factory object from JNDI</li> + <pre class="prettyprint"> + <code>ConnectionFactory cf = (ConnectionFactory) initialContext.lookup("/ConnectionFactory");</code> + </pre> + + <li>We create a JMS connection, session and producer for the queue</li> + <pre class="prettyprint"> + <code> connection = cf.createQueueConnection(); + QueueSession session = connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); + MessageProducer producer = session.createProducer(queue);</code> + </pre> + + <li>We create and send a JMS text message</li> + <pre class="prettyprint"> + <code>TextMessage message = session.createTextMessage("This is a text message"); + producer.send(message); + System.out.println("Sent message: " + message.getText());</code> + </pre> + + <li>We will now sleep a little bit to be sure the queue is sample. Since we have configure the sample period to be 2 seconds, + we will sleep for 3 seconds to be sure that a sample is taken</li> + <pre class="prettyprint"> + <code>System.out.println("Sleep a little bit to have the queue sampled..."); + Thread.sleep(3000);</code> + </pre> + + <p>We now need to retrieve the message counters. They're available from the JMS Queue management resource. In this example, we + will retrieve them using JMX (see the <a href="../jmx/readme.html">JMX example</a> for a more complete description). You can also use JMS message to retrieve them (see the <a href="../management/readme.html">Management example</a> to + learn about managing ActiveMQ Artemis using JMS messages).</p> + + <li>We retrieve the JMX MBean used to manage the JMS queue</li> + <pre class="prettyprint"> + <code>ObjectName on = ObjectNameBuilder.DEFAULT.getJMSQueueObjectName(queue.getQueueName()); + JMXConnector connector = JMXConnectorFactory.connect(new JMXServiceURL(JMX_URL), new HashMap()); + MBeanServerConnection mbsc = connector.getMBeanServerConnection(); + JMSQueueControl queueControl = (JMSQueueControl)MBeanServerInvocationHandler.newProxyInstance(mbsc, + on, + JMSQueueControl.class, + false);</code> + </pre> + + <li>We retrieve the message counter and display them. MessageCounters are retrieved as <code>JSON Strings</code> for portability reason (whether + JMX is used for management or JMS messages). To make it simpler to use them in the code, there is a <code>MessageCounterInfo</code> data structure.</li> + <pre class="prettyprint"> + <code>String counters = queueControl.listMessageCounter(); + MessageCounterInfo messageCounter = MessageCounterInfo.fromJSON(counters);</code>> + </pre> + + <li>We display the message counters</li> + <pre class="prettyprint"> + <code>displayMessageCounter(messageCounter);</code> + </pre> + + <p>The message counter contains a variety of metrics on the queue which is sampled (total messages added to the queue, current depth of the queue, deltas since the last sample, timestamp + of the last message added, timestamp of the last sample, etc.)</p> + <pre class="prettyprint"> + <code> + private void displayMessageCounter(MessageCounterInfo counter) + { + System.out.format("%s (sample updated at %s)\n", counter.getName(), counter.getUdpateTimestamp()); + System.out.format(" %s message(s) added to the queue (since last sample: %s)\n", counter.getCount(), + counter.getCountDelta()); + System.out.format(" %s message(s) in the queue (since last sample: %s)\n", counter.getDepth(), + counter.getDepthDelta()); + System.out.format(" last message added at %s\n\n", counter.getLastAddTimestamp()); + }</code> + </pre> + + <li>We sleep again to have the queue sampled</li> + <pre class="prettyprint"> + <code>System.out.println("Sleep a little bit again..."); + Thread.sleep(3000);</code> + </pre> + + <li>We list the message counters again</li> + <pre class="prettyprint"> + <code>counters = queueControl.listMessageCounter(); + messageCounter = MessageCounterInfo.fromJSON(counters); + displayMessageCounter(messageCounter);</code> + </pre> + + <p>We will now consume a message from the queue before listing a last time the message counters</p> + + <li>We create a consumer for the queue</li> + <pre class="prettyprint"> + <code>MessageConsumer consumer = session.createConsumer(queue);</code> + </pre> + + <li>We start the connection to receive messages on the consumer</li> + <pre class="prettyprint"> + <code>connection.start();</code> + </pre> + + <li>We receive a message from the queue</li> + <pre class="prettyprint"> + <code>TextMessage messageReceived = (TextMessage)consumer.receive(5000); + System.out.format("Received message: %s\n\n", messageReceived.getText());</code> + </pre> + + <li>We sleep one last time to have the queue sampled</li> + <pre class="prettyprint"> + <code>System.out.println("Sleep a little bit one last time..."); + Thread.sleep(3000);</code> + </pre> + + <li>We list the message counters a final time (this time with no message in the queue)</li> + <pre class="prettyprint"> + <code>counters = queueControl.listMessageCounter(); + messageCounter = MessageCounterInfo.fromJSON(counters); + displayMessageCounter(messageCounter);</code> + </pre> + + </p> + <li>And finally, <b>always</b> remember to close your JMS connections and resources after use, in a <code>finally</code> block. Closing a JMS connection will automatically close all of its sessions, consumers, producer and browser objects</li> + + <pre class="prettyprint"> + <code>finally + { + if (initialContext != null) + { + initialContext.close(); + } + if (connection != null) + { + connection.close(); + } + }</code> + </pre> + </ol> + + <li>User Manual's <a href="../../../docs/user-manual/en/html_single/index.html#management.message-counters">Message Counters chapter</a></li> + <li><a href="../../../docs/api/org/jboss/messaging/core/management/MessageCounterInfo.html">MessageCounterInfo</a> is a helper class used + to create a MessageCounterInfo object from the JSON String which represents message counters</li> + </body> +</html> http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/standard/message-counters/src/main/java/org/apache/activemq/artemis/jms/example/MessageCounterExample.java ---------------------------------------------------------------------- diff --git a/examples/features/standard/message-counters/src/main/java/org/apache/activemq/artemis/jms/example/MessageCounterExample.java b/examples/features/standard/message-counters/src/main/java/org/apache/activemq/artemis/jms/example/MessageCounterExample.java new file mode 100644 index 0000000..8e6cc26 --- /dev/null +++ b/examples/features/standard/message-counters/src/main/java/org/apache/activemq/artemis/jms/example/MessageCounterExample.java @@ -0,0 +1,134 @@ +/* + * 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.jms.example; + +import java.util.HashMap; + +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Queue; +import javax.jms.QueueConnection; +import javax.jms.QueueConnectionFactory; +import javax.jms.QueueSession; +import javax.jms.Session; +import javax.jms.TextMessage; +import javax.management.MBeanServerConnection; +import javax.management.MBeanServerInvocationHandler; +import javax.management.ObjectName; +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXConnectorFactory; +import javax.management.remote.JMXServiceURL; +import javax.naming.InitialContext; + +import org.apache.activemq.artemis.api.core.management.MessageCounterInfo; +import org.apache.activemq.artemis.api.core.management.ObjectNameBuilder; +import org.apache.activemq.artemis.api.jms.management.JMSQueueControl; + +/** + * An example showing how to use message counters to have information on a queue. + */ +public class MessageCounterExample { + + private static final String JMX_URL = "service:jmx:rmi:///jndi/rmi://localhost:3001/jmxrmi"; + + public static void main(final String[] args) throws Exception { + QueueConnection connection = null; + InitialContext initialContext = null; + try { + // Step 1. Create an initial context to perform the JNDI lookup. + initialContext = new InitialContext(); + + // Step 2. Perfom a lookup on the queue + Queue queue = (Queue) initialContext.lookup("queue/exampleQueue"); + + // Step 3. Perform a lookup on the Connection Factory + QueueConnectionFactory cf = (QueueConnectionFactory) initialContext.lookup("ConnectionFactory"); + + // Step 4.Create a JMS Connection, session and a producer for the queue + connection = cf.createQueueConnection(); + QueueSession session = connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); + MessageProducer producer = session.createProducer(queue); + + // Step 5. Create and send a Text Message + TextMessage message = session.createTextMessage("This is a text message"); + producer.send(message); + System.out.println("Sent message: " + message.getText()); + + // Step 6. Sleep a little bit so that the queue is sampled + System.out.println("Sleep a little bit to have the queue sampled..."); + Thread.sleep(3000); + + // Step 7. Use JMX to retrieve the message counters using the JMSQueueControl + ObjectName on = ObjectNameBuilder.DEFAULT.getJMSQueueObjectName(queue.getQueueName()); + JMXConnector connector = JMXConnectorFactory.connect(new JMXServiceURL(JMX_URL), new HashMap<String, Object>()); + MBeanServerConnection mbsc = connector.getMBeanServerConnection(); + JMSQueueControl queueControl = MBeanServerInvocationHandler.newProxyInstance(mbsc, on, JMSQueueControl.class, false); + + // Step 8. List the message counters and convert them to MessageCounterInfo data structure. + String counters = queueControl.listMessageCounter(); + MessageCounterInfo messageCounter = MessageCounterInfo.fromJSON(counters); + + // Step 9. Display the message counter + displayMessageCounter(messageCounter); + + // Step 10. Sleep again to have the queue sampled again + System.out.println("Sleep a little bit again..."); + Thread.sleep(3000); + + // Step 11. List the messages counters again + counters = queueControl.listMessageCounter(); + messageCounter = MessageCounterInfo.fromJSON(counters); + displayMessageCounter(messageCounter); + + // Step 12. Create a JMS consumer on the queue + MessageConsumer consumer = session.createConsumer(queue); + + // Step 13. Start the connection to receive messages on the consumer + connection.start(); + + // Step 14. Receive a JMS message from the queue. It corresponds to the message sent at step #5 + TextMessage messageReceived = (TextMessage) consumer.receive(5000); + System.out.format("Received message: %s%n%n", messageReceived.getText()); + + // Step 15. Sleep on last time to have the queue sampled + System.out.println("Sleep a little bit one last time..."); + Thread.sleep(3000); + + // Step 16. Display one last time the message counter + counters = queueControl.listMessageCounter(); + messageCounter = MessageCounterInfo.fromJSON(counters); + displayMessageCounter(messageCounter); + } + finally { + // Step 17. Be sure to close our JMS resources! + if (initialContext != null) { + initialContext.close(); + } + if (connection != null) { + connection.close(); + } + } + } + + private static void displayMessageCounter(final MessageCounterInfo counter) { + System.out.format("%s (sample updated at %s)%n", counter.getName(), counter.getUdpateTimestamp()); + System.out.format(" %s message(s) added to the queue (since last sample: %s)%n", counter.getCount(), counter.getCountDelta()); + System.out.format(" %s message(s) in the queue (since last sample: %s)%n", counter.getDepth(), counter.getDepthDelta()); + System.out.format(" last message added at %s%n%n", counter.getLastAddTimestamp()); + } + +} http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/standard/message-counters/src/main/resources/activemq/server0/artemis-roles.properties ---------------------------------------------------------------------- diff --git a/examples/features/standard/message-counters/src/main/resources/activemq/server0/artemis-roles.properties b/examples/features/standard/message-counters/src/main/resources/activemq/server0/artemis-roles.properties new file mode 100644 index 0000000..4e2d44c --- /dev/null +++ b/examples/features/standard/message-counters/src/main/resources/activemq/server0/artemis-roles.properties @@ -0,0 +1,17 @@ +## --------------------------------------------------------------------------- +## 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. +## --------------------------------------------------------------------------- +guest=guest \ No newline at end of file http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/standard/message-counters/src/main/resources/activemq/server0/artemis-users.properties ---------------------------------------------------------------------- diff --git a/examples/features/standard/message-counters/src/main/resources/activemq/server0/artemis-users.properties b/examples/features/standard/message-counters/src/main/resources/activemq/server0/artemis-users.properties new file mode 100644 index 0000000..4e2d44c --- /dev/null +++ b/examples/features/standard/message-counters/src/main/resources/activemq/server0/artemis-users.properties @@ -0,0 +1,17 @@ +## --------------------------------------------------------------------------- +## 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. +## --------------------------------------------------------------------------- +guest=guest \ No newline at end of file http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/standard/message-counters/src/main/resources/activemq/server0/broker.xml ---------------------------------------------------------------------- diff --git a/examples/features/standard/message-counters/src/main/resources/activemq/server0/broker.xml b/examples/features/standard/message-counters/src/main/resources/activemq/server0/broker.xml new file mode 100644 index 0000000..8d4ed29 --- /dev/null +++ b/examples/features/standard/message-counters/src/main/resources/activemq/server0/broker.xml @@ -0,0 +1,86 @@ +<?xml version='1.0'?> +<!-- +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. +--> + +<configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="urn:activemq" + xsi:schemaLocation="urn:activemq ../../../../src/schema/artemis-server.xsd"> + + <jms xmlns="urn:activemq:jms"> + <!--the queue used by the example--> + <queue name="exampleQueue"/> + + <!--the expiry queue where expired messages will be sent--> + <queue name="expiryQueue"/> + </jms> + + <core xmlns="urn:activemq:core"> + + <bindings-directory>${data.dir}/server0/data/messaging/bindings</bindings-directory> + + <journal-directory>${data.dir}/server0/data/messaging/journal</journal-directory> + + <large-messages-directory>${data.dir}/server0/data/messaging/largemessages</large-messages-directory> + + <paging-directory>${data.dir}/server0/data/messaging/paging</paging-directory> + + + <jmx-management-enabled>true</jmx-management-enabled> + <message-counter-enabled>true</message-counter-enabled> + <message-counter-sample-period>2000</message-counter-sample-period> + <message-counter-max-day-history>2</message-counter-max-day-history> + + <!-- Acceptors --> + <acceptors> + <acceptor name="netty-acceptor">tcp://localhost:61616</acceptor> + </acceptors> + + <!-- Other config --> + + <security-settings> + <!--security for example queue--> + <security-setting match="jms.queue.exampleQueue"> + <permission type="createDurableQueue" roles="guest"/> + <permission type="deleteDurableQueue" roles="guest"/> + <permission type="createNonDurableQueue" roles="guest"/> + <permission type="deleteNonDurableQueue" roles="guest"/> + <permission type="consume" roles="guest"/> + <permission type="send" roles="guest"/> + </security-setting> + + <!--security for dead letter queue--> + <security-setting match="jms.queue.expiryQueue"> + <permission type="createDurableQueue" roles="guest"/> + <permission type="deleteDurableQueue" roles="guest"/> + <permission type="createNonDurableQueue" roles="guest"/> + <permission type="deleteNonDurableQueue" roles="guest"/> + <permission type="consume" roles="guest"/> + <permission type="send" roles="guest"/> + </security-setting> + </security-settings> + + <address-settings> + <!--override the expiry address for the example--> + <address-setting match="jms.queue.exampleQueue"> + <expiry-address>jms.queue.expiryQueue</expiry-address> + </address-setting> + </address-settings> + + </core> +</configuration> http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/standard/message-counters/src/main/resources/jndi.properties ---------------------------------------------------------------------- diff --git a/examples/features/standard/message-counters/src/main/resources/jndi.properties b/examples/features/standard/message-counters/src/main/resources/jndi.properties new file mode 100644 index 0000000..231fa30 --- /dev/null +++ b/examples/features/standard/message-counters/src/main/resources/jndi.properties @@ -0,0 +1,21 @@ +# 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. + +java.naming.factory.initial=org.apache.activemq.artemis.jndi.ActiveMQInitialContextFactory +connectionFactory.ConnectionFactory=tcp://localhost:61616 +queue.queue/exampleQueue=exampleQueue +queue.queue/expiryQueue=expiryQueue http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/standard/message-group/pom.xml ---------------------------------------------------------------------- diff --git a/examples/features/standard/message-group/pom.xml b/examples/features/standard/message-group/pom.xml new file mode 100644 index 0000000..1c97866 --- /dev/null +++ b/examples/features/standard/message-group/pom.xml @@ -0,0 +1,109 @@ +<?xml version='1.0'?> +<!-- +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. +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.activemq.examples.broker</groupId> + <artifactId>jms-examples</artifactId> + <version>1.0.1-SNAPSHOT</version> + </parent> + + <artifactId>message-group</artifactId> + <packaging>jar</packaging> + <name>ActiveMQ Artemis JMS Message Group Example</name> + + <properties> + <activemq.basedir>${project.basedir}/../../../..</activemq.basedir> + </properties> + + <dependencies> + <dependency> + <groupId>org.apache.activemq</groupId> + <artifactId>artemis-jms-client</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.activemq</groupId> + <artifactId>artemis-maven-plugin</artifactId> + <executions> + <execution> + <id>create</id> + <goals> + <goal>create</goal> + </goals> + <configuration> + <ignore>${noServer}</ignore> + </configuration> + </execution> + <execution> + <id>start</id> + <goals> + <goal>cli</goal> + </goals> + <configuration> + <ignore>${noServer}</ignore> + <spawn>true</spawn> + <testURI>tcp://localhost:61616</testURI> + <args> + <param>run</param> + </args> + </configuration> + </execution> + <execution> + <id>runClient</id> + <goals> + <goal>runClient</goal> + </goals> + <configuration> + <clientClass>org.apache.activemq.artemis.jms.example.MessageGroupExample</clientClass> + </configuration> + </execution> + <execution> + <id>stop</id> + <goals> + <goal>cli</goal> + </goals> + <configuration> + <ignore>${noServer}</ignore> + <args> + <param>stop</param> + </args> + </configuration> + </execution> + </executions> + <dependencies> + <dependency> + <groupId>org.apache.activemq.examples.broker</groupId> + <artifactId>message-group</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> + </plugin> + </plugins> + </build> + +</project> http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/standard/message-group/readme.html ---------------------------------------------------------------------- diff --git a/examples/features/standard/message-group/readme.html b/examples/features/standard/message-group/readme.html new file mode 100644 index 0000000..56d2afe --- /dev/null +++ b/examples/features/standard/message-group/readme.html @@ -0,0 +1,152 @@ +<!-- +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. +--> + +<html> + <head> + <title>ActiveMQ Artemis Message Group Example</title> + <link rel="stylesheet" type="text/css" href="../../../common/common.css" /> + <link rel="stylesheet" type="text/css" href="../../../common/prettify.css" /> + <script type="text/javascript" src="../../../common/prettify.js"></script> + </head> + <body onload="prettyPrint()"> + <h1>Message Group Example</h1> + + <pre>To run the example, simply type <b>mvn verify</b> from this directory, <br>or <b>mvn -PnoServer verify</b> if you want to start and create the server manually.</pre> + + <p>This example shows you how to configure and use message groups with ActiveMQ Artemis.</p> + + <p>Message groups are sets of messages that has the following characteristics: </p> + <li>Messages in a message group share the same group id, i.e. they have same JMSXGroupID string property values.</li> + <li>Messages in a message group will be all delivered to no more than one of the queue's consumers. The consumer that receives the + first message of a group will receive all the messages that belong to the group.</li> + + <p>You can make any message belong to a message group by setting its 'JMXGroupID' string property to the group id. + In this example we create a message group 'Group-0'. And make such a message group of 10 messages. It also create two consumers on the queue + where the 10 'Group-0' group messages are to be sent. You can see that with message grouping enabled, all the 10 messages will be received by + the first consumer. The second consumer will receive none. </p> + + <p>Alternatively, ActiveMQ's connection factories can be configured to <em>auto group</em> messages. By setting <code>autogroup</code> to </code>true</code> on the <code>ActiveMQConnectionFactory</code> + (or setting <code><autogroup>true</autogroup></code> in <code>activemq-jms.xml</code>'s connection factory settings), a random unique id + will be picked to create a message group. <em>Every messages</em> sent by a producer created from this connection factory will automatically + be part of this message group.</p> + + <h2>Example step-by-step</h2> + + <ol> + <li>First we need to get an initial context so we can look-up the JMS connection factory and destination objects from JNDI. This initial context will get it's properties from the <code>client-jndi.properties</code> file in the directory <code>../common/config</code></li> + <pre class="prettyprint"> + <code>InitialContext initialContext = getContext();</code> + </pre> + + <li>We look-up the JMS queue object from JNDI</li> + <pre class="prettyprint"> + <code>Queue queue = (Queue) initialContext.lookup("/queue/exampleQueue");</code> + </pre> + + <li>We look-up the JMS connection factory object from JNDI</li> + <pre class="prettyprint"> + <code>ConnectionFactory cf = (ConnectionFactory) initialContext.lookup("/ConnectionFactory");</code> + </pre> + + <li>We create a JMS connection</li> + <pre class="prettyprint"> + <code>connection = cf.createConnection();</code> + </pre> + + <li>We create a JMS session. The session is created as non transacted and will auto acknowledge messages.</li> + <pre class="prettyprint"> + <code>Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);</code> + </pre> + + <li>We create a JMS message producer on the session. This will be used to send the messages.</li> + <pre class="prettyprint"> + <code>MessageProducer messageProducer = session.createProducer(topic);</code> + </pre> + + <li>We create two consumers.</li> + <pre class="prettyprint"> + <code> + MessageConsumer consumer1 = session.createConsumer(queue); + consumer1.setMessageListener(new SimpleMessageListener("consumer-1")); + MessageConsumer consumer2 = session.createConsumer(queue); + consumer2.setMessageListener(new SimpleMessageListener("consumer-2")); + </code> + </pre> + + <li>We create and send 10 text messages with group id 'Group-0'</li> + <pre class="prettyprint"> + <code> + int msgCount = 10; + TextMessage[] groupMessages = new TextMessage[msgCount]; + for (int i = 0; i < msgCount; i++) + { + groupMessages[i] = session.createTextMessage("Group-0 message " + i); + groupMessages[i].setStringProperty("JMSXGroupID", "Group-0"); + producer.send(groupMessages[i]); + System.out.println("Sent message: " + groupMessages[i].getText()); + } + </code> + </pre> + + <li>We start the connection.</li> + <pre class="prettyprint"> + <code>connection.start();</code> + </pre> + + <li>We check the group messages are received by only one consumer</li> + <pre class="prettyprint"> + <code> + String trueReceiver = messageReceiverMap.get(groupMessages[0].getText()); + for (TextMessage grpMsg : groupMessages) + { + String receiver = messageReceiverMap.get(grpMsg.getText()); + if (!trueReceiver.equals(receiver)) + { + System.out.println("Group message [" + grpMsg.getText() + "[ went to wrong receiver: " + receiver); + result = false; + } + } + </code> + </pre> + + <li>And finally, <b>always</b> remember to close your JMS connections and resources after use, in a <code>finally</code> block. Closing a JMS connection will automatically close all of its sessions, consumers, producer and browser objects</li> + + <pre class="prettyprint"> + <code>finally + { + if (initialContext != null) + { + initialContext.close(); + } + if (connection != null) + { + connection.close(); + } + }</code> + </pre> + </ol> + + <h2>More information</h2> + + <ul> + <li>User Manual's <a href="../../../docs/user-manual/en/html_single/index.html#message-grouping">Message Grouping chapter</a></li> + </ul> + + </body> +</html>