A MicroArchitecture production.
Problem: We need to connect two separate systems.
Context: These systems may exist already, may be physically separated, may be in different execution environments and different languages. We may not have access to code.
Solution: Build message adapters which convert function calls into commands and use a generic interface to make the encoded method calls across a MessageBus.
Thesis: DCE, RMI, CORBA-IDL and related technologies combine a transactional synchronous messaging system with a language translation function. It allows two separate systems to be statically composed of objects which semi-transparently call each other as if the other system were local. Clients compile in stubs which have message translation code and communication code. These communicate with compiled-in skeletons on the server system which call the function before returning an object in a similar fashion.
To use these systems in the normal way, one uses the translation/marshalling facilities supplied by the ORB. All method calls require separate interface specification and deployment to all parties, who must cooperate. The bindings are static, so multiple systems must be recompiled to be reconfigured.
The problem lies in a confusion of roles. If instead we explicitly separate the concerns, have a separate synchronous messaging service from translation logic, then a lot of the problems go away. We can refactor code to work like this. First we define a message for each method signature. This format could well be XML, or some compact representation. A translation adapter converts arbitrary method calls into this message. The message is applied to a generic CORBA (or whatever) returnMessage getReturnMessage(parameterMessage) call. The IDL for this can be compiled and deployed once. It won't change for different message types because it is content neutral (though different calling styles may require additional mechanisms e.g. asynchronous calling sequence).
From here on we can ignore the messaging aspect and concentrate on pairs of translation adapters at each end. Configuration and deployment is now local, and has predictable runtime behaviour if a message isn't understood (sounds like Smalltalk?).
This is the typical pattern used in large-scale distributed systems. XML-RPC/SOAP implicitly uses such a scheme, but it is easy enough to construct marshalling code for DIY'ers. Automatic generation of message codes and adapters is not too difficult. I imagine there are a few people around Wiki who could whip one up in a couple of days. Reliable communication buses are easy to find, hey, use CORBA. It's a great transactional message bus.
This is an architecture made out of a MessageBus and MessageAdapter s.
See also: CanonicalMessageDataFormat.
From FacadeAtTheDistributionBoundary.
[refactored out some argument pre-clarification]
Despite its faults, CORBA has a clearly defined and well documented architecture that addresses many of the problems/contexts being described here, in particular how to separate the protocols at the upper end of the OSI reference model: application, presentation, session and transport layers. It would be a shame not to mine such a rich seam of patterns for whatever gems it contains. Certainly some of the same architectural approaches can be applied to message-oriented middleware. --NatPryce
Exactly Nat. I don't think we are far apart in substance. CORBA is an excellent messaging and transaction service. Its just the IDL bit I don't like (oh, and IIOP sucks also). I'll keep shuffling things around until it looks more like that's what the page says :). Cheers --RichardHenderson.
I have to admit... the IDL idea was one the main bit of CORBA I did keep! I found that it was easier to maintain a declarative description of input and output messages (I used asynchronous messages, not synchronous RPC), and generate all the code to interpret those messages, rather than maintain the interpretation code by hand in different places. OTOH, I expect that tradeoff will be very different in different systems, such as the context of more loosely coupled messaging systems, which is another good source for patterns. Fascinating stuff.
Yes, very interesting. Again I'm not being clear (sigh). IDL itself is just a specification language, it is the static deployment mode that I don't like. I prefer dumb but reliable infrastructure, dynamic parsing from (possibly IDL) specification, and extended processing at the point of connection instantiation. Whatever, all RPC systems must use the CommandMessagePattern. The pattern is forced by the need to cross execution space boundaries (see PushPullAdapter).