JMS Transactions

JMS transactions are how Java applications group messaging operations into units of work that can succeed or fail together on IBM MQ—mirroring the syncpoint concepts COBOL programs express with MQCMIT and MQBACK, but through Session APIs or container-managed JTA. A payment service might get an order message, insert a row in Db2, and put an acknowledgment message; if the insert fails, you want the get rolled back and the acknowledgment never visible—otherwise customers see charged accounts without confirmation or duplicate processing after redelivery. Beginners confuse three layers: acknowledgement mode on a non-transacted session, JMS transacted sessions (local messaging UOW), and global JTA/XA transactions spanning MQ plus a database. This tutorial explains each layer, when commit and rollback run, how IBM MQ maps JMS to syncpoints, interaction with MDB container-managed transactions, pitfalls mixing APIs, performance trade-offs versus saga patterns, and operational recovery when transactions stay indoubt after a server crash.

Three Layers of Transactionality

JMS transaction models on IBM MQ
ModelScopeHow to commit
Acknowledgement modeSingle message consume ackAutomatic or message.acknowledge()
Transacted sessionAll ops in one Sessionsession.commit() / rollback()
JTA / XA globalMQ + DB + other RMTransaction manager commit()

Pick one primary model per code path. Mixing manual session.commit inside a CMT MDB or calling MQCMIT while enlisted in XA breaks atomicity and creates heuristics operations teams dread.

Transacted Session Example

java
1
2
3
4
5
6
7
8
9
QueueSession session = connection.createQueueSession(true, 0); // true = transacted; second arg ignored for transacted QueueReceiver receiver = session.createReceiver(queue); Message msg = receiver.receive(); process(msg); // if this throws, call rollback instead of commit session.commit(); // success — syncpoint on IBM MQ // session.rollback(); // failure — uncommitted get/put undone

createQueueSession(true, 0) enables transacted mode; the acknowledgement constant is ignored because the session itself defines the boundary. All sends and receives in that session between commit and rollback belong to one unit of work. Multiple puts to different queues in the same session commit together—useful for fan-out within messaging only, not across databases unless you upgrade to XA.

What Commit and Rollback Do on IBM MQ

session.commit() maps to MQ syncpoint commit for the resources that session touched: syncpointed puts become visible to other applications; syncpointed gets are removed permanently from the queue. session.rollback() backs out uncommitted puts and returns uncommitted gets to the queue, incrementing BackoutCount on the message descriptor. This mirrors MQCMIT and MQBACK in MQI terminology. Persistent messages participate according to the same rules as native clients; non-persistent messages may disappear on rollback without disk trace.

Acknowledgement Modes Versus Transacted Sessions

  • AUTO_ACKNOWLEDGE on a non-transacted session acknowledges delivery when the provider hands the message to your thread—business failure afterward does not automatically undo the get.
  • CLIENT_ACKNOWLEDGE lets you acknowledge after successful processing without a transacted session—still not atomic with a database unless you add XA or outbox patterns.
  • Transacted session ties ack of consumed messages and visibility of produced messages to session.commit().

JTA Global Transactions

Enterprise applications enlist an XA ConnectionFactory in a UserTransaction or @Transactional boundary. The transaction manager runs prepare and commit across IBM MQ and Db2. Spring with JtaTransactionManager and XA-aware DataSource plus XA JMS ConnectionFactory achieves the same when configured correctly. Failure during prepare rolls back all participants. Indoubt transactions after a crash require recovery tools—see the XA transactions tutorial. Do not call session.commit() inside an active JTA transaction unless documentation for your stack explicitly allows it; containers usually forbid double commit.

text
1
2
3
4
5
6
7
8
Typical global flow: @Transactional void handleOrder() { jmsTemplate.convertAndSend("ORD.ACK", "OK"); orderRepository.save(order); } // Spring/JTA commits JMS + DB together on success

MDB Container-Managed Transactions

Message-Driven Beans with @TransactionAttribute(REQUIRED) wrap onMessage in a container transaction. Success commits JMS get and any enlisted datasources; runtime exceptions roll back. NOT_SUPPORTED suspends transactions for logging-only helpers. Understand which exceptions trigger rollback—checked exceptions may not unless configured. MDB transaction boundaries are the most common place beginners first encounter XA without writing XA code directly.

Performance and Design Alternatives

Transacted sessions and XA add latency versus fire-and-forget NON_PERSISTENT sends. High-throughput telemetry may accept at-most-once delivery. Financial workflows often require XA or the outbox pattern: write business row and outbox event in one database transaction; a separate poller publishes to MQ—avoiding XA cost while keeping consistency through eventual delivery. Sagas compensate with reversal messages instead of atomic commit across services.

Explainer: Shopping Cart Checkout

A transacted session is paying for groceries and gas in one checkout—if the card fails, neither purchase completes. Acknowledgement modes are like paying for each item at separate registers; one can succeed while another fails.

Explain Like I'm Five: JMS Transactions

A transaction is a promise that either everything in the group happens or nothing does. If you put a toy in the cart and your mom says no, you put the toy back—rollback. If she says yes, you keep it—commit.

Practice Exercises

Exercise 1

Map a flow that needs transacted session only versus full XA with a database.

Exercise 2

Describe what happens to queue depth when onMessage rolls back repeatedly on the same poison message.

Exercise 3

Compare outbox pattern versus XA for a new microservice—list one pro and one con each.

Troubleshooting

  1. Duplicate processing—AUTO_ACK with crash after process; move to transacted or CLIENT_ACK plus idempotency.
  2. Lost messages—commit before business logic completes; reorder or use XA.
  3. Heuristic mixed outcome—mixed manual MQ and JTA APIs; audit code paths.
  4. Indoubt after crash—transaction manager recovery procedures.

Frequently Asked Questions

Frequently Asked Questions

Test Your Knowledge

Test Your Knowledge

1. session.commit() on transacted session:

  • Commits JMS UOW
  • Deletes queue manager
  • Starts listener
  • Formats BSDS

2. JTA coordinates:

  • Multiple XA resources
  • Only logging
  • Only TCP
  • Only topics

3. AUTO_ACK is:

  • Non-transacted ack mode
  • Same as XA
  • MQSC command
  • Channel type

4. rollback after get typically:

  • Returns message to queue
  • Deletes QMGR
  • Purges topic tree
  • Disables TLS
Published
Read time22 min
AuthorMainframeMaster
Verified: IBM MQ 9.3 documentation