JMS Mapping

Stale development discussion details

Many of the details on the page are not reflective of current state, and were only used in initial discussion of various functionality. They are only preserved for historic reference.


Define a mapping from the JMS API (see to the AMQP core protocol (

The mapping MUST allow for an unambiguous mapping such that any implementation of the JMS API which conforms to the mapping will interoperate with any AMQP 1.0 intermediary providing it supports required extensions defined within this document.

There are anticipated to be two classes of implementation:

  1. client libraries providing the JMS API which allow integration into AMQP networks
  2. AMQP protocol implementations integrated into existing providers of JMS services which currently use alternative wire level protocols.

There are two main concerns for any such mapping

  1. Mapping between the AMQP and JMS Message Models
    The mapping must define how any conformant AMQP 1.0 message is represented through the JMS API with full fidelity.

  2. Mapping required JMS operational behaviour to AMQP

In order to aid migration to the AMQP 1.0 protocol for users/vendors of existing JMS products we should also document behaviours which are mnot defined by the JMS standard but which users may be relying upon in their applications. If there are obvious ways to implement this functionality in AMQP 1.0 we should look to see if this can be offered through the JMS Mapping.


In Scope

Potentially In Scope

Out of scope

Document Source

The underlying XML source of the mapping document can be found in SVN:

Specificaly, the core of the document can be viewed at:


Node Type Information

In order to transmit type information about the remote node during link attachment for producers and consumers, specify source/target capabilities:

"queue", "topic", "temporary-queue", "temporary-topic".

JMSDestination and JMSReplyTo Type Information

In order to transmit type information about the JMSDestination and JMSReplyTo values for a particular message, add message annotations.

Old Annotations:

Names: "x-opt-to-type", "x-opt-reply-type".

Values: A string with unordered comma separated set of attributes from "queue", "topic", "temporary". E.g "temporary,queue".

New annotations:

Names: "x-opt-jms-dest", "x-opt-jms-reply-to".

Values: A byte of particular value for each type: Queue = 0, Topic = 1, TemporaryQueue = 2, TemporaryTopic = 3.

Alternative Suggestion:

Group any JMS related message annotations within a map, e.g "x-opt-jms", to avoid overhead of initial "x-opt-[jms]" for each additional annotation. Obviously adds map overhead initially.

Further Alternative:

Use encoding as described type to save more bytes if its of sufficient concern.

Temporary Queues/Topics

JMS allows for creation of TemporaryQueues and TemporaryTopics by a Session, which can only be consumed by the Connection that created them. Their existence is scoped to the lifetime of the Connection which created their creating Session. They can however also be explicitly deleted before the Connection is closed, so long as no consumers exist.

Method 1:

Create a link to a Target with dynamic=true, expiry-policy of 'link-detach', and ensure a lifetime-policy for the new node of 'delete on close'. Keep the creating link open until the Connection is closed, or the delete() method is called.

This necessitates each Connection having a private session which can be used to create temporary queues in this way, so that the links may exist for the lifetime of the connection.

Method 2: (can't meet JMS spec requirements without extensions)

Use of the "connection-close" terminus-expiry policy in some way?

Can a dynamic node always live as long as the connection-expired terminus that caused its creation, using the standard lifetyime policies? It appears all of them allow for it to go away earlier.

"Definitionally, the lifetime will never be less than the lifetime of the link which caused its creation, however it is possible to extend the lifetime of dynamically created node using a lifetime policy. The value of this entry MUST be of a type which provides the lifetime-policy archetype. The following standard lifetime-policies are defined below: delete-on-close, delete-on-no-links, delete-on-no-messages or delete-on-no-links-or-messages."

Anonymous Producers

Define a capability to signal that an anonymous producer may be implemented by attaching a link to a specific target address, which will relay messages containing the relevant details (i.e 'to' field, and JMSDestination type annotation value) to their destination on that container, or reject them if it cant be resolved.

Candidates: ANONYMOUS-RELAY capability, $relay target address.

Questions: Addresing spec? E.g prior notes: "Links from the anonymous relay to a container-address are not permitted."

Discussion: Go with the Addressing spec. Use target with null or empty string address, tag message 'to' with container-scoped address. ANONYMOUS-RELAY capability to identify support.

Durable Subscriptions (non-shared)

JMS Durable Subscriptions (non-shared) require that a ClientID be set. Subscriptions are created during creation of the new subscriber, passing a subscription name. Closing the subscriber does not end the subscription. If the topic or slector used with a given subscription name changes when reattaching the subscriber, the old subscription is effectively unsuscribed and a new one created.

Method 1: (The old client currently doing this is relying on broker not to end the subscription when it does a Detach with close=true, which is incorrect.)

Subscribe + Close: Attach a link to the Topic node, set durable field to unsettled-state/2, expiry-policy to never, use the subscription name as the link name. Close the subscriber by using detach with close=true or false, subscription remains.

Unsubscribe: [Re]Attach a link to the terminus and update its durable field to none/0, and expiry-policy to link-detach. Close the link to end the subscription.

Method 2:

Subscribe + Close: Attach a link to the Topic node, set durable field to configuration/1 or unsettled-state/2, expiry-policy to never, use the subscription name as the link name. Close the JMS TopicSubscriber by using Detach(close=false), subscription remains. Potentially add a capability to signal durable-subscription.

Unsubscribe: [Re]Attach a link to the terminus and detach the link with close=true to end the subscription.

Shared Subscriptions (durable & non-durable)

JMS 2.0 allows shared subscription to Topics, both durable and non-durable. Shared durable subscriptions exist in the same namespace as non-shared durable subscriptions. Shared non-durable subsctiptions have their own namespace. Subscription names are scoped to a particular ClientID, which need not be set for either durable or non-durable shared subscriptions.

The above means that strategy used for non-shared durable subscriptions, of setting the link name to the subscription name, is no longer sufficient for shared ubscriptions. Multiple subscribers from the same Connection (and thus the same container name) are allowed to use the same subscription name whether a ClientID is set, or not, and multiple subscribers from different connections are allowed to do so if a ClientID is not set. Link identity must be unique for {containerA, link name, containerB} triplets.

Proposal1: Define a "shared" capability on source to indicate use of a shared subscription. Possibly a link property to convey the subscription name?

Proposal2: Define a "shared" capability on source to indicate use of a shared subscription. Add an option to the end of the address to convey subscription: E.g "topic?subscription=mysubscription" or "topic[mysubscription]"

Further Subscription Discussion

Further discussion and outline of durable and shared subscription handling. See


Certain existing client implementations use the ClientID as the container name, and certain existing broker implementations enforce only a single connection uses a given container name, whereas the AMQP specification does not state such a restriction and instead implies multiple connections from a given container are allowed. JMS 2.0 also makes the ClientID optional.

Suggestion: Continue setting the ClientID as the container name if set (generate a container name if not), but add a connection capability or property to optionally request that the remote container enforces sole usage of the chosen container name when a ClientID has been set.

Clients which do not set a ClientID will get the same default container name (necessary for namespacing links representing shared subscriptions etc), e.g "JMS_AMQP_DEFAULT_CONTAINER_ID".


Define a filter which accepts AMQP-named fields/properties/etc for selection. Translate the JMS selector string using a defined mapping, send this as the filter value.

See also:

Note: The above filter defines use of 'jms-type' as message annotation to represent the JMSType header, which is in conflict with the x-opt-jms-type annotation currently defined in the JMS mapping. Annotations that dont begin "x-opt" and arent understood by recipients must be met by closing the link. It also defines ability to select on various fields that JMS does not allow selection of but in doing so does not consider the new JMSDeliveryTime header (only JMSDeliveryMode, JMSPriority, JMSMessageID, JMSTimestamp, JMSCorrelationID, and JMSType. JMSMessageID, JMSCorrelationID, and JMSType are stated as allowed).


Define a filter to exclude from a subscription any messages sent by the same connection.

See also:

JMSMapping (last edited 2017-06-26 10:12:31 by gemmellr)