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