Skip to content

Sahan-Kaushalya/JMS-FirstClient

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Java Message Service (JMS) Demonstration - Subscriber Client

This project is the Subscriber part of a message-based communication system built in Java using the Java Message Service (JMS) API. It communicates through a central message broker with a corresponding Publisher client.

Message Broker / Server: Payara Server

Overview and Theory

Java Message Service (JMS) is a Java API that enables distributed communication which is loosely coupled, reliable, and asynchronous. This project implements the Subscriber side of the Publish/Subscribe (Pub/Sub) messaging model using a JMS Topic.


JMS Messaging Models: Queue vs. Topic

JMS supports two primary messaging models: Point-to-Point (Queue) and Publish/Subscribe (Topic). Understanding the difference is crucial for designing an effective messaging architecture.

1. Point-to-Point (PTP) with Queues

The PTP model is built around the concept of a Queue. Messages are sent to a specific queue, and receivers listen to that queue to consume the messages.

  • One-to-One Communication: Each message is delivered to exactly one receiver. Even if multiple receivers are listening on the same queue, the message broker ensures that only one of them will process a given message. This model is often used for load balancing, where multiple instances of a service can pull tasks from a shared queue.
  • Durable by Default: Messages sent to a queue are stored by the broker until a consumer successfully receives and acknowledges it. If no consumers are active when the message is sent, it will wait in the queue until one becomes available.
  • Coupling: The sender and receiver are loosely coupled. The sender only needs to know the name of the queue, not anything about the receiver.

Real-World Use Cases for Queues:

  • Order Processing System: When a customer places an order, the order details are sent as a message to a pending-orders queue. One of several order processing worker services picks up the message, processes the order, and updates the database.
  • Task Scheduling: A web application sends an email confirmation task to a mail-queue. A separate email service consumes the message and sends the email, preventing the user from having to wait.
  • Financial Transactions: Ensuring that each payment transaction is processed exactly once.

Code Example: Queue Sender & Receiver

// --- Queue Sender (Producer) ---
QueueConnectionFactory factory = (QueueConnectionFactory) ic.lookup("myQueueFactory");
QueueConnection connection = factory.createQueueConnection();
QueueSession session = connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
Queue queue = (Queue) ic.lookup("myQueue");
QueueSender sender = session.createSender(queue);

TextMessage message = session.createTextMessage("This is a message for the queue.");
sender.send(message);
connection.close();

// --- Queue Receiver (Consumer) ---
QueueConnectionFactory factory = (QueueConnectionFactory) ic.lookup("myQueueFactory");
QueueConnection connection = factory.createQueueConnection();
connection.start();
QueueSession session = connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
Queue queue = (Queue) ic.lookup("myQueue");
QueueReceiver receiver = session.createReceiver(queue);

Message receivedMessage = receiver.receive(); // Blocks until a message is available
System.out.println(((TextMessage) receivedMessage).getText());
connection.close();

2. Publish/Subscribe (Pub/Sub) with Topics

The Pub/Sub model is built around the concept of a Topic. A publisher sends messages to a topic, and the message is broadcast to all active subscribers who have registered interest in that topic.

  • One-to-Many Communication: Each message is delivered to all interested subscribers. It's a broadcast mechanism.
  • Non-Durable Subscribers (by default): By default, subscribers must be active and connected to receive messages. If a subscriber is offline when a message is published, it will miss that message.
  • Durable Subscribers (optional): JMS allows the creation of "durable subscribers." A durable subscriber can disconnect and, upon reconnecting, will receive all the messages that were published while it was offline. This project uses a non-durable subscriber.
  • Decoupling: This model offers very high decoupling. The publisher has no knowledge of the number or type of subscribers.

Real-World Use Cases for Topics:

  • Live News Feeds: A news agency publishes breaking news alerts to a news-alerts topic. Multiple subscribers (a mobile app, a website, an email notifier) all receive the alert simultaneously.
  • Stock Market Tickers: Financial data providers publish real-time stock price updates to a topic. Any number of trading applications or dashboards can subscribe to receive these updates.
  • Live Sports Scores: A sports service broadcasts score updates to a topic, and all connected fan applications receive the updates instantly.
  • System Monitoring: A central monitoring service publishes system health alerts. Different teams (database, network, application support) can subscribe to these alerts to take appropriate action.

Code Example: Topic Publisher & Subscriber (This Project)

// --- Topic Publisher (Producer) ---
TopicConnectionFactory factory = (TopicConnectionFactory) ic.lookup("myTopicFactory");
TopicConnection connection = factory.createTopicConnection();
TopicSession session = connection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
Topic topic = (Topic) ic.lookup("myTopic");
TopicPublisher publisher = session.createPublisher(topic);

TextMessage message = session.createTextMessage("This is a broadcast message for the topic.");
publisher.publish(message);
connection.close();


// --- Topic Subscriber (Consumer) ---
TopicConnectionFactory factory = (TopicConnectionFactory) ic.lookup("myTopicFactory");
TopicConnection connection = factory.createTopicConnection();
connection.start();
TopicSession session = connection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
Topic topic = (Topic) ic.lookup("myTopic");
TopicSubscriber subscriber = session.createSubscriber(topic);

Message receivedMessage = subscriber.receive();
System.out.println(((TextMessage) receivedMessage).getText());
connection.close();

Summary of Differences

Feature Queue (Point-to-Point) Topic (Publish/Subscribe)
Delivery Model One-to-one One-to-many (broadcast)
Message Consumers Only one consumer gets a specific message All subscribers get a copy of the message
Message Persistence Messages persist until consumed and acknowledged Messages are lost for offline non-durable subscribers
Main Use Case Task distribution, load balancing, guaranteed processing Broadcasting events, notifications, real-time data streams
Coupling Loosely coupled Very loosely coupled (decoupled)

This Project: JMS-FirstClient (Consumer / Subscriber)

Implementation: JMS-FirstClient acts as the message subscriber using a Topic.

  • It uses JNDI (InitialContext) to look up the TopicConnectionFactory (myTopicConnectionFactory) and the Topic (myTopic).
  • A TopicConnection and a TopicSession (non-transacted, AUTO_ACKNOWLEDGE) are created.
  • It creates a TopicSubscriber and waits to receive a message.
  • Once a message arrives, it extracts the string body from the message and prints it to the console.

Producer Client (JMS-SecondClient)

The corresponding producer/publisher client, JMS-SecondClient, is in a separate repository. You will need to run it to send messages to this subscriber.

Find the producer client here: https://github.com/Sahan-Kaushalya/JMS-SecondClient.git

Prerequisites

  • Java Development Kit (JDK 17)
  • Payara Server (Must be running for the clients to connect and communicate. Ensure resources like myTopicConnectionFactory and myTopic are configured on the server).

Troubleshooting & Common Issues

If the application does not run normally or throws exceptions on startup, please follow these steps:

1. Check JDK and Payara Versions

Ensure that your installed JDK version is compatible with your version of Payara Server. Mismatched versions can cause unexpected runtime failures. This project is configured for Java 17.

2. Add VM Options (For Module Access Errors)

If you are using a modern JDK (Java 16 or newer), you might encounter IllegalAccessError or InaccessibleObjectException due to strict module encapsulation. You need to explicitly grant the application access to internal Java APIs.

Add the following arguments to the VM Options in your IDE's Run Configuration:

--add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED --add-opens java.management/javax.management.openmbean=ALL-UNNAMED --add-opens java.management/javax.management=ALL-UNNAMED

How to Run

  1. Start the Payara Server.
  2. Run this JMS-FirstClient (Consumer) so it is ready and waiting to receive messages.
  3. Clone and run the JMS-SecondClient (Producer) from its repository. Start typing messages in its console.
  4. You should see those messages appearing instantly in the console of this JMS-FirstClient.

About

This project is the Subscriber part of a message-based communication system built in Java using the Java Message Service (JMS) API. It communicates through a central message broker with a corresponding Publisher client.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages