While looking at the frontend of the Eve server
I still need to check that one out...the buzz is increasing :D
I began to realize a trend
emerging after I introduced a central publish and subscribe facility. The
pattern decouples components by enabling communication using events and the
notifier pattern. This also lead to the disappearence of methods on service
interfaces.
I've thought about this a great deal, and so have many others. But I have yet to find a thought actually worth writing down (not even talking about it making sense, too). Since this is such a fun topic, I'll try anyway :D. This will have a high RT level. It'll get better at the bottom.
At a very high abstraction level, you might say that the interface/service world is call-based ("composer calls method on component" is what the avalon terms used to be). OTOH, publish/subscribe and event systems are message-based ("sender sends message to receiver"). Let's take a look at these seperately and see if the emerging technologies can work together.
Realizations in service-based design
------------------------------------
A service will use other services to accomplish its task. This is a dependency. The simplest case is where a service is responsible for every aspect of the "other service" that it depends on.
The next step is to delegate some responsibility to another entity. This can be a registry, a container, or some hybrid form. We tend to prefer the container paradigm as opposed to the registry paradigm because the container view of the world centralizes some responsibilities, which makes it easier for a human to figure out exactly what is going on (We call that IoC). It is more logical, and more secure.
We can go further, and delegate different kinds of responsibility in different directions. We can identify distinct (human and/or machine) roles in our systems and decompose the system further to allow for that (ie, we'll use terms like assembler, composer, publisher, subscribe, poller, manager, kernel, hub, configurator, administrator) as our system grows more complex. At some point it becomes natural to think in terms of responsibilities (we call that seperation of concerns).
In summary, we apply SoC and IoC on a call-based system.
In avalon, the decomposition choices have slowly evolved (exactly what concerns we seperate into distinct "blocks" or "components" or "facilities" or ...) from nearly non-specified (we stop at the concept of ComponentManager) to nearly set-in-stone (we use a very rigid and uniformly structured model as the basis of the merlin system). As long as I've been at avalon, the trend has been towards more rigidity, predicatibility, stability, etc. There have been a few attempts to change that direction, but none of them ever gained the neccessary momentum.
Up to a few months ago, most people looking towards IoC were looking for rigidity.
Realizations in message-based systems
-------------------------------------
An entity will send message to other entities to accomplish "something". One of the simplest cases is probably where a browser sends a GET to a server. This is request/response messaging.
The next step is to decouple entities by introducing an addressing scheme (ie some form of URIs), possibly namespaces, and, again, the term registry will pop up again. I tend to prefer the kernel paradigm (ie, mach). Another popular trend is the use of a discovery mechanism in place of something centralized like a kernel or a registry. And of course the whole "spaces" area is subject to active academic research.
IMV, the communication/protocol/message format/style choices in message-based systems are as vital as the decomposition in the service-based systems, and just as hard.
In summary, message-based systems are difficult.
In avalon, we've tried marriage of the service paradigm with the message paradigm a few times, at one point by introducing Commands and Commandables into avalon-framework, at another point by defining responsibilities of a message-based system (sender, receiver, queue, ...) in excalibur-event. However, our resource identifiers (roles) have always been particular, and never uniform. We did talk for a few weeks about changing that, but never got round to it.
The most popular form of merging message-based systems with service-based systems is probably found in some applications of the servlet api, where HTTP messages are mapped to and from services. The cleanest version of that is probably found in SOAP, and something like Axis does a good job of mapping some core abstractions.
Message<->Service adapters
--------------------------
You can use tomcat+axis+a good bit of configuration and assembly to map HTTP messages to services. You'll need to use a few registries and discovery mechanisms before you can though (TCP/IP, DNS, WSDL, and more).
You can intersect a message layer between tomcat and your service engine to translate between human-readable (HTML) and machine readable (the method call, or often "action", which is a high-abstraction method call). You'll need to use several registries as well here.
Many similar solutions are in active use in many problem domains.
Observation: combine everything together, and these adapters, registries, containers, etc, are rather *big*.
If Joe User has a message/action/use case/whatever like
update the first paragraph of the article "News From The Foo Bar Corporation" to read "..."
there are rather a lot of adapters and intermediary steps, prerequisites and postrequisites).
I *think* we are looking for a way to use less of these adapters, and simpler, more predicatible ones. In Eve, you're not wanting to build something the size and scale of the web, but you do need to translate some kind of message to a method call and back again.
The magic word
--------------
"Universal" in "Universal Resource Identifier (URI)" is rather powerful. "Uniform" in "Uniform Resource Name (URN)" is of similar power. We're looking for things that have these qualifications. "universal", "uniform", "general".
Some of the work is already done, and is ready to be applied. We have URI, URN, JNDI, HTTP, XML, SOAP, etc, on the message/registry side. We have no such thing yet on the service side, but for the moment lets just live with the type1/2/3/4/5 versions of "IoC" and assume you're doing a merlin-based system.
Now, we want, maybe, a "uniform" and "general" message<->service adapter.
This is, I think, just about what jicarilla-framework is about (though I've only just realized that!). Let me try and explain.
The uniform message<->service adapter
-------------------------------------
At some point, you have some kind of message that you want some kind of service to handle. Lets introduce an intermediary form. An Invocation. Define services that can receive and handle invocations. Define transformers that can convert between message formats and invocations. Define how to create URNs for these transformers. Define mappings from URIs to URNs. That's it.
I'm currently working on as generic and universal a message<->service adapter as possible, which is at the same time also quite small. I'm focussing on the web domain atm. It should (will) look like this...
A client fires of a HTTP message. The web server handles the low-level protocol. It sends the object representation of the message to a broker/mapper. The broker handles the URI/URN translation, and sends the message to a transformer found by URN. The transformer is half of the bridge between the message-based system and the service-based system. It creates an invocation and feeds it to the service. The other half of the message<->service adapter lives in the service itself or in some intermediary and transforms the conceptual Invocation into an actual invocation.
Intermezzo
----------
phew! That's a whole lot of typing, and I haven't really even talked about notifications and dependencies. Lets try and get back down to earth a little more.
Notification and callbacks
--------------------------
Not described above are callbacks/responses. Invocations create responses, which need to be translated back to messages, and sent somewhere. We might travel the whole "message bus" in reverse, or we might go forward through a different bus. It's not that difficult to figure out the former can be mapped to the latter, so in the quest for "uniform" we'll pick the latter. Continuing my example
The intermediary between the transformer and the service applies the invocation to the service. The service returns a result from the method call. The intermediary feeds this back to the transformer, which translates the response to an object representation of an HTTP message. This message is fed back to the web server, which handles the low level protocol. The response arrives back at the client.
This is a request/response architecture, and its not general enough. It seems we need an "event bus" or listener approach, where there can be multiple publishers of the same message, and multiple recipients. we can ath this point drift into the realm of JINI, JavaSpaces, and the like. Since I don't fully understand most of that I won't go there.
However, I think stuff like multicasters and aggregators can be used to adapt a simple pipeline to a more complex one. So lets keep the basics of the pipeline simple until we are sure we need complexity.
The point to take away ---------------------- I think this is the big thing. The response to this:
So the dependency graph turns into a star with all components depending on the event router, hub, bus or whatever you call it in the center. Event types and interfaces essentially become the dependency as opposed to the service interfaces. This way you can introduce new subscribers and publishers. Also the dynamic rerouting of events is possible at runtime. What this means is that the dependencies between components can change on the fly! Wow not a bad thang.
well, its less rigid. Have you gone through the introduction of lots of rigidity by introducing a strict model for lots of things (declaring loads of metadata and creating facilities to read/write/store it), only to build a layer on top of it that takes all the rigidity away again?
What does this mean for service interfaces? Well they start looking bleak
because the Subscriber interface replaces them. Basically methods are called
internally by the Subscriber handling code on the component itself rather
than exposing them on the service interface for direct calls by what are now
publishers. This is crazy my service interfaces are all empty now!
I think you want to introduce a layer between your event-based system that maps events to-and-from method calls. Your services don't change (good thing), but you still get all the benefit of the event-based approach.
Otherwise, what's the benefit of using avalon at all?
-- cheers,
- Leo Simons
----------------------------------------------------------------------- Weblog -- http://leosimons.com/ IoC Component Glue -- http://jicarilla.org/ Articles & Opinions -- http://articles.leosimons.com/ ----------------------------------------------------------------------- "We started off trying to set up a small anarchist community, but people wouldn't obey the rules." -- Alan Bennett
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
