JMS Queues

JMS queues are how Java and Jakarta applications do point-to-point work on IBM MQ without calling MQPUT and MQGET directly. You create a Session, obtain a Queue destination (often by name), use a QueueSender to put work, and a QueueReceiver or MessageListener to consume it. Under the hood the IBM MQ JMS provider opens the same QLOCAL your COBOL batch job uses, enforces the same authority records, honors persistence and syncpoint rules, and increments depth the operations console already monitors. Beginners often treat the JMS name as a logical label separate from MQSC reality—it is not. The string you pass to createQueue is the queue manager object name unless your team configured a custom destination resolver. This tutorial explains JMS queue semantics on IBM MQ, how they differ from Topic destinations, producer and consumer patterns, acknowledgement and transaction interaction, persistence and priority, request-reply over queues, administration with MQSC, and troubleshooting when messages never arrive or consumers fight each other unexpectedly.

JMS Queue Versus IBM MQ Queue Object

In the JMS specification, javax.jakarta.jms.Queue is an interface representing a point-to-point destination. IBM MQ implements that interface by binding to a queue object defined on the server. When your code calls session.createQueue("ORDERS.NEW"), the provider typically issues an MQOPEN against ORDERS.NEW as a queue. If the object does not exist and your queue manager policy forbids dynamic creation, you receive a JMSException whose linked MQ reason explains the failure—often 2085 object not found. Alias queues (QALIAS) let you expose a stable JMS name while routing to different physical queues per environment. Remote queues are usually not opened directly from JMS clients; integration architects place a local queue in front of remote routing so JMS programs keep simple names.

JMS queue programming artifacts and IBM MQ backing
JMS APIRoleIBM MQ equivalent
QueueDestination identityQLOCAL / QALIAS name
QueueSenderProducerMQPUT to queue
QueueReceiverPull consumerMQGET (destructive)
MessageListenerPush consumerAsync MQGET dispatch
MessagePayload + headersBuffer + MQMD

Point-to-Point Semantics

Point-to-point means each message has one intended consumer among those listening on the queue. If three Spring @JmsListener instances consume PAY.IN with concurrency 3, IBM MQ still delivers a given message to only one of them. This differs from JMS Topic publish/subscribe where every active subscriber receives a copy. Architects choose queues when work must be load-balanced—payment files, job tickets, inventory updates—rather than broadcast. Ordering is FIFO for a single active consumer sequence; multiple consumers interleave completion times so strict global order requires a single consumer or application-level sequencing keys.

Creating Producers and Consumers

java
1
2
3
4
5
6
7
8
9
10
11
12
13
QueueConnectionFactory qcf = /* MQConnectionFactory with host, port, channel, QM */; QueueConnection conn = qcf.createQueueConnection(); conn.start(); QueueSession session = conn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); Queue ordersQueue = session.createQueue("ORDERS.NEW"); QueueSender sender = session.createSender(ordersQueue); TextMessage msg = session.createTextMessage("{\"orderId\": 1001}"); msg.setJMSDeliveryMode(DeliveryMode.PERSISTENT); sender.send(msg); QueueReceiver receiver = session.createQueueReceiver(ordersQueue); TextMessage received = (TextMessage) receiver.receive(5000);

createQueueSession's first parameter false means non-transacted session for this example; the second parameter AUTO_ACKNOWLEDGE tells the provider to acknowledge consumption when the message is delivered to the application. A transacted session (true as first parameter) groups sends and receives into a unit committed with session.commit() or rolled back with session.rollback(). Connection.start() begins message delivery to listeners; without start, a synchronous receive may block indefinitely. Always close senders, receivers, sessions, and connections in finally blocks or try-with-resources patterns your framework provides.

Delivery Mode and Persistence

JMS DeliveryMode.PERSISTENT maps to MQ persistent messages; NON_PERSISTENT maps to non-persistent. Persistence interacts with queue DEFPSIST when the application leaves defaults. Persistent messages survive queue manager restart if they reached the queue on disk under syncpoint rules. Non-persistent messages trade durability for speed—appropriate for refresh notifications you can afford to lose. Beginners should align JMS delivery mode with operations backup and recovery expectations; marking marketing email persistent on a high-volume queue can fill disks during incidents.

JMS delivery mode effects on IBM MQ
JMS modeMQMD persistenceTypical effect
PERSISTENTMQPER_PERSISTENTLogged to queue logs; survives restart if committed
NON_PERSISTENTMQPER_NOT_PERSISTENTMemory path; lost if failure before consumption
Default from queueMQPER_AS_Q_DEFDEFPSIST on QLOCAL decides

Acknowledgement Modes on Queues

  • AUTO_ACKNOWLEDGE—simplest; provider acknowledges after delivery to your thread; processing failure after receive may lose the message unless you use transacted sessions or CLIENT_ACK.
  • CLIENT_ACKNOWLEDGE—you call message.acknowledge() after successful business logic; finer control for long-running handlers.
  • DUPS_OK_ACKNOWLEDGE—allows duplicate delivery under failure for higher throughput; consumers must be idempotent.
  • Transacted session—commit rolls in all operations in the session; rollback returns uncommitted gets per MQ rules.

Poison messages that always throw exceptions increment BackoutCount; when BOTHRESH on the queue is exceeded, IBM MQ routes to BOQNAME. JMS does not hide backout behavior—configure BOTHRESH and monitor backout depth alongside main queue depth.

Request-Reply Over JMS Queues

Request-reply uses a temporary or model-defined dynamic queue for replies. The request message sets JMSReplyTo to that destination; the server puts the response there. IBM MQ implements temporary queues via model queues (QMODEL). Correlation uses JMSCorrelationID and JMSMessageID mapping to MQ CorrelId and MsgId. Mixed estates with COBOL requesters and Java responders need a documented byte layout for correlation fields—hex padding mistakes strand replies on the queue forever.

Spring and Listener Containers

Spring Boot configures a DefaultJmsListenerContainer with concurrency to spin multiple consumers on one queue name—each consumer thread owns session discipline. @JmsListener("PAY.IN") is the common pattern. Set acknowledge mode explicitly when defaults are wrong for your recovery story. Enable IBM MQ client reconnect on the ConnectionFactory bean so listener containers survive queue manager restarts without manual intervention.

MQSC Administration for JMS Queues

text
1
2
3
4
5
6
7
DEFINE QLOCAL('ORDERS.NEW') REPLACE + DESCR('JMS point-to-point work queue') + MAXDEPTH(500000) DEFPSIST(YES) BOTHRESH(3) + BOQNAME('ORDERS.BOQ') DISPLAY QLOCAL('ORDERS.NEW') CURDEPTH IPPROCS OPROCS DISPLAY AUTHREC PROFILE('ORDERS.NEW') OBJTYPE(QUEUE)

Grant +put and +get to the MCAUSER or application principal your JMS client uses on SVRCONN. IPPROCS and OPROCS in DISPLAY QLOCAL show open handles—useful when JMS connection leaks leave consumers attached. MAXDEPTH protects against runaway producers; tune with peak message size and disk capacity.

JMS Queues Versus JMS Topics

Use Queue when one consumer should process each unit of work. Use Topic when many subscribers must each receive the same event. Putting order status on a queue when five microservices each need a copy forces sequential handoffs or duplicate manual gets—wrong tool. Putting payroll files on a topic floods every subscriber with data only one service should touch—also wrong. The next tutorial in this track covers JMS Topics in depth.

Explainer: One Ticket Window

A JMS queue is a single ticket window at the deli. Each customer number is served by one clerk. Topics are the loudspeaker that calls everyone in the mall—different pattern entirely.

Explain Like I'm Five: JMS Queues

A JMS queue is a line where each note goes to the next person waiting—not to every person in the room. If three friends are waiting, only one friend gets each note.

Practice Exercises

Exercise 1

Design queue names for order capture and fulfillment when both use JMS. Explain why you would not use one shared topic.

Exercise 2

Your consumer uses AUTO_ACK but crashes after receive and before database commit. List two configuration changes that reduce message loss risk.

Exercise 3

Run DISPLAY QLOCAL for a JMS workload queue during a test. Record CURDEPTH, IPPROCS, and what they imply.

Troubleshooting

  1. 2085 not found—queue name typo or missing DEFINE QLOCAL.
  2. 2035 not authorized—AUTHREC for queue and SVRCONN MCAUSER.
  3. Messages stuck—consumer not started, session not committed, or backout loop.
  4. Uneven load—one slow consumer thread; check Spring concurrency settings.

Frequently Asked Questions

Frequently Asked Questions

Test Your Knowledge

Test Your Knowledge

1. A JMS Queue on IBM MQ maps to:

  • An IBM MQ queue object
  • A TCP listener
  • A channel only
  • A topic tree root

2. Two consumers on the same JMS queue:

  • Compete for each message
  • Each get every message
  • Disable the queue
  • Create a topic

3. PERSISTENT delivery mode means:

  • Survives restart when rules allow
  • Never uses disk
  • Skips syncpoint
  • Only for topics

4. QueueSender sends to:

  • A Queue destination
  • All subscribers
  • A listener port
  • The coupling facility
Published
Read time22 min
AuthorMainframeMaster
Verified: IBM MQ 9.3 documentation