TL;DR

  • Scenario: Java systems doing async decoupling and event-driven need unified understanding of JMS message model, object model and message types
  • Conclusion: JMS is a standard API (like JDBC), key is Queue/Topic semantics, Session and acknowledgment/transaction boundaries
  • Output: A directly deployable JMS basics article: concepts — object model — message types — implementation/version differences quick reference

Version Matrix

ItemDescription
JMS 2.0Part of Java EE 7, API still in javax.jms namespace
Jakarta Messaging 3.1Part of Jakarta EE 10, corresponding API namespace is jakarta.jms
ActiveMQ ClassicFull JMS 1.1 support
ActiveMQ ArtemisImplements own protocol, provides client-side JNDI
RabbitMQNot a JMS Provider itself, requires plugin

JMS Mode

Basic Introduction

JMS (Java Message Service) is a standard API provided by Java platform for implementing message-oriented middleware (MOM) programming interfaces.

Core Features:

  1. Cross-platform: JMS provides implementation-agnostic abstract interfaces
  2. Loosely Coupled Communication: Decouples producers and consumers through message broker
  3. Supports Two Message Models:
    • Point-to-Point: Based on Queue
    • Publish/Subscribe: Based on Topic

JMS Messages

All JMS Message Header Fields:

  • JMSMessageID
  • JMSDestination
  • JMSDeliveryMode
  • JMSExpiration
  • JMSPriority
  • JMSTimestamp
  • JMSCorrelationID
  • JMSReplyTo
  • JMSType
  • JMSRedelivered

6 Standard Message Types:

  1. TextMessage: Most commonly used message type, contains plain string content
  2. ObjectMessage: Contains one serializable Java object
  3. MapMessage: Contains a set of key-value pair data
  4. BytesMessage: Contains uninterpreted byte stream data
  5. StreamMessage: Contains a series of Java primitive type stream data
  6. Message: Contains no actual data, only message headers and properties

Architecture

JMS consists of the following elements:

  • JMS Provider: An implementation of JMS interface
  • JMS Client: Java application that produces or consumes messages
  • JMS Producer: JMS client that creates and sends messages
  • JMS Consumer: JMS client that receives messages
  • JMS Message: Data object passed between JMS clients
  • JMS Queue: Container that caches messages
  • JMS Topic: Pub/Sub mode

Object Model

Connection Factory

Connection factory is an important managed object in JMS, responsible for creating and managing connections with JMS provider:

ConnectionFactory cf = (ConnectionFactory)ctx.lookup("ConnectionFactory");
Connection connection = cf.createConnection();

Session

Represents a single-threaded context for sending and receiving messages:

Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

MessageProducer

MessageProducer is the core interface in JMS for sending messages:

MessageProducer producer = session.createProducer(destination);
producer.send(message);

MessageConsumer

MessageConsumer is one of the core interfaces in JMS, representing message consumer:

Synchronous Receive:

Message message = consumer.receive();
Message message = consumer.receive(5000);

Asynchronous Receive:

consumer.setMessageListener(new MessageListener() {
    @Override
    public void onMessage(Message message) {
        // Handle message
    }
});

Error Quick Reference

SymptomRoot CauseFix
NoClassDefFoundError: javax/jms/...Dependency namespace mismatchUnify to one API
Topic subscription can’t receive historical messagesNon-durable subscription only receives messages after subscriptionUse durable subscription
Consumer keeps blockingDidn’t call connection.start()Call in correct order
Duplicate consumptionACK/transaction boundary incorrectEnable transaction and successfully commit
Message order unstableMultiple consumers concurrent, prefetch causes disorderStrong ordering needed: single consumer
ObjectMessage deserialization failsConsumer missing class with same nameUse TextMessage (JSON)