= preface =
[RT] are Ramdom Thoughts. They are tradition in the Avalon community. RTs are basically long and thought-provocing mails with new project propositions, that are discussed and scrutinized at length. One distinguishing characteristic about RTs is the complete and utter lack of consistency with respect to quality: some are pure crap, others are pure genius. Even the original author of a RT is not sure which category any given posting falls into at the time it is issued. This posting is no exception. [*]
I've been sitting on this one a while (I typed the below a week or two ago I think). Let's open up a big can of worms :D
= Introduction =
here's a rather 'big' question: when can we say that a container is compatible with avalon-framework?
I want the answer, because I have a project for which I want to claim it is compatible. Actually, I've wanted an answer for a long time, but there is now sufficient itch to spend time on it.
I have spent a few weeks researching all of this. This e-mail contains many assorted thoughts on the subject. I'm sorry for its length. It is probably best to discuss all the particular issues piece by piece, but I felt I couldn't make most of my categorizations and choices clear without resorting to the extensive use of examples. Please do snip all specific issues on replies and talk about the general cases. When we nail those down we can get to specifics.
= Defining the question =
For definition purposes, a container is that piece of software which fulfills the container side of the avalon-framework container<->component contract. "Something" which the user can configure in "some" way to host any component that complies with the component side of the avalon-framework container<->component contract.
A container is compatible with avalon-framework when it fully fulfills the avalon-framework container<->component contract.
That much is clear to everyone (I think). But that's still pretty vague. There's two subissues:
* how do we verify compatibility? * what is the avalon-framework container<->component contract, *exactly*?
= Issue 1: how do we verify compatibility? =
Well, as far as java-level compatibility is concerned, I have an answer, at least a "batteplan" [1]. You create some test components that log whatever happens to them, specify that a container must load up these components, then verify that the component log is in accordance with the specification. So you test the container<->component contract by making the component side of that contract verify that things happen as they should.
= Issue 2: what is the container<->component contract? =
This is the really big one. Let's split it.
== The obvious parts ==
Many things are obvious. Let's call these the "fully specified contracts". A few examples are:
* if a component implements the LogEnabled interface, the container must provide a logger to it in accordance with the LogEnabled contract;
* if a component implements the Loggable interface, the container must provide a logger to it in accordance with the Loggable contract;
* if a component implements the Servicable interface, the container must provide a service manager to it in accordance with the ServiceManager contract.
=== What do we do? ===
There's not much to do. This stuff is already specified in documentation+reference.
=== IMHO ===
Within the TCK setup I'm working on, these are easily tested.
== The somewhat less obvious parts ==
Then there are things that would probably be easily "fully specified", but aren't at the moment. Let's call these the "underspecified contracts". A few examples:
* if a component implements the LogEnabled interface and the Loggable interface, the container must not load the component, but rather, generate and report some sort of exception.
* if a component does not implement the Component interface, the container must use some kind of technique to make sure the component is still available through the ComponentManager provided to Composable components (typically using some kind of proxying).
These are currently underspecified simply because we've never really dealt very much with "formal compliance". We simply had container implementations which did most of these the same way (though I can't tell from memory what exactly all the containers do with the LogEnabled/Loggable ambiguity at the moment, for example), to the extend that 99% of users would never encounter them, or just accept their behaviour when they found them and work around the issue.
=== what do we do? ===
within the TCK setup I'm working on, these are usually easily tested as well, but it is not always clear to me what to test for. Do we want to unambiguously specify these kinds of things? If we do, here's some likely consequences:
* we will spend many hours in debate over some of these issues as they pop up; * when any particular choice is made, it is likely to impact many existing applications as they will suddenly not be compliant; * dated releases of containers developed internally to avalon will likely not be compliant with out own specifications anymore.
An alternative is to keep them vague. May sound like a bad idea, but we've managed to do so for quite some time now.
=== IMHO ===
We should work on specifying these one by one.
== The contentious parts ==
Then there are some things that are more or less "fully specified", but not supported in many container implementations. Making these part of the compatibility stamp would actually render various containers incompatible. The avalon development team has historically been in disagreement over these. For want of a better term, let's call these "malspecified contracts".
Specifically, ECM and Fortress support some parts of the avalon-framework contract, that merlin and phoenix do not support. Top-of-head, these are:
* Selector semantics within provided ComponentManager and ServiceManagers * ThreadSafe and SingleThreaded marker interfaces
These are also easily tested, but the question "are these a requirement?" is much more difficult to answer. For example, it is not particularly likely that merlin will provide support for these contracts anytime soon, yet merlin will probably soon grow into the de facto reference implementation for avalon. That would mean the reference implementation is incompatible with the reference.
Yet there's a whole range of applications out there that absolutely depend on selector semantics. The most visible one is cocoon. You can't run cocoon on merlin because cocoon really needs Selector wiring.
=== what do we do? ===
It's a rather nasty issue. Furthermore, reaching consensus on it will probably be rather painful. Judging from the past, it might even be impossible. We can preserve the status quo, we can make all containers support all of these, or we can reject some of it (with that, rejecting some of our users).
=== IMHO ===
Selector semantics are and should remain part of the avalon-framework contract, because it has been in the distro's and documentation for a long time and there are a large number of componentns that use them. OTOH, ThreadSafe and SingleThreaded should be "soft-deprecated" (ie we put notices in the docs but no '@deprecated' tags), and compatibility should mean that containers do not check for or depend on their usage.
== Extensions of the container<->component contract ==
And then there's a whole range of things that are a rather essential part of working with any one of the current containers, but are not really part of the avalon-framework contract at all. Let's call these the "unspecified contracts". They're often specified, but not as part of the avalon-framework contract. Some examples:
* ECM, Fortress and Merlin support different lifestyles for components, like "singleton", "singlethreaded", and "transient". ECM, Fortress and older versions of Merlin also support "pooled". Phoenix supports only "singleton". There are some "hints" about lifestyle in the avalon-framework interfaces (the aforementioned ThreadSafe and SingleThreaded interfaces), but in general lifestyle is not part of the avalon-framework contract.
* AIUI, merlin will not allow you to run a component for which you have not fully specified (or at least specified you want the merlin defaults) what you want to do...a component author or assembler must declare what parts of the container<->component contract any particular component will use, and if it violates those declarations merlin will complain. This is quite different from (for example) ECM, which does not provide a mechanism for declaring this kind of information. Fortress and Phoenix are somewhat inbetween the two, but all of them use a different mechanism.
* phoenix supports "[]" and "{}" postfixes on the role provided to the
ServiceManager/ComponentManager lookup method, which, when used, will
return an array or list containing all of the=== what do we do? ===
On the one hand is the option of making all of these things part of the avalon-framework contract. On the other hand is the option of making none of these things part of the avalon-framework contract. Then there's options in between, like making them standard extensions.
The pros and cons of each of these choices vary for each of these issues vary per issue. For example, making merlin-style contract declaration into an extension doesn't make a component less portable: if you include the definitions, the component can run in all containers. But with the "[]" semantics, if you have a component that uses it, that component is from there on just about nonportable (unless you go out of your way) (which is an argument for either making it official or rejecting it outright).
Figuring these choices out is also going to be difficult. For example, active users and proponents of a particular feature/choice will likely want it to be standard, whereas container developers who don't want to support the feature will not want it to be standard.
With java, these things are easy: sun/the jcp lays down absolute rules. For us, we probably won't reach consensus without spending *much* energy, and that's something we (I) don't like.
=== IMHO ===
* we should reject "[]" and "{}" semantics and any other semantics or
conventions like that (URIs in Context, etc);* make support for lifestyle semantics part of the core contracts insofar as that we standardize them and require that a container specify (in its end user documentation) which ones it supports. Additionally, they should be part of the TCK and the TCK should inform anyone that runs it of the semantics a container supports;
* all of the other things I mention here (well, that I snipped for brevity but that fit the category) should be seen as "standard extensions", just like, for example JDBC is/was for the jdk. When something like them is in use, and there is a "solid" specification, they should follow whatever the stable release of merlin does. This places a heavy responsibility on merlin. With the example of packaging standards, it means that fortress and ecm are compatible (it doesn't work with any archive format or does any kind of classloader control), merlin is compatible (by definition) and phoenix is incompatible (merlin's block format is different from the phoenix bar and sar formats).
== The user<->container contract ==
And then there's things like SAR archives, BAR archives, other packaging formats (like standard places for storing metadata) dynamic blocks, classloader management. It might be best for some users if some of that were part of the core contracts. I don't think so, and I don't think its a realistically attainable goal for the near future, but I thought I'd mention it.
=== what do we do? ===
Agree that classloader management, archiving, service discovery, security, all of these things are not part of the avalon-framework contract but are additional contracts in a different problem domain. While they're neccessary, and probably deserve specifications and TCKs of their own, they have nothing to do with "avalon-framework compatible".
=== IMHO ===
* we should strive to define these things as standard extensions as well, but be very clear that they are totally seperate from avalon-framework and the container-component contract.
= So, what do we do? =
Here's the question again: when can we say that a container is compatible with avalon-framework?
I provided some examples of different aspects of that question, some examples, and some opinions. It should be clear from the above that this is a complex topic. Here's the current answer to this question: we don't have an answer.
Without jumping into several-week-long discussion about each and every issue as it comes by according to our interests, let us think for a little about ways to formulate an answer together.
* We could say that compatibility is defined by the the least common denominator of the current ecm/fortress/phoenix/merlin featureset. That LCD is definable, testable, and hence not subject to much debate (if there's debate, you can write a test to show compatibility or incompatibility). It rules out any lifestyle but singleton, marker interfaces, any combination of Loggable/LogEnabled or Composable/Servicable, Executable, Re***, making avalon-meta part of the avalon-framework contract, and many other things.
* Similarly, but with just current fortress/merlin as the LCD. This is the "drop-a-lot-of-legacy" option. This would allow for lifestyles but still rule out everything else.
* We could say that compatibility is defined by the ability to host and run all applications that merlin can run. This in effect means that the only compatible container is merlin, and everything else is incompatible.
* We could say that only the established and fully specified contracts define compatibility. This means there will be components (for example, those dependent on "[]" semantics or that will only run in a pooled environment) that will be compatible that are impossible to run inside a compatible container without (extensive) modification of the sources.
* We could just follow the "IMHO" bits and let me built the TCK on my own and let that define compatible :D.
* We could categorize the compatibility issues along lines similar to what I did above, discuss per-category, and make a choice per category. This will likely leave some people unhappy with the result (I expect at least myself :D), but its a workable way for moving forward.
* We could discuss each and every issue seperately. This will likely take many months (after all, it has already taken some months in some cases). This is an option that's not really a "we" as I will probably run out of steam and drop the whole effort.
== IMHO ==
I don't know yet. I wanna hear other people's thoughts first.
= Battleplan =
What I would like to do is something like this:
1) brainstorm about all this together (throw out all those [RT]s :D) for a week or two. 2) take some time to digest those braindumps. 3) do a summary of the important things in those braindumps, focussing on finding what we already agree upon. 4) draft a proposal outline a procedure, decision process, and roadmap for tackling the issues. 5) discuss, refine, then perhaps even vote on that proposal. 6) work step-by-step according to what's in the proposal (can't of course, be more specific yet, but it'd better involve baby steps and use of Jira :D).
= References =
[*] Preface courtesy of Sam Ruby :D [1] http://cvs.sourceforge.net/viewcvs.py/jicarilla/jicarilla-sandbox/platform/container/tck/
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]
