Coding a JMS client to an Artemis JMS cluster
This tutorial demonstrates how to code a remote JMS client application which connects to an Artemis AMQ Broker and how to balance connections on the server side.
The provided code (taken from artemis examples) demonstrates how to connect to an Artemis clustered broker, sending and receiving messages from a queue. It also shows how the distribution of messages between multiple servers in the cluster works.
Include the Artemis Client dependencies
Firstly, add the your pom.xml the libraries to connect to the Artemis Server
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>artemis-jms-client</artifactId>
<version>${artemis.version}</version>
</dependency>
Code the JMS Client
Next, add the following ClusteredQueueExample that shows how to create a Connection to the two nodes of a Cluster and send a message to one node. Artemis will load balance the messages between the cluster nodes:
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.artemis.api.jms.ActiveMQJMSClient;
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
public class ClusteredQueueExample {
public static void main(final String[] args) throws Exception {
Connection connection0 = null;
Connection connection1 = null;
try {
// Step 2. Instantiate the Queue
Queue queue = ActiveMQJMSClient.createQueue("exampleQueue");
// Instantiate connection towards server 0
ConnectionFactory cf0 = new ActiveMQConnectionFactory("tcp://localhost:61616");
// Step 5. Look-up a JMS Connection Factory object from JNDI on server 1
ConnectionFactory cf1 = new ActiveMQConnectionFactory("tcp://localhost:61617");
// Step 6. We create a JMS Connection connection0 which is a connection to server 0
connection0 = cf0.createConnection();
// Step 7. We create a JMS Connection connection1 which is a connection to server 1
connection1 = cf1.createConnection();
// Step 8. We create a JMS Session on server 0
Session session0 = connection0.createSession(false, Session.AUTO_ACKNOWLEDGE);
// Step 9. We create a JMS Session on server 1
Session session1 = connection1.createSession(false, Session.AUTO_ACKNOWLEDGE);
// Step 10. We start the connections to ensure delivery occurs on them
connection0.start();
connection1.start();
// Step 11. We create JMS MessageConsumer objects on server 0 and server 1
MessageConsumer consumer0 = session0.createConsumer(queue);
MessageConsumer consumer1 = session1.createConsumer(queue);
Thread.sleep(1000);
// Step 12. We create a JMS MessageProducer object on server 0
MessageProducer producer = session0.createProducer(queue);
// Step 13. We send some messages to server 0
final int numMessages = 10;
for (int i = 0; i < numMessages; i++) {
TextMessage message = session0.createTextMessage("This is text message " + i);
producer.send(message);
System.out.println("Sent message: " + message.getText());
}
// Step 14. We now consume those messages on *both* server 0 and server 1.
// We note the messages have been distributed between servers in a round robin fashion
// JMS Queues implement point-to-point message where each message is only ever consumed by a
// maximum of one consumer
for (int i = 0; i < numMessages; i += 2) {
TextMessage message0 = (TextMessage) consumer0.receive(5000);
System.out.println("Got message: " + message0.getText() + " from node 0");
TextMessage message1 = (TextMessage) consumer1.receive(5000);
System.out.println("Got message: " + message1.getText() + " from node 1");
}
} finally {
// Step 15. Be sure to close our resources!
if (connection0 != null) {
connection0.close();
}
if (connection1 != null) {
connection1.close();
}
}
}
}
This example uses a JMS queue deployed on two different nodes. The two nodes are configured to form a cluster.
<cluster-connection name="my-cluster">
<connector-ref>netty-connector</connector-ref>
<retry-interval>500</retry-interval>
<use-duplicate-detection>true</use-duplicate-detection>
<message-load-balancing>STRICT</message-load-balancing>
<max-hops>1</max-hops>
<discovery-group-ref discovery-group-name="my-discovery-group"/>
</cluster-connection>
We then send some messages via the producer, and we verify that both consumers receive the sent messages in a round-robin fashion. This examples demonstrates how ActiveMQ Artemis load balances the sent messages across all consumers on the cluster
Connection Failover
To connect to the cluster, it is sufficient to provide a single hostname which needs to be available when you initiate the connection. If you want to use more than one broker as a possible initial connection, group the host:port entries as in the following example:
(tcp://host1:port,tcp://host2:port)?ha=true&reconnectAttempts=3
You can include the name-value pair ha=true as part of the query string to ensure the client receives information about each master and slave broker in the cluster.
Finally, include the name-value pair reconnectAttempts=n, where n is an integer greater than 0. This parameter sets the number of times the client attempts to reconnect to a broker.
Recommended Articles
Implementing JMS Clustering in WildFly and JBoss EAP for High Availability
Learn how to achieve high availability in JMS clustering using WildFly and JBoss EAP, including data replication and shared storage configurations.
How to Configure TCPPING with WildFly 14 or Newer for Clustered Applications
Learn how to use TCPPING in combination with WildFly 14 or newer and static cluster members addresses.
Develop and Deploy Message Driven Beans on WildFly Application Server - A Comprehensive Guide
Learn how to develop and deploy MDBs on WildFly. Includes configuration, development, deployment steps & example code.
Configure Firewall Rules for WildFly on Linux
Learn how to configure firewall rules for running WildFly on a Linux machine. Includes steps for allowing incoming connections on port 8080 and managing the management port (9990). #WildFly #LinuxFirewall #Java #Middleware #CloudNative