JMS (Java Message Service) รองรับ 2 โมเดลการส่งข้อความหลัก:
ตารางเปรียบเทียบ
| ลำดับ | หัวข้อ | Point-to-Point (PTP) - Queue | Publish/Subscribe (Pub/Sub) - Topic |
| 1 | พื้นฐาน | One-to-One: ข้อความ 1 ตัว → 1 Consumer | One-to-Many: ข้อความ 1 ตัว → หลาย Subscribers |
| 2 | Destination | Queue | Topic |
| 3 | Mechanism | Pull - Consumer poll/receive เอง | Push - Broker ส่งให้ Subscribers ทุกตัว |
| 4 | Message Consumption | **Competing Consumers**: หลาย consumer แต่อ่านคนละ msg (load balancing) | **Broadcast**: ทุก subscriber ได้ message ทุกตัว |
| 5 | Acknowledgment | บังคับ (Client/ Auto/ Dups_ok) | Optional (ขึ้นกับ subscription type) |
| 6 | Timing Dependency | ไม่มี - Sender/Receiver ไม่ต้อง online พร้อมกัน | มี - Subscriber ต้อง online (durable subscriber ได้) |
| 7 | Message Retention | จนกว่าจะถูก consume + ack | จนกว่าจะส่งให้ทุก durable subscriber แล้ว |
| 8 | Use Case | Task distribution, Work queues, Load balancing | Broadcast, Notifications, Event distribution |
Point-to-Point (Queue) - รายละเอียด
Producer → [Queue] → Consumer 1 (gets msg 1)
→ Consumer 2 (gets msg 2)
→ Consumer 3 (gets msg 3)
• 1 message = 1 consumer only (competing)
• Message อยู่ใน queue จนกว่าจะถูก consume + ack
• Sender ไม่ต้องรู้ว่าใครจะ receive
• เหมาะสำหรับ: Job queue, Task distribution, Load balancing
โค้ดตัวอย่าง PTP
// Sender
Queue queue = session.createQueue("TASK_QUEUE");
MessageProducer producer = session.createProducer(queue);
producer.send(session.createTextMessage("Process order #123"));
// Receiver (หลายตัวรันพร้อมกันได้ - competing)
MessageConsumer consumer = session.createConsumer(queue);
connection.start();
TextMessage msg = (TextMessage) consumer.receive(); // Block จนกว่าจะมี msg
System.out.println("Received: " + msg.getText());
Publish/Subscribe (Topic) - รายละเอียด
Publisher → [Topic] → Subscriber A (gets msg)
→ Subscriber B (gets msg)
→ Subscriber C (gets msg)
• 1 message = ทุก subscribers ได้รับ (broadcast)
• Subscriber ต้อง subscribe ก่อน publish (เว้นแต่ Durable)
• เหมาะสำหรับ: Notifications, Events, Stock prices, Alerts
Subscription Types
| ประเภท | คำอธิบาย |
| Non-durable | Subscriber ต้อง online ตอน publish → หายไปถ้า offline |
| Durable | Server เก็บ message ไว้ให้ subscriber ที่ offline → ได้ message ตอนกลับมา |
| Shared (JMS 2.0+) | หลาย consumers แบ่งกันรับจาก topic เดียว (competing на topic) |
โค้ดตัวอย่าง Pub/Sub
// Publisher
Topic topic = session.createTopic("STOCK_PRICES");
MessageProducer publisher = session.createProducer(topic);
publisher.send(session.createTextMessage("AAPL: 150.25"));
// Durable Subscriber (ได้ message แม้ offline)
Topic topic = session.createTopic("STOCK_PRICES");
MessageConsumer subscriber = session.createDurableConsumer(topic, "subscriber-1");
connection.start();
Message msg = subscriber.receive(); // ได้ message แม้ส่งตอน offline
JMS 2.0+ Simplified API
// JMS 2.0 - ใช้ JMSContext (auto-closeable)
try (JMSContext context = factory.createContext()) {
// Send to Queue
context.createProducer().send(context.createQueue("QUEUE"), "Message");
// Send to Topic
context.createProducer().send(context.createTopic("TOPIC"), "Broadcast");
// Receive (synchronous)
String body = context.createConsumer(context.createQueue("QUEUE"))
.receiveBody(String.class);
// Async listener
context.createConsumer(context.createTopic("TOPIC"))
.setMessageListener(msg -> System.out.println("Got: " + msg.getBody(String.class)));
}
สรุปการเลือกใช้
| สถานการณ์ | เลือก | เหตุผล |
| Work distribution (หลาย worker แบ่งงาน) | Queue (PTP) | Competing consumers, load balancing |
| Event notification (ทุก service ต้องรู้) | Topic (Pub/Sub) | Broadcast to all interested parties |
| Order processing (1 order → 1 processor) | Queue | Exactly-once processing per order |
| Price updates / Alerts | Topic | Multiple subscribers need same data |
| Audit log / Audit trail | Topic (Durable) | Multiple consumers, replay capability |
ข้อสังเกตเพิ่มเติม
- JMS เป็น **API/Spec** ไม่ใช่ implementation → ต้องมี Provider (ActiveMQ, RabbitMQ, IBM MQ, WebLogic, ...)
- Kafka 結合了 2 โมเดล: Consumer Group = PTP (competing) + Multiple Groups = Pub/Sub (broadcast)
- Modern apps มักใช้ Kafka/RabbitMQ/gRPC แทน JMS โดยตรง