http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/ha/multiple-failover-failback/src/main/java/org/apache/activemq/artemis/jms/example/MultipleFailoverFailbackExample.java ---------------------------------------------------------------------- diff --git a/examples/features/ha/multiple-failover-failback/src/main/java/org/apache/activemq/artemis/jms/example/MultipleFailoverFailbackExample.java b/examples/features/ha/multiple-failover-failback/src/main/java/org/apache/activemq/artemis/jms/example/MultipleFailoverFailbackExample.java new file mode 100644 index 0000000..ab0baec --- /dev/null +++ b/examples/features/ha/multiple-failover-failback/src/main/java/org/apache/activemq/artemis/jms/example/MultipleFailoverFailbackExample.java @@ -0,0 +1,142 @@ +/* + * 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.util.ServerUtil; + +import javax.jms.Connection; +import javax.jms.ConnectionFactory; +import javax.jms.JMSException; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Queue; +import javax.jms.Session; +import javax.jms.TextMessage; +import javax.naming.InitialContext; + +public class MultipleFailoverFailbackExample { + + public static void main(final String[] args) throws Exception { + final int numMessages = 30; + + Connection connection = null; + + InitialContext initialContext = null; + + Process[] servers = new Process[3]; + + try { + for (int i = 0; i < args.length; i++) { + servers[i] = ServerUtil.startServer(args[i], MultipleFailoverFailbackExample.class.getSimpleName() + i, i, 5000); + } + + // Step 1. Get an initial context for looking up JNDI from the server #1 + initialContext = new InitialContext(); + + // Step 2. Look up the JMS resources from JNDI + Queue queue = (Queue) initialContext.lookup("queue/exampleQueue"); + ConnectionFactory connectionFactory = (ConnectionFactory) initialContext.lookup("ConnectionFactory"); + + // Step 3. Create a JMS Connection + connection = connectionFactory.createConnection(); + + // Step 4. Create a *non-transacted* JMS Session with client acknowledgement + Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE); + + // Step 5. Start the connection to ensure delivery occurs + connection.start(); + + // Step 6. Create a JMS MessageProducer and a MessageConsumer + MessageProducer producer = session.createProducer(queue); + MessageConsumer consumer = session.createConsumer(queue); + + // Step 7. Send some messages to server #1, the live server + for (int i = 0; i < numMessages; i++) { + TextMessage message = session.createTextMessage("This is text message " + i); + producer.send(message); + System.out.println("Sent message: " + message.getText()); + } + + // Step 8. Receive and acknowledge a third of the sent messages + TextMessage message0 = null; + for (int i = 0; i < numMessages / 3; i++) { + message0 = (TextMessage) consumer.receive(5000); + System.out.println("Got message: " + message0.getText()); + } + message0.acknowledge(); + + // Step 9. Receive the rest third of the sent messages but *do not* acknowledge them yet + for (int i = numMessages / 3; i < numMessages; i++) { + message0 = (TextMessage) consumer.receive(5000); + System.out.println("Got message: " + message0.getText()); + } + + // Step 10. Crash server #1, the live server, and wait a little while to make sure + // it has really crashed + ServerUtil.killServer(servers[0]); + + // Step 11. Acknowledging the 2nd half of the sent messages will fail as failover to the + // backup server has occurred + try { + message0.acknowledge(); + } + catch (JMSException e) { + System.err.println("Got exception while acknowledging message: " + e.getMessage()); + } + + // Step 12. Consume again the 2nd third of the messages again. Note that they are not considered as redelivered. + for (int i = numMessages / 3; i < (numMessages / 3) * 2; i++) { + message0 = (TextMessage) consumer.receive(5000); + System.out.printf("Got message: %s (redelivered?: %s)%n", message0.getText(), message0.getJMSRedelivered()); + } + message0.acknowledge(); + + servers[0] = ServerUtil.startServer(args[0], MultipleFailoverFailbackExample.class.getSimpleName() + 0, 0, 5000); + + // Step 11. Acknowledging the 2nd half of the sent messages will fail as failover to the + // backup server has occurred + try { + message0.acknowledge(); + } + catch (JMSException e) { + System.err.println("Got exception while acknowledging message: " + e.getMessage()); + } + + // Step 12. Consume again the 2nd third of the messages again. Note that they are not considered as redelivered. + for (int i = (numMessages / 3) * 2; i < numMessages; i++) { + message0 = (TextMessage) consumer.receive(5000); + System.out.printf("Got message: %s (redelivered?: %s)%n", message0.getText(), message0.getJMSRedelivered()); + } + message0.acknowledge(); + } + finally { + // Step 13. Be sure to close our resources! + + if (connection != null) { + connection.close(); + } + + if (initialContext != null) { + initialContext.close(); + } + + for (int i = 0; i < args.length; i++) { + ServerUtil.killServer(servers[i]); + } + } + } +}
http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/ha/multiple-failover-failback/src/main/resources/jndi.properties ---------------------------------------------------------------------- diff --git a/examples/features/ha/multiple-failover-failback/src/main/resources/jndi.properties b/examples/features/ha/multiple-failover-failback/src/main/resources/jndi.properties new file mode 100644 index 0000000..7f7a19f --- /dev/null +++ b/examples/features/ha/multiple-failover-failback/src/main/resources/jndi.properties @@ -0,0 +1,20 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +java.naming.factory.initial=org.apache.activemq.artemis.jndi.ActiveMQInitialContextFactory +connectionFactory.ConnectionFactory=tcp://localhost:61616?ha=true&retryInterval=1000&retryIntervalMultiplier=1.0&reconnectAttempts=-1 +queue.queue/exampleQueue=exampleQueue http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/ha/multiple-failover/pom.xml ---------------------------------------------------------------------- diff --git a/examples/features/ha/multiple-failover/pom.xml b/examples/features/ha/multiple-failover/pom.xml new file mode 100644 index 0000000..a9a0b03 --- /dev/null +++ b/examples/features/ha/multiple-failover/pom.xml @@ -0,0 +1,121 @@ +<?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.failover</groupId> + <artifactId>broker-failover</artifactId> + <version>1.0.1-SNAPSHOT</version> + </parent> + + <artifactId>multiple-failover</artifactId> + <packaging>jar</packaging> + <name>ActiveMQ Artemis JMS Multiple Failover Example</name> + + <properties> + <activemq.basedir>${project.basedir}/../../../..</activemq.basedir> + </properties> + + <dependencies> + <dependency> + <groupId>org.apache.activemq</groupId> + <artifactId>artemis-cli</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.apache.geronimo.specs</groupId> + <artifactId>geronimo-jms_2.0_spec</artifactId> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.activemq</groupId> + <artifactId>artemis-maven-plugin</artifactId> + <executions> + <execution> + <id>create0</id> + <goals> + <goal>create</goal> + </goals> + <configuration> + <instance>${basedir}/target/server0</instance> + <sharedStore>true</sharedStore> + <slave>false</slave> + <dataFolder>../data</dataFolder> + <failoverOnShutdown>true</failoverOnShutdown> + </configuration> + </execution> + <execution> + <id>create1</id> + <goals> + <goal>create</goal> + </goals> + <configuration> + <instance>${basedir}/target/server1</instance> + <sharedStore>true</sharedStore> + <slave>true</slave> + <dataFolder>../data</dataFolder> + <failoverOnShutdown>true</failoverOnShutdown> + </configuration> + </execution> + <execution> + <id>create2</id> + <goals> + <goal>create</goal> + </goals> + <configuration> + <instance>${basedir}/target/server2</instance> + <sharedStore>true</sharedStore> + <slave>true</slave> + <dataFolder>../data</dataFolder> + </configuration> + </execution> + <execution> + <id>runClient</id> + <goals> + <goal>runClient</goal> + </goals> + <configuration> + <clientClass>org.apache.activemq.artemis.jms.example.MultipleFailoverExample</clientClass> + <args> + <param>${basedir}/target/server0</param> + <param>${basedir}/target/server1</param> + <param>${basedir}/target/server2</param> + </args> + </configuration> + </execution> + </executions> + <dependencies> + <dependency> + <groupId>org.apache.activemq.examples.failover</groupId> + <artifactId>multiple-failover</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/ha/multiple-failover/src/main/java/org/apache/activemq/artemis/jms/example/MultipleFailoverExample.java ---------------------------------------------------------------------- diff --git a/examples/features/ha/multiple-failover/src/main/java/org/apache/activemq/artemis/jms/example/MultipleFailoverExample.java b/examples/features/ha/multiple-failover/src/main/java/org/apache/activemq/artemis/jms/example/MultipleFailoverExample.java new file mode 100644 index 0000000..41d9e52 --- /dev/null +++ b/examples/features/ha/multiple-failover/src/main/java/org/apache/activemq/artemis/jms/example/MultipleFailoverExample.java @@ -0,0 +1,142 @@ +/* + * 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.util.ServerUtil; + +import javax.jms.Connection; +import javax.jms.ConnectionFactory; +import javax.jms.JMSException; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Queue; +import javax.jms.Session; +import javax.jms.TextMessage; +import javax.naming.InitialContext; + +public class MultipleFailoverExample { + + public static void main(final String[] args) throws Exception { + final int numMessages = 30; + + Connection connection = null; + + InitialContext initialContext = null; + + Process[] servers = new Process[3]; + + try { + for (int i = 0; i < args.length; i++) { + servers[i] = ServerUtil.startServer(args[i], MultipleFailoverExample.class.getSimpleName() + i, i, 5000); + } + + // Step 1. Get an initial context for looking up JNDI from the server #1 + initialContext = new InitialContext(); + + // Step 2. Look up the JMS resources from JNDI + Queue queue = (Queue) initialContext.lookup("queue/exampleQueue"); + ConnectionFactory connectionFactory = (ConnectionFactory) initialContext.lookup("ConnectionFactory"); + + // Step 3. Create a JMS Connection + connection = connectionFactory.createConnection(); + + // Step 4. Create a *non-transacted* JMS Session with client acknowledgement + Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE); + + // Step 5. Start the connection to ensure delivery occurs + connection.start(); + + // Step 6. Create a JMS MessageProducer and a MessageConsumer + MessageProducer producer = session.createProducer(queue); + MessageConsumer consumer = session.createConsumer(queue); + + // Step 7. Send some messages to server #1, the live server + for (int i = 0; i < numMessages; i++) { + TextMessage message = session.createTextMessage("This is text message " + i); + producer.send(message); + System.out.println("Sent message: " + message.getText()); + } + + // Step 8. Receive and acknowledge a third of the sent messages + TextMessage message0 = null; + for (int i = 0; i < numMessages / 3; i++) { + message0 = (TextMessage) consumer.receive(5000); + System.out.println("Got message: " + message0.getText()); + } + message0.acknowledge(); + + // Step 9. Receive the rest third of the sent messages but *do not* acknowledge them yet + for (int i = numMessages / 3; i < numMessages; i++) { + message0 = (TextMessage) consumer.receive(5000); + System.out.println("Got message: " + message0.getText()); + } + + // Step 10. Crash server #1, the live server, and wait a little while to make sure + // it has really crashed + ServerUtil.killServer(servers[0]); + + // Step 11. Acknowledging the 2nd half of the sent messages will fail as failover to the + // backup server has occurred + try { + message0.acknowledge(); + } + catch (JMSException e) { + System.err.println("Got exception while acknowledging message: " + e.getMessage()); + } + + // Step 12. Consume again the 2nd third of the messages again. Note that they are not considered as redelivered. + for (int i = numMessages / 3; i < (numMessages / 3) * 2; i++) { + message0 = (TextMessage) consumer.receive(5000); + System.out.printf("Got message: %s (redelivered?: %s)%n", message0.getText(), message0.getJMSRedelivered()); + } + message0.acknowledge(); + + ServerUtil.killServer(servers[ServerUtil.getServer(connection)]); + + // Step 11. Acknowledging the 2nd half of the sent messages will fail as failover to the + // backup server has occurred + try { + message0.acknowledge(); + } + catch (JMSException e) { + throw new IllegalStateException("Got exception while acknowledging message: " + e.getMessage()); + } + + // Step 12. Consume again the 2nd third of the messages again. Note that they are not considered as redelivered. + for (int i = (numMessages / 3) * 2; i < numMessages; i++) { + message0 = (TextMessage) consumer.receive(5000); + System.out.printf("Got message: %s (redelivered?: %s)%n", message0.getText(), message0.getJMSRedelivered()); + } + message0.acknowledge(); + } + finally { + // Step 13. Be sure to close our resources! + + if (connection != null) { + connection.close(); + } + + if (initialContext != null) { + initialContext.close(); + } + + for (int i = 0; i < args.length; i++) { + ServerUtil.killServer(servers[i]); + } + } + } +} http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/ha/multiple-failover/src/main/resources/jndi.properties ---------------------------------------------------------------------- diff --git a/examples/features/ha/multiple-failover/src/main/resources/jndi.properties b/examples/features/ha/multiple-failover/src/main/resources/jndi.properties new file mode 100644 index 0000000..7f7a19f --- /dev/null +++ b/examples/features/ha/multiple-failover/src/main/resources/jndi.properties @@ -0,0 +1,20 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +java.naming.factory.initial=org.apache.activemq.artemis.jndi.ActiveMQInitialContextFactory +connectionFactory.ConnectionFactory=tcp://localhost:61616?ha=true&retryInterval=1000&retryIntervalMultiplier=1.0&reconnectAttempts=-1 +queue.queue/exampleQueue=exampleQueue http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/ha/non-transaction-failover/pom.xml ---------------------------------------------------------------------- diff --git a/examples/features/ha/non-transaction-failover/pom.xml b/examples/features/ha/non-transaction-failover/pom.xml new file mode 100644 index 0000000..1b5a600 --- /dev/null +++ b/examples/features/ha/non-transaction-failover/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.failover</groupId> + <artifactId>broker-failover</artifactId> + <version>1.0.1-SNAPSHOT</version> + </parent> + + <artifactId>non-transaction-failover</artifactId> + <packaging>jar</packaging> + <name>ActiveMQ Artemis JMS Non Transaction Failover Example</name> + + <properties> + <activemq.basedir>${project.basedir}/../../../..</activemq.basedir> + </properties> + + <dependencies> + <dependency> + <groupId>org.apache.activemq</groupId> + <artifactId>artemis-cli</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.apache.activemq</groupId> + <artifactId>artemis-jms-client</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.activemq</groupId> + <artifactId>artemis-maven-plugin</artifactId> + <executions> + <execution> + <id>create0</id> + <goals> + <goal>create</goal> + </goals> + <configuration> + <instance>${basedir}/target/server0</instance> + <sharedStore>true</sharedStore> + <slave>false</slave> + <dataFolder>../data</dataFolder> + <failoverOnShutdown>true</failoverOnShutdown> + </configuration> + </execution> + <execution> + <id>create1</id> + <goals> + <goal>create</goal> + </goals> + <configuration> + <instance>${basedir}/target/server1</instance> + <sharedStore>true</sharedStore> + <slave>true</slave> + <dataFolder>../data</dataFolder> + <failoverOnShutdown>true</failoverOnShutdown> + </configuration> + </execution> + <execution> + <id>runClient</id> + <goals> + <goal>runClient</goal> + </goals> + <configuration> + <clientClass>org.apache.activemq.artemis.jms.example.NonTransactionFailoverExample</clientClass> + <args> + <param>${basedir}/target/server0</param> + <param>${basedir}/target/server1</param> + </args> + </configuration> + </execution> + </executions> + <dependencies> + <dependency> + <groupId>org.apache.activemq.examples.failover</groupId> + <artifactId>non-transaction-failover</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/ha/non-transaction-failover/readme.html ---------------------------------------------------------------------- diff --git a/examples/features/ha/non-transaction-failover/readme.html b/examples/features/ha/non-transaction-failover/readme.html new file mode 100644 index 0000000..647e7b8 --- /dev/null +++ b/examples/features/ha/non-transaction-failover/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 Failover Without Transactions 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 Failover Without Transactions Example</h1> + + <pre>To run the example, simply type <b>mvn verify</b> from this directory.</pre> + + + <p>This example demonstrates two servers coupled as a live-backup pair for high availability (HA), and a client + connection failing over from live to backup when the live server is crashed.</p> + <p>Failover behavior differs whether the JMS session is transacted or not.</p> + <p>When a <em>non-transacted</em> JMS session is used, once and only once delivery is not guaranteed + and it is possible some messages will be lost or delivered twice, depending when the failover to the backup server occurs.</p> + <p>It is up to the client to deal with such cases. To ensure once and only once delivery, the client must + use transacted JMS sessions (as shown in the example for <a href="../transaction-failover/readme.html">failover with transactions</a>).</p> + <p>For more information on ActiveMQ Artemis failover and HA, and clustering in general, please see the clustering + section of the user manual.</p> + + <h2>Example step-by-step</h2> + <p>In this example, the live server is server 1, and the backup server is server 0</p> + <p>The connection will initially be created to server1, server 1 will crash, and the client will carry on + seamlessly on server 0, the backup server.</p> + <ol> + <li>Get an initial context for looking up JNDI from server #1.</li> + <pre class="prettyprint"> + initialContext = getContext(1); + </pre> + + <li>Look up the JMS resources from JNDI on server #1.</li> + <pre class="prettyprint"> + Queue queue = (Queue)initialContext.lookup("/queue/exampleQueue"); + ConnectionFactory connectionFactory = (ConnectionFactory)initialContext.lookup("/ConnectionFactory"); + </pre> + + <li>Create a JMS Connection</li> + <pre class="prettyprint"> + connection = connectionFactory.createConnection(); + </pre> + + <li>Create a JMS <em>non-transacted</em> Session with client acknowledgement</li> + <pre class="prettyprint"> + Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE); + </pre> + + <li>Start the connection to ensure delivery occurs</li> + <pre class="prettyprint"> + connection.start(); + </pre> + + <li>Create a JMS MessageProducer and MessageConsumer</li> + <pre class="prettyprint"> + MessageProducer producer = session.createProducer(queue); + MessageConsumer consumer = session.createConsumer(queue); + </pre> + + <li>Send some messages to server #1</li> + <pre class="prettyprint"> + for (int i = 0; i < numMessages; i++) + { + TextMessage message = session.createTextMessage("This is text message " + i); + producer.send(message); + System.out.println("Sent message: " + message.getText()); + } + </pre> + + <li>Receive and acknowledge half of the sent messages</li> + <pre class="prettyprint"> + TextMessage message0 = null; + for (int i = 0; i < numMessages / 2; i++) + { + message0 = (TextMessage)consumer.receive(5000); + System.out.println("Got message: " + message0.getText()); + } + message0.acknowledge(); + </pre> + + <li>Receive the second half of the sent messages but <em>do not acknowledge them yet</em></li> + <pre class="prettyprint"> + for (int i = numMessages / 2; i < numMessages; i++) + { + message0 = (TextMessage)consumer.receive(5000); + System.out.println("Got message: " + message0.getText()); + } + </pre> + + <li>Crash server #1, the live server, and wait a little while to make sure it has really crashed.</li> + <pre class="prettyprint"> + killServer(1); + Thread.sleep(2000); + </pre> + + <li>Acknowledging the second half of the sent messages will fail as failover to the backup server has occurred</li> + <pre class="prettyprint"> + try + { + message0.acknowledge(); + } + catch (JMSException e) + { + System.err.println("Got exception while acknowledging message: " + e.getMessage()); + } + </pre> + + <li>Consume again the second half of the messages againg. Note that they are not considered as redelivered</li> + <pre class="prettyprint"> + for (int i = numMessages / 2; i < numMessages; i++) + { + message0 = (TextMessage)consumer.receive(5000); + System.out.printf("Got message: %s (redelivered?: %s)\n", message0.getText(), message0.getJMSRedelivered()); + } + message0.acknowledge(); + </pre> + + <li>And finally, <strong>always</strong> remember to close your 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"> + finally + { + if (connection != null) + { + connection.close(); + } + + if (initialContext != null) + { + initialContext.close(); + } + } + </pre> + + </ol> + </body> +</html> http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/ha/non-transaction-failover/src/main/java/org/apache/activemq/artemis/jms/example/NonTransactionFailoverExample.java ---------------------------------------------------------------------- diff --git a/examples/features/ha/non-transaction-failover/src/main/java/org/apache/activemq/artemis/jms/example/NonTransactionFailoverExample.java b/examples/features/ha/non-transaction-failover/src/main/java/org/apache/activemq/artemis/jms/example/NonTransactionFailoverExample.java new file mode 100644 index 0000000..9352ac5 --- /dev/null +++ b/examples/features/ha/non-transaction-failover/src/main/java/org/apache/activemq/artemis/jms/example/NonTransactionFailoverExample.java @@ -0,0 +1,128 @@ +/* + * 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.util.ServerUtil; + +import javax.jms.Connection; +import javax.jms.ConnectionFactory; +import javax.jms.JMSException; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Queue; +import javax.jms.Session; +import javax.jms.TextMessage; +import javax.naming.InitialContext; + +/** + * A simple example that demonstrates failover of the JMS connection from one node to another + * when the live server crashes using a JMS <em>non-transacted</em> session. + */ +public class NonTransactionFailoverExample { + + public static void main(final String[] args) throws Exception { + final int numMessages = 10; + + Connection connection = null; + + InitialContext initialContext = null; + + Process[] servers = new Process[2]; + + try { + for (int i = 0; i < args.length; i++) { + servers[i] = ServerUtil.startServer(args[i], NonTransactionFailoverExample.class.getSimpleName() + i, i, 5000); + } + + // Step 1. Get an initial context for looking up JNDI from the server #1 + initialContext = new InitialContext(); + + // Step 2. Look up the JMS resources from JNDI + Queue queue = (Queue) initialContext.lookup("queue/exampleQueue"); + ConnectionFactory connectionFactory = (ConnectionFactory) initialContext.lookup("ConnectionFactory"); + + // Step 3. Create a JMS Connection + connection = connectionFactory.createConnection(); + + // Step 4. Create a *non-transacted* JMS Session with client acknowledgement + Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE); + + // Step 5. Start the connection to ensure delivery occurs + connection.start(); + + // Step 6. Create a JMS MessageProducer and a MessageConsumer + MessageProducer producer = session.createProducer(queue); + MessageConsumer consumer = session.createConsumer(queue); + + // Step 7. Send some messages to server #1, the live server + for (int i = 0; i < numMessages; i++) { + TextMessage message = session.createTextMessage("This is text message " + i); + producer.send(message); + System.out.println("Sent message: " + message.getText()); + } + + // Step 8. Receive and acknowledge half of the sent messages + TextMessage message0 = null; + for (int i = 0; i < numMessages / 2; i++) { + message0 = (TextMessage) consumer.receive(5000); + System.out.println("Got message: " + message0.getText()); + } + message0.acknowledge(); + + // Step 9. Receive the 2nd half of the sent messages but *do not* acknowledge them yet + for (int i = numMessages / 2; i < numMessages; i++) { + message0 = (TextMessage) consumer.receive(5000); + System.out.println("Got message: " + message0.getText()); + } + + // Step 10. Crash server #1, the live server, and wait a little while to make sure + // pending Acks are on the server's side + ServerUtil.killServer(servers[0]); + + // Step 11. Acknowledging the 2nd half of the sent messages will fail as failover to the + // backup server has occurred + try { + message0.acknowledge(); + } + catch (JMSException e) { + System.err.println("Got exception while acknowledging message: " + e.getMessage()); + } + + // Step 12. Consume again the 2nd half of the messages again. Note that they are not considered as redelivered. + for (int i = numMessages / 2; i < numMessages; i++) { + message0 = (TextMessage) consumer.receive(5000); + System.out.printf("Got message: %s (redelivered?: %s)%n", message0.getText(), message0.getJMSRedelivered()); + } + message0.acknowledge(); + } + finally { + // Step 13. Be sure to close our resources! + + if (connection != null) { + connection.close(); + } + + if (initialContext != null) { + initialContext.close(); + } + + for (int i = 0; i < args.length; i++) { + ServerUtil.killServer(servers[i]); + } + } + } +} http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/ha/non-transaction-failover/src/main/resources/jndi.properties ---------------------------------------------------------------------- diff --git a/examples/features/ha/non-transaction-failover/src/main/resources/jndi.properties b/examples/features/ha/non-transaction-failover/src/main/resources/jndi.properties new file mode 100644 index 0000000..7f7a19f --- /dev/null +++ b/examples/features/ha/non-transaction-failover/src/main/resources/jndi.properties @@ -0,0 +1,20 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +java.naming.factory.initial=org.apache.activemq.artemis.jndi.ActiveMQInitialContextFactory +connectionFactory.ConnectionFactory=tcp://localhost:61616?ha=true&retryInterval=1000&retryIntervalMultiplier=1.0&reconnectAttempts=-1 +queue.queue/exampleQueue=exampleQueue http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/ha/pom.xml ---------------------------------------------------------------------- diff --git a/examples/features/ha/pom.xml b/examples/features/ha/pom.xml new file mode 100644 index 0000000..016d9b1 --- /dev/null +++ b/examples/features/ha/pom.xml @@ -0,0 +1,95 @@ +<?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.clustered</groupId> + <artifactId>broker-features</artifactId> + <version>1.0.1-SNAPSHOT</version> + </parent> + + <groupId>org.apache.activemq.examples.failover</groupId> + <artifactId>broker-failover</artifactId> + <packaging>pom</packaging> + <name>ActiveMQ Artemis Failover Examples</name> + + <!-- Properties --> + <properties> + <!-- + Explicitly declaring the source encoding eliminates the following + message: [WARNING] Using platform encoding (UTF-8 actually) to copy + filtered resources, i.e. build is platform dependent! + --> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <activemq.basedir>${project.basedir}/../../..</activemq.basedir> + </properties> + + <profiles> + <profile> + <id>release</id> + <modules> + <module>application-layer-failover</module> + <module>client-side-failoverlistener</module> + <module>colocated-failover</module> + <module>colocated-failover-scale-down</module> + <module>ha-policy-autobackup</module> + <module>multiple-failover</module> + <module>multiple-failover-failback</module> + <module>non-transaction-failover</module> + <module>replicated-failback</module> + <module>replicated-failback-static</module> + <module>replicated-multiple-failover</module> + <module>replicated-transaction-failover</module> + <module>scale-down</module> + <module>stop-server-failover</module> + <module>transaction-failover</module> + </modules> + </profile> + <profile> + <id>examples</id> + <modules> + <module>application-layer-failover</module> + <module>client-side-failoverlistener</module> + + <!-- ARTEMIS-197 FIX ME: + <module>colocated-failover</module> + <module>colocated-failover-scale-down</module> --> + + <module>ha-policy-autobackup</module> + <module>multiple-failover</module> + <module>multiple-failover-failback</module> + <module>non-transaction-failover</module> + + <!-- ARTEMIS-197 FIX ME: + <module>replicated-failback</module> + <module>replicated-failback-static</module> --> + + <module>replicated-multiple-failover</module> + <module>replicated-transaction-failover</module> + <module>scale-down</module> + <module>transaction-failover</module> + </modules> + </profile> + </profiles> + +</project> http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/ha/replicated-failback-static/pom.xml ---------------------------------------------------------------------- diff --git a/examples/features/ha/replicated-failback-static/pom.xml b/examples/features/ha/replicated-failback-static/pom.xml new file mode 100644 index 0000000..91bb01e --- /dev/null +++ b/examples/features/ha/replicated-failback-static/pom.xml @@ -0,0 +1,104 @@ +<?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.failover</groupId> + <artifactId>broker-failover</artifactId> + <version>1.0.1-SNAPSHOT</version> + </parent> + + <artifactId>replicated-failback-static</artifactId> + <packaging>jar</packaging> + <name>ActiveMQ Artemis JMS Replicated Failback Static Example</name> + + <properties> + <activemq.basedir>${project.basedir}/../../../..</activemq.basedir> + </properties> + + <dependencies> + <dependency> + <groupId>org.apache.activemq</groupId> + <artifactId>artemis-cli</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.apache.activemq</groupId> + <artifactId>artemis-jms-client</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.activemq</groupId> + <artifactId>artemis-maven-plugin</artifactId> + <executions> + <execution> + <id>create0</id> + <goals> + <goal>create</goal> + </goals> + <configuration> + <instance>${basedir}/target/server0</instance> + <configuration>${basedir}/target/classes/activemq/server0</configuration> + <javaOptions>-Dudp-address=${udp-address}</javaOptions> + </configuration> + </execution> + <execution> + <id>create1</id> + <goals> + <goal>create</goal> + </goals> + <configuration> + <instance>${basedir}/target/server1</instance> + <configuration>${basedir}/target/classes/activemq/server1</configuration> + <javaOptions>-Dudp-address=${udp-address}</javaOptions> + </configuration> + </execution> + <execution> + <id>runClient</id> + <goals> + <goal>runClient</goal> + </goals> + <configuration> + <clientClass>org.apache.activemq.artemis.jms.example.ReplicatedFailbackStaticExample</clientClass> + <args> + <param>${basedir}/target/server0</param> + <param>${basedir}/target/server1</param> + </args> + </configuration> + </execution> + </executions> + <dependencies> + <dependency> + <groupId>org.apache.activemq.examples.failover</groupId> + <artifactId>replicated-failback-static</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/ha/replicated-failback-static/readme.html ---------------------------------------------------------------------- diff --git a/examples/features/ha/replicated-failback-static/readme.html b/examples/features/ha/replicated-failback-static/readme.html new file mode 100644 index 0000000..cab789a --- /dev/null +++ b/examples/features/ha/replicated-failback-static/readme.html @@ -0,0 +1,38 @@ +<!-- +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 Failback using Static selectors 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 Multiple Failover using Replication Example</h1> + + <pre>To run the example, simply type <b>mvn verify</b> from this directory.</pre> + + <p>This example demonstrates three servers coupled as a live-backup-backup group for high availability (HA) using replication, and a client + connection failing over from live to backup when the live server is crashed and then to the second backup once the new live fails.</p> + + <p>For more information on ActiveMQ Artemis failover and HA, and clustering in general, please see the clustering + section of the user manual.</p> + </body> +</html> http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/ha/replicated-failback-static/src/main/java/org/apache/activemq/artemis/jms/example/ReplicatedFailbackStaticExample.java ---------------------------------------------------------------------- diff --git a/examples/features/ha/replicated-failback-static/src/main/java/org/apache/activemq/artemis/jms/example/ReplicatedFailbackStaticExample.java b/examples/features/ha/replicated-failback-static/src/main/java/org/apache/activemq/artemis/jms/example/ReplicatedFailbackStaticExample.java new file mode 100644 index 0000000..d2f74ba --- /dev/null +++ b/examples/features/ha/replicated-failback-static/src/main/java/org/apache/activemq/artemis/jms/example/ReplicatedFailbackStaticExample.java @@ -0,0 +1,149 @@ +/* + * 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.util.ServerUtil; + +import javax.jms.Connection; +import javax.jms.ConnectionFactory; +import javax.jms.JMSException; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Queue; +import javax.jms.Session; +import javax.jms.TextMessage; +import javax.naming.InitialContext; + +/** + * Example of live and replicating backup pair. + * <p> + * After both servers are started, the live server is killed and the backup becomes active ("fails-over"). + * <p> + * Later the live server is restarted and takes back its position by asking the backup to stop ("fail-back"). + */ +public class ReplicatedFailbackStaticExample { + + private static Process server0; + + private static Process server1; + + public static void main(final String[] args) throws Exception { + final int numMessages = 30; + + Connection connection = null; + + InitialContext initialContext = null; + + try { + server0 = ServerUtil.startServer(args[0], ReplicatedFailbackStaticExample.class.getSimpleName() + "0", 0, 30000); + server1 = ServerUtil.startServer(args[1], ReplicatedFailbackStaticExample.class.getSimpleName() + "1", 1, 10000); + + // Step 1. Get an initial context for looking up JNDI from the server #1 + initialContext = new InitialContext(); + + // Step 2. Look up the JMS resources from JNDI + Queue queue = (Queue) initialContext.lookup("queue/exampleQueue"); + ConnectionFactory connectionFactory = (ConnectionFactory) initialContext.lookup("ConnectionFactory"); + + // Step 3. Create a JMS Connection + connection = connectionFactory.createConnection(); + + // Step 4. Create a *non-transacted* JMS Session with client acknowledgement + Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE); + + // Step 5. Start the connection to ensure delivery occurs + connection.start(); + + // Step 6. Create a JMS MessageProducer and a MessageConsumer + MessageProducer producer = session.createProducer(queue); + MessageConsumer consumer = session.createConsumer(queue); + + // Step 7. Send some messages to server #1, the live server + for (int i = 0; i < numMessages; i++) { + TextMessage message = session.createTextMessage("This is text message " + i); + producer.send(message); + System.out.println("Sent message: " + message.getText()); + } + + // Step 8. Receive and acknowledge a third of the sent messages + TextMessage message0 = null; + for (int i = 0; i < numMessages / 3; i++) { + message0 = (TextMessage) consumer.receive(5000); + System.out.println("Got message: " + message0.getText()); + } + message0.acknowledge(); + + // Step 9. Receive the rest third of the sent messages but *do not* acknowledge them yet + for (int i = numMessages / 3; i < numMessages; i++) { + message0 = (TextMessage) consumer.receive(5000); + System.out.println("Got message: " + message0.getText()); + } + + // Step 10. Crash server #0, the live server, and wait a little while to make sure + // it has really crashed + ServerUtil.killServer(server0); + + // Step 11. Acknowledging the 2nd half of the sent messages will fail as failover to the + // backup server has occurred + try { + message0.acknowledge(); + } + catch (JMSException e) { + System.out.println("Got (the expected) exception while acknowledging message: " + e.getMessage()); + } + + // Step 12. Consume again the 2nd third of the messages again. Note that they are not considered as redelivered. + for (int i = numMessages / 3; i < (numMessages / 3) * 2; i++) { + message0 = (TextMessage) consumer.receive(5000); + System.out.printf("Got message: %s (redelivered?: %s)\n", message0.getText(), message0.getJMSRedelivered()); + } + message0.acknowledge(); + + server0 = ServerUtil.startServer(args[0], ReplicatedFailbackStaticExample.class.getSimpleName() + "0", 0, 10000); + + // Step 11. Acknowledging the 2nd half of the sent messages will fail as failover to the + // backup server has occurred + try { + message0.acknowledge(); + } + catch (JMSException e) { + System.err.println("Got exception while acknowledging message: " + e.getMessage()); + } + + // Step 12. Consume again the 2nd third of the messages again. Note that they are not considered as redelivered. + for (int i = (numMessages / 3) * 2; i < numMessages; i++) { + message0 = (TextMessage) consumer.receive(5000); + System.out.printf("Got message: %s (redelivered?: %s)\n", message0.getText(), message0.getJMSRedelivered()); + } + message0.acknowledge(); + } + finally { + // Step 13. Be sure to close our resources! + + if (connection != null) { + connection.close(); + } + + if (initialContext != null) { + initialContext.close(); + } + + ServerUtil.killServer(server0); + ServerUtil.killServer(server1); + } + } +} http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/ha/replicated-failback-static/src/main/resources/activemq/server0/broker.xml ---------------------------------------------------------------------- diff --git a/examples/features/ha/replicated-failback-static/src/main/resources/activemq/server0/broker.xml b/examples/features/ha/replicated-failback-static/src/main/resources/activemq/server0/broker.xml new file mode 100644 index 0000000..f6fa349 --- /dev/null +++ b/examples/features/ha/replicated-failback-static/src/main/resources/activemq/server0/broker.xml @@ -0,0 +1,87 @@ +<?xml version='1.0'?> +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +--> + +<configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="urn:activemq" + xsi:schemaLocation="urn:activemq /schema/artemis-server.xsd"> + + <jms xmlns="urn:activemq:jms"> + <!--the queue used by the example--> + <queue name="exampleQueue"/> + </jms> + + <core xmlns="urn:activemq:core"> + + <bindings-directory>./data/bindings</bindings-directory> + + <journal-directory>./data/journal</journal-directory> + + <large-messages-directory>./data/largemessages</large-messages-directory> + + <paging-directory>./data/paging</paging-directory> + + <cluster-user>exampleUser</cluster-user> + + <cluster-password>secret</cluster-password> + + <ha-policy> + <replication> + <master> + <!--we need this for auto failback--> + <check-for-live-server>true</check-for-live-server> + </master> + </replication> + </ha-policy> + + <connectors> + <connector name="netty-connector">tcp://localhost:61616</connector> + <connector name="netty-backup-connector">tcp://localhost:61617</connector> + </connectors> + + <!-- Acceptors --> + <acceptors> + <acceptor name="netty-acceptor">tcp://localhost:61616</acceptor> + </acceptors> + + <cluster-connections> + <cluster-connection name="my-cluster"> + <address>jms</address> + <connector-ref>netty-connector</connector-ref> + <static-connectors> + <connector-ref>netty-backup-connector</connector-ref> + </static-connectors> + </cluster-connection> + </cluster-connections> + <!-- 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> + + </core> +</configuration> http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/ha/replicated-failback-static/src/main/resources/activemq/server1/broker.xml ---------------------------------------------------------------------- diff --git a/examples/features/ha/replicated-failback-static/src/main/resources/activemq/server1/broker.xml b/examples/features/ha/replicated-failback-static/src/main/resources/activemq/server1/broker.xml new file mode 100644 index 0000000..9b89d80 --- /dev/null +++ b/examples/features/ha/replicated-failback-static/src/main/resources/activemq/server1/broker.xml @@ -0,0 +1,89 @@ +<?xml version='1.0'?> +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +--> + +<configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="urn:activemq" + xsi:schemaLocation="urn:activemq /schema/artemis-server.xsd"> + + <jms xmlns="urn:activemq:jms"> + <!--the queue used by the example--> + <queue name="exampleQueue"/> + </jms> + + <core xmlns="urn:activemq:core"> + + <bindings-directory>./data/bindings</bindings-directory> + + <journal-directory>./data/journal</journal-directory> + + <large-messages-directory>./data/largemessages</large-messages-directory> + + <paging-directory>./data/paging</paging-directory> + + <cluster-user>exampleUser</cluster-user> + + <cluster-password>secret</cluster-password> + + <ha-policy> + <replication> + <slave> + <allow-failback>true</allow-failback> + <!-- not needed but tells the backup not to restart after failback as there will be > 0 backups saved --> + <max-saved-replicated-journals-size>0</max-saved-replicated-journals-size> + </slave> + </replication> + </ha-policy> + + <!-- Connectors --> + <connectors> + <connector name="netty-live-connector">tcp://localhost:61616</connector> + <connector name="netty-connector">tcp://localhost:61617</connector> + </connectors> + + <!-- Acceptors --> + <acceptors> + <acceptor name="netty-acceptor">tcp://localhost:61617</acceptor> + </acceptors> + + <cluster-connections> + <cluster-connection name="my-cluster"> + <address>jms</address> + <connector-ref>netty-connector</connector-ref> + <static-connectors> + <connector-ref>netty-live-connector</connector-ref> + </static-connectors> + </cluster-connection> + </cluster-connections> + <!-- 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> + + </core> +</configuration> http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/ha/replicated-failback-static/src/main/resources/jndi.properties ---------------------------------------------------------------------- diff --git a/examples/features/ha/replicated-failback-static/src/main/resources/jndi.properties b/examples/features/ha/replicated-failback-static/src/main/resources/jndi.properties new file mode 100644 index 0000000..7f7a19f --- /dev/null +++ b/examples/features/ha/replicated-failback-static/src/main/resources/jndi.properties @@ -0,0 +1,20 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +java.naming.factory.initial=org.apache.activemq.artemis.jndi.ActiveMQInitialContextFactory +connectionFactory.ConnectionFactory=tcp://localhost:61616?ha=true&retryInterval=1000&retryIntervalMultiplier=1.0&reconnectAttempts=-1 +queue.queue/exampleQueue=exampleQueue http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/ha/replicated-failback/pom.xml ---------------------------------------------------------------------- diff --git a/examples/features/ha/replicated-failback/pom.xml b/examples/features/ha/replicated-failback/pom.xml new file mode 100644 index 0000000..d996718 --- /dev/null +++ b/examples/features/ha/replicated-failback/pom.xml @@ -0,0 +1,103 @@ +<?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.failover</groupId> + <artifactId>broker-failover</artifactId> + <version>1.0.1-SNAPSHOT</version> + </parent> + + <artifactId>replicated-failback</artifactId> + <packaging>jar</packaging> + <name>ActiveMQ Artemis JMS Replicated Failback Example</name> + + <properties> + <activemq.basedir>${project.basedir}/../../../..</activemq.basedir> + </properties> + + <dependencies> + <dependency> + <groupId>org.apache.activemq</groupId> + <artifactId>artemis-cli</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.apache.geronimo.specs</groupId> + <artifactId>geronimo-jms_2.0_spec</artifactId> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.activemq</groupId> + <artifactId>artemis-maven-plugin</artifactId> + <executions> + <execution> + <id>create0</id> + <goals> + <goal>create</goal> + </goals> + <configuration> + <instance>${basedir}/target/server0</instance> + <configuration>${basedir}/target/classes/activemq/server0</configuration> + <javaOptions>-Dudp-address=${udp-address}</javaOptions> + </configuration> + </execution> + <execution> + <id>create1</id> + <goals> + <goal>create</goal> + </goals> + <configuration> + <instance>${basedir}/target/server1</instance> + <configuration>${basedir}/target/classes/activemq/server1</configuration> + <javaOptions>-Dudp-address=${udp-address}</javaOptions> + </configuration> + </execution> + <execution> + <id>runClient</id> + <goals> + <goal>runClient</goal> + </goals> + <configuration> + <clientClass>org.apache.activemq.artemis.jms.example.ReplicatedFailbackExample</clientClass> + <args> + <param>${basedir}/target/server0</param> + <param>${basedir}/target/server1</param> + </args> + </configuration> + </execution> + </executions> + <dependencies> + <dependency> + <groupId>org.apache.activemq.examples.failover</groupId> + <artifactId>replicated-failback</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/ha/replicated-failback/readme.html ---------------------------------------------------------------------- diff --git a/examples/features/ha/replicated-failback/readme.html b/examples/features/ha/replicated-failback/readme.html new file mode 100644 index 0000000..4e53739 --- /dev/null +++ b/examples/features/ha/replicated-failback/readme.html @@ -0,0 +1,38 @@ +<!-- +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 Multiple Failover using Replication 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 Multiple Failover using Replication Example</h1> + + <pre>To run the example, simply type <b>mvn verify</b> from this directory.</pre> + + <p>This example demonstrates three servers coupled as a live-backup-backup group for high availability (HA) using replication, and a client + connection failing over from live to backup when the live server is crashed and then to the second backup once the new live fails.</p> + + <p>For more information on ActiveMQ Artemis failover and HA, and clustering in general, please see the clustering + section of the user manual.</p> + </body> +</html> http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/ha/replicated-failback/src/main/java/org/apache/activemq/artemis/jms/example/ReplicatedFailbackExample.java ---------------------------------------------------------------------- diff --git a/examples/features/ha/replicated-failback/src/main/java/org/apache/activemq/artemis/jms/example/ReplicatedFailbackExample.java b/examples/features/ha/replicated-failback/src/main/java/org/apache/activemq/artemis/jms/example/ReplicatedFailbackExample.java new file mode 100644 index 0000000..29ae381 --- /dev/null +++ b/examples/features/ha/replicated-failback/src/main/java/org/apache/activemq/artemis/jms/example/ReplicatedFailbackExample.java @@ -0,0 +1,149 @@ +/* + * 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.util.ServerUtil; + +import javax.jms.Connection; +import javax.jms.ConnectionFactory; +import javax.jms.JMSException; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Queue; +import javax.jms.Session; +import javax.jms.TextMessage; +import javax.naming.InitialContext; + +/** + * Example of live and replicating backup pair. + * <p> + * After both servers are started, the live server is killed and the backup becomes active ("fails-over"). + * <p> + * Later the live server is restarted and takes back its position by asking the backup to stop ("fail-back"). + */ +public class ReplicatedFailbackExample { + + private static Process server0; + + private static Process server1; + + public static void main(final String[] args) throws Exception { + final int numMessages = 30; + + Connection connection = null; + + InitialContext initialContext = null; + + try { + server0 = ServerUtil.startServer(args[0], ReplicatedFailbackExample.class.getSimpleName() + "0", 0, 30000); + server1 = ServerUtil.startServer(args[1], ReplicatedFailbackExample.class.getSimpleName() + "1", 1, 10000); + + // Step 1. Get an initial context for looking up JNDI from the server #1 + initialContext = new InitialContext(); + + // Step 2. Look up the JMS resources from JNDI + Queue queue = (Queue) initialContext.lookup("queue/exampleQueue"); + ConnectionFactory connectionFactory = (ConnectionFactory) initialContext.lookup("ConnectionFactory"); + + // Step 3. Create a JMS Connection + connection = connectionFactory.createConnection(); + + // Step 4. Create a *non-transacted* JMS Session with client acknowledgement + Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE); + + // Step 5. Start the connection to ensure delivery occurs + connection.start(); + + // Step 6. Create a JMS MessageProducer and a MessageConsumer + MessageProducer producer = session.createProducer(queue); + MessageConsumer consumer = session.createConsumer(queue); + + // Step 7. Send some messages to server #1, the live server + for (int i = 0; i < numMessages; i++) { + TextMessage message = session.createTextMessage("This is text message " + i); + producer.send(message); + System.out.println("Sent message: " + message.getText()); + } + + // Step 8. Receive and acknowledge a third of the sent messages + TextMessage message0 = null; + for (int i = 0; i < numMessages / 3; i++) { + message0 = (TextMessage) consumer.receive(5000); + System.out.println("Got message: " + message0.getText()); + } + message0.acknowledge(); + + // Step 9. Receive the rest third of the sent messages but *do not* acknowledge them yet + for (int i = numMessages / 3; i < numMessages; i++) { + message0 = (TextMessage) consumer.receive(5000); + System.out.println("Got message: " + message0.getText()); + } + + // Step 10. Crash server #0, the live server, and wait a little while to make sure + // it has really crashed + ServerUtil.killServer(server0); + + // Step 11. Acknowledging the 2nd half of the sent messages will fail as failover to the + // backup server has occurred + try { + message0.acknowledge(); + } + catch (JMSException e) { + System.out.println("Got (the expected) exception while acknowledging message: " + e.getMessage()); + } + + // Step 12. Consume again the 2nd third of the messages again. Note that they are not considered as redelivered. + for (int i = numMessages / 3; i < (numMessages / 3) * 2; i++) { + message0 = (TextMessage) consumer.receive(5000); + System.out.printf("Got message: %s (redelivered?: %s)\n", message0.getText(), message0.getJMSRedelivered()); + } + message0.acknowledge(); + + server0 = ServerUtil.startServer(args[0], ReplicatedFailbackExample.class.getSimpleName() + "0", 0, 10000); + + // Step 11. Acknowledging the 2nd half of the sent messages will fail as failover to the + // backup server has occurred + try { + message0.acknowledge(); + } + catch (JMSException e) { + System.err.println("Got exception while acknowledging message: " + e.getMessage()); + } + + // Step 12. Consume again the 2nd third of the messages again. Note that they are not considered as redelivered. + for (int i = (numMessages / 3) * 2; i < numMessages; i++) { + message0 = (TextMessage) consumer.receive(5000); + System.out.printf("Got message: %s (redelivered?: %s)\n", message0.getText(), message0.getJMSRedelivered()); + } + message0.acknowledge(); + } + finally { + // Step 13. Be sure to close our resources! + + if (connection != null) { + connection.close(); + } + + if (initialContext != null) { + initialContext.close(); + } + + ServerUtil.killServer(server0); + ServerUtil.killServer(server1); + } + } +} http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/6b17d966/examples/features/ha/replicated-failback/src/main/resources/activemq/server0/broker.xml ---------------------------------------------------------------------- diff --git a/examples/features/ha/replicated-failback/src/main/resources/activemq/server0/broker.xml b/examples/features/ha/replicated-failback/src/main/resources/activemq/server0/broker.xml new file mode 100644 index 0000000..c7f4783 --- /dev/null +++ b/examples/features/ha/replicated-failback/src/main/resources/activemq/server0/broker.xml @@ -0,0 +1,101 @@ +<?xml version='1.0'?> +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +--> + +<configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="urn:activemq" + xsi:schemaLocation="urn:activemq /schema/artemis-server.xsd"> + + <jms xmlns="urn:activemq:jms"> + <!--the queue used by the example--> + <queue name="exampleQueue"/> + </jms> + + <core xmlns="urn:activemq:core"> + + <bindings-directory>./data/bindings</bindings-directory> + + <journal-directory>./data/journal</journal-directory> + + <large-messages-directory>./data/largemessages</large-messages-directory> + + <paging-directory>./data/paging</paging-directory> + + <cluster-user>exampleUser</cluster-user> + + <cluster-password>secret</cluster-password> + + <ha-policy> + <replication> + <master> + <!--we need this for auto failback--> + <check-for-live-server>true</check-for-live-server> + </master> + </replication> + </ha-policy> + + <connectors> + <connector name="netty-connector">tcp://localhost:61616</connector> + </connectors> + + <!-- Acceptors --> + <acceptors> + <acceptor name="netty-acceptor">tcp://localhost:61616</acceptor> + </acceptors> + + <broadcast-groups> + <broadcast-group name="bg-group1"> + <group-address>${udp-address:231.7.7.7}</group-address> + <group-port>9876</group-port> + <broadcast-period>1000</broadcast-period> + <connector-ref>netty-connector</connector-ref> + </broadcast-group> + </broadcast-groups> + + <discovery-groups> + <discovery-group name="dg-group1"> + <group-address>${udp-address:231.7.7.7}</group-address> + <group-port>9876</group-port> + <refresh-timeout>5000</refresh-timeout> + </discovery-group> + </discovery-groups> + + <cluster-connections> + <cluster-connection name="my-cluster"> + <address>jms</address> + <connector-ref>netty-connector</connector-ref> + <discovery-group-ref discovery-group-name="dg-group1"/> + </cluster-connection> + </cluster-connections> + <!-- 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> + + </core> +</configuration>