avalon-phoenix-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Berin Loritsch <blorit...@apache.org>
Subject Re: Component Lookup Strategies and Tradeoffs (was Map and Array...)
Date Tue, 01 Oct 2002 20:39:12 GMT
Peter Donald wrote:
> 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 ;)

So is it something that will always exist? IOW, how would the user
releae it?

> 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
>        |
>        v
> Pooling Interceptor
>        |
>        V
>  Target Method

*!A light bulb goes off over my head!*

If we have sessions, etc. then the proxied interface performs the
release() and the client never sees it!  That would rock!

> 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;
>   }
>   else
>   {
>     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).

Here's me salivating over this future feature. ;)

>>   <dependency>
>>     <service name="org.apache.MyService" as="#"/>
>>   </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
> <dependencies>
>    <dependency>
>      <role>org.apache.MyService</role>
>      <service name="org.apache.MyService[]"/>
>    </dependency>
> </dependency>

Ah.  That is in contrast to the "Meta" package (Stephen's baby) which
has a distinction between ServiceDefinition and ReferenceDescriptor.
IOW, a Dependancy is separate from the service definition.  I like the
Service being a first class item (is that done for Phoenix?), and then
using a reference object when looking it up.

The difference is really minimal.

>>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 + "{}" );

Yes, but as long as you don't *force* it to be like that, it is ok.  I
am seeing the value of being able to name my components whatever I want,
and the container resolving them for me.

>>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"/>
> Again - it does not make it any clearer in my opinion to make the 
> interpretation of role context sensitive.

Yes, but the fewer places we declare the array/map/selector requirement,
the better.  Imagine this scenario:

   <service name="org.apache.MyService{}"/>


<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[]"/>


What is the type?  It is important to note that the dependency is
declared as a Map ("{}") and the assembly is declared as an array
("[]").  I would also like to bring up at this time that with certain
fonts there is little visual difference between curly braces and
square brackets.  The "#" was better, but the angle brackets were
also acceptable.

Does the container throw an error?  Does it provide an array,
and the component code throws a ClassCastException?  Or does
it ignore the designator in the assembly file and use what was
declared in the blockinfo?

If it is the last option, then I wouldn't put any designation
in the provide section.

>>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.

Which means its verbosity can be reduced quite a bit.


"They that give up essential liberty to obtain a little temporary safety
  deserve neither liberty nor safety."
                 - Benjamin Franklin

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

View raw message