Friday, December 14, 2007

JMS Interview Questions

Some nice interview questions for JMS from http://www.allapplabs.com/ . Covers most of what you might want a candidate to know when it comes to java messaging.

JMS Interview Questions

Question:
What is JMS?

Question:
How JMS is different from RPC?

Question:
What are the advantages of JMS?

Question:
Are you aware of any major JMS products available in the market?

Question:
What are the different types of messages available in the JMS API?

Question:
What are the different messaging paradigms JMS supports?

Question:
What is the difference between topic and queue?

Question:
What is the role of JMS in enterprise solution development?

Question:
What is the basic difference between Publish Subscribe model and P2P model?

Question:
What is the use of Message object?

Question:
What is the use of BytesMessage?

Question:
What is the use of StreamMessage?

Question:
What is the use of TextMessage?

Question:
What is the use of ObjectMessage?

Question:

What is the use of MapMessage?

Question:
What is the difference between BytesMessage and StreamMessage?

Q:

What is JMS?

A:
JMS is an acronym used for Java Messaging Service. It is Java's answer to creating software using asynchronous messaging. It is one of the official specifications of the J2EE technologies and is a key technology.

[ Received from Sandesh Sadhale]

TOP

Q:

How JMS is different from RPC?

A:
In RPC the method invoker waits for the method to finish execution and return the control back to the invoker. Thus it is completely synchronous in nature. While in JMS the message sender just sends the message to the destination and continues it's own processing. The sender does not wait for the receiver to respond. This is asynchronous behavior.

[ Received from Sandesh Sadhale]

TOP

Q:

What are the advantages of JMS?

A:
JMS is asynchronous in nature. Thus not all the pieces need to be up all the time for the application to function as a whole. Even if the receiver is down the MOM will store the messages on it's behalf and will send them once it comes back up. Thus at least a part of application can still function as there is no blocking.

[ Received from Sandesh Sadhale]

TOP

Q:

Are you aware of any major JMS products available in the market?

A:
IBM's MQ Series is one of the most popular product used as Message Oriented Middleware. Some of the other products are SonicMQ, iBus etc.All the J2EE compliant application servers come built with thier own implementation of JMS.

[ Received from Sandesh Sadhale]

TOP

Q:

What are the different types of messages available in the JMS API?

A:
Message, TextMessage, BytesMessage, StreamMessage, ObjectMessage, MapMessage are the different messages available in the JMS API.

TOP

Q:

What are the different messaging paradigms JMS supports?

A:
Publish and Subscribe i.e. pub/suc and Point to Point i.e. p2p.

[ Received from Sandesh Sadhale]

TOP

Q:

What is the difference between topic and queue?

A:
A topic is typically used for one to many messaging i.e. it supports publish subscribe model of messaging. While queue is used for one-to-one messaging i.e. it supports Point to Point Messaging.

[ Received from Sandesh Sadhale]

TOP

Q:

What is the role of JMS in enterprise solution development?

A:
JMS is typically used in the following scenarios
1. Enterprise Application Integration: - Where a legacy application is integrated with a new application via messaging.
2. B2B or Business to Business: - Businesses can interact with each other via messaging because JMS allows organizations to cooperate without tightly coupling their business systems.
3. Geographically dispersed units: - JMS can ensure safe exchange of data amongst the geographically dispersed units of an organization.
4. One to many applications: - The applications that need to push data in packet to huge number of clients in a one-to-many fashion are good candidates for the use JMS. Typical such applications are Auction Sites, Stock Quote Services etc.

[ Received from Sandesh Sadhale]

TOP

Q:

What is the use of Message object?

A:
Message is a light weight message having only header and properties and no payload. Thus if theIf the receivers are to be notified abt an event, and no data needs to be exchanged then using Message can be very efficient.

[ Received from Sandesh Sadhale]

TOP

Q:

What is the basic difference between Publish Subscribe model and P2P model?

A:
Publish Subscribe model is typically used in one-to-many situation. It is unreliable but very fast. P2P model is used in one-to-one situation. It is highly reliable.

[ Received from Sandesh Sadhale]

TOP

Q:

What is the use of BytesMessage?

A:
BytesMessage contains an array of primitive bytes in it's payload. Thus it can be used for transfer of data between two applications in their native format which may not be compatible with other Message types. It is also useful where JMS is used purely as a transport between two systems and the message payload is opaque to the JMS client. Whenever you store any primitive type, it is converted into it's byte representation and then stored in the payload. There is no boundary line between the different data types stored. Thus you can even read a long as short. This would result in erroneous data and hence it is advisable that the payload be read in the same order and using the same type in which it was created by the sender.

[ Received from Sandesh Sadhale]

TOP

Q:

What is the use of StreamMessage?

A:
StreamMessage carries a stream of Java primitive types as it's payload. It contains some conveient methods for reading the data stored in the payload. However StreamMessage prevents reading a long value as short, something that is allwed in case of BytesMessage. This is so because the StreamMessage also writes the type information alonwgith the value of the primitive type and enforces a set of strict conversion rules which actually prevents reading of one primitive type as another.

[ Received from Sandesh Sadhale]

TOP

Q:

What is the use of TextMessage?

A:
TextMessage contains instance of java.lang.String as it's payload. Thus it is very useful for exchanging textual data. It can also be used for exchanging complex character data such as an XML document.

[ Received from Sandesh Sadhale]

TOP

Q:

What is the use of ObjectMessage?

A:
ObjectMessage contains a Serializable java object as it's payload. Thus it allows exchange of Java objects between applications. This in itself mandates that both the applications be Java applications. The consumer of the message must typecast the object received to it's appropriate type. Thus the consumer should before hand know the actual type of the object sent by the sender. Wrong type casting would result in ClassCastException. Moreover the class definition of the object set in the payload should be available on both the machine, the sender as well as the consumer. If the class definition is not available in the consumer machine, an attempt to type cast would result in ClassNotFoundException. Some of the MOMs might support dynamic loading of the desired class over the network, but the JMS specification does not mandate this behavior and would be a value added service if provided by your vendor. And relying on any such vendor specific functionality would hamper the portability of your application. Most of the time the class need to be put in the classpath of both, the sender and the consumer, manually by the developer.

[ Received from Sandesh Sadhale]

TOP

Q:

What is the use of MapMessage?

A:
A MapMessage carries name-value pair as it's payload. Thus it's payload is similar to the java.util.Properties object of Java. The values can be Java primitives or their wrappers.

[ Received from Sandesh Sadhale]

TOP

Q:

What is the difference between BytesMessage and StreamMessage??

A:
BytesMessage stores the primitive data types by converting them to their byte representation. Thus the message is one contiguous stream of bytes. While the StreamMessage maintains a boundary between the different data types stored because it also stores the type information along with the value of the primitive being stored. BytesMessage allows data to be read using any type. Thus even if your payload contains a long value, you can invoke a method to read a short and it will return you something. It will not give you a semantically correct data but the call will succeed in reading the first two bytes of data. This is strictly prohibited in the StreamMessage. It maintains the type information of the data being stored and enforces strict conversion rules on the data being read.

[ Received from Sandesh Sadhale]

TOP

My Blog Archive so far

JMS and Distributed Software Development

Nice article on Java Lobby by Roger Voss.


Using JMS For Distributed Software Development

Let's start with some background on JMS. Java Messaging Service is an API specification only. It does not define any standard for how JMS messages are conveyed over the wire. This means that JMS implementations from different venders cannot directly interact with one another. However, most vendors have bridge products that enable integration with other messaging services. (Also, it is not very difficult to write a bridge. For instance at our company we wrote a bridge that is deployed as a JMX MBean service in a JBoss application server and bridges Oracle AQ to Tibco EMS. This enables PL/SQL developers to publish messages to AQ within Oracle and have those messages bridged into Tibco EMS queues or topics. Hence we can disseminate server-side push notifications from the rear-most back-end tier of our n-tiered distributed architecture.)

Some JMS Implementations

There are a number of JMS implementations - both proprietary and open source. Here are some of the proprietary products:

And some open source implementations:

This listing is not exhaustive but merely representative.

I use Tibco EMS in my professional software development so my experience will be from the perspective of that product. In conducting a JMS evaluation for our company a few years ago, I also became familiar with others as well and will interject an occasional comparison or contrast with Tibco.

Central Server, Star Topology

JMS is typically implemented as a star topology hubbed to a central server. Messaging end-points connect to the server where they - in loosely coupled fashion - interact with other end-points via queues and topics. Enterprise-ready JMS implementations will offer a high availability clustering capability, and in some cases an option to scale the JMS service via clustering. A typical approach for high availability is the active/passive cluster. At least one physical server is the active JMS server while other servers in the cluster are in passive standby. Tibco offers this approach to a HA solution so at our customer sites we establish two JMS servers, one running actively while the other is in standby mode.

Persistent Connections and Push Notification

Because JMS messaging can take place bidirectionally, it is usual that JMS end-points connect to the central server using a persistent TCP/IP socket connection. A very useful capability in JMS is publish/subscribe topics. This is a loosely coupled one-to-many notification pattern. Business logic in the middle-tier can publish to a topic (which is the only thing it has to know how to connect to) while zero or many end-points may be connected to the topic as consumers. Thus the persistent connection makes it feasible to do server-side push of notification messages out to end-points.

Pub-sub pattern

JMS doesn't mandate the over-the-wire implementation so it is conceivable that JMS might be implemented on top of connectionless UDP. This approach might be useful in respect to wireless devices. (Our company makes use of industrial hand-held wireless devices, for instance. Tibco offers another product, though, that is perhaps better specialized for this called SmartSockets. Tibco also offers a bridge for tying a SmartSockets sub network into a JMS-based enterprise messaging system.)

Scalability Issue

Because JMS is usually predicated on having end-points establishing persistent connections, this represents a significant issue in terms of scaling a JMS service. Prior to the introduction of Java NIO with the Java 1.4 release, a JMS server written in Java would be hampered in that a socket connection would consume a thread. Most operating systems have a relatively low number of threads that can be concurrently active before context switching becomes too much overhead - effectively, say, a few hundred. As a consequence of this problem with old-style Java socket servers, Tibco chose to implement their JMS server in the C language where the socket select call could be leveraged. This enables their server to scale to thousands of end-point connections per a single physical server. None-the-less, the Tibco EMS server is available on a large array of platforms: IBM RS6000 AIX, Sun Solaris, Linux, Microsoft Windows, and Apple Mac OS X. (Of course Tibco EMS has Java client bindings for Java end-points.) SonicMQ is implemented in Java but makes use of the Java NIO library such that a few threads can service many socket connections. Consequently it too is able to scale well on a single physical server. (JBossMQ is currently being rewritten to address performance and scaling concerns.)

Ironically, in some circles the fact that the Tibco EMS server is implemented in C is a comfort factor - obviously to those that don't know or feel comfortable with the Java language. What computer language the JMS server is written in is immaterial to the JMS software programmer as he/she will deal only in the client bindings. Yet for old school C/C++ programmers and even some C# folks, the notion of a C implemented server tends to lesson their skepticism toward messaging a little when going into it for the first time.

Fail-over State Management

High availability cluster solutions for JMS that I am aware of use two different approaches for managing active state. Tibco EMS requires that the active and passive standby server pair have access to the same shared-state on a file system. When fail-over occurs and the passive standby server becomes active, it will look to the persistent state in the shared file system by which to resume operation. (Non-persistent messages could be lost during the transition, though, so if the message data is crucial, then one should choose persistence when queuing it.)

SonicMQ offers an option to use a distributed two-phase commit replication of state between the active and passive standby server pair.

Minimal HA Installation

The difference of the two solution approaches boils down to performance vs monetary cost. A shared file state can be higher performing - but the quality of the cluster-aware file system that is used is all crucial as a poor implementation of such a file system could cripple performance and even lead to catastrophic data loss. A distributed replication of data means that the local file system of each server is ultimately used to store persistent state but with the overhead of performing lock step synchronous disk writes on two different machines.

The shared state approach can be significantly more expensive monetary-wise as a fully redundant hardware storage device must be established - down to redundant drive interface cards and redundant power supplies. Not having such redundancy would risk this storage device becoming a single point of failure - which would defeat the purpose of even having a high availability cluster.

FiroanoMQ offers an interface to JDBC storage such that a SQL relational database could be used for persisting state. If the database itself is clustered for high availability, then this might be a feasible solution. However, a SQL relational database used for messaging persistence will be slower relative to the solutions that use the file system directly. For modest messaging loads and where the back-end database is already redundant, this approach might be rather economical while still offering integrity against data or service loss.

Heterogeneous Client Support

If you write enterprise distributed software systems as I do then chances are you find that you're often faced with integrating software spanning across platforms, languages, and software providers (i.e., vendors). In other words, you deal with a heterogeneous computing network environment. When choosing an enterprise-capable messaging system, support for diverse client end-points was weighted very heavily in my decision matrix.

With Tibco EMS, I get client bindings for Java, C (and thus C++), .NET, and Compact Framework .NET for WinCE. For software I personally create, I write my middle-tier using Java and for my rich client apps I use C# .NET. I also have WinCE embedded computers that run Compact Framework .NET and that participate in JMS messaging. As to my external vendor relations, some use C# .NET while others use C++ (and thus use Tibco's C client library). Internally in my company we have an important product group that adopted Tibco EMS for use and they write their software throughout in C# .NET.

All of this software uses XML for the message payload format, which naturally can be readily processed by any of these end-points. A JMS messaging system is the one ring that binds them all.

At the time I made my JMS product selection other vendors in the running did not have client support for Compact Framework .NET for WinCE (an important platform for my company because of industrial WinCE devices we use that are a part of our distributed software systems). The Tibco JMS client binding for WinCE is 100% .NET managed code so there is no complication during deployment as to which CPU the WinCE devices are designed with (MIPS, StrongARM, Intel, Hitachi, etc.). It also has support for SSL connections.

Now I recall from my JMS product evaluation that there was one particular client implementation for .NET where C# wrapper classes were draped over an underlying implementation that was written in C++. This limited client support to desktop Windows .NET while greatly complicating that JMS vender's prospects of porting to Compact Framework .NET on WinCE. I also uncovered issues in this particular implementation in my testing. My word of advice is be sure that you select a vendor that has a 100% managed code implementation for .NET if that particular platform is important to you.

Administrative Configuration

While dwelling on the subject of client bindings, I should note that Tibco EMS provides administrative APIs for both Java and .NET. These APIs are specific to Tibco and are relevant to control and operation of their servers. Once you become immersed in using messaging, you're likely to find yourself writing various tools and utilities that interact with your messaging server at this level.

Out of the box Tibco EMS provides an interactive command line admin tool. This turns out to be an easy tool to use and it has mostly adequate online help. Of course there is more thorough HTML-style electronic documentation and PDF versions as well. Any configuration action can be performed using this command line admin tool. It also can remotely attach to the JMS server that is to be configured. Administrative username and passwords can be set to restrict access.

Tibco has yet another command line tool that can be used to process a configuration script text file in a batch fashion. This is the approach I currently employ. I created an all-encompassing configuration script and checked it into my Perforce source code repository. This one script addresses all of the configuration that is necessary for the distributed software products that my organizational group is responsible for. I use a java tool to preprocess this script file such that replacement variables of the form are replaced with java system property values of the same name. I apply this script from an ant build file so that the property values are easy to set up. This makes it straightforward to customize some aspects of the configuration with regard to the specific customer site.

Configuration is all important with JMS servers as the queues, topics, user accounts, permissions, bridge rules, etc., will all need to be administratively setup prior to running the messaging software. My group manages numerous customer sites so we want to be exact in our deployments. The batch script approach to configuration makes that straightforward to do.

Tibco additionally offers an optional product called Hawk that can be used to administer a domain of JMS servers across the enterprise WAN. It has a GUI interface. SonicMQ likewise offers a nice graphical UI domain administration tool.

Special Messaging Features

The JMS API specification is aimed at software developers that are using asynchronous messaging for distributed communication. There are some features which JMS implementations offer that exceed the specification. However, the ones I'm going to high light do not require using any special extensions to the JMS API, and so do not impact the portability of software.

Bridge Rule Selection Expressions

This is a feature offered in the Tibco EMS server that has become one of my very favorite over time. It builds on top of the message filtering and routing capability that is inherent with JMS via message properties and selection expressions. A JMS client can filter the messages it receives from, say, a topic that it is a subscriber to by specifying a selection expression that uses message property values to select which messages will actually be conveyed to the client. (Standard JMS message filtering and routing is a hugely useful feature and it is very difficult to imagine that there are other kinds of messaging systems that exist which have no such capability.) The expression syntax is based on SQL so will be familiar to most developers.

A bridge rule uses this same JMS selection expression syntax for specifying the routing of messages amongst queues and topics that exist in the server. Administratively one can create a bridge rule in the server that will copy messages from one place where they are being published to yet another place where there is a newly defined interest in consuming that message.

This is a feature that begins to make sense once one has accumulated an extensive portfolio of messaging applications. As the application population grows one becomes more focused on deployment and configuration issues. It is a simplifying matter if a JMS client application is written to consume messages from a single queue or topic and to publish to a single queue or topic. Think of this as an inbox and outbox per messaging application.

Now if some application is currently publishing messages to its outbox topic and another existing application needs to be altered to begin consuming some of those messages, it is easy to add a bridge rule that will copy the desired messages from where they're being published to where they now need to be consumed. It will not be necessary to recode the consuming application to become a subscriber to yet another topic and establish yet another JMS session. Instead the programmer need merely add new message handling code for the new type of message to be consumed. (Indeed, in C# .NET or Java it doesn't take much effort to build an architecture for applications where message handlers can be added as a plug-in modules.)

There is also a case where sometimes a message being published into a JMS topic must be copied into a JMS queue before it can be consumed by an intended end-point application. This arises typically where a JEE Message Driven Bean (MDB) is consuming messages from a queue. If one is using a cluster of JEE application servers then it is necessary to specifically use a queue in conjunction to the MDB in order to prevent a message from being processed more than once. (Will note here that the JMS server also does round-robin load balancing to a cluster of queue end-point subscribers.) So a bridge rule can be used to very nicely solve this particular dilemma.

Server-to-Server Bridging

This form of bridging is similar to the previous bridge rule feature but this time messages will be routed and copied between distinct JMS servers. It is a capability that will usually be found in the enterprise class of JMS products. If applications have been built to use messaging for distributed computing interactions, then using this feature is an effective way to tie applications together that are geographically far flung.

For instance, let us say that at one location a data center exist hosting relational database storage and JEE middle-tier application servers. At various branch offices rich client applications are in use that are designed to interact with the data center middle-tier via messaging. A JMS server would be set up at the data center site and a JMS server would be installed locally at each branch office. Client applications in the branch office would connect for their JMS sessions against their local JMS server. That server would forward all message traffic to the data center JMS server over a corporate WAN connection (or out over the public Internet using secure SSL connections). The JEE hosted middle-tier applications would likewise sustain only local connections against their network local JMS server.

The benefit of this arrangement is that the JMS servers can easily and reliably sustain hundreds of connections to local client applications while establishing and managing just a few remote connections over the WAN for the purpose of bridging JMS servers together. A client will consequently start up and establish connectivity very quickly as it only has to establish network local socket connections. Message publishing operations by client apps will also happen very quickly as out-going messages are swiftly queued up in local servers. The message traffic out-going over the WAN will be efficiently buffered as data is held safely in a JMS server until transmitted over the WAN connection and received by the JMS server at the other end. Momentary interruptions of WAN-spanning connectivity will not result in breaking the network local connections of end-user client applications - lending a better overall user experience.

SalesFore.com style SOA

If an enterprise needs to funnel many far flung users into a common data center (turning the data center into the messaging-based SOA analog of SalesForce.com), then bridged JMS servers are a better way to do that rather than have remote client applications attempt to connect directly to the data center middle-tier. Yet to take advantage of this manner of arrangement, end-user applications need to be designed to use asynchronous messaging. All of my end-user applications are built to use messaging exclusively (with exceptions to that rule being some streaming video and HTTP as used for retrieval of images from an archive server). After a few years of creating such software I can say it is very much doable and is indeed very much a superior way to design applications.

Message Trace Logging

Tibco EMS has a feature for enabling trace logging of specified message traffic. All JMS message types support the toString() method in some manner. When dumping a message for tracing, all properties and time-stamp information of a message will also be displayed. Of course this can be handy for debugging and verifying that the contents of messages are coming through as expected (if the content is clear text such as XML, name-value pair data, or JSON). With Tibco EMS, tracing should not be enabled for production as trace output is logged to file (the unix tail tool is handy for viewing these). It thus incurs the additional overhead of the file i/o, but also, if the messaging traffic being logged is heavy, the log file could grow to exhaust file storage and cause an operating system crash. On a production JMS server such would not go unnoticed.

Shadow Queue Monitoring

Another technique that is easy to rig up, though, is to create what I call a shadow queue. A bridge rule can be added to the JMS server that will copy messages to this shadow queue. One can then run a JMS console-based client app that will dump messages from the shadow queue to the console display. Most console mode programs on Windows, Macintosh, or Linux can have the console memory buffer significantly increased. This makes it possible to capture a fair amount of message traffic that one can scroll back and forth through to examine.

A message expiration policy of no more than a few seconds should be set on the shadow queue. When the message dump tool is not connected to the queue, messages copied into this queue will just expire and be harmlessly expunged. (One would not want messages to ever pile up in this shadow queue without being consumed as that could exhaust virtual memory and ultimately crash the JMS server.)

What is nice about this approach is that it can be used with production situations as the overhead from the shadow queue is very minimal such as to be of no consequence.

My company deals with hardware-based automation systems that result in the publishing of JMS messages. It is very useful to attach to a production JMS server to examine these messages when something may have gone out of adjustment or otherwise ceased to function correctly. Needless to say, the shadow queue monitoring technique has become a staple of my JMS messaging toolbox. (Notice how the bridge rule feature figures into this technique? It is just a wonderfully handy feature.)

JMS Auto-Discovery

When I first started using JMS messaging, one of the very first things I did was write a JMX mbean that is hosted as a high availability singleton in my JEE application server cluster. Its purpose is to provide a UDP-based auto-discovery service that client applications can use to discover the JMS cluster to connect to. My JMS client applications broadcast UDP datagrams that the JMS mbean will respond to by sending back the JMS connection URL (which for a high availability JMS cluster will consist of multiple URLs). The client applications will then proceed to connect to the JMS cluster. Once connected to JMS, the client app can proceed to retrieve a global configuration file from a config file repository. The retrieved config file will contain such things as what queues and topics to connect to.

This approach makes it possible to deploy zero configuration client applications - which is not bad considering it is distributed software. Of course, if necessary, it is possible to fall back to using a local config file containing JMS connection URL info. On occasion my product group encounters customer sites where the UDP broadcast approach is problematic and we have to fall back to old-fashioned manual local configuration.

I've mentioned this home brew feature to various relevant folk such that I think we'll see this manner of JMS auto-discovery showing up in JMS implementations as an out of the box feature. It doesn't break with compatibility to the JMS spec as it is just a way to determine what JMS service to connect to. Once the connection URL is determined, the JMS APIs are programmed to as usual. If the JMS product you're interested in doesn't support anything like this, then ask for it.

Conclusion

I've been developing software as a livelihood since 1986. Like a lot of folks, I've built my fair share of network distributed software over the years. JMS messaging is the best technology I've yet used for doing this. Now I didn't really dip down into the programming of JMS - there are books on how to do that. Instead I wanted to present a higher level perspective of using this kind of software technology - giving consideration to things that are important in enterprise computing: high availability, scaling, platform support, configuration, deployment, monitoring, etc. etc. I hope this experience write-up will be helpful to those considering JMS.

Using JMS For Distributed Software Development

Thursday, December 13, 2007

Enterprise Integration Patterns on Messaging

Asynchronous messaging is fundamentally a pragmatic reaction to the problems of distributed systems. Sending a message does not require both systems to be up and ready at the same time. Furthermore, thinking about the communication in an asynchronous manner forces developers to recognize that working with a remote application is slower, which encourages design of components with high cohesion (lots of work locally) and low adhesion (selective work remotely).

...

How can I integrate multiple applications so that they work together and can exchange information?

 

Use Messaging to transfer data frequently, immediately, reliably, and asynchronously

An enterprise has multiple applications that are being built independently, with different languages and platforms. The enterprise needs to share data and processes in a responsive way. This is the problem that messaging addresses.

EMS standards and durable subscribers

Java Message Service 1.1 (JMS) is a Java framework specification for messaging between applications. Sun Microsystems developed this specification, in conjunction with TIBCO and others, to supply a uniform messaging interface among enterprise applications.

The JMS framework (an interface specification, not an implementation) is designed to supply a basis for MOM development.

TIBCO Enterprise Message Service (Tibco EMS)implements JMS and integrates support for connecting other message services, such as TIBCO Rendezvous and TIBCO SmartSockets.

TIBCO Enterprise Message Service 4.4 is JMS compliant and has passed Sun Microsystem Technology Compatibility Kit (TCK) for Java Message Service 1.1 (JMS 1.1). Therefore, EMS 4.4 is compliant with the JMS 1.1 specification.

 

EMS Destination Features


TIBCO Enterprise Message Service allows you to configure destinations to enhance the functionality of each messaging model.

The EMS destination features include:

  • You can set a secure mode for access control at the queue or topic level, so that some destinations may require permission and others may not.
  • flowControl : You can set threshold limits for the amount of memory used by the EMS server to store messages for a topic or a queue and fine-tune the server’s response to when the threshold is exceeded.
  • You can route messages sent to destinations to other servers.
  • You can also create bridges between destinations of the same or different types to create a hybrid messaging model for your application. This can be useful if your application requires that you send the same message to both a topic and a queue. For more information on creating bridges between destinations and situations where this may be useful,
  • You can control the flow of messages to a destination. This is useful when message producers send messages much faster than message consumers can receive them.
  • You can exchange messages with other message services. Queues can receive TIBCO Rendezvous and TIBCO SmartSockets messages. Topics can either receive or send Rendezvous and TIBCO SmartSockets messages.
  • You can set queues to be exclusive or non-exclusive. Only one receiver can receive messages from an exclusive queue. More than one receiver can receive messages from non-exclusive queues.
  • You can specify a redelivery policy for queues. When messages must be redelivered, you can specify a property on the queue that determines the maximum number of times a message should be redelivered.
  • You can trace and log all messages passing through a destination.
  • You can include the user name of the message producer in the message.
  • Administrator operations can use wildcards in destination names. The wildcard destination name is the parent, and any names that match the wildcard destination name inherit the properties of the parent.
  • You can set the failsafe mode on a topic or queue to direct the server to write persistent messages to disk synchronously to guarantee messages are not lost under any circumstances.
  • You can specify that a consumer is to receive batches of messages in the background to improve performance. Alternatively, you can specify that queue receivers are to only receive one message at a time.

The EMS APIs allow you to create durable subscribers to ensure that messages are received, even if the message consumer is not currently running. Messages for durable subscriptions are stored on the server as long as durable subscribers exist for the topic, or until the message expiration time for the message has been reached, or until the storage limit has been reached for the topic. Durable subscribers can receive messages from a durable subscription even if the subscriber was not available when the message was originally delivered.

When an application restarts and recreates a durable subscriber with the same ID, all messages stored on the server for that topic are published to the durable subscriber

Java Message Service - Provider implementations

A few JMS implementations, some are free, some are not. I like ActiveMQ and OpenJMS for the open source implementations. For proprietary  implementations Tibco's EMS rocks.

Provider implementations

In order to use JMS, one must have a JMS provider that can manage the sessions and queues. There are free, open source and proprietary providers.

Articles about open source providers:

Articles about proprietary providers:

An exhaustive comparison matrix of JMS providers is available at: http://www.theserverside.com/reviews/matrix.tss

All Java EE application servers from version 1.4 and later are required to contain a JMS provider. This can be implemented using the message inflow management of the Java EE Connector Architecture, which was first made available in version 1.4.

Reliable Web services with Apache Axis and MOM

A great  article on  SOAP and JMS  by Gautam Shah covers how to use SOAP over JMS for reliable Web Services...

Over the past few years, SOAP has become the de facto standard and backbone for enabling inter-application communication. For the most part, SOAP has been successful in realizing the promise of cross-platform, cross-language integration of devices and software applications that need to communicate.

The strength of SOAP is in its simplicity, flexibility, and its universal acceptability. It lays out simple rules and an XML language of communication between devices and software that need to interact. These rules have been established by the World Wide Web Consortium and backed by industry heavyweights such as IBM, Microsoft, BEA, HP, and Sun Microsystems.

Most existing Java or Enterprise JavaBeans (EJB) applications that cater to specific business functions do not support such SOAP-specific XML consumption and generation. When undertaking standards-based integration efforts, these applications need to talk the language of SOAP and XML. Hence, for business applications that provide critical business functions, a need exists for a bridge layer that can consume and generate SOAP-specific XML. Apache Axis is the open source platform that provides the bridge layer between your applications and SOAP-based Web service interactions.

The Apache Axis Java toolkit provides a thin layer of in-direction between the client wishing to speak SOAP and the server wishing to understand SOAP. The beauty of Axis is that the same toolkit can be used at both the client and server. When used by the client, the Axis toolkit serves as an intermediary between native Java and the underlying encoding of information sent to the server in SOAP XML format. When used to enable a server as a Web service, the toolkit's role reverses and serves as an intermediary between underlying SOAP XML encoding and native Java.

Most common SOAP-based Web services implementations are over the HTTP protocol. However, in implementations that require SOAP to be enabled over a protocol more reliable than HTTP, message-oriented middleware (MOM) is an obvious choice. In addition, the features of commercially available MOM, such as guaranteed message delivery, transactional support, encryption, high performance, and high availability, make the case for combining SOAP and MOM more compelling and appealing.

Axis implementation for HTTP-based SOAP is straightforward. However, enabling Axis over MOM has not always been easy. In this article, I examine key components that come bundled in Axis and introduce additional components that are needed to let Axis work with MOM.

Please refer to resources Resources for the basics on SOAP and Axis.

Benefits of MOM

MOM-based Web services are not suitable for all types of applications. Ideally, they are suited for interaction between applications within an organization or between organizations that require SOA (service-oriented architecture) implementations with service-based consumer and provider paradigms. For such implementations, a MOM-based architecture offers the following benefits:

  • For applications that do not require immediate response from the service consumer and have long-running service provider operations, the service consumer and provider can run on different threads via one way calls. Such calls allow consumers to place a service call and not wait for a response back from the service provider. The second benefit is that the service provider does not need to be available at the time the call is placed by the service consumer because MOM provides a store-and-forward mechanism that stores the call message until it is picked up by the service consumer.
  • Service providers can scale horizontally by adding more servers for listening to the same MOM queues. The service consumer will remain completely agnostic of such changes at the server.
  • Applications requiring guaranteed delivery can rely on the persistent capabilities of MOM, which ensure message delivery in the event of hardware and software crashes.
Axis and asynchronous Web services architecture

In this article, we use Axis as the plumbing for SOAP Web services at both the client and the server. Thus, Axis is responsible for processing information that flows between the client and the server. Let's take an example of a stock-quote Web service to understand how Axis can be enabled over MOM. Our stock-quote Web service provides a stock price for a stock symbol. It has a single function, getStockPrice(String stockSymbol), that accepts a stock symbol string as a parameter and returns back a price string. Communication of the stock-quote Web service between the client and server is completed by Axis via MOM. Various types of MOMs, such as IBM's MQSeries or Sonic Software's SonicMQ, can be used. The only MOM requirement is that queues created in these MOMs should be accessible in an enterprise Java application server via Java Message Service (JMS). For purposes of our discussion, we assume one such MOM, and I do not go into the specifics of enabling the queue access in MOM. Your enterprise Java application server and MOM documentation serves as the best source for such information.

Let's first understand the importance of each of the components involved in enabling Axis and the MOM-based Web services application before delving into how these components interact to achieve the needed functionality.

 

Axis over message-oriented middleware. Click on thumbnail to view full-sized image.

As shown in the figure above, StockQuoteServiceProxy, JMSSender, JMSReceive, and the client and server Axis engine are the key components. Let's understand these components and how they interact.

Step 1: Client invokes getQuote on StockQuoteServiceProxy

Let's look at Client below:

 ...
public class Client
{
public static void main() throws Exception
{
String stockSymbol = "IBM";


// Initialize proxy
StockQuoteServiceProxy serviceProxy = new StockQuoteServiceProxy();


// Invoke function
String stockQuote = serviceProxy.getQuote(stockSymbol);
System.out.println("Price of " + stockSymbol + " is " + stockSymbol);
}
}
...


As illustrated in the code above, a Java client invokes getQuote(String stockSymbol) on the StockQuoteServiceProxy class. The client is completely unaware of the underlying SOAP and MOM plumbing used to enable the service.



Step 2: StockQuoteServiceProxy constructs and invokes the Call object


The StockQuoteService at the server is a Web service and thus has a WSDL (Web Services Description Language) file that defines the calls that can be made on the service. Axis provides the WSDL2Java tool that generates client-side proxies. Please see Apache Axis WSDL2Java to learn more about that tool. WSDL2Java is used to generate the initial StockQuoteServiceProxy Java class. Obviously, the generated Java will not contain code that supplies the transport class JMSTranport to the Axis engine. Thus, we add the following line to modify the generated Java file: call.setTransport(new JMSTransport());. The StockQuoteServiceProxy primarily creates and sets appropriate values on the org.apache.axis.client.Call object. The org.apache.axis.client.Call object is a JAXRPC (Java API for XML-based Remote Procedure Call) dynamic invocation interface implementation of the Call interface:



 ...
import org.apache.axis.client.*;
import org.apache.axis.configuration.FileProvider;
...
public class StockQuoteServiceProxy
{
...
public String getQuote(String stockSymbol) throws Exception
{
try
{
// Initialize client Axis service
Service axisService = new Service(new FileProvider("client-config.wsdd"));


// Create and construct Call object
call = (Call) axisService.createCall();
call.setUseSOAPAction(true);
call.setSOAPActionURI("");
call.setOperationStyle("rpc");
call.setTargetEndpointAddress(new java.net.URL("target end point"));


// Transport is set to JMSTransport, which returns name of chain that handles
// the transport using MOM
call.setTransport(new JMSTransport());





// getQuote() accepts one parameter of type string
call.addParameter(new javax.xml.namespace.QName("", "stockSymbol"),
new javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema", "string"),
java.lang.String.class,
javax.xml.rpc.ParameterMode.IN);


// getQuote() returns a string
call.setReturnType(org.apache.axis.encoding.XMLType.AXIS_STRING);


// Construct the parameter array
Object[] params = new java.lang.Object[] { stockSymbol};


// Finally, invoke the function
String stockQuote = (String) call.invoke(params);


// invokeOneWay can be used for fire and forget calls
//call.invokeOneWay(params)


return stockQuote;
}
catch (Exception exception)
{
...
}
}
}


When getQuote(String stockSymbol) is invoked on StockQuoteServiceProxy, it, as shown in the code above, initializes the Axis engine with the client-config.wsdd configuration file. It is highly recommended that the path of client.wsdd is externalized. QuoteServiceProxy then constructs the Call object. Since the getQuote() function accepts one parameter and returns a string, appropriate values are set on Call using addParameter() and setReturnType(), respectively. One of the key calls made by StockQuoteServiceProxy is setTransportType(). This call sets access to the class used for enabling Axis SOAP messages over MOM. Most of the code in StockQuoteServiceProxy is auto-generated by WSDL2Java; however, it does not set the transport type, so you will need to add setTransportType(). Also, if your application needs only one-way, fire- and forget-type calls by the client, invoke() will need to be changed to invokeOneWay().



The value returned by invoke() is passed by StockQuoteServiceProxy to the client.



Step 3: The Axis client engine locates JMSSender


The Axis engine locates JMSSender via the client-config.wsdd configuration file. JMSSender implements the standard Handler interface, and thus the Axis engine calls the invoke() function. This code is internal to Axis and not discussed here. Please see Resources for more on Axis internals.



The Axis client, org.apache.axis.client.Service, is Axis's JAXRPC dynamic invocation interface implementation of the Service interface. The org.apache.axis.client.Service comes bundled with the Axis toolkit. It provides the API for the proxy to access the Axis client functionality required to invoke Web services.



The client-config.wsdd used to initialize the Axis client and JMSTranport is a simple extension of the org.apache.axis.client.Transport Axis class. JMSTransport's constructor sets the transport chain's string name. Axis uses the JMSTransport class to get the transport chain's name. It then looks up values loaded from client-config.wsdd to locate the Handler Java class that is the transport plug-in. For our example, this transport plug-in is JMSSender, which does the grunt work of communicating with MOM.



The client.wsdd file is shown below:



 <?xml version="1.0" encoding="UTF-8"?> <deployment xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">


<handler name="JMSSender"
type="java:JMSSender">
</handler>
<transport name="JMSTransport" pivot="JMSSender"/>
</deployment>


The JMSSender is a transport plug-in for Axis. It implements the org.apache.axis.Handler Axis interface by extending the org.apache.axis.BasicHandler class that comes bundled with Axis. JMSSender contains the code for connecting to MOM queues, setting the names of MOM queues on which the server should return the response, creating the MOM message that contains the SOAP envelope, and dropping the MOM message that contains the SOAP envelope. There after, JMSSender listens to the MOM queue for the server to respond. On receiving the response MOM message back from the server, it creates the corresponding Axis org.apache.axis.Message and passes it back to the Axis client.



The JMSSender relies on the JMS API, making it independent of MOM infrastructure. Each MOM vender, such as MQSeries or SonicMQ, has its own proprietary mechanism for enabling MOM queue access via JMS. To maintain continuity of our discussion, please refer to your MOM and application server documentation to enable MOM to be accessible via JMS.



Step 4: JMSSender locates the MOM queues and places the JMS message on MOM queue


Let's look at JMSSender:



 ...
import javax.jms.*;
import javax.naming.*;
import org.apache.axis.*;
import org.apache.axis.handlers.*;
import org.apache.axis.utils.*;
import org.w3c.dom.Element;


public class JMSSender extends BasicHandler
{
...
public void invoke(MessageContext messageContext) throws AxisFault
{
try
{
// Step 4
//Retrieving initial context may vary slightly depending on your J2EE application server.
InitialContext context = new IntialContext();


// Locate JMS objects required for communication with MOM.
QueueConnectionFactory connectionFactory =
(QueueConnectionFactory) context.lookup("Queue Connection Factory JNDI Location");
QueueConnection connection = connectionFactory.createQueueConnection();
QueueSession session =
connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);


// Create JMS Queue object and point it to MOM's Request Queue.
Queue requestQueue = (Queue) context.lookup("Request MOM Queue JNDI Location");


//Create JMS Message object that can contain text content.
TextMessage jmsMessage = session.createTextMessage();

//Create JMS Sender object that will be used to send messages on MOM Request Queue.
QueueSender sender = session.createSender(requestQueue);


//Retrieve SOAP envelope from Axis Message.
Message axisMessage = messageContext.getRequestMessage();
SOAPEnvelope soapEnvelope = axisMessage.getSOAPEnvelope();
Element envElement = soapEnvelope.getAsDOM();
String strSOAPBody = XMLUtils.ElementToString(envElement);


//Set the SOAP envelope retrieved in previous step in JMS Message.
TextMessage jmsMessage = session.createTextMessage();
jmsMessage.setText(strSOAPBody);


//Create JMS Queue object and point it to MOM Response Queue.
Queue responseQueue = (Queue) context.lookup("Respnse Queue JNDI Location");


// Create JMS Receiver that listens to MOM Response Queue.
receiver = session.createReceiver(responseQueue);



//Set the JMS Queue object pointing to MOM Response Queue as replyTo on JMS Message.
jmsMessage.setJMSReplyTo(receiveQueue);


//Finally, send MOM Message using JMS Sender.
sender.send(jmsMessage);


// Deliver the message and start the listening by JMS receiver on MOM response queue.
connection.start();


// Step 11
// When response message is sent by server, it is received by receiver.
TextMessage replyMessage = (TextMessage) receiver.receive();

// Create Axis Message and set it in Axis Response Message object.
org.apache.axis.Message responseMessage = new org.apache.axis.Message(replyMessage.getText());
messageContext.setResponseMessage(responseMessage);


//Clean up the objects.
sender.close();
receiver.close();
session.close();
connection.close();
}
catch (Exception exception)
{
// Error handling here.
}
}
...
}


As shown in the code above, the key function that needs to be overridden is invoke(). The Axis engine calls this function as it processes various Handler(s); it needs to process the Handler assigned for handling transport of the SOAP envelope.



The JMSSender creates JMS QueueConnectionFactory, QueueConnection, and QueueSession objects. It then creates JMS Queues that point to the MOM request queue and MOM response queue. JMSSender then retrieves the SOAP XML envelope from the Axis MessageContext and places it in the JMS Message object. QueueSender then sends the message to the MOM queue.



At this point, JMSSender halts and waits for the response to come back from service endpoint StockQuoteService. Steps 5 through 10 detail how the message arrives at the service provider and how the response returns. When the response MOM message arrives on the reply queue, the receiver that has been listening to the queue retrieves the JMS message. It then extracts the SOAP XML text and sets it on the Axis engine's ResponseMessage object.



Step 5: MOM transports the MOM queue message containing SOAP envelope


The MOM infrastructure takes over from this point forward and transports the MOM message via its own protocols.



The MOM sender message queue, where the message has been dropped, connects to the receiver message queue. JMSReceiver listens to the receiver message queue.



The MOM queues should be set up so that the client and server can exchange MOM messages. MOMs generally use their own protocol wire transport. MOMs such as MQSeries and SonicMQ allow the transport of MOM messages over HTTP or HTTPS protocols. Setting up such a mechanism would prove convenient in scenarios where the service client and service provider are within their own firewalls. Please refer to your MOM documentation to set up these queues.



Step 6: The JMS message arrives at the server


The MOM infrastructure transfers the JMS message containing the SOAP envelope to the server. The MOM request queue is enabled to a message-driven bean via an enterprise Java application server.



Steps 7 and 9: The JMSReceiver invokes the Axis engine


Apache Axis comes bundled with SimpleJMSListener, which implements javax.jms.MessageListener. Therefore, SimpleJMSListener can be used to listen for messages arriving on a JMS-compliant MOM. SimpleJMSListener, however, is a weak implementation of the MessageListener interface. It is not built to scale and, hence, not recommended for production environments.



To have a scalable and robust solution, I created JMSReceiver, which is a message-driven bean (MDB) configured in an enterprise Java application server to listen to the JMS-enabled MOM request queue. JMSReceiver is the bridge between the MOM queues and the Axis engine at the server. Upon receiving the MOM message, JMSReceiver invokes the Axis server engine.



Let's look at a JMSReceiver code snippet:



 ...
import java.rmi.*;
import javax.jms.*;


import org.apache.axis.*;
import org.apache.axis.client.*;
import org.apache.axis.configuration.*;
import org.apache.axis.server.*;



public class JMSReceiver implements MessageDrivenBean, MessageListener
{
...
public void onMessage(Message jmsMessage)
{
try
{
// Step 7


// Create an instance of AxisServer with server configuration file.
FileProvider fileProvider = new FileProvider("server-config.wsdd");
Axis Engine axisEngine = new AxisServer(fileProvider);





// Create Axis message from incoming JMS Message.
org.apache.axis.Message soapMessage =


new org.apache.axis.Message(jmsMessage.getText());


// Create a MessageContext and associate with the engine.
MessageContext messageContext = new MessageContext(axisEngine);


// Set the request message in Axis MessageContext.
messageContext.setRequestMessage(soapMessage);


// Invoke AxisEngine. Axis Engine based on SOAP message
// and server-config.wsdd will invoke the StockQuoteService Java class.
// The return values from the Java class are placed in Axis MessageContext.
axisEngine.invoke(messageContext);


// Step 9


// Retrieve the response message from Axis Message Context.
org.apache.axis.Message responseMessage = messageContext.getResponseMessage();


// Get a String representation of response, this string will be placed
// in JMS Message that is sent back to the client.
SOAPEnvelope envelope = responseMessage.getSOAPEnvelope();
Element element = envelope.getAsDOM();


String soapResponse = XMLUtils.ElementToString(element);


// Before we can send JMS message back to the client,
// we need to locate the MOM queue that the
// client specified that response message be sent to.
InitialContext context = new IntialContext();


// Locate JMS objects required for communication with MOM.
Queue responseQueue = (Queue) jmsMessage.getJMSReplyTo();


QueueConnectionFactory connectionFactory =
(QueueConnectionFactory) context.lookup("Queue Connection Factory JNDI Location");
QueueConnection connection = connectionFactory.createQueueConnection();
QueueSession session = connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);


QueueSender sender = session.createSender(responseQueue);
TextMessage jmsResponseMessage = session.createTextMessage();


// Now that we have all required JMS objects, we place the response SOAP string
// in the JMS response message.
jmsResponseMessage.setText(soapResponse);


// Finally, send the response back to the on MOM queue that the
// client is expect to receive on.
sender.send(jmsResponseMessage);
}
catch (Exception e)
{
...
// Error handling here.
}
}
}


The key function for the MDB is onMessage(), which MOM invokes when a message arrives on the queue that JMSReceiver listens to. Please refer to your enterprise Java application server and MOM documentation to enable MDB listening on MOM queues.



The JMSReceiver initializes the AxisEngine via the server-config.wsdd configuration file. It then retrieves the SOAP envelope from the MOM JMS message and creates an Axis Message object and places this Message into the Axis MessageContext object.



Now when the Axis engine returns the value as described in Step 8 below, the JMSReceiver retrieves the SOAP response from Axis MessageContext. It then opens a connection to the MOM JMS response queue based on queue information supplied by the client. This information is retrieved by JMSReceiver by calling getJMSReplyTo() on the incoming JMS message. The SOAP response envelope from Axis is then placed in a JMS message and sent to the client via MOM.



Step 8: The Axis server engine invokes the call on StockQuoteService


The org.apache.axis.AxisServer is the core plumbing provided by Axis. It is the primary object that enables Java/enterprise Java classes for SOAP-based Web services. It is responsible for converting SOAP calls to Java-based calls understandable by service providers such as our StockQuoteService. The Axis engine is initialized with server-config.wsdd, which provides information such as the fully qualified name of the class implementing the service, its operations, and corresponding parameters enabled for the Web service. JMSTransport and corresponding entries in server-config.wsdd work along similar lines as on the client.



Please refer to server-config.wsdd to get details on using server-config.wsdd as a deployment descriptor for the Axis engine.



The server-config.wsdd file follows:



 <?xml version="1.0" encoding="UTF-8"?> 
<deployment xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
...
<handler name="JMSSender"
type="java:JMSSender">
</handler>
<transport name="JMSTransport" pivot="JMSSender"/>
<service name="StockQuoteService" provider="java:RPC">
<parameter name="className" value="StockQuoteService"/>
<operation xmlns:operNS="http://com.serviceprovider.stockquote " name="getQuote" qname="operNS:getQuote">
<parameter xmlns:tns="http://www.w3.org/2001/XMLSchema" name="" type="tns:string"/>
</operation>
<parameter name="allowedMethods" value="*"/>
</service>
...
</deployment>


The StockQuoteService class is the service end point. It has one function, getQuote(); for the simplicity of our example, it has hard-coded values of various quotes. As you can see from the code below, StockQuoteService is completely agnostic of the Axis plumbing used to enable the class as a SOAP-based Web service:



 ...
public class StockQuoteService
{
public String getQuote(String stockSymbol)
{
// Hard coded values for simplicity
if (stockSymbols.equals("IBM"))
{
return "45.34";
}
else if (stockSymbols.equals("MSFT"))
{
return "35.34";
}
else if (stockSymbols.equals("GOOG"))
{
return "120.78";
}
else
{
return "0";
}

}
}


Conclusion


In this article, we saw how Web services enabled a store-forward, guaranteed-delivery mechanism. For simplicity's sake, we used Axis at both ends—at the service consumer and at the service provider. This approach, however, is not required. For the brave of heart, one may have a .Net client service consumer and an Axis service provider, and the architecture will stand, for the most part. Every project in the real world has unique dynamics around the choice of technology, tools, and process. Implementing reliable Web services using Apache Axis and MOM may not be suitable for all projects, but can prove to be a good choice when the service provider and consumer want more reliable means of communicating and can agree on communicating via MOM in addition to Web services-based interaction.




http://www.javaworld.com/javaworld/jw-02-2006/jw-0220-axis.html