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 Berin Loritsch <bl...@apache.org> on 2002/10/01 16:54:22 UTC

Component Lookup Strategies and Tradeoffs (was Map and Array...)

Currently we have several ways of looking up components and resolving
them.  We typically refer to them by the container that implements them,
i.e. the ECM/Fortress way or the Phoenix/Merlin way.  Each has their
advantages and disadvantages.  Hopefully we can look at them and come
up with the best solution.

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 the embedded Avalon world (ECM and friends), the
ComponentSelector works very well because we can look up the components
we need from the selector by names supplied in the configuration.
It is a desparate need.

We have recently decided that we want to move away from a Selector
based approach--which would bring us back to Peter D.'s original
solution which is the hierarchical ComponentManager.  We still want
to explore that approach, because it gets rid of the intermediate
need of an additional lookup device (which includes Map/Array/
**Selector).

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.

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.


Issue #2:  Component Definition
-------------------------------

In the ECM/Fortress world, things are simple.  There is no meta info
(for the time being) to write, no assembly files to write.  That is
because they take advantage of the interface names as a lookup key
resolution policy.  They dynamically determine how to respond to a
lookup request.  In the Phoenix/Merlin world, things are more complex,
more powerful, and more static.  As a result, ECM/Fortress can easily
handle looking up components from a **Selector because the lookup
keys are typically part of the configuration.  That is a good thing
IMO.  The power of meta information comes at a price.

Until support was added for the array/hash return types (substitutes
for the **Selector), there was no real way to look at a collection
of components and determine at assembly/deployment time which components
you really wanted.  The problem is that the array/hash return types
really only work in the Phoenix arena because all the components are
ThreadSafe--not transient.  That said, I think the declaration of
array/hash/selector in meta information can be better stated.  At
development time, we know how we want to lookup information, we just
need to know the lookup value at runtime.  To support this, I propose
the following changes to the declaration and lookup of components:

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

With this change, we declare that we want the lookup for the specified
service to be a Map.  In fact we can do better by using words:
"array", "map", "selector".  The container knows how to bind the
required services from that point.  In our code, we have this:

void service( ServiceManager sm )
{
     Map services = (Map) sm.lookup( Service.ROLE );
     // use them here.
}

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>

There is no need to repeat the as="#"/as="map" in the assembly, because
we already know that the component is looking for multiple entries like
that.  This way we can leverage the power of meta-info with the
flexibility that was desired.  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.


-- 

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


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


Re: Component Lookup Strategies and Tradeoffs (was Map and Array...)

Posted by Stephen McConnell <mc...@apache.org>.

Leo Sutic wrote:

>>From: Peter Donald [mailto:peter@apache.org] 
>>
>>On Wed, 2 Oct 2002 06:39, Berin Loritsch wrote:
>>    
>>
>>>So is it something that will always exist? IOW, how would the user 
>>>releae it?
>>>      
>>>
>>Probably something like
>>
>>if( object instanceof Releaseable )
>>{
>>  ((Releaseable)object).release();
>>}
>>
>>or maybe
>>
>>ReleaseUtil.release( object );
>>    
>>
>
>or maybe even
> 
>manager.release( object );
>  
>

But would it be backward compatible ?

:-)

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

-- 

Stephen J. McConnell

OSM SARL
digital products for a global economy
mailto:mcconnell@osm.net
http://www.osm.net




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


RE: Component Lookup Strategies and Tradeoffs (was Map and Array...)

Posted by Leo Sutic <le...@inspireinfrastructure.com>.
> From: Peter Donald [mailto:peter@apache.org] 
> 
> On Wed, 2 Oct 2002 06:39, Berin Loritsch wrote:
> > So is it something that will always exist? IOW, how would the user 
> > releae it?
> 
> Probably something like
> 
> if( object instanceof Releaseable )
> {
>   ((Releaseable)object).release();
> }
> 
> or maybe
> 
> ReleaseUtil.release( object );

or maybe even
 
manager.release( object );

                          ?
/LS


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


Re: Component Lookup Strategies and Tradeoffs (was Map and Array...)

Posted by Peter Donald <pe...@apache.org>.
On Wed, 2 Oct 2002 06:39, Berin Loritsch wrote:
> > 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?

Probably something like

if( object instanceof Releaseable )
{
  ((Releaseable)object).release();
}

or maybe

ReleaseUtil.release( object );

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

yeppo - now imagine you generalize this to all 

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

Not in Phoenix for backwards compatability reasons but it will be handled like 
that when we upgrade to Info. 

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

yep.

> Yes, but the fewer places we declare the array/map/selector requirement,
> the better.  Imagine this scenario:
>
> <dependency>
>    <service name="org.apache.MyService{}"/>
> </dependency>
>
> ---------------------
>
> <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 generate en error. Something along the lines of;

 "myComp" of type "..." does not have a dependency on type 
"org.apache.Myservice[]" but was provided one in assembly.xml (or something 
similar).

-- 
Cheers,

Peter Donald
--------------------------------------------------
"An intellectual is someone who has been educated 
beyond their intelligence."
-------------------------------------------------- 


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


Re: Component Lookup Strategies and Tradeoffs (was Map and Array...)

Posted by Peter Donald <pe...@apache.org>.
On Wed, 2 Oct 2002 06:39, Berin Loritsch wrote:
> > 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?

Probably something like

if( object instanceof Releaseable )
{
  ((Releaseable)object).release();
}

or maybe

ReleaseUtil.release( object );

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

yeppo - now imagine you generalize this to all 

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

Not in Phoenix for backwards compatability reasons but it will be handled like 
that when we upgrade to Info. 

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

yep.

> Yes, but the fewer places we declare the array/map/selector requirement,
> the better.  Imagine this scenario:
>
> <dependency>
>    <service name="org.apache.MyService{}"/>
> </dependency>
>
> ---------------------
>
> <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 generate en error. Something along the lines of;

 "myComp" of type "..." does not have a dependency on type 
"org.apache.Myservice[]" but was provided one in assembly.xml (or something 
similar).

-- 
Cheers,

Peter Donald
--------------------------------------------------
"An intellectual is someone who has been educated 
beyond their intelligence."
-------------------------------------------------- 


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


Re: Component Lookup Strategies and Tradeoffs (was Map and Array...)

Posted by Berin Loritsch <bl...@apache.org>.
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. ;)


>><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
> 
> <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"/>
>></block>
> 
> 
> 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:

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

---------------------

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


----------------------

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:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: Component Lookup Strategies and Tradeoffs (was Map and Array...)

Posted by Berin Loritsch <bl...@apache.org>.
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. ;)


>><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
> 
> <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"/>
>></block>
> 
> 
> 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:

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

---------------------

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


----------------------

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:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: Interceptor architecture rocks (was Component Lookup Strategies and Tradeoffs)

Posted by Peter Donald <pe...@apache.org>.
On Wed, 2 Oct 2002 09:33, Leo Simons wrote:
> On Tue, 2002-10-01 at 17:38, Peter Donald wrote:
> <snip/>
>
> > Wait for Interceptors - they be magic.
>
> <snip/>
>
> > 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
> >
> >        v
> > Pooling Interceptor
> >
> >        V
> >  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;
> >   }
> >   else
> >   {
> >     return ctx.invokeNext( i, ctx );
> >   }
> > }
>
> <20 seconds of silence...>
>
> WAAAAAAH! This is f****ing neat. It also means total re-architecture of
> the container, but hey...that's all internals. IOW: I get it =)
>
> I figured The Biggest Thing This Week would be Red Hat 8, but this is
> such a big "gotcha", I think Pete's getting the honours.

;)

Think of it this way. 

You use info to describe features of your object - whether these features be 
transaction, security, pooling, activation or whatever. Each Attribute 
effectively describes a different aspect of your object. This is effectively 
the client side view of the system.

These attributes are then mapped onto interceptor chains so that each object 
"type" may have a separate set of interceptor chains. You need a new feature 
(maybe you need a service to be a proxy for webservice) then you create a new 
interceptor, hook it into the chain decorate the info file a little and bam. 
Done.

Containers effectively become simple to write and differentiated on their 
infrastructure (ie their deployment format, their Pool/Activation 
characteristerics and so forth).

Now add in the concept of tools. Implement the J2EE deployment API for Avalon 
and we will be able to deploy into any server using ant tasks or any gui (ie 
Eclipse, Netbeans or whatever) that supports it. We support the J2EE 
Management interface and we get integration with existing infrastrucutre and 
management consoles. We add ant tasks for validation, verification, info 
generation and so forth and things get a lot nicer.

Info + Interceptor + Tools is where I see Avalon going and it will be great ;)

-- 
Cheers,

Peter Donald
'Most men would rather die than think. Many do.'
                             Bertrand Russell


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


Interceptor architecture rocks (was Component Lookup Strategies and Tradeoffs)

Posted by Leo Simons <le...@apache.org>.
On Tue, 2002-10-01 at 17:38, Peter Donald wrote:
<snip/>

> Wait for Interceptors - they be magic.

<snip/>

> 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
>        |
>        v
> Pooling Interceptor
>        |
>        V
>  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;
>   }
>   else
>   {
>     return ctx.invokeNext( i, ctx );
>   }
> }

<20 seconds of silence...>

WAAAAAAH! This is f****ing neat. It also means total re-architecture of
the container, but hey...that's all internals. IOW: I get it =)

I figured The Biggest Thing This Week would be Red Hat 8, but this is
such a big "gotcha", I think Pete's getting the honours.

We'll have to wait the rest of the month to see more? Shame....

cheers,

Leo


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


Re: Component Lookup Strategies and Tradeoffs (was Map and Array...)

Posted by Peter Donald <pe...@apache.org>.
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
       |
       v
Pooling Interceptor
       |
       V
 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;
  }
  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).

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

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

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

-- 
Cheers,

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:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: Component Lookup Strategies and Tradeoffs (was Map and Array...)

Posted by Peter Donald <pe...@apache.org>.
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
       |
       v
Pooling Interceptor
       |
       V
 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;
  }
  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).

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

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

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

-- 
Cheers,

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:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>