You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by cl...@apache.org on 2015/08/13 06:13:20 UTC

[02/48] activemq-artemis git commit: renaming broker-features -> features on examples

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/standard/xa-heuristic/readme.html
----------------------------------------------------------------------
diff --git a/examples/features/standard/xa-heuristic/readme.html b/examples/features/standard/xa-heuristic/readme.html
new file mode 100644
index 0000000..bf44937
--- /dev/null
+++ b/examples/features/standard/xa-heuristic/readme.html
@@ -0,0 +1,48 @@
+<!--
+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 XA Heuristic 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 XA Heuristic 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 make an XA heuristic decision through the ActiveMQ Artemis Management Interface.</p>
+
+     <p>A heuristic decision is a unilateral decision to commit or rollback an XA transaction branch after it has
+     been prepared. </p>
+
+     <p>In this example we simulate a transaction manager to control the transactions. First we create an XASession
+     and enlist it in a transaction through its XAResource. We then send a text message, 'hello' and end/prepare the transaction
+     on the XAResource, but neither commit nor roll back the transaction. Another transaction is created and
+     associated with the same XAResource, and a second message, 'world' is sent on behalf of the second transaction. Again we leave
+     the second transaction in prepare state.
+     Then we get the MBeanServerConnection object to manipulate the prepared transactions. To illustrate, we roll back the first
+     transaction but commit the second. This will result in that only the message 'world' is received. </p>
+
+     <p>This example uses JMX to manipulate transactions in a ActiveMQ Artemis Server. For details on JMX facilities with ActiveMQ Artemis,
+     please look at the JMX Example.</p>
+  </body>
+</html>

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/standard/xa-heuristic/src/main/java/org/apache/activemq/artemis/jms/example/DummyXid.java
----------------------------------------------------------------------
diff --git a/examples/features/standard/xa-heuristic/src/main/java/org/apache/activemq/artemis/jms/example/DummyXid.java b/examples/features/standard/xa-heuristic/src/main/java/org/apache/activemq/artemis/jms/example/DummyXid.java
new file mode 100644
index 0000000..8b6be80
--- /dev/null
+++ b/examples/features/standard/xa-heuristic/src/main/java/org/apache/activemq/artemis/jms/example/DummyXid.java
@@ -0,0 +1,184 @@
+/*
+ * 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.transaction.xa.Xid;
+
+import org.apache.activemq.artemis.utils.Base64;
+
+public class DummyXid implements Xid {
+
+   private static final long serialVersionUID = 407053232840068514L;
+
+   private final byte[] branchQualifier;
+
+   private final int formatId;
+
+   private final byte[] globalTransactionId;
+
+   private int hash;
+
+   private boolean hashCalculated;
+
+   // Static --------------------------------------------------------
+
+   public static String toBase64String(final Xid xid) {
+      return Base64.encodeBytes(DummyXid.toByteArray(xid));
+   }
+
+   private static byte[] toByteArray(final Xid xid) {
+      byte[] branchQualifier = xid.getBranchQualifier();
+      byte[] globalTransactionId = xid.getGlobalTransactionId();
+      int formatId = xid.getFormatId();
+
+      byte[] hashBytes = new byte[branchQualifier.length + globalTransactionId.length + 4];
+      System.arraycopy(branchQualifier, 0, hashBytes, 0, branchQualifier.length);
+      System.arraycopy(globalTransactionId, 0, hashBytes, branchQualifier.length, globalTransactionId.length);
+      byte[] intBytes = new byte[4];
+      for (int i = 0; i < 4; i++) {
+         intBytes[i] = (byte) ((formatId >> i * 8) % 0xFF);
+      }
+      System.arraycopy(intBytes, 0, hashBytes, branchQualifier.length + globalTransactionId.length, 4);
+      return hashBytes;
+   }
+
+   // Constructors --------------------------------------------------
+
+   /**
+    * Standard constructor
+    *
+    * @param branchQualifier
+    * @param formatId
+    * @param globalTransactionId
+    */
+   public DummyXid(final byte[] branchQualifier, final int formatId, final byte[] globalTransactionId) {
+      this.branchQualifier = branchQualifier;
+      this.formatId = formatId;
+      this.globalTransactionId = globalTransactionId;
+   }
+
+   /**
+    * Copy constructor
+    *
+    * @param other
+    */
+   public DummyXid(final Xid other) {
+      branchQualifier = copyBytes(other.getBranchQualifier());
+      formatId = other.getFormatId();
+      globalTransactionId = copyBytes(other.getGlobalTransactionId());
+   }
+
+   // Xid implementation ------------------------------------------------------------------
+
+   public byte[] getBranchQualifier() {
+      return branchQualifier;
+   }
+
+   public int getFormatId() {
+      return formatId;
+   }
+
+   public byte[] getGlobalTransactionId() {
+      return globalTransactionId;
+   }
+
+   // Public -------------------------------------------------------------------------------
+
+   @Override
+   public int hashCode() {
+      if (!hashCalculated) {
+         calcHash();
+      }
+      return hash;
+   }
+
+   @Override
+   public boolean equals(final Object other) {
+      if (this == other) {
+         return true;
+      }
+      if (!(other instanceof Xid)) {
+         return false;
+      }
+      Xid xother = (Xid) other;
+      if (xother.getFormatId() != formatId) {
+         return false;
+      }
+      if (xother.getBranchQualifier().length != branchQualifier.length) {
+         return false;
+      }
+      if (xother.getGlobalTransactionId().length != globalTransactionId.length) {
+         return false;
+      }
+      for (int i = 0; i < branchQualifier.length; i++) {
+         byte[] otherBQ = xother.getBranchQualifier();
+         if (branchQualifier[i] != otherBQ[i]) {
+            return false;
+         }
+      }
+      for (int i = 0; i < globalTransactionId.length; i++) {
+         byte[] otherGtx = xother.getGlobalTransactionId();
+         if (globalTransactionId[i] != otherGtx[i]) {
+            return false;
+         }
+      }
+      return true;
+   }
+
+   @Override
+   public String toString() {
+      return "XidImpl (" + System.identityHashCode(this) +
+         " bq:" +
+         stringRep(branchQualifier) +
+         " formatID:" +
+         formatId +
+         " gtxid:" +
+         stringRep(globalTransactionId);
+   }
+
+   // Private -------------------------------------------------------------------------------
+
+   private String stringRep(final byte[] bytes) {
+      StringBuilder buff = new StringBuilder();
+      for (int i = 0; i < bytes.length; i++) {
+         byte b = bytes[i];
+
+         buff.append(b);
+
+         if (i != bytes.length - 1) {
+            buff.append('.');
+         }
+      }
+
+      return buff.toString();
+   }
+
+   private void calcHash() {
+      byte[] hashBytes = org.apache.activemq.artemis.jms.example.DummyXid.toByteArray(this);
+      String s = new String(hashBytes);
+      hash = s.hashCode();
+      hashCalculated = true;
+   }
+
+   private byte[] copyBytes(final byte[] other) {
+      byte[] bytes = new byte[other.length];
+
+      System.arraycopy(other, 0, bytes, 0, other.length);
+
+      return bytes;
+   }
+}

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/standard/xa-heuristic/src/main/java/org/apache/activemq/artemis/jms/example/XAHeuristicExample.java
----------------------------------------------------------------------
diff --git a/examples/features/standard/xa-heuristic/src/main/java/org/apache/activemq/artemis/jms/example/XAHeuristicExample.java b/examples/features/standard/xa-heuristic/src/main/java/org/apache/activemq/artemis/jms/example/XAHeuristicExample.java
new file mode 100644
index 0000000..d233731
--- /dev/null
+++ b/examples/features/standard/xa-heuristic/src/main/java/org/apache/activemq/artemis/jms/example/XAHeuristicExample.java
@@ -0,0 +1,219 @@
+/*
+ * 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.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 javax.jms.XAConnection;
+import javax.jms.XAConnectionFactory;
+import javax.jms.XASession;
+import javax.management.MBeanServerConnection;
+import javax.management.ObjectName;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXServiceURL;
+import javax.naming.InitialContext;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import org.apache.activemq.artemis.api.core.management.ObjectNameBuilder;
+import org.apache.activemq.artemis.utils.UUIDGenerator;
+
+/**
+ * A simple JMS example showing how to administer un-finished transactions.
+ */
+public class XAHeuristicExample {
+
+   private static final String JMX_URL = "service:jmx:rmi:///jndi/rmi://localhost:3001/jmxrmi";
+
+   public static void main(final String[] args) throws Exception {
+      Boolean result = true;
+      final ArrayList<String> receiveHolder = new ArrayList<String>();
+      XAConnection connection = null;
+      InitialContext initialContext = null;
+      try {
+         // Step 1. Create an initial context to perform the JNDI lookup.
+         initialContext = new InitialContext();
+
+         // Step 2. Lookup on the queue
+         Queue queue = (Queue) initialContext.lookup("queue/exampleQueue");
+
+         // Step 3. Perform a lookup on the XA Connection Factory
+         XAConnectionFactory cf = (XAConnectionFactory) initialContext.lookup("XAConnectionFactory");
+
+         // Step 4.Create a JMS XAConnection
+         connection = cf.createXAConnection();
+
+         // Step 5. Start the connection
+         connection.start();
+
+         // Step 6. Create a JMS XASession
+         XASession xaSession = connection.createXASession();
+
+         // Step 7. Create a normal session
+         Session normalSession = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+         // Step 8. Create a normal Message Consumer
+         MessageConsumer normalConsumer = normalSession.createConsumer(queue);
+         normalConsumer.setMessageListener(new SimpleMessageListener(receiveHolder, result));
+
+         // Step 9. Get the JMS Session
+         Session session = xaSession.getSession();
+
+         // Step 10. Create a message producer
+         MessageProducer producer = session.createProducer(queue);
+
+         // Step 11. Create two Text Messages
+         TextMessage helloMessage = session.createTextMessage("hello");
+         TextMessage worldMessage = session.createTextMessage("world");
+
+         // Step 12. create a transaction
+         Xid xid1 = new DummyXid("xa-example1".getBytes(StandardCharsets.ISO_8859_1), 1, UUIDGenerator.getInstance().generateStringUUID().getBytes());
+
+         // Step 13. Get the JMS XAResource
+         XAResource xaRes = xaSession.getXAResource();
+
+         // Step 14. Begin the Transaction work
+         xaRes.start(xid1, XAResource.TMNOFLAGS);
+
+         // Step 15. do work, sending hello message.
+         producer.send(helloMessage);
+
+         System.out.println("Sent message " + helloMessage.getText());
+
+         // Step 16. Stop the work for xid1
+         xaRes.end(xid1, XAResource.TMSUCCESS);
+
+         // Step 17. Prepare xid1
+         xaRes.prepare(xid1);
+
+         // Step 18. Check none should be received
+         checkNoMessageReceived(receiveHolder);
+
+         // Step 19. Create another transaction.
+         Xid xid2 = new DummyXid("xa-example2".getBytes(), 1, UUIDGenerator.getInstance().generateStringUUID().getBytes());
+
+         // Step 20. Begin the transaction work
+         xaRes.start(xid2, XAResource.TMNOFLAGS);
+
+         // Step 21. Send the second message
+         producer.send(worldMessage);
+
+         System.out.println("Sent message " + worldMessage.getText());
+
+         // Step 22. Stop the work for xid2
+         xaRes.end(xid2, XAResource.TMSUCCESS);
+
+         // Step 23. prepare xid2
+         xaRes.prepare(xid2);
+
+         // Step 24. Again, no messages should be received!
+         checkNoMessageReceived(receiveHolder);
+
+         // Step 25. Create JMX Connector to connect to the server's MBeanServer
+         JMXConnector connector = JMXConnectorFactory.connect(new JMXServiceURL(JMX_URL), new HashMap<String, String>());
+
+         // Step 26. Retrieve the MBeanServerConnection
+         MBeanServerConnection mbsc = connector.getMBeanServerConnection();
+
+         // Step 27. List the prepared transactions
+         ObjectName serverObject = ObjectNameBuilder.DEFAULT.getActiveMQServerObjectName();
+         String[] infos = (String[]) mbsc.invoke(serverObject, "listPreparedTransactions", null, null);
+
+         System.out.println("Prepared transactions: ");
+         for (String i : infos) {
+            System.out.println(i);
+         }
+
+         // Step 28. Roll back the first transaction
+         mbsc.invoke(serverObject, "rollbackPreparedTransaction", new String[]{DummyXid.toBase64String(xid1)}, new String[]{"java.lang.String"});
+
+         // Step 29. Commit the second one
+         mbsc.invoke(serverObject, "commitPreparedTransaction", new String[]{DummyXid.toBase64String(xid2)}, new String[]{"java.lang.String"});
+
+         Thread.sleep(2000);
+
+         // Step 30. Check the result, only the 'world' message received
+         checkMessageReceived("world", receiveHolder);
+
+         // Step 31. Check the prepared transaction again, should have none.
+         infos = (String[]) mbsc.invoke(serverObject, "listPreparedTransactions", null, null);
+         System.out.println("No. of prepared transactions now: " + infos.length);
+
+         // Step 32. Close the JMX Connector
+         connector.close();
+      }
+      finally {
+         // Step 32. Be sure to close our JMS resources!
+         if (initialContext != null) {
+            initialContext.close();
+         }
+         if (connection != null) {
+            connection.close();
+         }
+      }
+   }
+
+   private static void checkMessageReceived(final String value, ArrayList<String> receiveHolder) {
+      if (receiveHolder.size() != 1) {
+         throw new IllegalStateException("Number of messages received not correct ! -- " + receiveHolder.size());
+      }
+      String msg = receiveHolder.get(0);
+      if (!msg.equals(value)) {
+         throw new IllegalStateException("Received message [" + msg + "], but we expect [" + value + "]");
+      }
+      receiveHolder.clear();
+   }
+
+   private static void checkNoMessageReceived(ArrayList<String> receiveHolder) {
+      if (receiveHolder.size() > 0) {
+         throw new IllegalStateException("Message received, wrong!");
+      }
+      receiveHolder.clear();
+   }
+}
+
+class SimpleMessageListener implements MessageListener {
+
+   ArrayList<String> receiveHolder;
+   Boolean result;
+
+   SimpleMessageListener(ArrayList<String> receiveHolder, Boolean result) {
+      this.receiveHolder = receiveHolder;
+      this.result = result;
+   }
+
+   public void onMessage(final Message message) {
+      try {
+         System.out.println("Message received: " + ((TextMessage) message).getText());
+         receiveHolder.add(((TextMessage) message).getText());
+      }
+      catch (JMSException e) {
+         result = false;
+         e.printStackTrace();
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/standard/xa-heuristic/src/main/resources/jndi.properties
----------------------------------------------------------------------
diff --git a/examples/features/standard/xa-heuristic/src/main/resources/jndi.properties b/examples/features/standard/xa-heuristic/src/main/resources/jndi.properties
new file mode 100644
index 0000000..77561f7
--- /dev/null
+++ b/examples/features/standard/xa-heuristic/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
+connectionFactory.XAConnectionFactory=tcp://localhost:61616?type=XA_CF
+queue.queue/exampleQueue=exampleQueue

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/standard/xa-receive/pom.xml
----------------------------------------------------------------------
diff --git a/examples/features/standard/xa-receive/pom.xml b/examples/features/standard/xa-receive/pom.xml
new file mode 100644
index 0000000..f421aaf
--- /dev/null
+++ b/examples/features/standard/xa-receive/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>xa-receive</artifactId>
+   <packaging>jar</packaging>
+   <name>ActiveMQ Artemis JMS XA Receive 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.XAReceiveExample</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>xa-receive</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/xa-receive/readme.html
----------------------------------------------------------------------
diff --git a/examples/features/standard/xa-receive/readme.html b/examples/features/standard/xa-receive/readme.html
new file mode 100644
index 0000000..ab6d7d7
--- /dev/null
+++ b/examples/features/standard/xa-receive/readme.html
@@ -0,0 +1,48 @@
+<!--
+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 XA Receive 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 XA Receive 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 demonstrates receiving a message within the scope of an XA transaction. When using an XA transaction
+         the message will only be acknowledged and removed from the queue when the transaction is committed.
+     If the transaction is not committed the message maybe redelivered after rollback or during XA recovery.</p>
+
+     <p>ActiveMQ Artemis is JTA aware, meaning you can use ActiveMQ Artemis in an XA transactional environment
+     and participate in XA transactions. It provides the javax.transaction.xa.XAResource interface for that
+     purpose. Users can get a XAConnectionFactory to create XAConnections and XASessions.</p>
+
+     <p>In this example we simulate a transaction manager to control the transactions. First we create an XASession
+      for receiving and a normal session for sending. Then we start a new xa transaction and enlist the receiving
+      XASession through its XAResource. We then send two words, 'hello' and 'world', receive them, and let the
+      transaction roll back. The received messages are cancelled back to the queue. Next we start
+      a new transaction with the same XAResource enlisted, but this time we commit the transaction after receiving the
+      messages. Then we check that no more messages are to be received.</p>
+  </body>
+</html>

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/standard/xa-receive/src/main/java/org/apache/activemq/artemis/jms/example/DummyXid.java
----------------------------------------------------------------------
diff --git a/examples/features/standard/xa-receive/src/main/java/org/apache/activemq/artemis/jms/example/DummyXid.java b/examples/features/standard/xa-receive/src/main/java/org/apache/activemq/artemis/jms/example/DummyXid.java
new file mode 100644
index 0000000..4dbe2f8
--- /dev/null
+++ b/examples/features/standard/xa-receive/src/main/java/org/apache/activemq/artemis/jms/example/DummyXid.java
@@ -0,0 +1,184 @@
+/*
+ * 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 org.apache.activemq.artemis.utils.Base64;
+
+import javax.transaction.xa.Xid;
+
+public class DummyXid implements Xid {
+
+   private static final long serialVersionUID = 407053232840068514L;
+
+   private final byte[] branchQualifier;
+
+   private final int formatId;
+
+   private final byte[] globalTransactionId;
+
+   private int hash;
+
+   private boolean hashCalculated;
+
+   // Static --------------------------------------------------------
+
+   public static String toBase64String(final Xid xid) {
+      return Base64.encodeBytes(DummyXid.toByteArray(xid));
+   }
+
+   private static byte[] toByteArray(final Xid xid) {
+      byte[] branchQualifier = xid.getBranchQualifier();
+      byte[] globalTransactionId = xid.getGlobalTransactionId();
+      int formatId = xid.getFormatId();
+
+      byte[] hashBytes = new byte[branchQualifier.length + globalTransactionId.length + 4];
+      System.arraycopy(branchQualifier, 0, hashBytes, 0, branchQualifier.length);
+      System.arraycopy(globalTransactionId, 0, hashBytes, branchQualifier.length, globalTransactionId.length);
+      byte[] intBytes = new byte[4];
+      for (int i = 0; i < 4; i++) {
+         intBytes[i] = (byte) ((formatId >> i * 8) % 0xFF);
+      }
+      System.arraycopy(intBytes, 0, hashBytes, branchQualifier.length + globalTransactionId.length, 4);
+      return hashBytes;
+   }
+
+   // Constructors --------------------------------------------------
+
+   /**
+    * Standard constructor
+    *
+    * @param branchQualifier
+    * @param formatId
+    * @param globalTransactionId
+    */
+   public DummyXid(final byte[] branchQualifier, final int formatId, final byte[] globalTransactionId) {
+      this.branchQualifier = branchQualifier;
+      this.formatId = formatId;
+      this.globalTransactionId = globalTransactionId;
+   }
+
+   /**
+    * Copy constructor
+    *
+    * @param other
+    */
+   public DummyXid(final Xid other) {
+      branchQualifier = copyBytes(other.getBranchQualifier());
+      formatId = other.getFormatId();
+      globalTransactionId = copyBytes(other.getGlobalTransactionId());
+   }
+
+   // Xid implementation ------------------------------------------------------------------
+
+   public byte[] getBranchQualifier() {
+      return branchQualifier;
+   }
+
+   public int getFormatId() {
+      return formatId;
+   }
+
+   public byte[] getGlobalTransactionId() {
+      return globalTransactionId;
+   }
+
+   // Public -------------------------------------------------------------------------------
+
+   @Override
+   public int hashCode() {
+      if (!hashCalculated) {
+         calcHash();
+      }
+      return hash;
+   }
+
+   @Override
+   public boolean equals(final Object other) {
+      if (this == other) {
+         return true;
+      }
+      if (!(other instanceof Xid)) {
+         return false;
+      }
+      Xid xother = (Xid) other;
+      if (xother.getFormatId() != formatId) {
+         return false;
+      }
+      if (xother.getBranchQualifier().length != branchQualifier.length) {
+         return false;
+      }
+      if (xother.getGlobalTransactionId().length != globalTransactionId.length) {
+         return false;
+      }
+      for (int i = 0; i < branchQualifier.length; i++) {
+         byte[] otherBQ = xother.getBranchQualifier();
+         if (branchQualifier[i] != otherBQ[i]) {
+            return false;
+         }
+      }
+      for (int i = 0; i < globalTransactionId.length; i++) {
+         byte[] otherGtx = xother.getGlobalTransactionId();
+         if (globalTransactionId[i] != otherGtx[i]) {
+            return false;
+         }
+      }
+      return true;
+   }
+
+   @Override
+   public String toString() {
+      return "XidImpl (" + System.identityHashCode(this) +
+         " bq:" +
+         stringRep(branchQualifier) +
+         " formatID:" +
+         formatId +
+         " gtxid:" +
+         stringRep(globalTransactionId);
+   }
+
+   // Private -------------------------------------------------------------------------------
+
+   private String stringRep(final byte[] bytes) {
+      StringBuilder buff = new StringBuilder();
+      for (int i = 0; i < bytes.length; i++) {
+         byte b = bytes[i];
+
+         buff.append(b);
+
+         if (i != bytes.length - 1) {
+            buff.append('.');
+         }
+      }
+
+      return buff.toString();
+   }
+
+   private void calcHash() {
+      byte[] hashBytes = DummyXid.toByteArray(this);
+      String s = new String(hashBytes);
+      hash = s.hashCode();
+      hashCalculated = true;
+   }
+
+   private byte[] copyBytes(final byte[] other) {
+      byte[] bytes = new byte[other.length];
+
+      System.arraycopy(other, 0, bytes, 0, other.length);
+
+      return bytes;
+   }
+}

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/standard/xa-receive/src/main/java/org/apache/activemq/artemis/jms/example/XAReceiveExample.java
----------------------------------------------------------------------
diff --git a/examples/features/standard/xa-receive/src/main/java/org/apache/activemq/artemis/jms/example/XAReceiveExample.java b/examples/features/standard/xa-receive/src/main/java/org/apache/activemq/artemis/jms/example/XAReceiveExample.java
new file mode 100644
index 0000000..4c4448d
--- /dev/null
+++ b/examples/features/standard/xa-receive/src/main/java/org/apache/activemq/artemis/jms/example/XAReceiveExample.java
@@ -0,0 +1,145 @@
+/*
+ * 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.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Queue;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+import javax.jms.XAConnection;
+import javax.jms.XAConnectionFactory;
+import javax.jms.XASession;
+import javax.naming.InitialContext;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+import java.nio.charset.StandardCharsets;
+
+import org.apache.activemq.artemis.utils.UUIDGenerator;
+
+/**
+ * A simple JMS example showing the usage of XA support in JMS.
+ */
+public class XAReceiveExample {
+
+   public static void main(final String[] args) throws Exception {
+      XAConnection connection = null;
+      InitialContext initialContext = null;
+      try {
+         // Step 1. Create an initial context to perform the JNDI lookup.
+         initialContext = new InitialContext();
+
+         // Step 2. Lookup on the queue
+         Queue queue = (Queue) initialContext.lookup("queue/exampleQueue");
+
+         // Step 3. Perform a lookup on the XA Connection Factory
+         XAConnectionFactory cf = (XAConnectionFactory) initialContext.lookup("XAConnectionFactory");
+
+         // Step 4.Create a JMS XAConnection
+         connection = cf.createXAConnection();
+
+         // Step 5. Start the connection
+         connection.start();
+
+         // Step 6. Create a JMS XASession
+         XASession xaSession = connection.createXASession();
+
+         // Step 7. Create a normal session
+         Session normalSession = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+         // Step 8. Create a normal Message Producer
+         MessageProducer normalProducer = normalSession.createProducer(queue);
+
+         // Step 9. Get the JMS Session
+         Session session = xaSession.getSession();
+
+         // Step 10. Create a message consumer
+         MessageConsumer xaConsumer = session.createConsumer(queue);
+
+         // Step 11. Create two Text Messages
+         TextMessage helloMessage = session.createTextMessage("hello");
+         TextMessage worldMessage = session.createTextMessage("world");
+
+         // Step 12. create a transaction
+         Xid xid1 = new DummyXid("xa-example1".getBytes(StandardCharsets.US_ASCII), 1, UUIDGenerator.getInstance().generateStringUUID().getBytes());
+
+         // Step 13. Get the JMS XAResource
+         XAResource xaRes = xaSession.getXAResource();
+
+         // Step 14. Begin the Transaction work
+         xaRes.start(xid1, XAResource.TMNOFLAGS);
+
+         // Step 15. Send two messages.
+         normalProducer.send(helloMessage);
+         normalProducer.send(worldMessage);
+
+         // Step 16. Receive the message
+         TextMessage rm1 = (TextMessage) xaConsumer.receive();
+         System.out.println("Message received: " + rm1.getText());
+         TextMessage rm2 = (TextMessage) xaConsumer.receive();
+         System.out.println("Message received: " + rm2.getText());
+
+         // Step 17. Stop the work
+         xaRes.end(xid1, XAResource.TMSUCCESS);
+
+         // Step 18. Prepare
+         xaRes.prepare(xid1);
+
+         // Step 19. Roll back the transaction
+         xaRes.rollback(xid1);
+
+         // Step 20. Create another transaction
+         Xid xid2 = new DummyXid("xa-example2".getBytes(), 1, UUIDGenerator.getInstance().generateStringUUID().getBytes());
+
+         // Step 21. Start the transaction
+         xaRes.start(xid2, XAResource.TMNOFLAGS);
+
+         // Step 22. receive those messages again
+         rm1 = (TextMessage) xaConsumer.receive();
+         System.out.println("Message received again: " + rm1.getText());
+         rm2 = (TextMessage) xaConsumer.receive();
+         System.out.println("Message received again: " + rm2.getText());
+
+         // Step 23. Stop the work
+         xaRes.end(xid2, XAResource.TMSUCCESS);
+
+         // Step 24. Prepare
+         xaRes.prepare(xid2);
+
+         // Step 25. Commit!
+         xaRes.commit(xid2, false);
+
+         // Step 26. Check no more messages are received.
+         TextMessage rm3 = (TextMessage) xaConsumer.receive(2000);
+         if (rm3 == null) {
+            System.out.println("No message received after commit.");
+         }
+         else {
+            throw new IllegalStateException();
+         }
+      }
+      finally {
+         // Step 27. Be sure to close our JMS 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/xa-receive/src/main/resources/jndi.properties
----------------------------------------------------------------------
diff --git a/examples/features/standard/xa-receive/src/main/resources/jndi.properties b/examples/features/standard/xa-receive/src/main/resources/jndi.properties
new file mode 100644
index 0000000..77561f7
--- /dev/null
+++ b/examples/features/standard/xa-receive/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
+connectionFactory.XAConnectionFactory=tcp://localhost:61616?type=XA_CF
+queue.queue/exampleQueue=exampleQueue

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/standard/xa-send/pom.xml
----------------------------------------------------------------------
diff --git a/examples/features/standard/xa-send/pom.xml b/examples/features/standard/xa-send/pom.xml
new file mode 100644
index 0000000..b4dfdf4
--- /dev/null
+++ b/examples/features/standard/xa-send/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>xa-send</artifactId>
+   <packaging>jar</packaging>
+   <name>ActiveMQ Artemis JMS XA Send 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.XASendExample</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>xa-send</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/xa-send/readme.html
----------------------------------------------------------------------
diff --git a/examples/features/standard/xa-send/readme.html b/examples/features/standard/xa-send/readme.html
new file mode 100644
index 0000000..fb3db4c
--- /dev/null
+++ b/examples/features/standard/xa-send/readme.html
@@ -0,0 +1,215 @@
+<!--
+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 XA Send 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 XA Send Example</h1>
+     <p>This example shows you how message sending behaves in an XA transaction in ActiveMQ Artemis. When a message is sent within
+         the scope of an XA transaction, it will only reach the queue once the transaction is committed.
+     If the transaction is rolled back the sent messages will be discarded by the server.</p>
+
+     <p>ActiveMQ Artemis is JTA aware, meaning you can use ActiveMQ Artemis in a XA transactional environment
+     and participate in XA transactions. It provides the javax.transaction.xa.XAResource interface for that
+     purpose. Users can get a XAConnectionFactory to create XAConnections and XASessions.</p>
+
+     <p>In this example we simulate a transaction manager to control the transactions. First we create an XASession
+     and enlist it in a transaction through its XAResource. We then send two words, 'hello' and 'world', with
+     the session, let the transaction roll back. The messages are discarded and never be received. Next we start
+     a new transaction with the same XAResource, but this time we commit the transaction. Both messages are received.</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(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 perform a lookup on the XA Connection Factory</li>
+        <pre class="prettyprint">
+           <code>XAConnectionFactory cf = (XAConnectionFactory) initialContext.lookup("/XAConnectionFactory");</code>
+        </pre>
+
+        <li>We create a JMS XAConnection</li>
+        <pre class="prettyprint">
+           <code>connection = cf.createXAConnection();</code>
+        </pre>
+
+        <li>We Start the connection</li>
+        <pre class="prettyprint">
+           <code>connection.start();</code>
+        </pre>
+
+        <li>We create a JMS XASession</li>
+        <pre class="prettyprint">
+          <code>XASession xaSession = connection.createXASession();</code>
+       </pre>
+
+        <li>We create a normal session</li>
+        <pre class="prettyprint">
+          <code>Session normalSession = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);</code>
+       </pre>
+
+        <li>We create a normal Message Consumer</li>
+        <pre class="prettyprint">
+           <code>
+           MessageConsumer normalConsumer = normalSession.createConsumer(queue);
+           normalConsumer.setMessageListener(new SimpleMessageListener());
+           </code>
+       </pre>
+
+        <li>We get the JMS Session</li>
+        <pre class="prettyprint">
+          <code>Session session = xaSession.getSession();</code>
+       </pre>
+
+        <li>We create a message producer</li>
+        <pre class="prettyprint">
+          <code>MessageProducer producer = session.createProducer(queue);</code>
+       </pre>
+
+        <li>We create two Text Messages</li>
+        <pre class="prettyprint">
+          <code>
+          TextMessage helloMessage = session.createTextMessage("hello");
+          TextMessage worldMessage = session.createTextMessage("world");
+          </code>
+       </pre>
+
+        <li>We create a transaction</li>
+        <pre class="prettyprint">
+          <code>Xid xid1 = new XidImpl("xa-example1".getBytes(), 1, UUIDGenerator.getInstance().generateStringUUID().getBytes());</code>
+       </pre>
+
+        <li>We get the JMS XAResource</li>
+        <pre class="prettyprint">
+          <code>XAResource xaRes = xaSession.getXAResource();</code>
+       </pre>
+
+        <li>We begin the Transaction work</li>
+        <pre class="prettyprint">
+          <code>xaRes.start(xid1, XAResource.TMNOFLAGS);</code>
+       </pre>
+
+        <li>We do work, sending two messages.</li>
+        <pre class="prettyprint">
+          <code>
+          producer.send(helloMessage);
+          producer.send(worldMessage);
+          </code>
+       </pre>
+
+        <li>We check the result, it should receive none!</li>
+        <pre class="prettyprint">
+          <code>checkNoMessageReceived();</code>
+       </pre>
+
+        <li>We stop the work</li>
+        <pre class="prettyprint">
+          <code>xaRes.end(xid1, XAResource.TMSUCCESS);</code>
+       </pre>
+
+        <li>We prepare</li>
+        <pre class="prettyprint">
+          <code>xaRes.prepare(xid1);</code>
+       </pre>
+
+        <li>We roll back the transaction </li>
+        <pre class="prettyprint">
+          <code>xaRes.rollback(xid1);</code>
+       </pre>
+
+        <li>We check no messages should be received! </li>
+        <pre class="prettyprint">
+          <code>checkNoMessageReceived();</code>
+       </pre>
+
+        <li>We create another transaction</li>
+        <pre class="prettyprint">
+          <code>Xid xid2 = new XidImpl("xa-example2".getBytes(), 1, UUIDGenerator.getInstance().generateStringUUID().getBytes());</code>
+       </pre>
+
+        <li>We start the transaction</li>
+        <pre class="prettyprint">
+          <code>xaRes.start(xid2, XAResource.TMNOFLAGS);</code>
+       </pre>
+
+        <li>We re-send those messages</li>
+        <pre class="prettyprint">
+           <code>
+           producer.send(helloMessage);
+           producer.send(worldMessage);
+           </code>
+       </pre>
+
+        <li>We stop the work</li>
+        <pre class="prettyprint">
+          <code>xaRes.end(xid2, XAResource.TMSUCCESS);</code>
+       </pre>
+
+        <li>We prepare</li>
+        <pre class="prettyprint">
+          <code>xaRes.prepare(xid2);</code>
+       </pre>
+
+        <li>We check that no messages should be received at this moment</li>
+        <pre class="prettyprint">
+          <code>checkNoMessageReceived();</code>
+       </pre>
+
+        <li>We commit!</li>
+        <pre class="prettyprint">
+          <code>xaRes.commit(xid2, false);</code>
+       </pre>
+
+        <li>We check that all messages are received.</li>
+        <pre class="prettyprint">
+          <code>checkAllMessageReceived();</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/xa-send/src/main/java/org/apache/activemq/artemis/jms/example/DummyXid.java
----------------------------------------------------------------------
diff --git a/examples/features/standard/xa-send/src/main/java/org/apache/activemq/artemis/jms/example/DummyXid.java b/examples/features/standard/xa-send/src/main/java/org/apache/activemq/artemis/jms/example/DummyXid.java
new file mode 100644
index 0000000..4dbe2f8
--- /dev/null
+++ b/examples/features/standard/xa-send/src/main/java/org/apache/activemq/artemis/jms/example/DummyXid.java
@@ -0,0 +1,184 @@
+/*
+ * 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 org.apache.activemq.artemis.utils.Base64;
+
+import javax.transaction.xa.Xid;
+
+public class DummyXid implements Xid {
+
+   private static final long serialVersionUID = 407053232840068514L;
+
+   private final byte[] branchQualifier;
+
+   private final int formatId;
+
+   private final byte[] globalTransactionId;
+
+   private int hash;
+
+   private boolean hashCalculated;
+
+   // Static --------------------------------------------------------
+
+   public static String toBase64String(final Xid xid) {
+      return Base64.encodeBytes(DummyXid.toByteArray(xid));
+   }
+
+   private static byte[] toByteArray(final Xid xid) {
+      byte[] branchQualifier = xid.getBranchQualifier();
+      byte[] globalTransactionId = xid.getGlobalTransactionId();
+      int formatId = xid.getFormatId();
+
+      byte[] hashBytes = new byte[branchQualifier.length + globalTransactionId.length + 4];
+      System.arraycopy(branchQualifier, 0, hashBytes, 0, branchQualifier.length);
+      System.arraycopy(globalTransactionId, 0, hashBytes, branchQualifier.length, globalTransactionId.length);
+      byte[] intBytes = new byte[4];
+      for (int i = 0; i < 4; i++) {
+         intBytes[i] = (byte) ((formatId >> i * 8) % 0xFF);
+      }
+      System.arraycopy(intBytes, 0, hashBytes, branchQualifier.length + globalTransactionId.length, 4);
+      return hashBytes;
+   }
+
+   // Constructors --------------------------------------------------
+
+   /**
+    * Standard constructor
+    *
+    * @param branchQualifier
+    * @param formatId
+    * @param globalTransactionId
+    */
+   public DummyXid(final byte[] branchQualifier, final int formatId, final byte[] globalTransactionId) {
+      this.branchQualifier = branchQualifier;
+      this.formatId = formatId;
+      this.globalTransactionId = globalTransactionId;
+   }
+
+   /**
+    * Copy constructor
+    *
+    * @param other
+    */
+   public DummyXid(final Xid other) {
+      branchQualifier = copyBytes(other.getBranchQualifier());
+      formatId = other.getFormatId();
+      globalTransactionId = copyBytes(other.getGlobalTransactionId());
+   }
+
+   // Xid implementation ------------------------------------------------------------------
+
+   public byte[] getBranchQualifier() {
+      return branchQualifier;
+   }
+
+   public int getFormatId() {
+      return formatId;
+   }
+
+   public byte[] getGlobalTransactionId() {
+      return globalTransactionId;
+   }
+
+   // Public -------------------------------------------------------------------------------
+
+   @Override
+   public int hashCode() {
+      if (!hashCalculated) {
+         calcHash();
+      }
+      return hash;
+   }
+
+   @Override
+   public boolean equals(final Object other) {
+      if (this == other) {
+         return true;
+      }
+      if (!(other instanceof Xid)) {
+         return false;
+      }
+      Xid xother = (Xid) other;
+      if (xother.getFormatId() != formatId) {
+         return false;
+      }
+      if (xother.getBranchQualifier().length != branchQualifier.length) {
+         return false;
+      }
+      if (xother.getGlobalTransactionId().length != globalTransactionId.length) {
+         return false;
+      }
+      for (int i = 0; i < branchQualifier.length; i++) {
+         byte[] otherBQ = xother.getBranchQualifier();
+         if (branchQualifier[i] != otherBQ[i]) {
+            return false;
+         }
+      }
+      for (int i = 0; i < globalTransactionId.length; i++) {
+         byte[] otherGtx = xother.getGlobalTransactionId();
+         if (globalTransactionId[i] != otherGtx[i]) {
+            return false;
+         }
+      }
+      return true;
+   }
+
+   @Override
+   public String toString() {
+      return "XidImpl (" + System.identityHashCode(this) +
+         " bq:" +
+         stringRep(branchQualifier) +
+         " formatID:" +
+         formatId +
+         " gtxid:" +
+         stringRep(globalTransactionId);
+   }
+
+   // Private -------------------------------------------------------------------------------
+
+   private String stringRep(final byte[] bytes) {
+      StringBuilder buff = new StringBuilder();
+      for (int i = 0; i < bytes.length; i++) {
+         byte b = bytes[i];
+
+         buff.append(b);
+
+         if (i != bytes.length - 1) {
+            buff.append('.');
+         }
+      }
+
+      return buff.toString();
+   }
+
+   private void calcHash() {
+      byte[] hashBytes = DummyXid.toByteArray(this);
+      String s = new String(hashBytes);
+      hash = s.hashCode();
+      hashCalculated = true;
+   }
+
+   private byte[] copyBytes(final byte[] other) {
+      byte[] bytes = new byte[other.length];
+
+      System.arraycopy(other, 0, bytes, 0, other.length);
+
+      return bytes;
+   }
+}

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/standard/xa-send/src/main/java/org/apache/activemq/artemis/jms/example/XASendExample.java
----------------------------------------------------------------------
diff --git a/examples/features/standard/xa-send/src/main/java/org/apache/activemq/artemis/jms/example/XASendExample.java b/examples/features/standard/xa-send/src/main/java/org/apache/activemq/artemis/jms/example/XASendExample.java
new file mode 100644
index 0000000..fd87f61
--- /dev/null
+++ b/examples/features/standard/xa-send/src/main/java/org/apache/activemq/artemis/jms/example/XASendExample.java
@@ -0,0 +1,191 @@
+/*
+ * 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.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 javax.jms.XAConnection;
+import javax.jms.XAConnectionFactory;
+import javax.jms.XASession;
+import javax.naming.InitialContext;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.activemq.artemis.utils.UUIDGenerator;
+
+/**
+ * A simple JMS example showing the usage of XA support in JMS.
+ */
+public class XASendExample {
+
+   public static void main(final String[] args) throws Exception {
+      AtomicBoolean result = new AtomicBoolean(true);
+      final ArrayList<String> receiveHolder = new ArrayList<String>();
+      XAConnection connection = null;
+      InitialContext initialContext = null;
+      try {
+         // Step 1. Create an initial context to perform the JNDI lookup.
+         initialContext = new InitialContext();
+
+         // Step 2. Lookup on the queue
+         Queue queue = (Queue) initialContext.lookup("queue/exampleQueue");
+
+         // Step 3. Perform a lookup on the XA Connection Factory
+         XAConnectionFactory cf = (XAConnectionFactory) initialContext.lookup("XAConnectionFactory");
+
+         // Step 4.Create a JMS XAConnection
+         connection = cf.createXAConnection();
+
+         // Step 5. Start the connection
+         connection.start();
+
+         // Step 6. Create a JMS XASession
+         XASession xaSession = connection.createXASession();
+
+         // Step 7. Create a normal session
+         Session normalSession = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+         // Step 8. Create a normal Message Consumer
+         MessageConsumer normalConsumer = normalSession.createConsumer(queue);
+         normalConsumer.setMessageListener(new SimpleMessageListener(receiveHolder, result));
+
+         // Step 9. Get the JMS Session
+         Session session = xaSession.getSession();
+
+         // Step 10. Create a message producer
+         MessageProducer producer = session.createProducer(queue);
+
+         // Step 11. Create two Text Messages
+         TextMessage helloMessage = session.createTextMessage("hello");
+         TextMessage worldMessage = session.createTextMessage("world");
+
+         // Step 12. create a transaction
+         Xid xid1 = new DummyXid("xa-example1".getBytes(StandardCharsets.UTF_8), 1, UUIDGenerator.getInstance().generateStringUUID().getBytes());
+
+         // Step 13. Get the JMS XAResource
+         XAResource xaRes = xaSession.getXAResource();
+
+         // Step 14. Begin the Transaction work
+         xaRes.start(xid1, XAResource.TMNOFLAGS);
+
+         // Step 15. do work, sending two messages.
+         producer.send(helloMessage);
+         producer.send(worldMessage);
+
+         Thread.sleep(2000);
+
+         // Step 16. Check the result, it should receive none!
+         checkNoMessageReceived(receiveHolder);
+
+         // Step 17. Stop the work
+         xaRes.end(xid1, XAResource.TMSUCCESS);
+
+         // Step 18. Prepare
+         xaRes.prepare(xid1);
+
+         // Step 19. Roll back the transaction
+         xaRes.rollback(xid1);
+
+         // Step 20. No messages should be received!
+         checkNoMessageReceived(receiveHolder);
+
+         // Step 21. Create another transaction
+         Xid xid2 = new DummyXid("xa-example2".getBytes(), 1, UUIDGenerator.getInstance().generateStringUUID().getBytes());
+
+         // Step 22. Start the transaction
+         xaRes.start(xid2, XAResource.TMNOFLAGS);
+
+         // Step 23. Re-send those messages
+         producer.send(helloMessage);
+         producer.send(worldMessage);
+
+         // Step 24. Stop the work
+         xaRes.end(xid2, XAResource.TMSUCCESS);
+
+         // Step 25. Prepare
+         xaRes.prepare(xid2);
+
+         // Step 26. No messages should be received at this moment
+         checkNoMessageReceived(receiveHolder);
+
+         // Step 27. Commit!
+         xaRes.commit(xid2, false);
+
+         Thread.sleep(2000);
+
+         // Step 28. Check the result, all message received
+         checkAllMessageReceived(receiveHolder);
+
+         if (!result.get())
+            throw new IllegalStateException();
+      }
+      finally {
+         // Step 29. Be sure to close our JMS resources!
+         if (initialContext != null) {
+            initialContext.close();
+         }
+         if (connection != null) {
+            connection.close();
+         }
+      }
+   }
+
+   private static void checkAllMessageReceived(ArrayList<String> receiveHolder) {
+      if (receiveHolder.size() != 2) {
+         throw new IllegalStateException("Number of messages received not correct ! -- " + receiveHolder.size());
+      }
+      receiveHolder.clear();
+   }
+
+   private static void checkNoMessageReceived(ArrayList<String> receiveHolder) {
+      if (receiveHolder.size() > 0) {
+         throw new IllegalStateException("Message received, wrong!");
+      }
+      receiveHolder.clear();
+   }
+}
+
+class SimpleMessageListener implements MessageListener {
+
+   ArrayList<String> receiveHolder;
+   AtomicBoolean result;
+
+   public SimpleMessageListener(ArrayList<String> receiveHolder, AtomicBoolean result) {
+      this.receiveHolder = receiveHolder;
+      this.result = result;
+   }
+
+   public void onMessage(final Message message) {
+      try {
+         System.out.println("Message received: " + message);
+         receiveHolder.add(((TextMessage) message).getText());
+      }
+      catch (JMSException e) {
+         result.set(false);
+         e.printStackTrace();
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/standard/xa-send/src/main/resources/jndi.properties
----------------------------------------------------------------------
diff --git a/examples/features/standard/xa-send/src/main/resources/jndi.properties b/examples/features/standard/xa-send/src/main/resources/jndi.properties
new file mode 100644
index 0000000..77561f7
--- /dev/null
+++ b/examples/features/standard/xa-send/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
+connectionFactory.XAConnectionFactory=tcp://localhost:61616?type=XA_CF
+queue.queue/exampleQueue=exampleQueue

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/sub-modules/aerogear/pom.xml
----------------------------------------------------------------------
diff --git a/examples/features/sub-modules/aerogear/pom.xml b/examples/features/sub-modules/aerogear/pom.xml
new file mode 100644
index 0000000..c522d78
--- /dev/null
+++ b/examples/features/sub-modules/aerogear/pom.xml
@@ -0,0 +1,125 @@
+<?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.modules</groupId>
+      <artifactId>broker-modules</artifactId>
+      <version>1.0.1-SNAPSHOT</version>
+   </parent>
+
+   <properties>
+      <endpoint/>
+      <applicationid/>
+      <mastersecret/>
+      <activemq.basedir>${project.basedir}/../../../..</activemq.basedir>
+   </properties>
+
+   <artifactId>aerogear</artifactId>
+   <packaging>jar</packaging>
+   <name>ActiveMQ Artemis JMS AeroGear Example</name>
+
+   <dependencies>
+      <dependency>
+         <groupId>org.apache.activemq</groupId>
+         <artifactId>artemis-cli</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>
+                     <!-- this list was extracted from mvn dependency:tree on integration/aerogear -->
+                     <libList>
+                        <param>org.apache.activemq:artemis-aerogear-integration:${project.version}</param>
+                        <param>org.jboss.aerogear:unifiedpush-java-client:1.0.0</param>
+                        <param>net.iharder:base64:2.3.8</param>
+                        <param>com.fasterxml.jackson.core:jackson-annotations:2.3.0</param>
+                        <param>com.fasterxml.jackson.core:jackson-core:2.3.0</param>
+                        <param>org.jboss.resteasy:resteasy-jackson-provider:2.3.2.Final</param>
+                        <param>org.codehaus.jackson:jackson-core-asl:1.8.5</param>
+                        <param>org.codehaus.jackson:jackson-mapper-asl:1.8.5</param>
+                        <param>org.codehaus.jackson:jackson-jaxrs:1.8.5</param>
+                        <param>org.codehaus.jackson:jackson-xc:1.8.5</param>
+                     </libList>
+                  </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.AerogearExample</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.modules</groupId>
+                  <artifactId>aerogear</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/sub-modules/aerogear/readme.html
----------------------------------------------------------------------
diff --git a/examples/features/sub-modules/aerogear/readme.html b/examples/features/sub-modules/aerogear/readme.html
new file mode 100644
index 0000000..3534a4c
--- /dev/null
+++ b/examples/features/sub-modules/aerogear/readme.html
@@ -0,0 +1,157 @@
+<!--
+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 AeroGear 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 AeroGear 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 you can send a message to a mobile device by leveraging <a href="http://aerogear.org/push/">AeroGears push</a> technology which
+         provides support for different push notification technologies like Google Cloud Messaging, Apple's APNs or
+         Mozilla's SimplePush.</p>
+
+     <p>For this example you will need an AeroGear Application running somewhere, a good way to do this is to deploy the
+        Push Application on <href a="">openshift</href>, you can follow the AeroGear Push 0.X Quickstart.</p>
+
+     <p>Once you have created your AeroGear Push Application you can create a mobile application. Simply log into the application
+     on the web and create a new mobile application by clicking the 'create' button. Once created you will see an application id
+     and a master secret, you will need the later to run the example.</p>
+
+     <p>lastly you will need to create a variant. For this example we will be using Android so you will need to create a google project,
+     this <a href="http://aerogear.org/docs/guides/aerogear-push-android/google-setup/">article</a> explains how to do this.
+     Once created click on your app then click 'add' to add a variant. choose 'google cloud messaging', enter your google
+         API key and the project number from your google project and click create</p>
+
+     <p>Now before we run the example we need a mobile application to receive it. Writing a mobile app is beyond the scope
+     of this example but for testing purposes we have supplied an Android app you can use, simply install on your android phone.
+     It can be found <a href="http://downloads.jboss.org.apache.activemq/ActiveMQAeroGear.apk">here</a>. For a more in depth mobile
+         app example visit the AeroGear site.</p>
+
+     <p>Once you have installed the mobile app you will need to configure the following:</p>
+     <p>AeroGear Unified Push URL : This is the URL where your aerogear server is running, something like http://myapp-mydomain.rhcloud.com
+        AeroGear Variant ID : This is the ID of the variant you created in AeroGear
+        AeroGear Variant Secret : This is the secret for your variant
+        GCM Sender ID : this is the Google project Number you created on Google
+        Variant : you can use this to target messages if needed.
+     </p>
+
+     <p>Once you set all these correctly you should get a message saying your mobile app is registered, if you log into
+         your AeroGear app you should see it registered with the variant.</p>
+
+
+     <p>Now to run the example simply run the following command
+         'mvn -Dendpoint=my aerogear url -Dapplicationid=my application id -Dmastersecret=my master secret -Djsse.enableSNIExtension=false clean verify'.
+     If you arent using java 7 you can omit the 'jsse.enableSNIExtension=false'</p>
+
+   <p>You should see something like this in your ActiveMQServer</p>
+     <ol>
+        <pre class="prettyprint">
+           <code>
+   Dec 04, 2013 3:25:39 PM org.jboss.aerogear.unifiedpush.SenderClient submitPayload
+   INFO: HTTP Response code from UnifiedPush Server: 302
+   Dec 04, 2013 3:25:39 PM org.jboss.aerogear.unifiedpush.SenderClient submitPayload
+   INFO: Performing redirect to 'https://myapp-mydomain.rhcloud.com/rest/sender/'
+   Dec 04, 2013 3:25:40 PM org.jboss.aerogear.unifiedpush.SenderClient submitPayload
+   INFO: HTTP Response code from UnifiedPush Server: 200
+           </code>
+        </pre>
+     </ol>
+   <p>And on your mobile app you should see a message from ActiveMQ</p>
+
+  <p>Now lets look a bit more closely at the configuration in broker.xml</p>
+     <ol>
+        <pre class="prettyprint">
+           <code>
+   &lt;queues>
+       &lt;queue name="jms.queue.exampleQueue">
+           &lt;address>jms.queue.exampleQueue&lt;/address>
+       &lt;/queue>
+   &lt;/queues>
+
+   &lt;connector-services>
+       &lt;connector-service name="aerogear-connector">
+           &lt;factory-class>org.apache.activemq.integration.aerogear.AeroGearConnectorServiceFactory&lt;/factory-class>
+           &lt;param key="endpoint" value="${endpoint}"/>
+           &lt;param key="queue" value="jms.queue.exampleQueue"/>
+           &lt;param key="application-id" value="${applicationid}"/>
+           &lt;param key="master-secret" value="${mastersecret}"/>
+       &lt;/connector-service>
+   &lt;/connector-services>
+           </code>
+        </pre>
+     </ol>
+  <p>Firstly you will see that we have to create a core queue so it is available when the connector is started, the following are mandatory parameters:</p>
+  <ol>
+      <li>endpoint - The endpoint or URL of you AeroGear application</li>
+      <li>queue - The name of the queue to consume from</li>
+      <li>application-id - The application id of your mobile application in AeroGear</li>
+      <li>master-secret - the secret of your mobile application in AeroGear</li>
+  </ol>
+  <p>as well as those there are also the following optional parameters</p>
+  <ol>
+      <li>ttl - The time to live for the message once AeroGear receives it</li>
+      <li>badge - The badge the mobile app should use for the notification</li>
+      <li>sound - The sound the mobile app should use for the notification</li>
+      <li>filter - A message filter(selector) to use on the connector</li>
+      <li>retry-interval - If an error occurs on send, how long before we try again</li>
+      <li>retry-attempts - How many times we should try to reconnect after an error</li>
+      <li>variants - A comma separated list of variants that should get the message</li>
+      <li>aliases - A list of aliases that should get the message</li>
+      <li>device-types - A list of device types that should get the message</li>
+  </ol>
+  <p>More in depth explanations of these can be found in the AeroGear docs.</p>
+  <p>Now lets look at a snippet of code we used to send the message for our JMS client</p>
+  <pre class="prettyprint">
+      <code>
+  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
+  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 Text Message
+  Message message = session.createMessage();
+
+  message.setStringProperty("AEROGEAR_ALERT", "Hello this is a notification from ActiveMQ");
+
+  producer.send(message);
+      </code>
+  </pre>
+  <p> The most important thing here is string propert we have set on the message, i.e. 'AEROGEAR_ALERT'. This is the
+      actual alert that is sent via AeroGear</p>
+  <p>As well as the alert itself you can override any of the above optional parameters in the same fashionby using the
+      following propert names: AEROGEAR_SOUND,AEROGEAR_BADGE,AEROGEAR_TTL,AEROGEAR_VARIANTS,AEROGEAR_ALIASES and AEROGEAR_DEVICE_TYPES</p>
+  </body>
+</html>

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/sub-modules/aerogear/src/main/java/org/apache/activemq/artemis/jms/example/AerogearExample.java
----------------------------------------------------------------------
diff --git a/examples/features/sub-modules/aerogear/src/main/java/org/apache/activemq/artemis/jms/example/AerogearExample.java b/examples/features/sub-modules/aerogear/src/main/java/org/apache/activemq/artemis/jms/example/AerogearExample.java
new file mode 100644
index 0000000..b412d87
--- /dev/null
+++ b/examples/features/sub-modules/aerogear/src/main/java/org/apache/activemq/artemis/jms/example/AerogearExample.java
@@ -0,0 +1,77 @@
+/*
+ * 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.Message;
+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 AerogearExample {
+
+   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. Perfom 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
+         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 Text Message
+         Message message = session.createMessage();
+
+         message.setStringProperty("AEROGEAR_ALERT", "Hello this is a notification from ActiveMQ");
+
+         producer.send(message);
+
+         System.out.println("Sent message");
+
+         System.out.println("now check your mobile app and press enter");
+
+         System.in.read();
+      }
+      finally {
+         // Step 12. Be sure to close our JMS resources!
+         if (initialContext != null) {
+            initialContext.close();
+         }
+         if (connection != null) {
+            connection.close();
+         }
+      }
+   }
+}