You are viewing a plain text version of this content. The canonical link for it is here.
Posted to phoenix-dev@avalon.apache.org by Peter Donald <pe...@apache.org> on 2002/10/01 10:20:12 UTC

Re: Configuring components dynamically

Hi,

On Wed, 25 Sep 2002 06:55, Boris Belyarchik wrote:
> I have recently started using Avalon and Phoenix so please excuse my
> ignorance if I have things wrong.
>
> I am facing a different problem (dynamic dependency) with the application I
> am building but I believe that it's related to this discussion. I have many
> different components which all have the same role, let's say Role1. I have
> another component, Role1User, which uses some number of Role1 components.
> This number is not known at development time and therefore dependencies can
> not be described in the .xinfo file. What I would like to do is configure
> Role1User with names of Role1 components and have it lookup Role1
> components by name at initialization.
...
>
> What is the 'correct' way to develop this?

Up until about 50 minutes ago there was no "correct" way. However I have just 
gone and extended Phoenix to support this behaviour. There are two new types 
of dependencies; Map and Array dependencies.

To indicate an Array dependency you need to postfix the name of your service 
with the "[]" characters. So your dependency will look like

  <dependencies>
    <dependency>
      <service name="org.apache.MyService[]"/>
    </dependency>
  </dependencies>

Then you can access these dependencies from within your code via something 
like

void service( ServiceManager sm )
{
  Service[] services = (Service[])sm.lookup( Service[].class.getName() );
  //use returned services here
}

Rather than Service[].class.getName() you could also use Service.ROLE + "[]"

Then in your assembly.xml you can map 0-N services into dependency. ie It 
would look like

<block class="org.apache.MyComponent" name="myComp">
 <provide name="service1" role="org.apache.MyService[]"/>
 <provide name="service2" role="org.apache.MyService[]"/>
 <provide name="service3" role="org.apache.MyService[]"/>
</block>

This would map 3 blocks (service1, service2 and service3 into the array.

If arrays are not suitable for you you map also use the new an improved "Map" 
dependencies. You declare them with postfix "#"

  <dependencies>
    <dependency>
      <service name="org.apache.MyService#"/>
    </dependency>
  </dependencies>

And use them like

void service( ServiceManager sm )
{
  Map services = (Map)sm.lookup( Service.ROLE + "#" );
  //use returned services here
}

And you declare them in the assembly similar to how arrays are declared. ie

<block class="org.apache.MyComponent" name="myComp">
 <provide name="service1" role="org.apache.MyService#"/>
 <provide name="service2" role="org.apache.MyService#"/>
 <provide name="service3" 
       role="org.apache.MyService#"
       alias="myAlias"/>
</block>

Each provide will be mapped into map using their blocks name (the name 
attribute in provide tag) unless they also declare an alias in which case the 
alias will be used as key for map.

I have added a few unit tests for this and made sure it works in most (all?) 
cases. If you can check out the source to phoenix then it should be useful. 
Alternatively you could wait till the next release (which may be in next 
month or so).

-- 
Cheers,

Peter Donald
*------------------------------------------------*
| You can't wake a person who is pretending      |
|       to be asleep. -Navajo Proverb.           |
*------------------------------------------------* 


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>