JMS has many interfaces (ConnectionFactory, Connection, Session, Destination, Producer, Consumer) and a developer needs to understand the correct order to use them. Without a clear step-by-step model, the API feels overwhelming and error-prone.
The JMS programming model is a 6-step pipeline: lookup ConnectionFactory → create Connection → create Session → lookup Destination → create Producer/Consumer → send/receive messages. Think of it like a water supply system: factory makes the pipe, connection is the pipe, session is the valve, destination is the tank, producer/consumer is the pump.
- Lookup ConnectionFactory via JNDI: Get the factory object configured by administrator
- Create Connection: Use factory to create an active connection to the JMS provider (like a JDBC connection)
- Create Session: Use connection to create a session — helper for creating producers/consumers and wrapping messages in transactions
- Lookup Destination via JNDI: Get the Queue or Topic destination (configured by deployer)
- Create Producer or Consumer: Use session + destination to create a
QueueSender/TopicPublisherorQueueReceiver/TopicSubscriber - Send or Receive Message: Producer sends message to destination; Consumer receives from destination
- Session serves as factory for producers/consumers and enables transaction wrapping
- Connection represents physical network connection to JMS provider (may be load-balanced)
- Destination is the channel (Queue or Topic) — looked up by name in JNDI
- Producer sends messages; Consumer receives messages — both created from Session
- Two flavors:
Queue*interfaces for PTP,Topic*interfaces for Pub/Sub
- Forgetting to close Connection/Session causes resource leaks
- Session is NOT thread-safe — one session per thread
- JNDI lookups (steps 1 and 4) can be expensive — cache them if possible
- Transactions are per-session, not per-connection
- Using wrong interface flavor (Queue vs Topic) for your destination causes runtime errors