After looking at several container frameworks, I think we should add a new lookup mechanism to the Avalon Framework. I know this issue has been discussed before several times, but why not doing it again after some years inbetween?
Now with ECM and Fortress a Service (Interface) declares in most cases a constant ROLE, like this:
public interface MyService { String ROLE = MyService.class.getName(); ... }
I don't know how this is done with Merlin.
The fundamental difference between Merlin and the Fortress/ECM approach is "push" versus "pull". The following example is a pull based service acquisition:
public void service( ServiceManager manager ) { // ask the container to resolve a service Widget widget = (Widget) manager.lookup( Widget.class.getName() ); }
This basically is a component invoking a request on a container to provide the Widget service. In both ECM and Fortress this results in the potential establishment and delivery of the service to the component.
In Merlin things are "preemptive" - in that the component declares what it needs as part of its definition. The result is that the component will only be deployed IF all of its dependencies can be resolved prior to the establishment of the component. This is achieved via the following:
/** * @avalon.dependency type="org.whatever.Widget" */ public void service( ServiceManager manager ) { // ask the container to give me the widget it has // already established for me
Widget widget = (Widget) manager.lookup( Widget.class.getName() ); }
This approach can be simplified for the component implementation by declaring a lookup key (note tag declaration and lookup argument):
/** * @avalon.dependency type="org.whatever.Widget" key="widget" */ public void service( ServiceManager manager ) { // ask the container to give me the widget it has // already established for me
Widget widget = (Widget) manager.lookup( "widget" ); }
Anyways, the lookup is then done using this constant:
MyComponent c = (MyComponent)this.serviceManager.lookup( MyService.ROLE );
or
MyComponent c = (MyComponent)this.serviceManager.lookup( MyService.ROLE + '/' + hint );
There is never a lookup that uses some custom role name, like lookup("my-parser"); I think such lookups with custom role names should not be used anyway as they are way too error-prone.
It is only error prone if the lookup key is not scoped to the component implementation - for example in any merlin component a key is simply a convenience factor local to the implementation. The thing I think your getting at is when a string is passed to lookup who's semantics are relative to a configuration - which means that the component is tied to a particular deployment scenario - which is out and out bad.
And even worse, ECM has the ugly concept of Selectors, so you first lookup a selector using MyService.ROLE+"Selector" and then the component from the selector using the hint. With the following semantics you combine the two in one interface.
Now, what do you think of using an easier solution: public interface Locator { Object lookup(Class clazz, String hint); // or Object hint }
I *hate* the "hint" terminology. In English - hint means something I can use or ignore. If the string is a key - then call it a key - but beyond this - semantics are required. What does the key refer to? This is critical thing missing in the Selector spec - no declaration of semantics. Before considering any alternative the semantic contract needs to be nailed down tight .. and only then one should consider if this is a framework concern.
With this interface, you don't need the ROLE constant anymore and the
container can check the type of the returned object avoiding class cast
exceptions.
+1 to removal of anything dependent on ROLE constants.
> components.And you can see directly in your code which type is returned by the lookup. (Creating proxies is also a little bit easier as the lookup method knows which interface to proxy without having the need to get this information from somewhere else).
This approach is also used by other container frameworks and imho it gives the lookup method more meaning and reduces errors because of typos.
So, I propose to add a new interface with this lookup semantics to avalon framework with a corresponding IoC interface to give this locator to
Let's not talk about the framework - instead - get something in place using a facility - validate it, get the specs real clear - and then assess the necessity for inclusion in the framework. Immediate impressions are the the class argument is only required in pure dynamic lookup context in which case we are talking about finder semantics. As such I think the entire subject of the qualifying argument needs to be more fully addressed:
(a) properties of a component type? (b) properties of a service descriptor? (c) properties of a deployment scenario?
Beyond this there are the semantics of the request values:
(a) exact matching (b) regular expression matching (c) candidate selection
The default implementation for all containers at avalon could be that
a lookup(Class clazz, String hint) is "converted" to a serviceManager.lookup(clazz.getName()) if hint is null or
serviceManager.lookup(clazz.getName() + '/' + hint) otherwise.
WDYT?
I think we should break this into two things - firstly selection relative to component type attributes and service attributes - e.g:
/** * @avalon.dependency type="Widget" color="red" key="widget" */ public void service( ServiceManager manager ) { // get the ref widget Widget widget = (Widget) manager.lookup( "widget" ); }
Secondly - concerning dynamic lookup I think we should be following something closer to the approach suggested by Bruno Dumon - ie.:
/** * @avalon.dependency type="Locator" key="locator" */ public void service( ServiceManager manager ) { // get the ref widget Locator locator = (Locator) manager.lookup( "locator" ); Widget redWidget = locator.locate( Widget.class, m_map ); }
Given validation of the above - with complete specification of a generic set of semantics of allowable map keys and values and the corresponding selection criteria/semantics - then you may have a framework candidate.
Cheers, Steve.
--
|------------------------------------------------| | Magic by Merlin | | Production by Avalon | | | | http://avalon.apache.org/merlin | | http://dpml.net/merlin/distributions/latest | |------------------------------------------------|
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]