Posted by cajo
on June 19, 2008 at 6:58 PM PDT
The spirited debate following my last post on messaging being degenerate RPC got me thinking; is there some way to combine these two somewhat orthogonal methodologies, to create a unique hybrid approach? A bit of insight led me back to update the original cajo Queue messaging class, and the results were indeed most satisfying.
What is the fundamental premise of messaging , and how is it different from RPC?
Essentially, messaging focuses on the concept of loosely coupled, event/information delivery; between one or more producers, and one or more consumers. RPC focuses on the concept of tightly coupled synchronous functional invocation; between a client and a server. What would happen if we applied cajo technology to coalesce these two concepts?
This is precisely what the newly updated cajo Queue class does. Queue instances are initially constructed by providing a topic object. This object is a mutually agreed upon class, between producers and consumers, which provides the context for why the community is using this particular Queue instance. For example: the topic object could be something as simple as a string â€“ "Wine Enthusiasts" or as elaborate as a HashMap of subtopics and values.
Consumer objects can be either local or remote to the JVM in which the Queue object is operating, and register using its enqueue method. Producer objects can also be either local or remote, and create events by invoking arbitrary methods on a Queue object reference. These invocations return immediately for producers; and are asynchronously invoked on all registered consumers. The invocation's successful return to the producer, guarantees that the event has been accepted. As the object's name implies; producer invocations are queued, as necessary.
// Producer actions:
queue.ping(); // invokes the method ping() on all consumers
queue.position("37.391008, -122.082073"); // new location
queue.fill(x, y, width, height, Color.red); // mask area
// note: queue does not implement any of these methods itself
// they are invoked on the consumers, only if they support them
The real gist of fusion takes place in the concept of method invocation on the Queue object. A producer may invoke a method taking no arguments; this is traditional notification messaging. A producer could invoke a method taking a single argument; this is traditional data messaging. Finally, a producer could invoke methods taking multiple arguments; this is traditional RPC, but loosely coupled, i.e. functional messaging -- exhibiting three key features:
* The function signatures are independent of any class or interface definition
* The potential one-to-many relationship, between the producer and its consumers
* The consumer is not required to implement the functions being invoked by the producer
The Queue class performs the consumer invocations asynchronously from the producer's; it discards any direct return values, and exceptions from the consumers. Therefore, if the producer wanted feedback from consumers, it could provide a callback reference as an argument, for example.
If there is only one producer, and one consumer, this is what is commonly referred to as point-to-point messaging. When there is one or more producers, and more than one consumer; this is what is commonly referred to as publish/subscribe messaging. With the Queue class approach, these are just variations in how the object is used.
Lastly, just for fun, the Queue class is serialisable, meaning Queue objects can be passed between JVMs at runtime, (i.e. cloned) whilst retaining all producer and consumer links. The possibilities created by this, are nothing short of mind-boggling. ;-)
Best of all, Queue is implemented in a single class , consisting of less than 100 lines of code. I recommend giving it a try; it is extremely simple to use, highly intuitive, and very powerful. It is a handy new tool, to add to your kit.