Mapping Pulsar concepts to JMS specifications

JMS specifications are built upon the concepts of Topics and Queues, but Apache Pulsar™ has only a general concept of Topics that can model both of those two domains.

In Pulsar there is no concept of a queue: DataStax Fast JMS for Apache Pulsar treats Pulsar topics as queues when queue-related JMS API are in use. There is no strict, cluster wide, verification that you are accessing a JMS Queue using the Topic API or vice versa.

In JMS a Topic is written by many Producers and read by many Consumers that share one or many Subscriptions. Subscriptions may be Durable or Non-Durable (meaning the client position not retained on restart), and Shared or Non-Shared determining whether the same message may be received and processed by more than one consumer.

Mappings between JMS Consumer/Subscriptions and Apache Pulsar consumers for topics:

JMS Concept Pulsar Concept

Topic

Persistent topic

Consumer

Exclusive non-durable subscription with random name (UUID)

DurableConsumer

Exclusive durable subscription with the given name + clientId

SharedConsumer

Shared non-durable subscription with the given name + clientId

SharedDurableConsumer

Shared durable subscription with the given name + clientId

DurableSubscriber

Exclusive durable subscription with the given name + clientId

As of Pulsar version 2.7.x, delayed messages don’t work with exclusive subscriptions. You can, however, force the usage of shared non-durable subscriptions for simple consumers by setting jms.useExclusiveSubscriptionsForSimpleConsumers=false.

For SharedConsumer and SharedDurableConsumer, set jms.topicSharedSubscriptionType to Key_Shared to use the Key_Shared subscription type.

In JMS a Queue is written by many Producers but only one Consumer eventually processes each message.

In order to emulate that behavior, the first time you create a consumer over a queue, DataStax Fast JMS for Apache Pulsar creates a durable subscription named jms-queue at the beginning (initial position = Earliest) of the Pulsar topic.

Every access to the queue passes through the shared subscription and guarantees that only one consumer receives and processes each message.

Mappings between JMS consumer/subscriptions and Apache Pulsar consumers for queues

JMS Concept Pulsar Concept

Queue

Persistent topic

Consumer

Shared durable subscription with name jms-queue

QueueBrowser

Pulsar Reader for the topic, beginning from the next message on jms-queue subscription

You can change the name of the shared subscription using the jms.queueSubscriptionName configuration parameter, but you must ensure that you change it on every client.

In order to implement QueueBrowser, DataStax Fast JMS for Apache Pulsar uses the Pulsar Reader API, starting from the next message available on the jms-queue subscription. In order to peek at the next message DataStax Fast JMS for Apache Pulsar uses the Pulsar Admin API peekMessages.

In certain cases, the peekMessages API can return the last consumed message of the subscription, so the QueueBrowser may return inaccurate results.

Interoperability between DataStax Fast JMS for Apache Pulsar and other Pulsar clients

DataStax Fast JMS for Apache Pulsar doesn’t deal with schema, and it treats every message as a raw array of bytes, interpreting the content of the message according to the JMS API that is used, and to a special JMSPulsarMessageType property.

JMS specs require that, on the consumer side, you receive a message of the same type sent by the producer:

  • TextMessage

  • BytesMessage

  • StreamMessage

  • MapMessage

  • ObjectMessage

When the JMS consumer receives a message that has not been produced by DataStax Fast JMS for Apache Pulsar itself and lacks the JMSPulsarMessageType property, it converts the message to a BytesMessage.

Pulsar message keys and JMSXGroupID

The special JMSXGroupID property is defined in the JMS specs as a way to group messages and enable routing to the same destination.

DataStax Fast JMS for Apache Pulsar maps that property to the message key in Pulsar, ensuring that JMSXGroupID is used as the routing key.

This is the same behavior implemented in Apache ActiveMQ.

Next