I'm not quite sure what the autowire algorithm is but the best I've
figured out is:
* The root RuntimeContext autowires to itself for services it
provides
and if not found delegates to the root system context
* A SystemAggregateContext autowires to itself for services it
provides
or to SystemEntryPointContexts it immediately contains
* A regular AggregateContext autowires to itself and to entry points
it contains. If not found, it delegates to its parent
As a result, autowires from application contexts propogate up the
aggregate tree until they hit the runtime at the root which then
delgates to the top-level system context.
I'd like to propose a change to this algorithm to simplify the
addition
of system components as follows:
* A component can request autowire to a service
* The component's context delegates to its parent aggregate
* A aggregate resolves autowire requests from contained children
against any immediately contained child (EP, Component or ES)
* If it cannot resolve the autowire, it delegates to its parent
which will in turn attempt to resolve the autowire
* This continues up to the roor where it stops because the root
has no parent
This is perhaps best illustrated with an example :-)
Suppose I have the following tree of contexts:
tuscany.runtime
|
+ tuscany.system
| |
| + system1
| | |
| | + system1a
| |
| + system2
|
+ tuscany.root
|
+ app1
|
+ app1a
|
+ app1b
Suppose component app1a requests autowire to a service exposed as an
entry point by tuscany.system. It passes this request to app1 which
looks to see if the service is provided by any of its immediate
children
(app1a and app1b). It does not find any so delegates the request to
tuscany.root. Again it is not resolved so the request is delegated to
tuscany.runtime. tuscany.runtime sees that the service is provided
by an
entry point on its child tuscany.system and so that is the used as
the
target.
If the service was instead just a component in tuscany.system, it
would
not be exposed as an entry point and hence tuscany.runtime would not
resolved to it.
Now suppose that component app1a requests autowire to a service
that is
provided by app1b. app1 would immediately resolve this to app1b. This
supports autowire between components with the same parent.
Finally, support component system1a requests autowire to a service
exposed by system2. It would request resolution from system1 which
would
delegate to tuscany.system which in turn would resolve it to system.
From a user's perspective, autowire would work as follows:
* it would resolve to components in the same module
* it would resolve to components in any parent module
* it would resolve to entry points exposed by siblings
or siblings of parents (uncles?)
* it would not resolve to components contained by
siblings or children
Doing this results in one autowire algorithm across the whole
system and
eliminates the special-case behaviour in RuntimeContextImpl and
SystemAggregateContextImpl.
Comments welcome and if no-one has issues I will start to
implement this
later this week.
--
Jeremy