avalon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Peter Donald <pe...@apache.org>
Subject Re: Component Lookup Strategies and Tradeoffs (was Map and Array...)
Date Tue, 01 Oct 2002 15:38:25 GMT
On Wed, 2 Oct 2002 00:54, Berin Loritsch wrote:
> Issue #1: Component Lookup/Release
> ----------------------------------
> Part of what the ComponentSelector solved was the need for lookup and
> release mechanisms.  Simple types cannot provide release mechanisms,
> so only ThreadSafe components can be safely used with simple types.
> In the Phoenix realm, that is not a real problem as most services are
> ThreadSafe anyway.  However, at lower levels (i.e. Avalon embedded
> in another container hierarchy like Servlets) developing all components
> as ThreadSafe is not always practical.  We need transient components.
> Since the solution we come up with must work in the general case, the
> compromise was the ComponentSelector--something that Peter D. regrets
> to this day ;p. 


> In order to fully get away from the need of the *Selector interface,
> we need a way to mask the component management for transient components.
> One way is through dynamic proxies that will pull an instance from
> a pool as needed, and will automatically return it after a specified
> period of inactivity.  The major issue is managing state information.
> In order to work with transient/stateful components we need a session
> mechanism so that a component can store its state in the session so
> the client will never be the wiser.

Wait for Interceptors - they be magic. Request, Session and Application scopes 
are what I am using now and they work brilliantly. The only problem is that 
each call incurs too much overhead atm ;( 

Its a work in progress but needs to be completely rewritten with BCEL at each 
end to get required speed.

> BTW, for the benefit of all who weren't around the last time we had
> the many components for one role discussion, a Releasable interface
> was vetoed.  I proposed adding a method like "release()" to the
> component interface that would provide real semantics for having a
> Component interface as well as not requiring release() on the
> CM/CS interfaces.  I think I was the only one in favor of that at
> the time.

I have completely changed my mind. I think something like the following is the 
way to go.

interface Releaseable
  void release();

The magic thing about what I am going to propose in about amonth is that no 
component will ever implement this interface ;)

Lets assume that every component is exposed via a proxy with an interceptor 
chain attached to it. So when you invoke a method it will be passed through 
each interceptor in chain. 

Just say our chain looks something like

Service Interface
Pooling Interceptor
 Target Method

Now lets just say that our pooling interceptor looks something like

Object invoke( Invocation i, InterceptorContext ctx )
  if( i.getMethod() == m_cachedReleaseMethod )
    ObjectPool pool = (ObjectPool)ctx.get( ObjectPool.KEY );
    Object object = ctx.remove( InterceptorContext.TARGET );
    pool.release( object );
    return null;
    return ctx.invokeNext( i, ctx );

So what does this mean? This means that the proxy implements the Releaseable 
interface but the underlying object doesn't and in fact may not even know 
that it is being pooled. When you call release on an object the call never 
makes it to the target object but is intercepted and handled by the 
interceptor that grabs target object, removes it from correct context and 
places it back in the pool. (The correct context being related to how 
sharable the object is).

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

That was how I originally implemented it today but it introduced more 
complexity into the code and into documentation. Part of this is because of 
BlockInfo format (Service is shared between service publishing declaration 
and service dependency declaration). Effectively the above is same as

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

> void service( ServiceManager sm )
> {
>      Map services = (Map) sm.lookup( Service.ROLE );

I still prefer the convention that key coresponds to type if unspecified 
rather than coresponding to component type and thus even if following the 
convention Service.ROLE could return a Map, Selector or Array depending on 
the host component. I much prefer a simpler one to one mapping like

      Service service = (Service) sm.lookup( Service.ROLE );
      Service[] service = (Service[]) sm.lookup( Service[].class.getName() );

      //Next line different as java no have associative arrays
      Map service = (Map) sm.lookup( Service.ROLE + "{}" );

> At assembly time, we specify them like this:
> <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>

Again - it does not make it any clearer in my opinion to make the 
interpretation of role context sensitive.

> I would even go farther and say that we
> would be able to remove the necesity for the role="..." attribute in the
> assembly if the component only implements one role.

yep. 99% of assembly.xml can be autogenerated with a smart enough bit of 
discovery code.


Peter Donald
"Therefore it can be said that victorious warriors 
win first, and then go to battle, while defeated 
warriors go to battle first, and then seek to win." 
              - Sun Tzu, the Art Of War

To unsubscribe, e-mail:   <mailto:avalon-dev-unsubscribe@jakarta.apache.org>
For additional commands, e-mail: <mailto:avalon-dev-help@jakarta.apache.org>

View raw message