Basics of Java Message Service - II

In previous Article, we have read about basics of JMS with some simple programs. Here we shall continue with the introduction of basic programming elements, and objects of JMS Design. These basic objects are required for every JMS program. So it is important to understand these from conceptual and working aspect.

These JMS objects are called Administered JMS objects. JMS API has come in existence to provide a standard for messaging service and to standardize the interfaces and working of various messaging service providers. But, as many of the service providers were already in market, so it was not possible to define a strict protocol. Hence, JMS defines a compratively flexible protocol which take care of client protability by providing the standard interface, however, at the same time given ample flexbility to service providers to continue with their existence implementation by just changing the interfaces. JMS Administered objects are the standard objects specified by JMS API which every service provider should implement. These are important to ensure client portability. Beyond these administered objects, service providers are free to provide their custom implementation.

Following is the list of important Administered Objects:

Object Type - Implementing Objects
-----------------------------------------------
  1. ConnectionFactory - TopicFactory, QueueFactory
  2. Connection - TopicConnection, QueueConnection
  3. Session - TopicSession, QueueSession
  4. MessageProducer - TopicProducer, QueueProducer
  5. MessageConsumer - TopicSubscriber, QueueConsumer
In brief, every JMS user needs to create a connection factory first. Connection Factory can be specific to Topic or Queue messaging module depending upon requirements. JMS API defines a separate concrete object for Topic/Queue messaging model correspodning to each interface. So once we have connection factor, it can be used to ask Connection. Connection is like a factory for session objects. Session is a kind of separate working area for each client of JMS. One connection may provide multiple sessions, and each session will have its separate working space. After getting session, next step will be to create message producer and message consumer. Session acts as factory for message producers and consumers, so it is used to create message producers and consumers. Once message producer and consumers are created, now, these can be used to produce and consume the messages. Certainly, if you want to use Topic Publish/Subscribe model, you need to use Topic type of objects or otherwise you will use Queue type of objects.
These are the main objects defined by JMS API. Again JMS API does not specifies how to create Connection Factory etc. However, a general approach is that JMS provider makes a way to list these main objects in JNDI listing. Then API user can get the Administered objects from JNDI and use these further to create other objects. But this approach is not standard across the JMS providers. Hence, you may need to provide some abstraction layer to get the administered objects. That could help you for portability. Moreover, always remember to code to the interfaces defined by JMS API. If you use the JMS Provider specific API, your imlementation won't be portable to other service providers.

Now let us study the Administered objects one by one briefly.
    
ConnectionFactory- Connection Factory encasulate the knowledge of making connection with JMS provider. JMS API does not define any standard about connection parameters. Only this marker interface
is being provided which make a bridge to take connection for JMS. It is extended by two interfaces for Topic and Queue, which are, TopicConnectionFactory and QueueConnectionFactory. Both of these interfaces provide method to take their type of connections like 'createTopicConnection' and 'createQueueConnection'.

Connection- It represents a connection with JMS Provider, which facilitates to take other working objects for JMS. If any authentication is required to connect to JMS Provider, those authentication parameters will also be specified at the time of creating connection. However, authentication is purely on the wish of JMS service provider, and hence can be enabled or disabled. Here is a brief description of main methods of Connection Interface.


  • getClientId()/SetClientId()- These methods are used to get or set the client id for connection. Client ID is a unique identifier for the client. It is used to uniquely identifying the states of client with JMS provider. Client ID can can ither be set by JMS provider or by client tself. This behavior varies from implementation to implementation. If it is from JMS provider, client id will be set to Connection before returning its instance to Client. If it is from client, ID should be set to connection object before performing any other operation on it; otherwise the operations should raise the error.   
  • getExceptionListener()/SetExceptionListener()- These methods are used to get or set the 'ExceptionListener' type object to Connection. Method (onException) of this object will be invokved every time, there is any exception occured in the operation. So this object can be used to log the exception or related information.
  • getMetaData()- It is used to get the metadata of connection. Metadata is an object which provides the information for JMS API Versions, JMS Provider's product name, JMS Provider's Versions, and various other JMS defined properties.
  • start()- This method is used to start the connection. Connection and other objects taken from it can not be used to send or receive message, till connection is not started.
  • stop()- It is used to stop the operations of connection.
  • close()- This method is used to close the connection. Closing means to finally release all resources acquired by this connection and related operations. This method is important for resource management. If we close the connection, all objects taken from this connection will also be closed automatically. Close method will not return till the operations are completely closed. Like if any receiver was receiving the message, close method will wait for that operation to be completed.

Session - As mentioned above, session represents a private area of operations for a client interaction. Session interface is a big interface having methods for creating different type of messages, to know whether JMS interaction is in transaction or without transaction, to get or set the message listener, to commit / rollback / close or recover the session operations. Session interface also provides various type of acknowledgement modes.
  • acknowledgement - There are three types of acknowledgement modes. AUTO_ACKNOWLEDGE means that session will automatically acknowledge the receipt for each message sent. CLIENT_ACKNOWLEDGE means that client will acknowledge each message by using 'acknowledge' method on it. If any message is not acknowledged, JMS may redeliver it again to the client. DUPS_OK_ACKNOWLEDGE means that session may lazily acknowledge the messages. It also means that JMS may deliver the duplicate messages and that is ok with the client. In this mode, generally JMS have less overhead as it does not need to track the messages operations to avoid duplicates.
  • Methods to create various type of messages - There are various methods to create different type of messages like text message, object message, and stream message.
  • getTransacted() - This method is used to know the transacted status of JMS. If it is non-transacted, it means that one message should be sent or received at a time. If it is transacted, then more than one messages can be sent and received in groups. Point to remember, if session is transacted the only valid acknowledgement mode is 'AUTO_ACKNOWLEDGED'. It is because, in case of transacted operation, all messages are sent or or available for consumption automatically on call to commit/rollback.
  • commit()/rollback() - These methods are used to commit or rollback the transaction in case if session is transacted. If session is not transacted, these methods will throw an error.
  • get/setMessageListener() - These methods are used to set or get the message listener on session. The listener can be used to receive the delivered message asynchronously. Whenever there is any message, 'onMessage' method will be called of this 'MessageListener' type object. This is a way to receive the messages asynchronously.
  • recover() - This method is used to recover the session from any undesired state. If we recover a session, this method will stop the session and then start it again. In term of message delivery, session will start from the first unacknowledge message maintained with it. It assumes that all messages which are acknowledged are actually delivered, so it skip those and start with un-acknowledged messages. The order of message delivery may be different than last opeartion process, because session may have received other high priority messages or some message may have expired.

MessageProducer- Message producer is used to produce the messages. Session works as a factory for creating the message producer type of objects. Various methods with 'MessageProducer' are
  • get/setDisabledMessageId() - Every message in JMS used to have a unique message id. However, this behavior can be altered using these methods. So it is like a hint to JMS that whether it needs to set the message ids or not. If it is set as 'not', that can add to the performance of operations.
  • get/setDisabledMessageTimeStamp() - Every message in JMS used to have a time stamp with it. This time stamp tells the time when this message was sent. These methods help to alter this behavior. If timestamp is disabled, this can again add to the performance.
  • get/setTimeToLive() - Every message in JMS can be configured to be alive for a specific time duration. After that time, this message will be expired automatically. These methods help to set the ime. If time is set to zero, it means that message will never expire. However, if you want to set some specific time, that value can be passed in this method (in milliseconds).
  • get/setPriority() - These methods are used to set the priority of a messag in JMS. JMS specification states recommends that JMS Provider should respect the priorities set by client and should try their best to deliver the message as per the priorities. However, if any JMS provider is not following it, that would still be considered as JMS Compliant but may not be that competent.
  • get/setDeliveryMode() - JMS supports two delivery modes, which are, persistent and non-persistent. Persistent means that message given to JMS for delivery will be persisted by JMS Provider to make sure that it won't be lost due to JMS failure. Hence, this mode can be considered more reliable. Non-Persistent mode is where messages will not be persisted and hence may be lost due to any failure. Point to consider is that persistent mode will also add performance overhead. So client should make a informed decision based on requirements. 
  • close() - This method is used to close the operations of message producer and release any resource acquired for operations.

MessageConsumer- Object of this type will act as consumer of messages. Session acts as factory for message consumers also, hence, these objects are being produced by session. Various methods specified in this interface are given below.
  • getMessageSelector() - Message Selector String is like a filter specified with message consumer which will help JMS to filter specific kind of messages for this message consumer based on given message selector string. Message Selector string can be specified while registering the message consumer with JMS.
  • get/setMessageListener() - Message Listener type object are used to receive the messages asynchronously. If this object is set, JMS will call the 'onMessage' method of this object and hand over the message to process asynchronously.
  • receive/receive(long timeout)/receiveNoWait() - These are various methods to receive the message synchronously. Simple receive() method is a blocking method, which will wait (when called) till any message is not received. receive(long timeout) method will wait for the specified time before it receive any message and return after that. receiveNoWait() will not wait at all. It will simply look for the message. If it exist, take it and return. If it does not exist, return without message.
  • close() - Close method is to close the operations of message consumer and to releaes any resoruce acquired for operation. This will help in resource management.

close() method is very important in all of these objects. It is a safe and right way to release the resources used in operations. One should not rely on Garbage Collection process for cleaning the resoruces acquired, rather, should use close() method to release the resources as soon as operations are finished.

In this article, we have learnt about the API basics intefaces and methods.   

People who read this post also read :



0 comments:

Post a Comment