http://git-wip-us.apache.org/repos/asf/activemq-6/blob/8ecd255f/examples/jms/bridge/pom.xml ---------------------------------------------------------------------- diff --git a/examples/jms/bridge/pom.xml b/examples/jms/bridge/pom.xml new file mode 100644 index 0000000..0121db6 --- /dev/null +++ b/examples/jms/bridge/pom.xml @@ -0,0 +1,152 @@ +<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.hornetq.examples.jms</groupId> + <artifactId>jms-examples</artifactId> + <version>2.5.0-SNAPSHOT</version> + </parent> + + <artifactId>hornetq-jms-bridge-example</artifactId> + <packaging>jar</packaging> + <name>HornetQ JMS Bridge Example</name> + + <dependencies> + <dependency> + <groupId>org.hornetq.examples.jms</groupId> + <artifactId>hornetq-jms-examples-common</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.hornetq</groupId> + <artifactId>hornetq-server</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.jboss.spec.javax.jms</groupId> + <artifactId>jboss-jms-api_2.0_spec</artifactId> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.hornetq</groupId> + <artifactId>hornetq-maven-plugin</artifactId> + <executions> + <execution> + <id>start0</id> + <goals> + <goal>start</goal> + </goals> + <configuration> + <hornetqConfigurationDir>${basedir}/target/classes/hornetq/server0</hornetqConfigurationDir> + </configuration> + </execution> + <execution> + <id>start1</id> + <goals> + <goal>start</goal> + </goals> + <configuration> + <jndiPort>1199</jndiPort> + <jndiRmiPort>1198</jndiRmiPort> + <hornetqConfigurationDir>${basedir}/target/classes/hornetq/server1</hornetqConfigurationDir> + <fork>true</fork> + </configuration> + </execution> + <execution> + <id>runClient</id> + <goals> + <goal>runClient</goal> + </goals> + <configuration> + <clientClass>org.hornetq.jms.example.BridgeExample</clientClass> + <args> + <param>jnp://localhost:1099</param> + <param>jnp://localhost:1199</param> + </args> + <systemProperties> + <property> + <name>exampleConfigDir</name> + <value>${basedir}/target/classes/hornetq</value> + </property> + </systemProperties> + </configuration> + </execution> + <execution> + <id>stop0</id> + <goals> + <goal>stop</goal> + </goals> + <configuration> + <hornetqConfigurationDir>${basedir}/target/classes/hornetq/server0</hornetqConfigurationDir> + </configuration> + </execution> + <execution> + <id>stop1</id> + <goals> + <goal>stop</goal> + </goals> + <configuration> + <hornetqConfigurationDir>${basedir}/target/classes/hornetq/server1</hornetqConfigurationDir> + </configuration> + </execution> + </executions> + <dependencies> + <dependency> + <groupId>org.hornetq.examples.jms</groupId> + <artifactId>hornetq-jms-bridge-example</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.hornetq</groupId> + <artifactId>hornetq-core-client</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.hornetq</groupId> + <artifactId>hornetq-server</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.hornetq</groupId> + <artifactId>hornetq-jms-client</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.hornetq</groupId> + <artifactId>hornetq-jms-server</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>io.netty</groupId> + <artifactId>netty-all</artifactId> + <version>${netty.version}</version> + </dependency> + <dependency> + <groupId>org.jboss.javaee</groupId> + <artifactId>jboss-jms-api</artifactId> + <version>1.1.0.GA</version> + </dependency> + <dependency> + <groupId>org.jboss.naming</groupId> + <artifactId>jnpserver</artifactId> + <version>5.0.3.GA</version> + </dependency> + </dependencies> + <configuration> + <waitOnStart>false</waitOnStart> + <systemProperties> + <property> + <name>build.directory</name> + <value>${basedir}/target/</value> + </property> + </systemProperties> + </configuration> + </plugin> + </plugins> + </build> + +</project> \ No newline at end of file
http://git-wip-us.apache.org/repos/asf/activemq-6/blob/8ecd255f/examples/jms/bridge/readme.html ---------------------------------------------------------------------- diff --git a/examples/jms/bridge/readme.html b/examples/jms/bridge/readme.html new file mode 100644 index 0000000..6f8da67 --- /dev/null +++ b/examples/jms/bridge/readme.html @@ -0,0 +1,215 @@ +<html> + <head> + <title>HornetQ Core Bridge 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>Core Bridge Example</h1> + + <p>This example demonstrates a core bridge deployed on one server, which consumes messages from a + local queue and forwards them to an address on a second server.</p> + + <p>Core bridges are used to create message flows between any two HornetQ servers which are remotely separated. + Core bridges are resilient and will cope with temporary connection failure allowing them to be an ideal + choice for forwarding over unreliable connections, e.g. a WAN.</p> + <p>They can also be configured with an optional filter expression, and will only forward messages that + match that filter.</p> + <p>Furthermore they can be configured to use an optional Transformer class. A user-defined Transformer class + can be specified which is called at forwarding time. This gives the user the opportunity to transform + the message in some ways, e.g. changing its properties or body</p> + <p>HornetQ also includes a <b>JMS Bridge</b>. This is similar to a core bridge, but uses the JMS API + and can be used to bridge between any two JMS 1.1 compliant messaging systems. The core bridge is limited to bridging + between HornetQ instances, but may provide better performance than the JMS bridge. The JMS bridge is covered in + a separate example.</p> + <p>For more information on bridges, please see the HornetQ user manual.</p> + + <p>In this example we will demonstrate a simple sausage factory for aardvarks.</p> + <p>We have a JMS queue on server 0 named <code>sausage-factory</code>, and we have a + JMS queue on server 1 named <code>mincing-machine</code></p> + <p>We want to forward any messages that are sent to the <code>sausage-factory</code> queue on server 0, to the <code>mincing-machine</code> + on server 1.</p> + <p>We only want to make aardvark sausages, so we only forward messages where the property "name" is set + to "aardvark". It is known that other things, such are Sasquatches are also sent to the <code>sausage-factory</code> and we + want to reject those.</p> + <p>Moreover it is known that Aardvarks normally wear blue hats, and it's important that we only make sausages using + Aardvarks with green hats, so on the way we are going transform the property "hat" from "green" to "blue".</p> + <p>Here's a snippet from <code>hornetq-configuration.xml</code> showing the bridge configuration</p> + <pre class="prettyprint"> + <code> + <bridge name="my-bridge"> + <queue-name>jms.queue.sausage-factory</queue-name> + <forwarding-address>jms.queue.mincing-machine</forwarding-address> + <filter string="name='aardvark'"/> + <transformer-class-name>org.hornetq.jms.example.HatColourChangeTransformer</transformer-class-name> + <reconnect-attempts>-1</reconnect-attempts> + <static-connectors> + <connector-ref>remote-connector</connector-ref> + </static-connectors> + </bridge> + </code> + </pre> + <h2>Example step-by-step</h2> + <p><i>To run the example, simply type <code>mvn verify</code> from this directory</i></p> + + <ol> + <li>We create an initial context for looking up JNDI on node 0</li> + <pre class="prettyprint"> + <code> + ic0 = getContext(0); + </code> + </pre> + + <li>We look up the sausage-factory queue from node 0</li> + <pre class="prettyprint"> + <code>Queue sausageFactory = (Queue)ic0.lookup("/queue/sausage-factory");</code> + </pre> + + <li>We look up a JMS ConnectionFactory object from node 0</li> + <pre class="prettyprint"> + <code>ConnectionFactory cf0 = (ConnectionFactory)ic0.lookup("/ConnectionFactory");</code> + </pre> + + <li>We create an initial context for looking up JNDI on node 1</li> + <pre class="prettyprint"> + <code>ic1 = getContext(1);</code> + </pre> + + <li>We look up the mincing-machine queue on node 1</li> + <pre class="prettyprint"> + <code>Queue mincingMachine = (Queue)ic1.lookup("/queue/mincing-machine"); + </code> + </pre> + + <li>We look up a JMS ConnectionFactory object from node 1</li> + <pre class="prettyprint"> + <code> + ConnectionFactory cf1 = (ConnectionFactory)ic1.lookup("/ConnectionFactory"); + </code> + </pre> + + <li>We create a JMS Connection connection0 which is a connection to server 0</li> + <pre class="prettyprint"> + <code> + connection0 = cf0.createConnection(); + </code> + </pre> + + <li>We create a JMS Connection connection1 which is a connection to server 1</li> + <pre class="prettyprint"> + <code> + connection1 = cf1.createConnection(); + </code> + </pre> + + <li>We create a JMS Session on server 0</li> + <pre class="prettyprint"> + <code> + Session session0 = connection0.createSession(false, Session.AUTO_ACKNOWLEDGE); + </code> + </pre> + + <li>We create a JMS Session on server 1</li> + <pre class="prettyprint"> + <code> + Session session1 = connection1.createSession(false, Session.AUTO_ACKNOWLEDGE); + </code> + </pre> + + <li>We start the connection to ensure delivery occurs on them</li> + <pre class="prettyprint"> + <code> + connection1.start(); + </code> + </pre> + + <li>We create a JMS MessageConsumer object on server 1</li> + <pre class="prettyprint"> + <code> + MessageConsumer consumer = session1.createConsumer(mincingMachine); + </code> + </pre> + + <li>We create a JMS MessageProducer object on server 0.</li> + <pre class="prettyprint"> + <code> + MessageProducer producer = session0.createProducer(sausageFactory);</code> + </pre> + + <li>We create and send a message representing an aardvark with a green hat to the sausage-factory + on node 0</li> + <pre class="prettyprint"> + <code> + Message message = session0.createMessage(); + + message.setStringProperty("name", "aardvark"); + + message.setStringProperty("hat", "green"); + + producer.send(message); + </code> + </pre> + + <li>We successfully receive the aardvark message from the mincing-machine one node 1. The aardvark's + hat is now blue since it has been transformed!</li> + <pre class="prettyprint"> + <code> + Message receivedMessage = consumer.receive(5000); + </code> + </pre> + + <li>We create and send another message, this time representing a sasquatch with a mauve hat to the + sausage-factory on node 0. This won't be bridged to the mincing-machine since we only want aardvarks, not sasquatches.</li> + <pre class="prettyprint"> + <code> + message = session0.createMessage(); + + message.setStringProperty("name", "sasquatch"); + + message.setStringProperty("hat", "mauve"); + + producer.send(message); + </code> + </pre> + + <li>We don't receive the sasquatch message since it's not an aardvark!</li> + <pre class="prettyprint"> + <code> + receivedMessage = (TextMessage)consumer.receive(1000); + </code> + </pre> + + + <li>And finally (no pun intended), <b>always</b> remember to close your JMS 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 (connection0 != null) + { + connection0.close(); + } + + if (connection1 != null) + { + connection1.close(); + } + + if (ic0 != null) + { + ic0.close(); + } + + if (ic1 != null) + { + ic1.close(); + } + } + </code> + </pre> + + </ol> + </body> +</html> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/activemq-6/blob/8ecd255f/examples/jms/bridge/src/main/java/org/hornetq/jms/example/BridgeExample.java ---------------------------------------------------------------------- diff --git a/examples/jms/bridge/src/main/java/org/hornetq/jms/example/BridgeExample.java b/examples/jms/bridge/src/main/java/org/hornetq/jms/example/BridgeExample.java new file mode 100644 index 0000000..79a36e3 --- /dev/null +++ b/examples/jms/bridge/src/main/java/org/hornetq/jms/example/BridgeExample.java @@ -0,0 +1,184 @@ +/* + * Copyright 2005-2014 Red Hat, Inc. + * Red Hat 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.hornetq.jms.example; + +import javax.jms.Connection; +import javax.jms.ConnectionFactory; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Queue; +import javax.jms.Session; +import javax.naming.InitialContext; + +import org.hornetq.common.example.HornetQExample; + +/** + * This example demonstrates a core bridge set-up between two nodes, consuming messages from a queue + * on one node and forwarding them to an address on the second node. + * + * @author <a href="tim....@jboss.com>Tim Fox</a> + */ +public class BridgeExample extends HornetQExample +{ + public static void main(final String[] args) + { + new BridgeExample().run(args); + } + + @Override + public boolean runExample() throws Exception + { + Connection connection0 = null; + + Connection connection1 = null; + + InitialContext ic0 = null; + + InitialContext ic1 = null; + + try + { + // Step 1 - we create an initial context for looking up JNDI on node 0 + + ic0 = getContext(0); + + // Step 2 - we look up the sausage-factory queue from node 0 + + Queue sausageFactory = (Queue)ic0.lookup("/queue/sausage-factory"); + + // Step 3 - we look up a JMS ConnectionFactory object from node 0 + + ConnectionFactory cf0 = (ConnectionFactory)ic0.lookup("/ConnectionFactory"); + + // Step 4 - we create an initial context for looking up JNDI on node 1 + + ic1 = getContext(1); + + // Step 5 - we look up the mincing-machine queue on node 1 + + Queue mincingMachine = (Queue)ic1.lookup("/queue/mincing-machine"); + + // Step 6 - we look up a JMS ConnectionFactory object from node 1 + + ConnectionFactory cf1 = (ConnectionFactory)ic1.lookup("/ConnectionFactory"); + + // Step 7. We create a JMS Connection connection0 which is a connection to server 0 + + connection0 = cf0.createConnection(); + + // Step 8. We create a JMS Connection connection1 which is a connection to server 1 + connection1 = cf1.createConnection(); + + // Step 9. We create a JMS Session on server 0 + + Session session0 = connection0.createSession(false, Session.AUTO_ACKNOWLEDGE); + + // Step 10. We create a JMS Session on server 1 + + Session session1 = connection1.createSession(false, Session.AUTO_ACKNOWLEDGE); + + // Step 10. We start the connection to ensure delivery occurs on them + + connection1.start(); + + // Step 11. We create JMS MessageConsumer object + MessageConsumer consumer = session1.createConsumer(mincingMachine); + + // Step 12. We create a JMS MessageProducer object on server 0 + MessageProducer producer = session0.createProducer(sausageFactory); + + // Step 13. We create and send a message representing an aardvark with a green hat to the sausage-factory + // on node 0 + Message message = session0.createMessage(); + + message.setStringProperty("name", "aardvark"); + + message.setStringProperty("hat", "green"); + + producer.send(message); + + System.out.println("Sent " + message.getStringProperty("name") + + " message with " + + message.getStringProperty("hat") + + " hat to sausage-factory on node 0"); + + // Step 14 - we successfully receive the aardvark message from the mincing-machine one node 1. The aardvark's + // hat is now blue since it has been transformed! + + Message receivedMessage = consumer.receive(5000); + + System.out.println("Received " + receivedMessage.getStringProperty("name") + + " message with " + + receivedMessage.getStringProperty("hat") + + " hat from mincing-machine on node 1"); + + // Step 13. We create and send another message, this time representing a sasquatch with a mauve hat to the + // sausage-factory on node 0. This won't be bridged to the mincing-machine since we only want aardvarks, not + // sasquatches + + message = session0.createMessage(); + + message.setStringProperty("name", "sasquatch"); + + message.setStringProperty("hat", "mauve"); + + producer.send(message); + + System.out.println("Sent " + message.getStringProperty("name") + + " message with " + + message.getStringProperty("hat") + + " hat to sausage-factory on node 0"); + + // Step 14. We don't receive the message since it has not been bridged. + + receivedMessage = consumer.receive(1000); + + if (receivedMessage == null) + { + System.out.println("Didn't receive that message from mincing-machine on node 1"); + } + else + { + return false; + } + + return true; + } + finally + { + // Step 15. Be sure to close our resources! + + if (connection0 != null) + { + connection0.close(); + } + + if (connection1 != null) + { + connection1.close(); + } + + if (ic0 != null) + { + ic0.close(); + } + + if (ic1 != null) + { + ic1.close(); + } + } + } + +} http://git-wip-us.apache.org/repos/asf/activemq-6/blob/8ecd255f/examples/jms/bridge/src/main/java/org/hornetq/jms/example/HatColourChangeTransformer.java ---------------------------------------------------------------------- diff --git a/examples/jms/bridge/src/main/java/org/hornetq/jms/example/HatColourChangeTransformer.java b/examples/jms/bridge/src/main/java/org/hornetq/jms/example/HatColourChangeTransformer.java new file mode 100644 index 0000000..ca8b10d --- /dev/null +++ b/examples/jms/bridge/src/main/java/org/hornetq/jms/example/HatColourChangeTransformer.java @@ -0,0 +1,42 @@ +/* + * Copyright 2005-2014 Red Hat, Inc. + * Red Hat 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.hornetq.jms.example; + +import org.hornetq.api.core.SimpleString; +import org.hornetq.core.server.ServerMessage; +import org.hornetq.core.server.cluster.Transformer; + +/** + * A HatColourChangeTransformer + * + * @author <a href="mailto:tim....@jboss.com">Tim Fox</a> + * + * + */ +public class HatColourChangeTransformer implements Transformer +{ + public ServerMessage transform(final ServerMessage message) + { + SimpleString propName = new SimpleString("hat"); + + SimpleString oldProp = message.getSimpleStringProperty(propName); + + // System.out.println("Old hat colour is " + oldProp); + + // Change the colour + message.putStringProperty(propName, new SimpleString("blue")); + + return message; + } + +} http://git-wip-us.apache.org/repos/asf/activemq-6/blob/8ecd255f/examples/jms/bridge/src/main/resources/hornetq/server0/hornetq-configuration.xml ---------------------------------------------------------------------- diff --git a/examples/jms/bridge/src/main/resources/hornetq/server0/hornetq-configuration.xml b/examples/jms/bridge/src/main/resources/hornetq/server0/hornetq-configuration.xml new file mode 100644 index 0000000..728117a --- /dev/null +++ b/examples/jms/bridge/src/main/resources/hornetq/server0/hornetq-configuration.xml @@ -0,0 +1,72 @@ +<configuration xmlns="urn:hornetq" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="urn:hornetq /schema/hornetq-configuration.xsd"> + + <bindings-directory>${build.directory}/server0/data/messaging/bindings</bindings-directory> + + <journal-directory>${build.directory}/server0/data/messaging/journal</journal-directory> + + <large-messages-directory>${build.directory}/server0/data/messaging/largemessages</large-messages-directory> + + <paging-directory>${build.directory}/server0/data/messaging/paging</paging-directory> + + <!-- Connectors --> + <connectors> + <connector name="netty-connector"> + <factory-class>org.hornetq.core.remoting.impl.netty.NettyConnectorFactory</factory-class> + <param key="port" value="5445"/> + </connector> + + <!-- Connector to the other node --> + <connector name="remote-connector"> + <factory-class>org.hornetq.core.remoting.impl.netty.NettyConnectorFactory</factory-class> + <param key="port" value="5446"/> + </connector> + </connectors> + + <!-- Acceptors --> + <acceptors> + <acceptor name="netty-acceptor"> + <factory-class>org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class> + <param key="port" value="5445"/> + </acceptor> + </acceptors> + + <!-- We need to create a core queue for the JMS queue explicitly because the bridge will be deployed + before the JMS queue is deployed, so the first time, it otherwise won't find the queue --> + <queues> + <queue name="jms.queue.sausage-factory"> + <address>jms.queue.sausage-factory</address> + </queue> + </queues> + + <!-- We set-up a bridge that forwards from a queue on this node to an address on another node. + We specify a filter with the bridge, and a transformer too. The filter and transformer are optional --> + <bridges> + <bridge name="my-bridge"> + <queue-name>jms.queue.sausage-factory</queue-name> + <forwarding-address>jms.queue.mincing-machine</forwarding-address> + <filter string="name='aardvark'"/> + <transformer-class-name>org.hornetq.jms.example.HatColourChangeTransformer</transformer-class-name> + <reconnect-attempts>-1</reconnect-attempts> + <static-connectors> + <connector-ref>remote-connector</connector-ref> + </static-connectors> + </bridge> + </bridges> + + <!-- Other config --> + + <security-settings> + <!--security for example queue--> + <security-setting match="jms.queue.#"> + <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> + +</configuration> http://git-wip-us.apache.org/repos/asf/activemq-6/blob/8ecd255f/examples/jms/bridge/src/main/resources/hornetq/server0/hornetq-jms.xml ---------------------------------------------------------------------- diff --git a/examples/jms/bridge/src/main/resources/hornetq/server0/hornetq-jms.xml b/examples/jms/bridge/src/main/resources/hornetq/server0/hornetq-jms.xml new file mode 100644 index 0000000..8f77abe --- /dev/null +++ b/examples/jms/bridge/src/main/resources/hornetq/server0/hornetq-jms.xml @@ -0,0 +1,19 @@ +<configuration xmlns="urn:hornetq" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="urn:hornetq /schema/hornetq-jms.xsd"> + <!--the connection factory used by the example--> + <connection-factory name="ConnectionFactory"> + <connectors> + <connector-ref connector-name="netty-connector"/> + </connectors> + <entries> + <entry name="ConnectionFactory"/> + </entries> + </connection-factory> + + <!--the queue used by the example--> + <queue name="sausage-factory"> + <entry name="/queue/sausage-factory"/> + </queue> + +</configuration> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/activemq-6/blob/8ecd255f/examples/jms/bridge/src/main/resources/hornetq/server0/hornetq-users.xml ---------------------------------------------------------------------- diff --git a/examples/jms/bridge/src/main/resources/hornetq/server0/hornetq-users.xml b/examples/jms/bridge/src/main/resources/hornetq/server0/hornetq-users.xml new file mode 100644 index 0000000..934306c --- /dev/null +++ b/examples/jms/bridge/src/main/resources/hornetq/server0/hornetq-users.xml @@ -0,0 +1,7 @@ +<configuration xmlns="urn:hornetq" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="urn:hornetq /schema/hornetq-users.xsd"> + <!-- the default user. this is used where username is null--> + <defaultuser name="guest" password="guest"> + <role name="guest"/> + </defaultuser> +</configuration> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/activemq-6/blob/8ecd255f/examples/jms/bridge/src/main/resources/hornetq/server1/hornetq-configuration.xml ---------------------------------------------------------------------- diff --git a/examples/jms/bridge/src/main/resources/hornetq/server1/hornetq-configuration.xml b/examples/jms/bridge/src/main/resources/hornetq/server1/hornetq-configuration.xml new file mode 100644 index 0000000..f84aecd --- /dev/null +++ b/examples/jms/bridge/src/main/resources/hornetq/server1/hornetq-configuration.xml @@ -0,0 +1,44 @@ +<configuration xmlns="urn:hornetq" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="urn:hornetq /schema/hornetq-configuration.xsd"> + + <bindings-directory>${build.directory}/server1/data/messaging/bindings</bindings-directory> + + <journal-directory>${build.directory}/server1/data/messaging/journal</journal-directory> + + <large-messages-directory>${build.directory}/server1/data/messaging/largemessages</large-messages-directory> + + <paging-directory>${build.directory}/server1/data/messaging/paging</paging-directory> + + <!-- Connectors --> + + <connectors> + <connector name="netty-connector"> + <factory-class>org.hornetq.core.remoting.impl.netty.NettyConnectorFactory</factory-class> + <param key="port" value="5446"/> + </connector> + </connectors> + + <!-- Acceptors --> + <acceptors> + <acceptor name="netty-acceptor"> + <factory-class>org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class> + <param key="port" value="5446"/> + </acceptor> + </acceptors> + + <!-- Other config --> + + <security-settings> + <!--security for example queue--> + <security-setting match="jms.queue.#"> + <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> + +</configuration> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/activemq-6/blob/8ecd255f/examples/jms/bridge/src/main/resources/hornetq/server1/hornetq-jms.xml ---------------------------------------------------------------------- diff --git a/examples/jms/bridge/src/main/resources/hornetq/server1/hornetq-jms.xml b/examples/jms/bridge/src/main/resources/hornetq/server1/hornetq-jms.xml new file mode 100644 index 0000000..23fb370 --- /dev/null +++ b/examples/jms/bridge/src/main/resources/hornetq/server1/hornetq-jms.xml @@ -0,0 +1,19 @@ +<configuration xmlns="urn:hornetq" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="urn:hornetq /schema/hornetq-jms.xsd"> + <!--the connection factory used by the example--> + <connection-factory name="ConnectionFactory"> + <connectors> + <connector-ref connector-name="netty-connector"/> + </connectors> + <entries> + <entry name="ConnectionFactory"/> + </entries> + </connection-factory> + + <!--the queue used by the example--> + <queue name="mincing-machine"> + <entry name="/queue/mincing-machine"/> + </queue> + +</configuration> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/activemq-6/blob/8ecd255f/examples/jms/bridge/src/main/resources/hornetq/server1/hornetq-users.xml ---------------------------------------------------------------------- diff --git a/examples/jms/bridge/src/main/resources/hornetq/server1/hornetq-users.xml b/examples/jms/bridge/src/main/resources/hornetq/server1/hornetq-users.xml new file mode 100644 index 0000000..934306c --- /dev/null +++ b/examples/jms/bridge/src/main/resources/hornetq/server1/hornetq-users.xml @@ -0,0 +1,7 @@ +<configuration xmlns="urn:hornetq" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="urn:hornetq /schema/hornetq-users.xsd"> + <!-- the default user. this is used where username is null--> + <defaultuser name="guest" password="guest"> + <role name="guest"/> + </defaultuser> +</configuration> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/activemq-6/blob/8ecd255f/examples/jms/browser/pom.xml ---------------------------------------------------------------------- diff --git a/examples/jms/browser/pom.xml b/examples/jms/browser/pom.xml new file mode 100644 index 0000000..a0a3f96 --- /dev/null +++ b/examples/jms/browser/pom.xml @@ -0,0 +1,114 @@ +<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.hornetq.examples.jms</groupId> + <artifactId>jms-examples</artifactId> + <version>2.5.0-SNAPSHOT</version> + </parent> + + <artifactId>hornetq-jms-browser-example</artifactId> + <packaging>jar</packaging> + <name>HornetQ JMS Browser Example</name> + + <dependencies> + <dependency> + <groupId>org.hornetq.examples.jms</groupId> + <artifactId>hornetq-jms-examples-common</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.jboss.spec.javax.jms</groupId> + <artifactId>jboss-jms-api_2.0_spec</artifactId> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.hornetq</groupId> + <artifactId>hornetq-maven-plugin</artifactId> + <executions> + <execution> + <id>start</id> + <goals> + <goal>start</goal> + </goals> + </execution> + <execution> + <id>runClient</id> + <goals> + <goal>runClient</goal> + </goals> + <configuration> + <clientClass>org.hornetq.jms.example.QueueBrowserExample</clientClass> + <args> + <param>jnp://localhost:1099</param> + </args> + </configuration> + </execution> + <execution> + <id>stop</id> + <goals> + <goal>stop</goal> + </goals> + </execution> + </executions> + <dependencies> + <dependency> + <groupId>org.hornetq.examples.jms</groupId> + <artifactId>hornetq-jms-browser-example</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.hornetq</groupId> + <artifactId>hornetq-core-client</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.hornetq</groupId> + <artifactId>hornetq-server</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.hornetq</groupId> + <artifactId>hornetq-jms-client</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.hornetq</groupId> + <artifactId>hornetq-jms-server</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>io.netty</groupId> + <artifactId>netty-all</artifactId> + <version>${netty.version}</version> + </dependency> + <dependency> + <groupId>org.jboss.javaee</groupId> + <artifactId>jboss-jms-api</artifactId> + <version>1.1.0.GA</version> + </dependency> + <dependency> + <groupId>org.jboss.naming</groupId> + <artifactId>jnpserver</artifactId> + <version>5.0.3.GA</version> + </dependency> + </dependencies> + <configuration> + <waitOnStart>false</waitOnStart> + <hornetqConfigurationDir>${basedir}/target/classes/hornetq/server0</hornetqConfigurationDir> + <systemProperties> + <property> + <name>build.directory</name> + <value>${basedir}/target/</value> + </property> + </systemProperties> + </configuration> + </plugin> + </plugins> + </build> + +</project> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/activemq-6/blob/8ecd255f/examples/jms/browser/readme.html ---------------------------------------------------------------------- diff --git a/examples/jms/browser/readme.html b/examples/jms/browser/readme.html new file mode 100644 index 0000000..42551ae --- /dev/null +++ b/examples/jms/browser/readme.html @@ -0,0 +1,128 @@ +<html> + <head> + <title>HornetQ JMS QueueBrowser 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 QueueBrowser Example</h1> + + <p>This example shows you how to use a JMS <a href="http://java.sun.com/javaee/5/docs/api/javax/jms/QueueBrowser.html">QueueBrowser</a> with HornetQ.<br /> + Queues are a standard part of JMS, please consult the JMS 1.1 specification for full details.<br /> + A QueueBrowser is used to look at messages on the queue without removing them. + It can scan the entire content of a queue or only messages matching a message selector.</p> + <p> + The example will send 2 messages on a queue, use a QueueBrowser to browse + the queue (looking at the message without removing them) and finally consume the 2 messages + </p> + <h2>Example step-by-step</h2> + <p><i>To run the example, simply type <code>mvn verify</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 2 JMS text messages that we are going to send.</li> + <pre class="prettyprint"> + <code> TextMessage message_1 = session.createTextMessage("this is the 1st message"); + TextMessage message_2 = session.createTextMessage("this is the 2nd message");</code> + </pre> + + <li>We send messages to the queue</li> + <pre class="prettyprint"> + <code>messageProducer.send(message_1); + messageProducer.send(message_2);</code> + </pre> + + <li>We create a JMS QueueBrowser.<br /> + We have not specified a message selector so the browser will enumerate the entire content of the queue. + </li> + <pre class="prettyprint"> + <code>QueueBrowser browser = session.createBrowser(queue);</code> + </pre> + + <li>We browse the queue and display all the messages' text + </li> + <pre class="prettyprint"> + <code>Enumeration messageEnum = browser.getEnumeration(); + while (messageEnum.hasMoreElements()) + { + TextMessage message = (TextMessage)messageEnum.nextElement(); + System.out.println("Browsing: " + message.getText()); + }</code> + </pre> + + <li>We close the browser once we have finished to use it</li> + <pre class="prettyprint"> + <code>browser.close();</code> + </pre> + + <p>The messages were browsed but they were not removed from the queue. We will now consume them.</p> + + <li>We create a JMS Message Consumer to receive the messages.</li> + <pre class="prettyprint"> + <code>MessageConsumer messageConsumer = session.createConsumer(queue);</code> + </pre> + + <li>We start the connection. In order for delivery to occur on any consumers or subscribers on a connection, the connection must be started</li> + <pre class="prettyprint"> + <code>connection.start();</code> + </pre> + + <li>The 2 messages arrive at the consumer</li> + <pre class="prettyprint"> + <code>TextMessage messageReceived = (TextMessage)messageConsumer.receive(5000); + System.out.println("Received message: " + messageReceived.getText()); + messageReceived = (TextMessage)messageConsumer.receive(5000); + System.out.println("Received message: " + messageReceived.getText());</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> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/activemq-6/blob/8ecd255f/examples/jms/browser/src/main/java/org/hornetq/jms/example/QueueBrowserExample.java ---------------------------------------------------------------------- diff --git a/examples/jms/browser/src/main/java/org/hornetq/jms/example/QueueBrowserExample.java b/examples/jms/browser/src/main/java/org/hornetq/jms/example/QueueBrowserExample.java new file mode 100644 index 0000000..d4204e1 --- /dev/null +++ b/examples/jms/browser/src/main/java/org/hornetq/jms/example/QueueBrowserExample.java @@ -0,0 +1,119 @@ +/* + * Copyright 2005-2014 Red Hat, Inc. + * Red Hat 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.hornetq.jms.example; + +import java.util.Enumeration; + +import javax.jms.Connection; +import javax.jms.ConnectionFactory; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Queue; +import javax.jms.QueueBrowser; +import javax.jms.Session; +import javax.jms.TextMessage; +import javax.naming.InitialContext; + +import org.hornetq.common.example.HornetQExample; + +/** + * A simple example which shows how to use a QueueBrowser to look at messages of a queue without removing them from the queue + * + * @author <a href="mailto:jmes...@redhat.com">Jeff Mesnil</a> + * + * + */ +public class QueueBrowserExample extends HornetQExample +{ + public static void main(final String[] args) + { + new QueueBrowserExample().run(args); + } + + @Override + public boolean runExample() throws Exception + { + Connection connection = null; + InitialContext initialContext = null; + try + { + // Step 1. Create an initial context to perform the JNDI lookup. + initialContext = getContext(0); + + // 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 2 Text Messages + TextMessage message_1 = session.createTextMessage("this is the 1st message"); + TextMessage message_2 = session.createTextMessage("this is the 2nd message"); + + // Step 8. Send the Message + producer.send(message_1); + producer.send(message_2); + + // Step 9. Create the JMS QueueBrowser + QueueBrowser browser = session.createBrowser(queue); + + // Step 10. Browse the messages on the queue + // Browsing a queue does not remove the messages from the queue + Enumeration messageEnum = browser.getEnumeration(); + while (messageEnum.hasMoreElements()) + { + TextMessage message = (TextMessage)messageEnum.nextElement(); + System.out.println("Browsing: " + message.getText()); + } + + // Step 11. Close the browser + browser.close(); + + // Step 12. Create a JMS Message Consumer + MessageConsumer messageConsumer = session.createConsumer(queue); + + // Step 13. Start the Connection + connection.start(); + + // Step 14. Receive the 2 messages + TextMessage messageReceived = (TextMessage)messageConsumer.receive(5000); + System.out.println("Received message: " + messageReceived.getText()); + messageReceived = (TextMessage)messageConsumer.receive(5000); + System.out.println("Received message: " + messageReceived.getText()); + + return true; + + } + finally + { + // Step 15. 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-6/blob/8ecd255f/examples/jms/browser/src/main/resources/hornetq/server0/hornetq-configuration.xml ---------------------------------------------------------------------- diff --git a/examples/jms/browser/src/main/resources/hornetq/server0/hornetq-configuration.xml b/examples/jms/browser/src/main/resources/hornetq/server0/hornetq-configuration.xml new file mode 100644 index 0000000..9584a6b --- /dev/null +++ b/examples/jms/browser/src/main/resources/hornetq/server0/hornetq-configuration.xml @@ -0,0 +1,42 @@ +<configuration xmlns="urn:hornetq" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="urn:hornetq /schema/hornetq-configuration.xsd"> + + <bindings-directory>${build.directory}/server0/data/messaging/bindings</bindings-directory> + + <journal-directory>${build.directory}/server0/data/messaging/journal</journal-directory> + + <large-messages-directory>${build.directory}/server0/data/messaging/largemessages</large-messages-directory> + + <paging-directory>${build.directory}/server0/data/messaging/paging</paging-directory> + + <!-- Connectors --> + + <connectors> + <connector name="netty-connector"> + <factory-class>org.hornetq.core.remoting.impl.netty.NettyConnectorFactory</factory-class> + </connector> + </connectors> + + <!-- Acceptors --> + <acceptors> + <acceptor name="netty-acceptor"> + <factory-class>org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class> + </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-settings> + +</configuration> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/activemq-6/blob/8ecd255f/examples/jms/browser/src/main/resources/hornetq/server0/hornetq-jms.xml ---------------------------------------------------------------------- diff --git a/examples/jms/browser/src/main/resources/hornetq/server0/hornetq-jms.xml b/examples/jms/browser/src/main/resources/hornetq/server0/hornetq-jms.xml new file mode 100644 index 0000000..678e7f5 --- /dev/null +++ b/examples/jms/browser/src/main/resources/hornetq/server0/hornetq-jms.xml @@ -0,0 +1,19 @@ +<configuration xmlns="urn:hornetq" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="urn:hornetq /schema/hornetq-jms.xsd"> + <!--the connection factory used by the example--> + <connection-factory name="ConnectionFactory"> + <connectors> + <connector-ref connector-name="netty-connector"/> + </connectors> + <entries> + <entry name="ConnectionFactory"/> + </entries> + </connection-factory> + + <!--the queue used by the example--> + <queue name="exampleQueue"> + <entry name="/queue/exampleQueue"/> + </queue> + +</configuration> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/activemq-6/blob/8ecd255f/examples/jms/browser/src/main/resources/hornetq/server0/hornetq-users.xml ---------------------------------------------------------------------- diff --git a/examples/jms/browser/src/main/resources/hornetq/server0/hornetq-users.xml b/examples/jms/browser/src/main/resources/hornetq/server0/hornetq-users.xml new file mode 100644 index 0000000..934306c --- /dev/null +++ b/examples/jms/browser/src/main/resources/hornetq/server0/hornetq-users.xml @@ -0,0 +1,7 @@ +<configuration xmlns="urn:hornetq" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="urn:hornetq /schema/hornetq-users.xsd"> + <!-- the default user. this is used where username is null--> + <defaultuser name="guest" password="guest"> + <role name="guest"/> + </defaultuser> +</configuration> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/activemq-6/blob/8ecd255f/examples/jms/client-kickoff/pom.xml ---------------------------------------------------------------------- diff --git a/examples/jms/client-kickoff/pom.xml b/examples/jms/client-kickoff/pom.xml new file mode 100644 index 0000000..48ce373 --- /dev/null +++ b/examples/jms/client-kickoff/pom.xml @@ -0,0 +1,139 @@ +<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.hornetq.examples.jms</groupId> + <artifactId>jms-examples</artifactId> + <version>2.5.0-SNAPSHOT</version> + </parent> + + <artifactId>hornetq-jms-client-kickoff-example</artifactId> + <packaging>jar</packaging> + <name>HornetQ JMS Kick Off Example</name> + + <dependencies> + <dependency> + <groupId>org.hornetq.examples.jms</groupId> + <artifactId>hornetq-jms-examples-common</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.hornetq</groupId> + <artifactId>hornetq-core-client</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.jboss.spec.javax.jms</groupId> + <artifactId>jboss-jms-api_2.0_spec</artifactId> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.hornetq</groupId> + <artifactId>hornetq-maven-plugin</artifactId> + <executions> + <execution> + <id>start</id> + <goals> + <goal>start</goal> + </goals> + <configuration> + <!--we need to fork the server as we have system props that need set pre runtime--> + <fork>true</fork> + <systemProperties> + <property> + <name>build.directory</name> + <value>${basedir}/target/</value> + </property> + <property> + <name>com.sun.management.jmxremote</name> + <value></value> + </property> + <property> + <name>com.sun.management.jmxremote.port</name> + <value>3000</value> + </property> + <property> + <name>com.sun.management.jmxremote.ssl</name> + <value>false</value> + </property> + <property> + <name>com.sun.management.jmxremote.authenticate</name> + <value>false</value> + </property> + </systemProperties> + </configuration> + </execution> + <execution> + <id>runClient</id> + <goals> + <goal>runClient</goal> + </goals> + <configuration> + <clientClass>org.hornetq.jms.example.ClientKickoffExample</clientClass> + <args> + <param>jnp://localhost:1099</param> + </args> + </configuration> + </execution> + <execution> + <id>stop</id> + <goals> + <goal>stop</goal> + </goals> + </execution> + </executions> + <dependencies> + <dependency> + <groupId>org.hornetq.examples.jms</groupId> + <artifactId>hornetq-jms-client-kickoff-example</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.hornetq</groupId> + <artifactId>hornetq-core-client</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.hornetq</groupId> + <artifactId>hornetq-server</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.hornetq</groupId> + <artifactId>hornetq-jms-client</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.hornetq</groupId> + <artifactId>hornetq-jms-server</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>io.netty</groupId> + <artifactId>netty-all</artifactId> + <version>${netty.version}</version> + </dependency> + <dependency> + <groupId>org.jboss.javaee</groupId> + <artifactId>jboss-jms-api</artifactId> + <version>1.1.0.GA</version> + </dependency> + <dependency> + <groupId>org.jboss.naming</groupId> + <artifactId>jnpserver</artifactId> + <version>5.0.3.GA</version> + </dependency> + </dependencies> + <configuration> + <waitOnStart>false</waitOnStart> + <hornetqConfigurationDir>${basedir}/target/classes/hornetq/server0</hornetqConfigurationDir> + </configuration> + </plugin> + </plugins> + </build> + +</project> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/activemq-6/blob/8ecd255f/examples/jms/client-kickoff/readme.html ---------------------------------------------------------------------- diff --git a/examples/jms/client-kickoff/readme.html b/examples/jms/client-kickoff/readme.html new file mode 100644 index 0000000..23a95ac --- /dev/null +++ b/examples/jms/client-kickoff/readme.html @@ -0,0 +1,137 @@ +<html> + <head> + <title>HornetQ Client Kickoff 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>Client Kickoff Example</h1> + + <p>This example shows how to kick off a client connected to HornetQ + using <a href="http://java.sun.com/javase/technologies/core/mntr-mgmt/javamanagement/">JMX</a></p> + + <p>The example will connect to HornetQ. Using JMX, we will list the remote addresses connected to the + server and close the corresponding connections. The client will be kicked off from HornetQ receiving + an exception that its JMS connection was interrupted.</p> + + <h2>Example configuration</h2> + + <p>HornetQ exposes its managed resources by default on the platform MBeanServer.</p> + <p>To access this MBeanServer remotely, the Java Virtual machine must be started with system properties: + <pre class="prettyprint"> + <code>-Dcom.sun.management.jmxremote + -Dcom.sun.management.jmxremote.port=3000 + -Dcom.sun.management.jmxremote.ssl=false + -Dcom.sun.management.jmxremote.authenticate=false</code> + </pre> + <p>These properties are explained in the Java 5 <a href="http://java.sun.com/j2se/1.5.0/docs/guide/management/agent.html#remote">Management guide</a> + (please note that for this example, we will disable user authentication for simplicity).</p> + <p>With these properties, HornetQ server will be manageable remotely using standard JMX URL on port <code>3000</code>.</p> + </p> + + <h2>Example step-by-step</h2> + <p><em>To run the example, simply type <code>mvn verify</code> from this directory</em></p> + <ol> + <li>First we need to get an initial context so we can look-up the JMS connection factory and destination objects from JNDI. This initial context will get its properties from <a href="src/main/resources/hornetq/server0/client-jndi.properties">client-jndi.properties</a></li> + <pre class="prettyprint"> + <code>InitialContext initialContext = getContext(0);</code> + </pre> + + <li>We look up the JMS 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 set a <code>ExceptionListener</code> on the connection to be notified after a problem occurred</li> + <pre class="prettyprint"> + <code>final AtomicReference<JMSException> exception = new AtomicReference<JMSException>(); + connection.setExceptionListener(new ExceptionListener() + { + public void onException(JMSException e) + { + exception.set(e); + } + });</code> + </pre> + + <li>We start the connection</li> + <pre class="prettyprint"> + <code>connection.start();</code> + </pre> + + <li>We create a MBean proxy to the HornetQServerControlMBean used to manage HornetQ server + (see <a href="../jmx/readme.html">JMX example</a> for a complete explanation of the different steps)</li> + <pre class="prettyprint"> + <code>ObjectName on = ObjectNameBuilder.DEFAULT.getHornetQServerObjectName(); + JMXConnector connector = JMXConnectorFactory.connect(new JMXServiceURL(JMX_URL), new HashMap<String, String>()); + MBeanServerConnection mbsc = connector.getMBeanServerConnection(); + HornetQServerControlMBean serverControl = (HornetQServerControlMBean)MBeanServerInvocationHandler.newProxyInstance(mbsc, + on, + HornetQServerControlMBean.class, + false); + </code> + </pre> + + <li>Using the server MBean, we list the remote address connected to the server</li> + <pre class="prettyprint"> + <code>String[] remoteAddresses = serverControl.listRemoteAddresses(); + for (String remoteAddress : remoteAddresses) + { + System.out.println(remoteAddress); + } + </code> + </pre> + + <p>It will display a single address corresponding to the connection opened at step 3.</p> + + <li>We close the connections corresponding to this remote address</li> + <pre class="prettyprint"> + <code>serverControl.closeConnectionsForAddress(remoteAddresses[0]);</code> + </pre> + + <p>Warnings be displayed on the server output:</p> + <pre class="prettyprint"> + <code>org.hornetq.jms.example.SpawnedJMSServer out:11:22:33,034 WARN @RMI TCP Connection(3)-192.168.0.10 [RemotingConnectionImpl] Connection failure has been detected connections for /192.168.0.10:52707 closed by management:0 + org.hornetq.jms.example.SpawnedJMSServer out:11:22:33,035 WARN @RMI TCP Connection(3)-192.168.0.10 [ServerSessionImpl] Client connection failed, clearing up resources for session 4646da35-2fe8-11de-9ce9-752ccc2b26e4 + org.hornetq.jms.example.SpawnedJMSServer out:11:22:33,035 WARN @RMI TCP Connection(3)-192.168.0.10 [ServerSessionImpl] Cleared up resources for session 4646da35-2fe8-11de-9ce9-752ccc2b26e4 + </code> + </pre> + + <li>We display the exception received by the connection's ExceptionListener</li> + <pre class="prettyprint"> + <code>exception.get().printStackTrace();</code> + </pre> + + <p>When the connection was closed on the server-side by the call to <code>serverControl.closeConnectionsForAddress()</code>, + the client's connection was disconnected and its exception listener was notified.</p> + + <li>And finally, <b>always</b> remember to close your JMS connections and resources after use, in a <code>finally</code> block. Closing a JMS connection will automatically close all of its sessions, consumers, producer and browser objects</li> + + <pre class="prettyprint"> + <code>finally + { + if (initialContext != null) + { + initialContext.close(); + } + if (connection != null) + { + connection.close(); + } + }</code> + </pre> + </ol> + + <h2>More information</h2> + + <ul> + <li><a href="http://java.sun.com/j2se/1.5.0/docs/guide/management/agent.html">Java 5 Management guide</a></li> + </ul> + </body> +</html> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/activemq-6/blob/8ecd255f/examples/jms/client-kickoff/src/main/java/org/hornetq/jms/example/ClientKickoffExample.java ---------------------------------------------------------------------- diff --git a/examples/jms/client-kickoff/src/main/java/org/hornetq/jms/example/ClientKickoffExample.java b/examples/jms/client-kickoff/src/main/java/org/hornetq/jms/example/ClientKickoffExample.java new file mode 100644 index 0000000..6923faa --- /dev/null +++ b/examples/jms/client-kickoff/src/main/java/org/hornetq/jms/example/ClientKickoffExample.java @@ -0,0 +1,126 @@ +/* + * Copyright 2005-2014 Red Hat, Inc. + * Red Hat 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.hornetq.jms.example; + +import java.util.HashMap; +import java.util.concurrent.atomic.AtomicReference; + +import javax.jms.ExceptionListener; +import javax.jms.JMSException; +import javax.jms.QueueConnection; +import javax.jms.QueueConnectionFactory; +import javax.management.MBeanServerConnection; +import javax.management.MBeanServerInvocationHandler; +import javax.management.ObjectName; +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXConnectorFactory; +import javax.management.remote.JMXServiceURL; +import javax.naming.InitialContext; + +import org.hornetq.api.core.management.HornetQServerControl; +import org.hornetq.api.core.management.ObjectNameBuilder; +import org.hornetq.common.example.HornetQExample; + +/** + * An example that shows how to kick off a client connected to HornetQ by using JMX. + * + * @author <a href="mailto:jmes...@redhat.com">Jeff Mesnil</a> + */ +public class ClientKickoffExample extends HornetQExample +{ + private static final String JMX_URL = "service:jmx:rmi:///jndi/rmi://localhost:3000/jmxrmi"; + + public static void main(final String[] args) + { + new ClientKickoffExample().run(args); + } + + @Override + public boolean runExample() throws Exception + { + QueueConnection connection = null; + InitialContext initialContext = null; + try + { + // Step 1. Create an initial context to perform the JNDI lookup. + initialContext = getContext(0); + + // Step 2. Perform a lookup on the Connection Factory + QueueConnectionFactory cf = (QueueConnectionFactory)initialContext.lookup("/ConnectionFactory"); + + // Step 3.Create a JMS Connection + connection = cf.createQueueConnection(); + + // Step 4. Set an exception listener on the connection to be notified after a problem occurred + final AtomicReference<JMSException> exception = new AtomicReference<JMSException>(); + connection.setExceptionListener(new ExceptionListener() + { + @Override + public void onException(final JMSException e) + { + exception.set(e); + } + }); + + // Step 5. We start the connection + connection.start(); + + // Step 6. Create a HornetQServerControlMBean proxy to manage the server + ObjectName on = ObjectNameBuilder.DEFAULT.getHornetQServerObjectName(); + JMXConnector connector = JMXConnectorFactory.connect(new JMXServiceURL(JMX_URL), new HashMap<String, String>()); + MBeanServerConnection mbsc = connector.getMBeanServerConnection(); + HornetQServerControl serverControl = MBeanServerInvocationHandler.newProxyInstance(mbsc, + on, + HornetQServerControl.class, + false); + + // Step 7. List the remote address connected to the server + System.out.println("List of remote addresses connected to the server:"); + System.out.println("----------------------------------"); + String[] remoteAddresses = serverControl.listRemoteAddresses(); + for (String remoteAddress : remoteAddresses) + { + System.out.println(remoteAddress); + } + System.out.println("----------------------------------"); + + // Step 8. Close the connections for the 1st remote address and kickoff the client + serverControl.closeConnectionsForAddress(remoteAddresses[0]); + + // Sleep a little bit so that the stack trace from the server won't be + // mingled with the JMSException received on the ExceptionListener + Thread.sleep(1000); + + // Step 9. Display the exception received by the connection's ExceptionListener + System.err.println("\nException received from the server:"); + System.err.println("----------------------------------"); + exception.get().printStackTrace(); + System.err.println("----------------------------------"); + + return true; + } + finally + { + // Step 10. Be sure to close the resources! + if (initialContext != null) + { + initialContext.close(); + } + if (connection != null) + { + connection.close(); + } + } + } + +} http://git-wip-us.apache.org/repos/asf/activemq-6/blob/8ecd255f/examples/jms/client-kickoff/src/main/resources/hornetq/server0/hornetq-configuration.xml ---------------------------------------------------------------------- diff --git a/examples/jms/client-kickoff/src/main/resources/hornetq/server0/hornetq-configuration.xml b/examples/jms/client-kickoff/src/main/resources/hornetq/server0/hornetq-configuration.xml new file mode 100644 index 0000000..8acfd26 --- /dev/null +++ b/examples/jms/client-kickoff/src/main/resources/hornetq/server0/hornetq-configuration.xml @@ -0,0 +1,30 @@ +<configuration xmlns="urn:hornetq" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="urn:hornetq /schema/hornetq-configuration.xsd"> + + <bindings-directory>${build.directory}/server0/data/messaging/bindings</bindings-directory> + + <journal-directory>${build.directory}/server0/data/messaging/journal</journal-directory> + + <large-messages-directory>${build.directory}/server0/data/messaging/largemessages</large-messages-directory> + + <paging-directory>${build.directory}/server0/data/messaging/paging</paging-directory> + + <!-- true to expose HornetQ resources through JMX --> + <jmx-management-enabled>true</jmx-management-enabled> + + <!-- Connectors --> + <connectors> + <connector name="netty"> + <factory-class>org.hornetq.core.remoting.impl.netty.NettyConnectorFactory</factory-class> + </connector> + </connectors> + + <!-- Acceptors --> + <acceptors> + <acceptor name="netty"> + <factory-class>org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class> + </acceptor> + </acceptors> + +</configuration> http://git-wip-us.apache.org/repos/asf/activemq-6/blob/8ecd255f/examples/jms/client-kickoff/src/main/resources/hornetq/server0/hornetq-jms.xml ---------------------------------------------------------------------- diff --git a/examples/jms/client-kickoff/src/main/resources/hornetq/server0/hornetq-jms.xml b/examples/jms/client-kickoff/src/main/resources/hornetq/server0/hornetq-jms.xml new file mode 100644 index 0000000..b0e4f89 --- /dev/null +++ b/examples/jms/client-kickoff/src/main/resources/hornetq/server0/hornetq-jms.xml @@ -0,0 +1,14 @@ +<configuration xmlns="urn:hornetq" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="urn:hornetq /schema/hornetq-jms.xsd"> + <!--the connection factory used by the example--> + <connection-factory name="ConnectionFactory" signature="queue"> + <connectors> + <connector-ref connector-name="netty"/> + </connectors> + <entries> + <entry name="ConnectionFactory"/> + </entries> + </connection-factory> + +</configuration> http://git-wip-us.apache.org/repos/asf/activemq-6/blob/8ecd255f/examples/jms/client-kickoff/src/main/resources/hornetq/server0/hornetq-users.xml ---------------------------------------------------------------------- diff --git a/examples/jms/client-kickoff/src/main/resources/hornetq/server0/hornetq-users.xml b/examples/jms/client-kickoff/src/main/resources/hornetq/server0/hornetq-users.xml new file mode 100644 index 0000000..934306c --- /dev/null +++ b/examples/jms/client-kickoff/src/main/resources/hornetq/server0/hornetq-users.xml @@ -0,0 +1,7 @@ +<configuration xmlns="urn:hornetq" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="urn:hornetq /schema/hornetq-users.xsd"> + <!-- the default user. this is used where username is null--> + <defaultuser name="guest" password="guest"> + <role name="guest"/> + </defaultuser> +</configuration> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/activemq-6/blob/8ecd255f/examples/jms/client-side-failoverlistener/pom.xml ---------------------------------------------------------------------- diff --git a/examples/jms/client-side-failoverlistener/pom.xml b/examples/jms/client-side-failoverlistener/pom.xml new file mode 100644 index 0000000..b940f17 --- /dev/null +++ b/examples/jms/client-side-failoverlistener/pom.xml @@ -0,0 +1,168 @@ +<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.hornetq.examples.jms</groupId> + <artifactId>jms-examples</artifactId> + <version>2.5.0-SNAPSHOT</version> + </parent> + + <artifactId>hornetq-jms-client-side-fileoverlistener-example</artifactId> + <packaging>jar</packaging> + <name>HornetQ JMS Client Side Failover listener Example</name> + + <dependencies> + <dependency> + <groupId>org.hornetq.examples.jms</groupId> + <artifactId>hornetq-jms-examples-common</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.jboss.spec.javax.jms</groupId> + <artifactId>jboss-jms-api_2.0_spec</artifactId> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.hornetq</groupId> + <artifactId>hornetq-maven-plugin</artifactId> + <executions> + <execution> + <id>start0</id> + <goals> + <goal>start</goal> + </goals> + <configuration> + <hornetqConfigurationDir>${basedir}/target/classes/hornetq/server0</hornetqConfigurationDir> + <systemProperties> + <property> + <name>build.directory</name> + <value>${basedir}/target/</value> + </property> + <property> + <name>udp-address</name> + <value>${udp-address}</value> + </property> + </systemProperties> + </configuration> + </execution> + <execution> + <id>start1</id> + <goals> + <goal>start</goal> + </goals> + <configuration> + <jndiPort>1199</jndiPort> + <jndiRmiPort>1198</jndiRmiPort> + <hornetqConfigurationDir>${basedir}/target/classes/hornetq/server1</hornetqConfigurationDir> + <fork>true</fork> + <systemProperties> + <property> + <name>build.directory</name> + <value>${basedir}/target/</value> + </property> + <property> + <name>udp-address</name> + <value>${udp-address}</value> + </property> + </systemProperties> + </configuration> + </execution> + + <execution> + <id>runClient</id> + <goals> + <goal>runClient</goal> + </goals> + <configuration> + <clientClass>org.hornetq.jms.example.ClientSideFailoverListerExample</clientClass> + <args> + <param>jnp://localhost:1099</param> + <param>jnp://localhost:1199</param> + </args> + <systemProperties> + <property> + <name>exampleConfigDir</name> + <value>${basedir}/target/classes/hornetq</value> + </property> + </systemProperties> + </configuration> + </execution> + <execution> + <id>stop0</id> + <goals> + <goal>stop</goal> + </goals> + <configuration> + <hornetqConfigurationDir>${basedir}/target/classes/hornetq/server0</hornetqConfigurationDir> + </configuration> + </execution> + <execution> + <id>stop1</id> + <goals> + <goal>stop</goal> + </goals> + <configuration> + <hornetqConfigurationDir>${basedir}/target/classes/hornetq/server1</hornetqConfigurationDir> + </configuration> + </execution> + </executions> + <dependencies> + <dependency> + <groupId>org.hornetq.examples.jms</groupId> + <artifactId>hornetq-jms-client-side-fileoverlistener-example</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.hornetq</groupId> + <artifactId>hornetq-core-client</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.hornetq</groupId> + <artifactId>hornetq-server</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.hornetq</groupId> + <artifactId>hornetq-jms-client</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.hornetq</groupId> + <artifactId>hornetq-jms-server</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>io.netty</groupId> + <artifactId>netty-all</artifactId> + <version>${netty.version}</version> + </dependency> + <dependency> + <groupId>org.jboss.javaee</groupId> + <artifactId>jboss-jms-api</artifactId> + <version>1.1.0.GA</version> + </dependency> + <dependency> + <groupId>org.jboss.naming</groupId> + <artifactId>jnpserver</artifactId> + <version>5.0.3.GA</version> + </dependency> + </dependencies> + <configuration> + <waitOnStart>false</waitOnStart> + <systemProperties> + <property> + <name>build.directory</name> + <value>${basedir}/target/</value> + </property> + </systemProperties> + </configuration> + </plugin> + </plugins> + </build> + +</project> http://git-wip-us.apache.org/repos/asf/activemq-6/blob/8ecd255f/examples/jms/client-side-failoverlistener/readme.html ---------------------------------------------------------------------- diff --git a/examples/jms/client-side-failoverlistener/readme.html b/examples/jms/client-side-failoverlistener/readme.html new file mode 100644 index 0000000..b67642b --- /dev/null +++ b/examples/jms/client-side-failoverlistener/readme.html @@ -0,0 +1,94 @@ +<html> + <head> + <title>HornetQ Client Side Failover Listener 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>Client Side Kickoff Example</h1> + + <p>This example demonstrates how you can listen on failover event on the client side.</p> + + <p>In this example there are two nodes running in a cluster, both server will be running for start, + but after a while the first server will crash. This will trigger an fail oever event.</p> + + <h2>Example step-by-step</h2> + <p><em>To run the example, simply type <code>mvn verify</code> from this directory</em></p> + <ol> + <li>First we need to get an initial context so we can look-up the JMS connection factory and destination objects from JNDI. This initial context will get its properties from <a href="src/main/resources/hornetq/server0/client-jndi.properties">client-jndi.properties</a></li> + <pre class="prettyprint"> + <code>InitialContext initialContext = getContext(0);</code> + </pre> + + <li>We look up the JMS Queue object from JNDI</li> + <pre class="prettyprint"> + <code>Queue queue = (Queue)initialContext.lookup("/queue/exampleQueue");</code> + </pre> + + <li>We look up a JMS Connection Factory object from JNDI on server 0</li> + <pre class="prettyprint"> + <code>ConnectionFactory connectionFactory = (ConnectionFactory)initialContext.lookup("/ConnectionFactory");</code> + </pre> + + <li>We create a JMS connection from the same connection factory, wait a little while to make sure broadcasts from all nodes have reached the client</li> + <pre class="prettyprint"> + <code> + Thread.sleep(5000); + connectionA = connectionFactory.createConnection(); + ((HornetQConnection)connectionA).setFailoverListener(new FailoverListenerImpl()); + </code> + </pre> + + <li>We create JMS Sessions</li> + <pre class="prettyprint"> + <code>Session sessionA = connectionA.createSession(false, Session.AUTO_ACKNOWLEDGE);</code> + </pre> + + <li>We create JMS MessageProducer objects on the sessions</li> + <pre class="prettyprint"> + <code>MessageProducer producerA = sessionA.createProducer(queue);</code> + </pre> + + <li>We send some messages on each producer</li> + <pre class="prettyprint"> + <code> + final int numMessages = 10; + + for (int i = 0; i < numMessages; i++) + { + TextMessage messageA = sessionA.createTextMessage("A:This is text message " + i); + producerA.send(messageA); + System.out.println("Sent message: " + messageA.getText()); + } + </code> + </pre> + + <li>We start the connection to consume messages</li> + <pre class="prettyprint"> + <code>connectionA.start();</code> + </pre> + + <li>We consume messages from the session A, one at a time. We reached message no 5 the first server will crash</li> + <pre class="prettyprint"> + <code>consume(sessionA, queue, numMessages, "A");</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> + if (connectionA != null) + { + connectionA.close(); + } + + if (initialContext != null) + { + initialContext.close(); + } + </code> + </pre> + </ol> + </body> +</html> \ No newline at end of file