http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/standard/message-group/src/main/java/org/apache/activemq/artemis/jms/example/MessageGroupExample.java ---------------------------------------------------------------------- diff --git a/examples/features/standard/message-group/src/main/java/org/apache/activemq/artemis/jms/example/MessageGroupExample.java b/examples/features/standard/message-group/src/main/java/org/apache/activemq/artemis/jms/example/MessageGroupExample.java new file mode 100644 index 0000000..c614860 --- /dev/null +++ b/examples/features/standard/message-group/src/main/java/org/apache/activemq/artemis/jms/example/MessageGroupExample.java @@ -0,0 +1,122 @@ +/* + * 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.Connection; +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.TextMessage; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.activemq.artemis.api.jms.ActiveMQJMSClient; +import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory; + +/** + * A simple JMS Queue example that sends and receives message groups. + */ +public class MessageGroupExample { + + public static void main(final String[] args) throws Exception { + final Map<String, String> messageReceiverMap = new ConcurrentHashMap<String, String>(); + Connection connection = null; + try { + + // Step 2. Perform a lookup on the queue + Queue queue = ActiveMQJMSClient.createQueue("queue/exampleQueue"); + + // Step 3. Perform a lookup on the Connection Factory + ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory(); + + // Step 4. Create a JMS Connection + connection = cf.createConnection(); + + // Step 5. Create a JMS Session + Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + + // Step 6. Create a JMS Message Producer + MessageProducer producer = session.createProducer(queue); + + // Step 7. Create two consumers + MessageConsumer consumer1 = session.createConsumer(queue); + consumer1.setMessageListener(new SimpleMessageListener("consumer-1", messageReceiverMap)); + MessageConsumer consumer2 = session.createConsumer(queue); + consumer2.setMessageListener(new SimpleMessageListener("consumer-2", messageReceiverMap)); + + // Step 8. Create and send 10 text messages with group id 'Group-0' + 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()); + } + + System.out.println("all messages are sent"); + + // Step 9. Start the connection + connection.start(); + + Thread.sleep(2000); + + // Step 10. check the group messages are received by only one consumer + String trueReceiver = messageReceiverMap.get(groupMessages[0].getText()); + for (TextMessage grpMsg : groupMessages) { + String receiver = messageReceiverMap.get(grpMsg.getText()); + if (!trueReceiver.equals(receiver)) { + throw new IllegalStateException("Group message [" + grpMsg.getText() + "[ went to wrong receiver: " + receiver); + } + } + + cf.close(); + } + finally { + // Step 11. Be sure to close our JMS resources! + if (connection != null) { + connection.close(); + } + } + } +} + +class SimpleMessageListener implements MessageListener { + + private final String name; + private final Map<String, String> messageReceiverMap; + + public SimpleMessageListener(final String listenerName, Map<String, String> messageReceiverMap) { + name = listenerName; + this.messageReceiverMap = messageReceiverMap; + } + + public void onMessage(final Message message) { + try { + TextMessage msg = (TextMessage) message; + System.out.format("Message: [%s] received by %s%n", msg.getText(), name); + messageReceiverMap.put(msg.getText(), name); + } + catch (JMSException e) { + e.printStackTrace(); + } + } +} \ No newline at end of file
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/standard/message-group/src/main/resources/jndi.properties ---------------------------------------------------------------------- diff --git a/examples/features/standard/message-group/src/main/resources/jndi.properties b/examples/features/standard/message-group/src/main/resources/jndi.properties new file mode 100644 index 0000000..93537c4 --- /dev/null +++ b/examples/features/standard/message-group/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-group2/pom.xml ---------------------------------------------------------------------- diff --git a/examples/features/standard/message-group2/pom.xml b/examples/features/standard/message-group2/pom.xml new file mode 100644 index 0000000..1a0363d --- /dev/null +++ b/examples/features/standard/message-group2/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-group2</artifactId> + <packaging>jar</packaging> + <name>ActiveMQ Artemis JMS Message Group Example 2</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.MessageGroup2Example</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-group2</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-group2/readme.html ---------------------------------------------------------------------- diff --git a/examples/features/standard/message-group2/readme.html b/examples/features/standard/message-group2/readme.html new file mode 100644 index 0000000..983a442 --- /dev/null +++ b/examples/features/standard/message-group2/readme.html @@ -0,0 +1,161 @@ +<!-- +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 via a connection factory 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 belongs to the group.</li> + + <p>You can make any message belong to a message group by setting a 'group-id' on the connection factory. All producers created via this connection factory will set that group id on its messages. + In this example we set the group id 'Group-0'on a connection factory and send messages via 2 different producers and check that only 1 consumer receives them. </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 2 JMS message producers on the session. This will be used to send the messages.</li> + <pre class="prettyprint"> + <code> + MessageProducer producer1 = session.createProducer(queue); + + MessageProducer producer2 = session.createProducer(queue);</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 using each producer</li> + <pre class="prettyprint"> + <code> + int msgCount = 10; + for (int i = 0; i < msgCount; i++) + { + TextMessage m = session.createTextMessage("producer1 message " + i); + producer1.send(m); + System.out.println("Sent message: " + m.getText()); + TextMessage m2 = session.createTextMessage("producer2 message " + i); + producer2.send(m2); + System.out.println("Sent message: " + m2.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("producer1 message " + 0); + for (int i = 0; i < msgCount; i++) + { + String receiver = messageReceiverMap.get("producer1 message " + i); + if (!trueReceiver.equals(receiver)) + { + System.out.println("Group message [producer1 message " + i + "] went to wrong receiver: " + receiver); + result = false; + } + receiver = messageReceiverMap.get("producer2 message " + i); + if (!trueReceiver.equals(receiver)) + { + System.out.println("Group message [producer2 message " + i + "] 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-grouping2">Message Grouping chapter</a></li> + </ul> + + </body> +</html> http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/standard/message-group2/src/main/java/org/apache/activemq/artemis/jms/example/MessageGroup2Example.java ---------------------------------------------------------------------- diff --git a/examples/features/standard/message-group2/src/main/java/org/apache/activemq/artemis/jms/example/MessageGroup2Example.java b/examples/features/standard/message-group2/src/main/java/org/apache/activemq/artemis/jms/example/MessageGroup2Example.java new file mode 100644 index 0000000..a2164cf --- /dev/null +++ b/examples/features/standard/message-group2/src/main/java/org/apache/activemq/artemis/jms/example/MessageGroup2Example.java @@ -0,0 +1,129 @@ +/* + * 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.Connection; +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.TextMessage; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.activemq.artemis.api.jms.ActiveMQJMSClient; +import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory; + +/** + * A simple JMS Queue example that sends and receives message groups. + */ +public class MessageGroup2Example { + + private boolean result = true; + + public static void main(String[] args) throws Exception { + final Map<String, String> messageReceiverMap = new ConcurrentHashMap<String, String>(); + Connection connection = null; + try { + //Step 2. Perform a lookup on the queue + Queue queue = ActiveMQJMSClient.createQueue("exampleQueue"); + + //Step 3. Perform a lookup on the Connection Factory + ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory("tcp://localhost:61616?groupID=Group-0"); + + //Step 4. Create a JMS Connection + connection = cf.createConnection(); + + //Step 5. Create a JMS Session + Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + + //Step 6. Create 2 JMS Message Producers + MessageProducer producer1 = session.createProducer(queue); + + MessageProducer producer2 = session.createProducer(queue); + + //Step 7. Create two consumers + MessageConsumer consumer1 = session.createConsumer(queue); + consumer1.setMessageListener(new SimpleMessageListener("consumer-1", messageReceiverMap)); + MessageConsumer consumer2 = session.createConsumer(queue); + consumer2.setMessageListener(new SimpleMessageListener("consumer-2", messageReceiverMap)); + + //Step 8. Create and send 10 text messages with each producer + int msgCount = 10; + for (int i = 0; i < msgCount; i++) { + TextMessage m = session.createTextMessage("producer1 message " + i); + producer1.send(m); + System.out.println("Sent message: " + m.getText()); + TextMessage m2 = session.createTextMessage("producer2 message " + i); + producer2.send(m2); + System.out.println("Sent message: " + m2.getText()); + } + + System.out.println("all messages are sent"); + + //Step 9. Start the connection + connection.start(); + + Thread.sleep(2000); + + //Step 10. check the group messages are received by only one consumer + + String trueReceiver = messageReceiverMap.get("producer1 message " + 0); + for (int i = 0; i < msgCount; i++) { + String receiver = messageReceiverMap.get("producer1 message " + i); + if (!trueReceiver.equals(receiver)) { + throw new IllegalStateException("Group message [producer1 message " + i + "] went to wrong receiver: " + receiver); + } + receiver = messageReceiverMap.get("producer2 message " + i); + if (!trueReceiver.equals(receiver)) { + throw new IllegalStateException("Group message [producer2 message " + i + "] went to wrong receiver: " + receiver); + } + } + } + finally { + //Step 11. Be sure to close our JMS resources! + if (connection != null) { + connection.close(); + } + } + } +} + +class SimpleMessageListener implements MessageListener { + + private final String name; + final Map<String, String> messageReceiverMap; + + public SimpleMessageListener(String listenerName, Map<String, String> messageReceiverMap) { + name = listenerName; + this.messageReceiverMap = messageReceiverMap; + } + + public void onMessage(Message message) { + try { + TextMessage msg = (TextMessage) message; + System.out.format("Message: [%s] received by %s%n", msg.getText(), name); + messageReceiverMap.put(msg.getText(), name); + } + catch (JMSException e) { + e.printStackTrace(); + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/standard/message-priority/pom.xml ---------------------------------------------------------------------- diff --git a/examples/features/standard/message-priority/pom.xml b/examples/features/standard/message-priority/pom.xml new file mode 100644 index 0000000..b60aadc --- /dev/null +++ b/examples/features/standard/message-priority/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-priority</artifactId> + <packaging>jar</packaging> + <name>ActiveMQ Artemis JMS MessagePriorityExample 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.MessagePriorityExample</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-priority</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-priority/readme.html ---------------------------------------------------------------------- diff --git a/examples/features/standard/message-priority/readme.html b/examples/features/standard/message-priority/readme.html new file mode 100644 index 0000000..fc25297 --- /dev/null +++ b/examples/features/standard/message-priority/readme.html @@ -0,0 +1,159 @@ +<!-- +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 JMS Message Priority 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 Priority 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 how messages with different priorities are delivered in different orders.</p> + + <p>The Message Priority property carries the delivery preference of sent messages. It can be set by the message's + standard header field 'JMSPriority' as defined in JMS specification version 1.1. The value is of type + integer, ranging from 0 (the lowest) to 9 (the highest). When messages are being delivered, their priorities + will effect their order of delivery. Messages of higher priorities will likely be delivered before those + of lower priorities. Messages of equal priorities are delivered in the natural order of their arrival at + their destinations. Please consult the JMS 1.1 specification for full details.</p> + + <p>In this example, three messages are sent to a queue with different priorities. The first message is sent + with default priority (4), the second is sent with a higher priority (5), and the third has the highest + priority (9). At the receiving end, we will show the order of receiving of the three messages. You will + see that the third message, though last sent, will 'jump' forward to be the first one received. The second + is also received ahead of the message first sent, but behind the third message. The first message, regardless + of its being sent first, arrives last.</p> + + <h2>Example step-by-step</h2> + <p><i>To run the example, simply type <code>mvn verify -Pexample</code> from this directory</i></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 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 a JMS Message Consumer.</li> + <pre class="prettyprint"> + <code> + MessageConsumer redConsumer = session.createConsumer(queue); + redConsumer.setMessageListener(new SimpleMessageListener()); + </code> + </pre> + + <li>We Create three messages.</li> + <pre class="prettyprint"> + <code> + TextMessage[] sentMessages = new TextMessage[3]; + sentMessages[0] = session.createTextMessage("first message"); + sentMessages[1] = session.createTextMessage("second message"); + sentMessages[2] = session.createTextMessage("third message"); + </code> + </pre> + + <li>Send the Messages, each has a different priority.</li> + <pre class="prettyprint"> + <code> + producer.send(sentMessages[0]); + System.out.println("Message sent: " + sentMessages[0].getText() + " with priority: " + sentMessages[0].getJMSPriority()); + producer.send(sentMessages[1], DeliveryMode.NON_PERSISTENT, 5, 0); + System.out.println("Message sent: " + sentMessages[1].getText() + "with priority: " + sentMessages[1].getJMSPriority()); + producer.send(sentMessages[2], DeliveryMode.NON_PERSISTENT, 9, 0); + System.out.println("Message sent: " + sentMessages[2].getText() + "with priority: " + sentMessages[2].getJMSPriority()); + </code> + </pre> + + <li>We start the connection now.</li> + <pre class="prettyprint"> + <code> + connection.start(); + </code> + </pre> + + <li>We wait for message delivery completion</li> + <pre class="prettyprint"> + <code> + Thread.sleep(5000); + </code> + </pre> + + <li>We wait for message delivery completion</li> + <pre class="prettyprint"> + <code> + for (int i = 0; i < 3; i++) + { + TextMessage rm = msgReceived.get(i); + if (!rm.getText().equals(sentMessages[2-i].getText())) + { + System.err.println("Priority is broken!"); + 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> + </body> +</html> http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/standard/message-priority/src/main/java/org/apache/activemq/artemis/jms/example/MessagePriorityExample.java ---------------------------------------------------------------------- diff --git a/examples/features/standard/message-priority/src/main/java/org/apache/activemq/artemis/jms/example/MessagePriorityExample.java b/examples/features/standard/message-priority/src/main/java/org/apache/activemq/artemis/jms/example/MessagePriorityExample.java new file mode 100644 index 0000000..2c87d26 --- /dev/null +++ b/examples/features/standard/message-priority/src/main/java/org/apache/activemq/artemis/jms/example/MessagePriorityExample.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.ArrayList; +import java.util.concurrent.atomic.AtomicBoolean; + +import javax.jms.Connection; +import javax.jms.ConnectionFactory; +import javax.jms.DeliveryMode; +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.TextMessage; + +import org.apache.activemq.artemis.api.jms.ActiveMQJMSClient; +import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory; + +/** + * A simple JMS example that shows the delivery order of messages with priorities. + */ +public class MessagePriorityExample { + + public static void main(final String[] args) throws Exception { + AtomicBoolean result = new AtomicBoolean(true); + final ArrayList<TextMessage> msgReceived = new ArrayList<TextMessage>(); + Connection connection = null; + try { + + // Step 2. look-up the JMS queue object from JNDI + Queue queue = ActiveMQJMSClient.createQueue("exampleQueue"); + + // Step 3. look-up the JMS connection factory object from JNDI + ConnectionFactory cf = new ActiveMQConnectionFactory(); + + // Step 4. Create a JMS Connection + connection = cf.createConnection(); + + // Step 5. Create a JMS Session + Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + + // Step 6. Create a JMS Message Producer + MessageProducer producer = session.createProducer(queue); + + // Step 7. Create a JMS Message Consumer + MessageConsumer redConsumer = session.createConsumer(queue); + redConsumer.setMessageListener(new SimpleMessageListener(msgReceived, result)); + + // Step 8. Create three messages + TextMessage[] sentMessages = new TextMessage[3]; + sentMessages[0] = session.createTextMessage("first message"); + sentMessages[1] = session.createTextMessage("second message"); + sentMessages[2] = session.createTextMessage("third message"); + + // Step 9. Send the Messages, each has a different priority + producer.send(sentMessages[0]); + System.out.println("Message sent: " + sentMessages[0].getText() + + " with priority: " + + sentMessages[0].getJMSPriority()); + producer.send(sentMessages[1], DeliveryMode.NON_PERSISTENT, 5, 0); + System.out.println("Message sent: " + sentMessages[1].getText() + + "with priority: " + + sentMessages[1].getJMSPriority()); + producer.send(sentMessages[2], DeliveryMode.NON_PERSISTENT, 9, 0); + System.out.println("Message sent: " + sentMessages[2].getText() + + "with priority: " + + sentMessages[2].getJMSPriority()); + + // Step 10. Start the connection now. + connection.start(); + + // Step 11. Wait for message delivery completion + Thread.sleep(5000); + + // Step 12. Examine the order + for (int i = 0; i < 3; i++) { + TextMessage rm = msgReceived.get(i); + if (!rm.getText().equals(sentMessages[2 - i].getText())) { + throw new IllegalStateException("Priority is broken!"); + } + } + + if (!result.get()) + throw new IllegalStateException(); + } + finally { + // Step 13. Be sure to close our JMS resources! + if (connection != null) { + connection.close(); + } + } + } +} + +class SimpleMessageListener implements MessageListener { + + ArrayList<TextMessage> msgReceived; + AtomicBoolean result; + + public SimpleMessageListener(ArrayList<TextMessage> msgReceived, AtomicBoolean result) { + this.msgReceived = msgReceived; + this.result = result; + } + + public void onMessage(final Message msg) { + TextMessage textMessage = (TextMessage) msg; + try { + System.out.println("Received message : [" + textMessage.getText() + "]"); + } + catch (JMSException e) { + result.set(false); + } + msgReceived.add(textMessage); + } + +} http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/standard/no-consumer-buffering/pom.xml ---------------------------------------------------------------------- diff --git a/examples/features/standard/no-consumer-buffering/pom.xml b/examples/features/standard/no-consumer-buffering/pom.xml new file mode 100644 index 0000000..838980c --- /dev/null +++ b/examples/features/standard/no-consumer-buffering/pom.xml @@ -0,0 +1,108 @@ +<?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>no-consumer-buffering</artifactId> + <packaging>jar</packaging> + <name>ActiveMQ Artemis JMS No Consumer Buffering 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.NoConsumerBufferingExample</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>no-consumer-buffering</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/no-consumer-buffering/readme.html ---------------------------------------------------------------------- diff --git a/examples/features/standard/no-consumer-buffering/readme.html b/examples/features/standard/no-consumer-buffering/readme.html new file mode 100644 index 0000000..596562d --- /dev/null +++ b/examples/features/standard/no-consumer-buffering/readme.html @@ -0,0 +1,205 @@ +<!-- +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 No Consumer Buffering 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>No Consumer Buffering 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>By default, ActiveMQ Artemis consumers buffer messages from the server in a client side buffer + before actual delivery actually occurs.</p> + <p>This improves performance since otherwise every time you called receive() or had processed the last + message in a MessageListener onMessage() method, the ActiveMQ Artemis client would have to go the + server to request the next message involving a network round trip for every message reducing performance.</p> + <p>Therefore, by default, ActiveMQ Artemis pre-fetches messages into a buffer on each consumer. The total maximum size of + messages in bytes that will be buffered on each consumer is determined by the <code>consumer-window-size</code> + parameter on the connection factory.</p> + <p>In some cases it is not desirable to buffer any messages on the client side consumer.</p> + <p>An example would be an order queue which had multiple consumers that processed orders from the queue. + Each order takes a significant time to process, but each one should be processed in a timely fashion.</p> + <p>If orders were buffered in each consumer, and a new consumer was added that consumer would not be able + to process orders which were already in the client side buffer of another consumer.</p> + <p>To turn off client side buffering of messages, set <code>consumer-window-size</code> to zero.</p> + + <p>With ActiveMQ Artemis you can specify a maximum consume rate at which a JMS MessageConsumer will consume messages. + This can be specified when creating or deploying the connection factory. See <code>activemq-jms.xml</code></p> + <h2>Example step-by-step</h2> + <p>In this example we specify a <code>consumer-window-size</code> of <code>0</code> bytes in the <code>activemq-jms.xml</code> + file when deploying the connection factory:</p> + <pre class="prettyprint"> + <code> + <connection-factory name="ConnectionFactory"> + <connector-ref connector-name="netty-connector"/> + <entries> + <entry name="ConnectionFactory"/> + </entries> + + <!-- We set the consumer window size to 0, which means messages are not buffered at all + on the client side --> + <consumer-window-size>0</consumer-window-size> + + </connection-factory> + </code> + </pre> + <p>We create a consumer on a queue and send 10 messages to it. We then create another consumer on + the same queue.</p> + <p>We then consume messages from each consumer in a semi-random order. We note that the messages + are consumed in the order they were sent.</p> + <p>If the messages had been buffered in each consumer they would not be available to be consumed + in an order determined afer delivery.</p> + + <ol> + <li>Create an initial context to perform the JNDI lookup.</li> + <pre class="prettyprint"> + <code>initialContext = getContext(0);</code> + </pre> + + <li>Perfom a lookup on the queue</li> + <pre class="prettyprint"> + <code>Queue queue = (Queue)initialContext.lookup("/queue/exampleQueue");</code> + </pre> + + <li>Perform a lookup on the Connection Factory</li> + <pre class="prettyprint"> + <code>ConnectionFactory cf = (ConnectionFactory)initialContext.lookup("/ConnectionFactory");</code> + </pre> + + <li>Create a JMS Connection</li> + <pre class="prettyprint"> + <code>connection = cf.createConnection();</code> + </pre> + + <li>Create a JMS Session</li> + <pre class="prettyprint"> + <code>Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);</code> + </pre> + + <li>Create a JMS MessageProducer</li> + <pre class="prettyprint"> + <code>MessageProducer producer = session.createProducer(queue);</code> + </pre> + + <li>Create a JMS MessageConsumer</li> + <pre class="prettyprint"> + <code>MessageConsumer consumer1 = session.createConsumer(queue);</code> + </pre> + + <li>Start the connection</li> + + <pre class="prettyprint"> + <code> + connection.start(); + </code> + </pre> + + + <li>Send 10 messages to the queue</li> + <pre class="prettyprint"> + <code> + final int numMessages = 10; + + for (int i = 0; i < numMessages; i++) + { + TextMessage message = session.createTextMessage("This is text message: " + i); + + producer.send(message); + } + </code> + </pre> + + <li>Create another JMS MessageConsumer on the same queue.</li> + <pre class="prettyprint"> + <code>MessageConsumer consumer2 = session.createConsumer(queue);</code> + </pre> + + <li>Consume three messages from consumer2</li> + + <pre class="prettyprint"> + <code> + for (int i = 0; i < 3; i++) + { + TextMessage message = (TextMessage)consumer2.receive(2000); + + System.out.println("Consumed message from consumer2: " + message.getText()); + } + </code> + </pre> + + <li>Consume five messages from consumer1</li> + + <pre class="prettyprint"> + <code> + for (int i = 0; i < 5; i++) + { + TextMessage message = (TextMessage)consumer1.receive(2000); + + System.out.println("Consumed message from consumer1: " + message.getText()); + } + </code> + </pre> + + <li>Consume two more messages from consumer2</li> + + <pre class="prettyprint"> + <code> + for (int i = 0; i < 2; i++) + { + TextMessage message = (TextMessage)consumer1.receive(2000); + + System.out.println("Consumed message from consumer2: " + message.getText()); + } + </code> + </pre> + + + <li>Be sure to close our resources!</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#flow-control.consumer.window">Consumer Window-Based Flow Control chapter</a></li> + </ul> + + </body> +</html> http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/standard/no-consumer-buffering/src/main/java/org/apache/activemq/artemis/jms/example/NoConsumerBufferingExample.java ---------------------------------------------------------------------- diff --git a/examples/features/standard/no-consumer-buffering/src/main/java/org/apache/activemq/artemis/jms/example/NoConsumerBufferingExample.java b/examples/features/standard/no-consumer-buffering/src/main/java/org/apache/activemq/artemis/jms/example/NoConsumerBufferingExample.java new file mode 100644 index 0000000..6f321b0 --- /dev/null +++ b/examples/features/standard/no-consumer-buffering/src/main/java/org/apache/activemq/artemis/jms/example/NoConsumerBufferingExample.java @@ -0,0 +1,110 @@ +/* + * 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.Connection; +import javax.jms.ConnectionFactory; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Queue; +import javax.jms.Session; +import javax.jms.TextMessage; + +import org.apache.activemq.artemis.api.jms.ActiveMQJMSClient; +import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory; + +/** + * This example demonstrates how ActiveMQ Artemis consumers can be configured to not buffer any messages from + * the server. + */ +public class NoConsumerBufferingExample { + + public static void main(final String[] args) throws Exception { + Connection connection = null; + try { + // Step 2. Perfom a lookup on the queue + Queue queue = ActiveMQJMSClient.createQueue("exampleQueue"); + + // Step 3. new Connection factory with consumerWindowsize=0 + ConnectionFactory cf = new ActiveMQConnectionFactory("tcp://localhost:61616?consumerWindowSize=0"); + + // Step 4. Create a JMS Connection + connection = cf.createConnection(); + + // Step 5. Create a JMS Session + Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + + // Step 6. Create a JMS Message Producer + MessageProducer producer = session.createProducer(queue); + + // Step 7. Create a JMS MessageConsumer + + MessageConsumer consumer1 = session.createConsumer(queue); + + // Step 8. Start the connection + + connection.start(); + + // Step 9. Send 10 messages to the queue + + final int numMessages = 10; + + for (int i = 0; i < numMessages; i++) { + TextMessage message = session.createTextMessage("This is text message: " + i); + + producer.send(message); + } + + System.out.println("Sent messages"); + + // Step 10. Create another consumer on the same queue + + MessageConsumer consumer2 = session.createConsumer(queue); + + // Step 11. Consume three messages from consumer2 + + for (int i = 0; i < 3; i++) { + TextMessage message = (TextMessage) consumer2.receive(2000); + + System.out.println("Consumed message from consumer2: " + message.getText()); + } + + // Step 12. Consume five messages from consumer1 + + for (int i = 0; i < 5; i++) { + TextMessage message = (TextMessage) consumer1.receive(2000); + + System.out.println("Consumed message from consumer1: " + message.getText()); + } + + // Step 13. Consume another two messages from consumer2 + + for (int i = 0; i < 2; i++) { + TextMessage message = (TextMessage) consumer2.receive(2000); + + System.out.println("Consumed message from consumer1: " + message.getText()); + } + } + finally { + // Step 9. Be sure to close our resources! + + if (connection != null) { + connection.close(); + } + } + } +} http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/standard/no-consumer-buffering/src/main/resources/jndi.properties ---------------------------------------------------------------------- diff --git a/examples/features/standard/no-consumer-buffering/src/main/resources/jndi.properties b/examples/features/standard/no-consumer-buffering/src/main/resources/jndi.properties new file mode 100644 index 0000000..d9b77a6 --- /dev/null +++ b/examples/features/standard/no-consumer-buffering/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?consumerWindowSize=0 +queue.queue/exampleQueue=exampleQueue http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/standard/paging/pom.xml ---------------------------------------------------------------------- diff --git a/examples/features/standard/paging/pom.xml b/examples/features/standard/paging/pom.xml new file mode 100644 index 0000000..d78efc9 --- /dev/null +++ b/examples/features/standard/paging/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>paging</artifactId> + <packaging>jar</packaging> + <name>ActiveMQ Artemis JMS Paging 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.PagingExample</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>paging</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/paging/readme.html ---------------------------------------------------------------------- diff --git a/examples/features/standard/paging/readme.html b/examples/features/standard/paging/readme.html new file mode 100644 index 0000000..7c74320 --- /dev/null +++ b/examples/features/standard/paging/readme.html @@ -0,0 +1,187 @@ +<!-- +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 Paging 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>Paging 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 how ActiveMQ Artemis would avoid running out of memory resources by paging messages.</p> + <p>A maxSize can be specified per Destination via the destinations settings configuration file (broker.xml).</p> + <p>When messages routed to an address exceed the specified maxSize the server will begin to write messages to the file + system, this is called paging. This will continue to occur until messages have been delivered to consumers and subsequently + acknowledged freeing up memory. Messages will then be read from the file system , i.e. depaged, and routed as normal. </p> + <p>Acknowledgement plays an important factor on paging as messages will stay on the file system until the memory is released + so it is important to make sure that the client acknowledges its 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 connection factory object from JNDI</li> + <pre class="prettyprint"> + <code>ConnectionFactory cf = (ConnectionFactory) initialContext.lookup("/ConnectionFactory");</code> + </pre> + + <li>We look-up the JMS queue object from JNDI. pagingQueue is configured to hold a very limited number of bytes in memory</li> + <pre class="prettyprint"> + <code>Queue pageQueue = (Queue) initialContext.lookup("/queue/pagingQueue");</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 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. We will use client acknowledgement on this example.</li> + <pre class="prettyprint"> + <code>Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);</code> + </pre> + + + <li>Create a JMS Message Producer for pageQueueAddress</li> + <pre class="prettyprint"><code> + MessageProducer pageMessageProducer = session.createProducer(pageQueue); + </pre></code> + + <li>We don't need persistent messages in order to use paging. (This step is optional)</li> + <pre class="prettyprint"><code> + pageMessageProducer.setDeliveryMode(DeliveryMode.NON_PERSISTENT); + </pre></code> + + <li>Create a Binary Bytes Message with 10K arbitrary bytes</li> + <pre class="prettyprint"><code> + BytesMessage message = session.createBytesMessage(); + message.writeBytes(new byte[10 * 1024]); + </pre></code> + + + <li>Send only 20 messages to the Queue. This will be already enough for pagingQueue. Look at ./paging/config/activemq-queues.xml for the config.</li> + <pre class="prettyprint"><code> + for (int i = 0; i < 20; i++) + { + pageMessageProducer.send(message); + } + </pre></code> + + <li>Create a JMS Message Producer</li> + <pre class="prettyprint"><code> + MessageProducer messageProducer = session.createProducer(queue); + </pre></code> + + <li>We don't need persistent messages in order to use paging. (This step is optional)</li> + <pre class="prettyprint"><code> + messageProducer.setDeliveryMode(DeliveryMode.NON_PERSISTENT); + </pre></code> + + <li>Send the message for about 30K, which should be over the memory limit imposed by the server</li> + <pre class="prettyprint"><code> + for (int i = 0; i < 30000; i++) + { + messageProducer.send(message); + } + </pre></code> + + <li>if you pause the example here, you will several files under ./build/data/paging</li> + + <pre class="prettyprint"><code> + // Thread.sleep(30000); // if you want to just our of curiosity, you can sleep here and inspect the created files just for + </pre></code> + + + <li>Create a JMS Message Consumer</li> + <pre class="prettyprint"><code> + MessageConsumer messageConsumer = session.createConsumer(queue); + </pre></code> + + + <li>Start the JMS Connection. This step will activate the subscribers to receive messages.</li> + <pre class="prettyprint"><code> + connection.start(); + </pre></code> + + + <li>Receive the messages. It's important to ACK for messages as ActiveMQ Artemis will not read messages from paging until messages are ACKed</li> + + <pre class="prettyprint"><code> + for (int i = 0; i < 30000; i++) + { + message = (BytesMessage)messageConsumer.receive(1000); + + if (i % 1000 == 0) + { + System.out.println("Received " + i + " messages"); + + message.acknowledge(); + } + } + </pre></code> + + <li>Receive the messages from the Queue names pageQueue. Create the proper consumer for that.</li> + <pre class="prettyprint"><code> + messageConsumer.close(); + messageConsumer = session.createConsumer(pageQueue); + + for (int i = 0; i < 20; i++) + { + message = (BytesMessage)messageConsumer.receive(1000); + + System.out.println("Received message " + i + " from pageQueue"); + + message.acknowledge(); + } + </pre></code> + + <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> + </body> +</html> http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/standard/paging/src/main/java/org/apache/activemq/artemis/jms/example/PagingExample.java ---------------------------------------------------------------------- diff --git a/examples/features/standard/paging/src/main/java/org/apache/activemq/artemis/jms/example/PagingExample.java b/examples/features/standard/paging/src/main/java/org/apache/activemq/artemis/jms/example/PagingExample.java new file mode 100644 index 0000000..19d8a17 --- /dev/null +++ b/examples/features/standard/paging/src/main/java/org/apache/activemq/artemis/jms/example/PagingExample.java @@ -0,0 +1,135 @@ +/* + * 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.BytesMessage; +import javax.jms.Connection; +import javax.jms.ConnectionFactory; +import javax.jms.DeliveryMode; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Queue; +import javax.jms.Session; +import javax.naming.InitialContext; + +/** + * A simple JMS Queue example that creates a producer and consumer on a queue and sends then receives a message. + */ +public class PagingExample { + + 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 Connection Factory + ConnectionFactory cf = (ConnectionFactory) initialContext.lookup("ConnectionFactory"); + + // Step 3. We look-up the JMS queue object from JNDI. pagingQueue is configured to hold a very limited number + // of bytes in memory + Queue pageQueue = (Queue) initialContext.lookup("queue/pagingQueue"); + + // Step 4. Lookup for a JMS Queue + Queue queue = (Queue) initialContext.lookup("queue/exampleQueue"); + + // Step 5. Create a JMS Connection + connection = cf.createConnection(); + + // Step 6. Create a JMS Session + Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE); + + // Step 7. Create a JMS Message Producer for pageQueueAddress + MessageProducer pageMessageProducer = session.createProducer(pageQueue); + + // Step 8. We don't need persistent messages in order to use paging. (This step is optional) + pageMessageProducer.setDeliveryMode(DeliveryMode.NON_PERSISTENT); + + // Step 9. Create a Binary Bytes Message with 10K arbitrary bytes + BytesMessage message = session.createBytesMessage(); + message.writeBytes(new byte[10 * 1024]); + + // Step 10. Send only 20 messages to the Queue. This will be already enough for pagingQueue. Look at + // ./paging/config/activemq-queues.xml for the config. + for (int i = 0; i < 20; i++) { + pageMessageProducer.send(message); + } + + // Step 11. Create a JMS Message Producer + MessageProducer messageProducer = session.createProducer(queue); + + // Step 12. We don't need persistent messages in order to use paging. (This step is optional) + messageProducer.setDeliveryMode(DeliveryMode.NON_PERSISTENT); + + // Step 13. Send the message for about 1K, which should be over the memory limit imposed by the server + for (int i = 0; i < 1000; i++) { + messageProducer.send(message); + } + + // Step 14. if you pause this example here, you will see several files under ./build/data/paging + // Thread.sleep(30000); // if you want to just our of curiosity, you can sleep here and inspect the created + // files just for + + // Step 15. Create a JMS Message Consumer + MessageConsumer messageConsumer = session.createConsumer(queue); + + // Step 16. Start the JMS Connection. This step will activate the subscribers to receive messages. + connection.start(); + + // Step 17. Receive the messages. It's important to ACK for messages as ActiveMQ Artemis will not read messages from + // paging + // until messages are ACKed + + for (int i = 0; i < 1000; i++) { + message = (BytesMessage) messageConsumer.receive(3000); + + if (i % 100 == 0) { + System.out.println("Received " + i + " messages"); + message.acknowledge(); + } + } + + message.acknowledge(); + + // Step 18. Receive the messages from the Queue names pageQueue. Create the proper consumer for that + messageConsumer.close(); + messageConsumer = session.createConsumer(pageQueue); + + for (int i = 0; i < 20; i++) { + message = (BytesMessage) messageConsumer.receive(1000); + + System.out.println("Received message " + i + " from pageQueue"); + + message.acknowledge(); + } + } + finally { + // And finally, always remember to close your JMS connections after use, in a finally block. Closing a JMS + // connection will automatically close all of its sessions, consumers, producer and browser objects + + 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/paging/src/main/resources/activemq/server0/artemis-roles.properties ---------------------------------------------------------------------- diff --git a/examples/features/standard/paging/src/main/resources/activemq/server0/artemis-roles.properties b/examples/features/standard/paging/src/main/resources/activemq/server0/artemis-roles.properties new file mode 100644 index 0000000..4e2d44c --- /dev/null +++ b/examples/features/standard/paging/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/paging/src/main/resources/activemq/server0/artemis-users.properties ---------------------------------------------------------------------- diff --git a/examples/features/standard/paging/src/main/resources/activemq/server0/artemis-users.properties b/examples/features/standard/paging/src/main/resources/activemq/server0/artemis-users.properties new file mode 100644 index 0000000..4e2d44c --- /dev/null +++ b/examples/features/standard/paging/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/paging/src/main/resources/activemq/server0/broker.xml ---------------------------------------------------------------------- diff --git a/examples/features/standard/paging/src/main/resources/activemq/server0/broker.xml b/examples/features/standard/paging/src/main/resources/activemq/server0/broker.xml new file mode 100644 index 0000000..a7a1969 --- /dev/null +++ b/examples/features/standard/paging/src/main/resources/activemq/server0/broker.xml @@ -0,0 +1,93 @@ +<?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 topic used by the example--> + <queue name="exampleQueue"/> + + <queue name="pagingQueue"/> + </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> + + + <!-- Connectors --> + <connectors> + <connector name="netty-connector">tcp://localhost:61616</connector> + </connectors> + + <!-- 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-setting match="jms.queue.pagingQueue"> + <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> + <address-setting match="jms.queue.pagingQueue"> + <max-size-bytes>100000</max-size-bytes> + <page-size-bytes>20000</page-size-bytes> + </address-setting> + + <address-setting match="jms.queue.exampleQueue"> + <max-size-bytes>10485760</max-size-bytes> + <page-size-bytes>1048576</page-size-bytes> + </address-setting> + <address-setting match="#"> + <max-size-bytes>10485760</max-size-bytes> + <page-size-bytes>1048576</page-size-bytes> + </address-setting> + </address-settings> + + </core> +</configuration>