JMS, as the first widely-supported enterprise messaging API, has been in the market for close to 20 years and still plays critical roles in many enterprises nowadays. Many mission-critical business applications are still running in production that follows JMS (2.0) specification on various JMS platforms like ActiveMQ, TibcoEMS, and etc.
However, modern business activities have raised new challenges that JMS can't answer very well such as cross-region message replication, real-time complex event processing, seamless horizontal scalability, and etc. In order to address these challenges, newer enterprise messaging/streaming technologies like Apache Pulsar is needed.
In this presentation, I will do a deep dive investigation on how Apache Pulsar can be used as the next generation unified enterprise messaging/streaming platform that can serve existing JMS applications with very minimum code changes. I will also demonstrate JMS to Pulsar migration with several concrete use cases and examples.
4. History of JMS
● Jakarta Messaging (formerly called Java Messaging Service), as part
of Jakarta Enterprise Edition (EE) specifications
● A standard and generic Java API for message-oriented middleware
(MOM)
● JMS 2.0 (backward compatible with JMS 1.1) is still the mainstream
Introduction of JMS
5. Messaging Domains
Introduction of JMS
● Point to Point (P2P)
○ Queue as the JMS destination
○ Each message is delivered to one and ONLY one
receiver
○ No timing dependency between sender and receiver
○ Message acknowledgement is needed
● Publish/Subscribe (Pub/Sub)
○ Topic as the JMS destination
○ Each message is delivered to multiple subscribers
○ Timing dependency between publisher and
subscriber
○ Message acknowledgement is not required
6. JMS APIs
Introduction of JMS
● JMS API
○ JMS 1.0: Domain specific
○ JMS 1.1 (Classic):
ConnectionFactory, Connection,
Session, MessageProducer,
MessageConsumer
○ JMS 2.0 (Simplified):
ConnectionFactory, JMSContext,
JMSProducer, JMSConsumer
○ JMS 3.0: Jakarta Messaging Next
#242
● Classic API (1.1)
● Simplified API (2.0)
7. JMS Administration and JNDI Integration
Introduction of JMS
● JMS Administration
○ Connection Factory and Destination
○ Maximize JMS client application
portability
● JNDI Service Providers
○ Java RMI Registry
○ CORBA common object service
(COS) name service
○ LDAP
○ JMS Provider specific
9. What is Pulsar?
Introduction of Pulsar
● JMS is an old technology
○ Newer MOM technology like Kafka or
Pulsar is needed
● Cloud Native, distributed, and unified
messaging and streaming platform
● Apache TLP since Oct. 2018
10. Pulsar Key Differentiators
Introduction of Pulsar
● Tiered architecture design
○ Stateless broker
○ Segment-centric data persistence
○ Fast and robust scaling, disaster
recovery
● Unified and flexible messaging model
○ Queuing and Pub/Sub
● Native Geo-replication
● Robust and powerful multi-tenancy
13. What is Starlight JMS?
DataStax Starlight API for JMS
● DataStax Starlight API suite
○ Make Apache Pulsar as the unified processing
platform for other messaging protocols, with
minimal impact
■ JMS
■ Kafka
■ RabbitMQ (AMQP 0.9.1)
● Starlight JMS
○ Makes Apache Pulsar as a JMS Provider
○ Fully compatible with JMS 2.0
■ Backward compatible with JMS 1.1
○ Passed 98% JMS TCK compliance test
○ Java API
■ Based on Apache Pulsar Java Client API and
Admin API
○ Open Source (Apache-2.0 License)
14. Why Starlight JMS?
DataStax Starlight API for JMS
● Blazing Fast performance
○ 1M+ msg/s with single-digit latency
● Drop-in replacement for existing JMS
applications
● Horizontally scalable JMS
○ Fast and low impact scalability of
Apache Pulsar
○ Separation between compute and
storage
● Native message re-play in JMS
○ Travel back in time
● Consolidate JMS applications across
multiple legacy JMS providers
○ Reduced TCO, Operation Complexity
● Open source
○ Avoid vendor lock-in
● Cloud native
○ K8s
15. JMS to Pulsar Concepts Mapping
DataStax Starlight API for JMS
JMS Object Pulsar Object
JMS Message
- Message header and property
Pulsar Message
- Message property
Destination/Topic/Queue Persistent topic (with specified topic name)
Temporary Destination/Temporary Topic/Temporary Queue Persistent topic (with randomly generated topic name)
MessageProducer/TopicPublisher/QueueSender Producer
MessageConsumer/TopicSubscriber/QueueReceiver Consumer (with a subscription)
QueueBrowser Reader for a topic
16. Example code
DataStax Starlight API for JMS
Map<String, Object> configuration = new HashMap<>();
configuration.put("webServiceUrl", "http://localhost:8080");
configuration.put("brokerServiceUrl", "pulsar://localhost:6650");
PulsarConnectionFactory factory = new PulsarConnectionFactory(configuration);
try (JMSContext context = factory.createContext()) {
Destination destination = context.createQueue("persistent://public/default/test");
context.createProducer().send(destination, "text");
try (JMSConsumer consumer = context.createConsumer(destination)) {
String message = consumer.receiveBody(String.class);
...
}
}
17. Establish Connection
DataStax Starlight API for JMS
● Entry Point Objects
○ PulsarConnectionFactory
■ PulsarJMSContext
■ PulsarConnection & PulsarSession
● Connection Properties
○ webServiceUrl and brokerServiceUrl
○ producerConfig and consumerConfig
○ enableTransaction
■ At least Apache Pulsar 2.7.0+
■ Better with version 2.8.1+
○ Other Pulsar Client Connection specific
configuration
■ Authentication, TLS, etc.
○ Starlight JMS specific configuration
■ jms.systemNamespace
■ … …
18. Create Destinations
DataStax Starlight API for JMS
● Persistent Pulsar topics
○ Temporary destinations explicitly deleted
when JMS connection is closed
Destination
Type
Pulsar Topic Name
Queue Client provided string (<client_string>)
If it starts with “persistent://”, then <client_string>;
Otherwise, persistent://<jms.systemNamespace>/<client_string>
Topic
Temporary Queue persistent://<jms.systemNamespace>/jms-temp-queue-<UUID>
Temporary Topic persistent://<jms.systemNamespace>/jms-temp-topic-<UUID>
19. Create Producer and Consumer
DataStax Starlight API for JMS
● (Producer) Message Send
○ Pulsar producer API
○ Sync and Async mode
■ setAsync(CompletionListener)
● (Consumer) Message Receive
○ Pulsar consumer API
○ Sync and Async mode
■ setMessageListener(MessageLis
tener
● (QueueBrowser) Message Receive
○ Pulsar reader API
○ Peek messages in a Queue
20. Create Message
DataStax Starlight API for JMS
● JMS Headers
○ Mapped to Pulsar Properties
○ Not all JMS header behavior is relevant
in Pulsar
○ Starlight JMS client side emulated
behavior
■ JMSReplyTo
■ JMSPriority
■ JMSExpiration
■ … …
● JMS Properties
○ Application specific JMS properties
■ 1-1 mapping to Pulsar Properties
○ Standard JMS properties
■ JMSXGroupID → Pulsar message key
■ … …
■ Others: ignored
○ Vendor specific system JMS properties
■ Not supported
○ Starlight JMS added Property
■ JMSConnectionID
■ JMSPulsarMessageType
21. Create Message, continued
DataStax Starlight API for JMS
● JMS Message Body
○ All JMS Message types are supported
○ StreamMessage
■ Stream of Java primitive values
○ MapMessage
■ Key-value pairs (String / Java primitive
type)
○ TextMessage
○ ObjectMessage
■ Serializable Java object
○ BytesMessage (Default)
■ Stream of uninterpreted bytes.
● Pulsar Message Payload Type
○ Byte[]
○ JMSPulsarMessageType message
property
22. Session Mode and Message Acknowledgement
DataStax Starlight API for JMS
Session Mode Note
AUTO_ACKNOWLEDGE ● Starlight JMS API (runtime) immediately sends a client acknowledgment for each message it delivers to a
message consumer.
● From Pulsar server perspective, the messages are acknowledged in synchronous mode.
CLIENT_ACKNOWLEDGE ● The message consumer must explicitly call Message.acknowledge() method to acknowledge the receipt of a
message.
● Acknowledging a consumed message automatically acknowledges the receipt of all messages that have been
delivered by its session.
● From Pulsar server perspective, the messages are acknowledged in asynchronous mode; and the consumer
sends out acknowledgements without checking if there is any error.
DUPS_OK_ACKNOWLEDGE ● Starlight JMS API (runtime) sends a client acknowledgment for each message it delivers to a message
consumer, in asynchronous mode; but it will wait and capture any error in non-blocking way.
● From Pulsar server perspective, this mode is orthogonal with how Pulsar handles message duplication delivery.
SESSION_TRANSACTED ● Indicate this session is dealing with JMS message transactions. More on this in the next page.
23. Session Mode and Transacted Messages
DataStax Starlight API for JMS
● Enabled in Starlight JMS API when
○ Global ConnectionFactory configuration enableTransaction is set to true
○ Session mode is set to SESSION_TRANSACTED
● Maps to Pulsar Transaction
○ Atomic multi-topic(partition) writes
○ Atomic multi-subscription acknowledgement
● Apache Pulsar version
○ At least version 2.7.0+
○ Exactly-once semantics: 2.8.1+
24. Delayed Message Delivery
DataStax Starlight API for JMS
● JMS spec doesn’t specify how delayed messages should be implemented
● Most JMS Provider implements this using message property
○ message.setLongProperty(“property_name”, long)
● Starlight JMS API
○ producer.setDeliveryDelay(long)
○ Map to Pulsar
■ TypedMessageBuilder.deliverAfter(long delay, TimeUnit unit)
25. Message Selector
DataStax Starlight API for JMS
● Message Selector Recap
○ A String based on a subset of the SQL92 conditional expression syntax
○ Condition Identifier: All message properties (application, JMS, provider) and Message headers
except:
■ JMSDestination, JMSReplyTo, JMSRedelivered, JMSExpiration
● Apache Pulsar doesn’t have native message selector yet
○ Can be achieved via Pulsar Function programming
○ PIP-105 (maybe version 2.10?)
● Starlight JMS API emulates this feature
○ Message acknowledged and discarded at the client side
■ Negative acknowledgement for Shared consumer
26. Unsupported and Emulated Behaviors
DataStax Starlight API for JMS
● Not all JMS features are relevant or supported in Apache Pulsar
● Starlight JMS emulates most of these features
○ Message selector
○ Per-message TTL
○ Message priority
○ NoLocal subscription
○ Temporary destination
○ … …
● Implementation Detail Document
27. Security
DataStax Starlight API for JMS
● JMS spec doesn’t provide security features for message integration or privacy control
○ JMS provider is expected to implement it
● Starlight JMS relays security control completely to Pulsar
○ ConnectionFactory Configuration Map
○ Pluggable Authentication
■ TLS, JWT, Authnz, Kerberos, OAuth2.0
■ Do NOT support simple username/password authentication
○ Authorization
■ Admin role (Cluster, Tenant)
■ Non-admin role: produce, consume, or both
○ Transportation TLS Encryption
○ End-to-end message encryption
○ OpenID Integration, e.g. Keycloak (DataStax Luna Streaming)
28. Jakarta EE Integration
DataStax Starlight API for JMS
● Java EE Connector Architecture (JCA) defines a standard
architecture for Java EE systems to external Enterprise
Information Systems (EIS), e.g. databases and messaging
systems.
● Resource Adaptor (RA): deployable Java EE component for
communication between a Java EE application and an EIS using
JCA specification.
○ Resource Adapter Archive (RAR) file
● Starlight JMS Resource Adaptor
○ Main ResourceAdapter implementation
■ com.datastax.oss.pulsar.jms.rar.PulsarResourceAdapter
○ Outbound connection implementation
■ com.datastax.oss.pulsar.jms.rar.PulsarManagedConnecti
onFactory
○ Inbound Message implementation
■ com.datastax.oss.pulsar.jms.rar.PulsarActivationSpec
○ Resource Adaptor Configuration
■ Same as ConnectionFactory connection properties
■ JSON format
29. JNDI Integration
DataStax Starlight API for JMS
● Use JNDI to get the Administered object reference
○ ConnectionFactory
○ Destination (Queue and Topic)
● Starlight JMS Initial JNDI
○ Dummy implementation at the moment
■ Context.INITIAL_CONTEXT_FACTORY
● com.datastax.oss.pulsar.jms.jndi.PulsarInitialContextFactory
■ Context.PROVIDER_URL
● pulsar://localhost:6650
○ Need to enhanced with an actual JNDI service provider
■ LDAP, RMI Registry, DNS, CORBA COS
31. Summary
● JMS is still the dominating messaging technology for many large enterprises
● JMS is an outdated technology facing many challenges
○ Functional challenges
○ Non-functional challenges
● Apache Pulsar is THE replacing technology
○ Message persistence, replication, and time travel
○ Unified messaging semantics - Queuing and Pub/Sub
○ Unified messaging and streaming
○ Fast and low impact horizontal scaling and disaster recovery
○ Built-in, robust geo-replication and multi-tenancy
○ Cloud native and completely open source
● Starlight JMS is the tool to bridge the gap
Outline
32. Summary
● Starlight JMS API
○ GitHub Repo: https://github.com/datastax/pulsar-jms
○ DataStax Doc: https://docs.datastax.com/en/fast-pulsar-jms/docs/1.1/index.html
● Blog Post
○ Fast JMS for Apache Pulsar: Modernize and Reduce Costs with Blazing Performance
○ How to Migrate a JMS Application to Apache Pulsar Using Starlight for JMS API
● Sample Code
○ Starlight JMS Internal Examples
○ Pulsar JMS Workshop
Resources