Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

JMS Web Application

This is a simple Java web application demonstrating the use of the Java Message Service (JMS) with Jakarta EE. The application consists of a message producer (a servlet) and a message consumer (a Message-Driven Bean).

Technologies Used

  • Jakarta EE 10: The application is built on the Jakarta EE platform, which provides the APIs for developing and running enterprise Java applications.
  • Java Message Service (JMS) 3.1: JMS is a Java API that allows applications to create, send, receive, and read messages. It enables loosely coupled, reliable, and asynchronous communication between different components of a distributed application.
  • Maven: This project uses Maven for dependency management and building.

Dependencies

The project has one main dependency declared in the pom.xml:

<dependency>
    <groupId>jakarta.platform</groupId>
    <artifactId>jakarta.jakartaee-api</artifactId>
    <version>10.0.0</version>
    <scope>provided</scope>
</dependency>

This dependency provides all the necessary Jakarta EE APIs, including JMS. The scope is set to provided because the application server (like GlassFish, WildFly, or Payara) will provide the implementation of these APIs at runtime.

How It Works

This project demonstrates a simple Publish/Subscribe messaging model using a JMS Topic.

Core JMS Concepts

  • ConnectionFactory: A ConnectionFactory is an object that a client uses to create a connection with a JMS provider. It is the entry point to the JMS API. In this project, the ConnectionFactory is injected using the @Resource annotation:

    @Resource(lookup = "jms/myDefaultConnectionFactory")
    private ConnectionFactory factory;

    The lookup attribute specifies the JNDI name of the resource.

  • Topic: A Topic is a type of JMS destination used for publish/subscribe messaging. Messages are published to a topic, and all subscribed consumers will receive a copy of the message. The Topic is also injected via @Resource:

    @Resource(lookup = "myTopic")
    private Topic topic;
  • Message Producer: A MessageProducer is an object created by a Session that sends messages to a destination (a topic or a queue).

  • Message Consumer: A MessageConsumer is an object created by a Session that receives messages sent to a destination. In this project, we use a Message-Driven Bean (MDB) as our consumer, which is a more modern and convenient approach in Java EE.

Code Breakdown

1. Message Producer (Test.java)

This servlet acts as the message producer. When you access the /test URL, it sends 10 text messages to the myTopic.

package lk.kaushalya.jms;

import jakarta.annotation.Resource;
import jakarta.jms.*;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;

@WebServlet("/test")
public class Test extends HttpServlet {

    // 1. Inject the ConnectionFactory and Topic resources
    @Resource(lookup = "jms/myDefaultConnectionFactory")
    private ConnectionFactory factory;

    @Resource(lookup = "myTopic")
    private Topic topic;

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        try {
            // 2. Create a JMS Connection
            Connection connection = factory.createConnection();
            connection.start();

            // 3. Create a JMS Session
            // false -> not transacted
            // AUTO_ACKNOWLEDGE -> The session automatically acknowledges a client's receipt of a message.
            Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

            // 4. Create a Message Producer from the Session to the Topic
            MessageProducer producer = session.createProducer(topic);

            // 5. Create and send 10 messages
            for (int i = 1; i <= 10; i++) {
                String line = "Default Connection Message " + i + " - JMS-SecondClient -";
                TextMessage txtMessage = session.createTextMessage();
                txtMessage.setText(line);

                producer.send(txtMessage);
            }

        } catch (JMSException e) {
            throw new RuntimeException(e);
        }
    }
}

Commented Code Explanation:

The Test.java servlet contains some commented-out code:

// InitialContext ic = new InitialContext();
// ConnectionFactory factory = (ConnectionFactory) ic.lookup("jms/myDefaultConnectionFactory");

This shows the "old" way of looking up JNDI resources manually. Instead of manual lookup, the project uses @Resource annotation for dependency injection, which is a cleaner and more modern approach provided by Java EE.

// Topic topic = session.createTopic("newTopic");

This line shows how you could create a topic programmatically. However, in this application, the topic is pre-configured on the application server and looked up via JNDI, which is the standard practice.

2. Message Consumer (MessageReceiver.java)

This is a Message-Driven Bean (MDB) that acts as a message consumer. It listens for messages on myTopic.

package lk.kaushalya.jms;

import jakarta.ejb.ActivationConfigProperty;
import jakarta.ejb.MessageDriven;
import jakarta.jms.JMSException;
import jakarta.jms.Message;
import jakarta.jms.MessageListener;

// 1. Declare this class as a Message-Driven Bean
@MessageDriven(activationConfig = {
        // 2. Configure the MDB to listen on the "myTopic" destination
        @ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "myTopic"),
})
public class MessageReceiver implements MessageListener {

    // The onMessage method is automatically called by the container when a message arrives.
    @Override
    public void onMessage(Message message) {
        try {
            // 3. Extract the text from the message and print it to the console
            System.out.println("MessageReceiver onMessage : "+message.getBody(String.class));
        } catch (JMSException e) {
            throw new RuntimeException(e);
        }
    }
}

The @MessageDriven annotation tells the EJB container that this bean is driven by messages. The activationConfig properties configure the MDB, specifying the JNDI name of the destination (myTopic) it should listen to.

When a message is published to myTopic, the container invokes the onMessage method of the MessageReceiver bean, passing the message as an argument.

How to Run the Project

  1. Prerequisites: You need a Jakarta EE 10 compatible application server (e.g., GlassFish 7, Payara Server, WildFly).
  2. Configure JMS Resources: You need to configure the JMS resources (ConnectionFactory and Topic) on your application server.
    • Connection Factory JNDI Name: jms/myDefaultConnectionFactory
    • Topic JNDI Name: myTopic
  3. Build the Project: Build the project using Maven to produce a .war file.
    mvn clean install
  4. Deploy: Deploy the generated JMS-WebApplication.war file to your application server.
  5. Test: Access the following URL in your browser: http://localhost:8080/JMS-WebApplication/test (the host and port may vary depending on your server configuration).
  6. Check the Output: Check the server logs. You should see the messages printed by the MessageReceiver.

About

This is a simple Java web application demonstrating the use of the Java Message Service (JMS) with Jakarta EE. The application consists of a message producer (a servlet) and a message consumer (a Message-Driven Bean).

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages