JMS Compatibility
SwiftMQ fully implements both the Point-To-Point and Publish/Subscribe message model of JMS Version 1.0.2.
It does not implement:- Application server support such as ConnectionConsumer.
- Distributed transaction support (all JMS classes beginning with XA).
This might be supported in future releases of SwiftMQ.
Queue Location Dependency
Queues are the base for the Point-To-Point message model. This model is usually taken to implement server inbound queues. Queues are location dependent. They reside on a specific router, usually for a long time. Sending messages to a queue could be performed from every router in a network that has a route to the router where the queue is hosted. Receiving messages from a queue is limited to the queue's hosting router. It is not possible to create a QueueReceiver for a queue on a different router.
Multiple Queue Receivers
A queue is defined as a first-in-first-out message store. Usually a queue has one receiver that fetches and processes the messages. SwiftMQ provides the possibility to create multiple receivers per queue. With this approach a 'natural' round-robin scheduling comes in place where each receiver fetches the next available message from the top of the queue. This means that a load balancing on the client side could be easily implemented by simply starting more client process instances to increase the message troughput.
Queue Names
Due to location dependency, a queue name must always be completely qualified to ensure correct message routing:
In exception to this rule, the initial definition of queues in the QueueManager configuration must always be without the router name. This makes it easy to change it. For this reason it is suggested to define an JNDI alias for queues to avoid definitions of router names into JMS applications.
The <queue> part of the fully qualified name must consist of letters or digits.
Predefined Queue unroutable
There is one predefined queue on each router for messages that cannot be routed to their destination queue because the queue is dropped while the message is inside the router network. These messages become unroutable and will be forwarded to the queue unroutable on the specific router. To get this messages, a JMS application can create a QueueReceiver and send them again i. e. with a new destination.
Topic Location Independency
In contrast to queues (PTP message model), topics are location independent. They are available on every router in a connected router network due to automatic broadcasts of local subscribers from every router to all connected routers in the network. In fact, one can publish or subscribe from any router in a router network if the authentication process on the specific local router was successful. This means: - The topic must be defined in the local TopicManager configuration.
- The access to the topic must be granted in the AuthenticationSwiftlet configuration.
Topic Hierarchy
SwiftMQ provides the possibility to define topic hierarchies in the form <roottopic>.<subtopic>.<subsubtopic> etc.
Examples:
iit.sales.EU iit.sales.US iit.projects.swiftmq.users news.weather.forecasts sports.formula1.MichaelSchumacher
|
Publishing and subscribing rules to nodes in a hierarchy:- Selecting a specific node in a topic hierarchy publishes messages to the addressed node and all concerning sub-nodes. Example: publishing to node iit.sales sends the messages also to iit.sales, iit.sales.US, iit.sales.EU.
- Subscribing to a specific node in a topic hierarchy means to receive all messages addressed to this node and all parent and sub-nodes. Example: subscribing to iit.sales.US one receives all messages published in iit, iit.sales, and iit.sales.US; subscribing to iit.sales one receives all messages published in iit, iit.sales, iit.sales.US, iit.sales.EU, but you don’t receive the messages published in the iit.projects hierarchy.
- A subscriber receives a message only once, regardless of the number of topics his subscription matches.
Performance issues:
Unlike other JMS implementations, SwiftMQ has no virtual root node such as '*' to simply publish/subscribe to all messages for all nodes. Two reasons to choose a different approach: First, the performance. If there is one root node, there must be exactly one topic broker. All messages have to pass this root broker because there could be a subscriber on it. So, this root broker is a synchronization point for all messages published in the system. This is not really scalable. Next, SwiftMQ also uses topics to exchange system information. These topics should be completely hidden. Due to this reason, for every hierarchy SwiftMQ has a root broker that is responsible for the message delivery. Every root broker acts independently and asynchronous from every other root broker. Considering this point, it is better to define flat hierarchies than deep ones.
SQL-Like Predicate Topic Addressing
As an extension to the normal topic node- and subnode-addressing scheme, SwiftMQ provides SQL-Like predicate topic addressing. So every specified subnode could be a SQL-Like predicate. A SQL-Like predicate could contain wildcards which match a single character (the underscore’_’), or any characters (the percent sign '%'). Escape character is '\'.
Example:
To address the topic iit.sales.US one can also write iit.s%s._S; to address all subnodes within the same hierarchy level on hierarchy iit concerning swiftmq the predicate is iit.%.swiftmq.
Root nodes cannot be addressed as a predicate; i. e. it is not possible to specify i%.%.swiftmq.
Predicate topics are normal topic destinations and are not available via JNDI lookups. To create a predicate topic, one has to use the createTopic() method from a TopicSession.
Example:
Topic allSwiftMQ = topicSession.createTopic("iit.%.swiftmq"); msg.setJMSDestination(allSwiftMQ); publisher.publish(msg);
|
Access to predicate topics must be granted via the AuthenticationSwiftlet just like normal topics.
Note: Using predicate topics is not portable.
Predefined Topic swiftmq.jndi
There is only one predefined topic that is shared between JMS clients and internal SwiftMQ Swiftlets; the topic to broadcast JNDI lookups, the use of which is restricted to SwiftMQ's JNDI implementation. The topic name is swiftmq.jndi. To use this topic, a publish-grant is needed. This could simply be done by defining this grant within the public group. For details have a look at the AuthenticationSwiftlet configuration.
Message Selectors
Message selectors are implemented in SQL92 style syntax. The implementation belongs to the JMS specification 1.0.2. SwiftMQ's message selectors provide the extension to also use arithmetic expressions such as:
property1 = property2 * 10 * (property3+5) or property2/100 = 5
|
Note: Using arithmetic expressions in message selectors is not portable.
Client Id's
Client id’s can only be set as the first method call with setClientID() just after creating a connection. The client id must be unique for the specific router. If another client connects with the same client id, setClientID() will be rejected from SwiftMQ.
Durable Subscriber
The JMS specification may be unclear concerning creation, reconnection, change and deletion of durable subscribers. So, let's have a look at how it works in reality:
Creating a durable subscriber:- A valid client id must be set with setClientID() as the first method call after creating a connection.
- A TopicSession must be created.
- Choose one of the createDurableSubscriber() methods.
- The durable subscriber is now in place and receives all the messages addressed to this topic.
Reconnect to an existing durable subscriber:- Same procedure as above; supply the same parameters to createDurableSubscriber().
Changing an existing durable subscriber:- Same procedure as above, but supply different parameters on createDurableSubriber() (except the durable subscriber name, that must match, otherwise a new one is created).
- The durable subscriber will be dropped with all content and re-created with the new parameters.
Deleting an existing durable subscriber:- A valid client id must be set with setClientID() for the first method call after creating a connection.
- A TopicSession must be created.
- The unsubscribe() method must be called with the name of the durable subscriber.
- The durable subscriber will be dropped with all content.
Durable subscribers are location dependent. They reside on a specific router and can only be accessed from that router on which they have been created.
JMS_SWIFTMQ Message Properties
JMS provides the possibility to specify vendor specific message properties. These properties have the prefix JMS_<vendor>. SwiftMQ defines the following vendor properties:
Property Name | Type | Content |
|
JMS_SWIFTMQ_BC | boolean | Switch message body compression on/off. |
|
JMS_SWIFTMQ_CID | String | Contains the client id of the message producer. |
|
JMS_SWIFTMQ_REASON | String | Contains the reason for unroutable messages. |
|
JMS Examples
This SwiftMQ distribution contains a directory samples with original JMS examples from Sun Microsystems.
In some of these example programs were some timing problems if the program creates subscribers and publishers in different threads, because creating a subscriber is more heavyweight than creating a publisher in SwiftMQ, so sometimes the publishers are sending their messages before the subscribers are ready. For this reason we put a sleep just after creating the subscribers to give them a real chance to subscribe before the publishers are starting.
In SampleUtilities.java we've hardcoded the SMQP-URL and the InitialContextFactory. The URL points to the distributions router1 on port 4001. If you change your configuration, you must also change this URL.
To simplify the invocation of the various examples we've provided start scripts for both Unix and Windows named starter resp. starter.bat. These scripts requests as first parameter the name of the example and as second parameter usually the name of the queue or topic. As queue use testqueue, as topic testtopic, please. Both are pre-configured in this distribution.
Example to start the example TopicSelectors with the Unix start script from the samples directory:
./starter TopicSelectors testtopic
|
And a point-to-point example with SimpleQueueSender on testqueue at router1. Please note, that you must qualify the queue name with the router name (<queue>@<router>):
./starter SimpleQueueSender testqueue@router1
|
The samples directory also contains the original Readme file from Sun. Please consult this before using the examples.