Skip to end of metadata
Go to start of metadata

 This page is under construction.

Basic Operations

Objects

JMS

JMSPool

  • Constructor arguments, refer to the JavaDoc of ThreadPoolExecutor
    • corePoolSize: 10, maximumPoolSize: 20, keepAliveTime: 360, unit: TimeUnit.MILLISECONDS

APIs

receive()

  • for a queue, receive is the standard JMS receive method.
  • for topics, the receive() method is a blocking operation that create a 'temporary subscription'. The 'temporary subscription' wait for the first message and then unsubscribe and return the message. If a 'within' expiry time is provided, the 'temporary subscription' will be unsubscribed when the 'within' time is reached, and return null. This feature is typically used with message selector, and is useful for simulating a synchronous operation with the asynchronous JMS infrastructure. e.g. a client use a new thread to send a request with some delay, and in the main thread listen to the server response topic in synchronous manner.

Shared Features

Features that are used across APIs are listed in this section

Message Selector

  • In JMS, Message Selector is a String that defines some filtering conditions for receiving messages. Refer to the JMS Javadoc for details
  • In Groovy Messaging Service API, you may use the messageSelector parameter in receive and onMessage,the message selector parameter takes a String, a List, a Map, or a Closure with one parameter
    • For a String, the String will be used for every destination specified in the same call
    • For a List, it will be matched a against the List of Queue and Topic respectively. If the number of destination is less than the number of message selector items, the excess message selectors will be ignored. If the number of destination is more than the number of message selector items, the excess destination will have no message selector. You could use null for destination or message selector in doing matching. When both fromQueue and fromTopic are used, the two list of destinations will be muched respectively with the same list of message selector.
    • For a Map, the key of the map parameter will be matched against the destination name.
    • For a Closure, it works similar to a map and it passes in the destination name or destination and expect a String of return value as the message selector

 

Advanced Features

JMSPool

Overview

  • JMSPool is an advanced JMS instance that allow multiple threading messaging for incoming and outgoing messages. It is built on Java 5 concurrency library and also utilize the ActiveMQ Pooled Connection Factory. So only Java 5 and AMQ are supported.
  • For simple JMS usage,
    • a new connection and session are created on every JMS execution block. Resources are closed after usage.
    • user has to manage threads and concurrency. Without special coding, messages are sent and received in a single connection and session. 
  • The currently JMSPool is fairly simple. It does not support features like transaction, connection recovery etc. If you need a full feature JMS Pooling product, you are highly recommended to use Spring JMS or Jencks.
  • With JMSPool
    • You could use a JMSPool intance with multiple threads for incoming and outgoing messaging
    • The threads are managed by Java 5 ThreadExecutor
    • Each thread uses a JMS instance
    • All closure in any thread are run in the use(JMSCategory){ }  context. i.e. you could freely use GroovyJMS APIs

Outgoing messages (jms.send())

  • For outgoing messages to Queue or Topic, it works like the following diagram

    • Without the pool, multiple clients will have to send message in a serial manner. The JMSPool supports clients from multiple threads to send message asynchronously. When there are more concurrent message than worker threads, the messages will be put on a an internal buffer.
    • Worker threads are spawn to handle connection in parallel, each thread makes a connection to the JMS server.
    • In the initial implementation, the main advantage of the JMSPool over the original JMS are:
      • user could easily send outgoing message in parallel, e.g.
        It spawns 10 threads to send 10 messages in parallel.
      • Asynchronous sending
        every user call is returned asynchronously after it reaches the internal buffer, instead of waiting for the message to reach the external JMS server. It potentially provide a better throughput when you have a large volume of messages to send. Notice that this is not necessary the ideal behavior in every case and you should be cautious when using it, and without a recovery mechanism in place (as in the initial implementation), your outgoing message may lose if there is exception in delivery and you'll only get an exception via the global exception handler. TODO verify the exception implementation
      • connection reuse
        every thread get a connection from the AMQ connection pool to send message. The connection pool is supposed to provide connection re-use. Session is not shared.
      • parallel messaging for multiple destination (NOT implemented yet)
        A single send operation is split to three threads, and the message is sent in parallel. The number of threads should be less than the maximumPoolSize.

Async incoming message

  • Diagram

  • JMSPool assumes you want to use one thread per "destination and message selector" in each call. (TODO: message selector is not implemented) When there are multiple destination and message selector combination,
  • onMessage allows user to receive messages one by one in an asynchronous basis. It works differently depends on the destination:
    • for a queue, multiple threads will be spawn with the same listener to the queue. As messages are received one by one per thread. You are able to receive messages at a much higher rate.
    • for a topic, it doesn't make sense to subscribe with more than one thread. So the threads parameter will be ignored.
    • for multiple queues and topics, every queue will be listened by the specified number of threads, and every topic will be subscribed by one thread only. (as the 'threads' parameter is ignored)
  •  TODO: perhaps the 'threads' parameter could be implemented in a way similar to Message Selector and take a list or map of value

Sync receive message

  • synchronous message receiving, e.g. jms.receive fromQueue:"myQueue, works very similar to its asynchronous counterpart. But behave differently in the following ways:
    • when the receive method is used to receive all messages (it is by default if a 'limit' parameter is not used), there is no real need to use multiple thread and it may not improve performance unless you have a lot of messages. The 'threads' parameter will be honored and you should use it according to your need.
    • For queues, when multiple threads are used, it waits for every thread to complete their works, and aggregate all results to return to you. The 'with' closure for queue will be called once and only once with the aggregated result in the first parameter.
    • For topics, only one thread will be used for each topic-selector pair. When the number of topic-selector pairs is less than the number of 'threads', e.g. fromTopic:['t0','t1','t2'], threads:2, a 'temporary subscription' will be issued for the first 2 topics immediately, and only after one of them has return, a 'temporary subscription' will be issued for the 3rd topic. And only after all 3 topics are done, you'll get the aggregated return value.
  • No labels