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: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>