Isn't this a chicken-and-the-egg problem? The CM must know which component instance to call lookup() on! Perhaps if it was a static method that was introspected, but I'm not sure that is a viable solution. JNDI has some nifty solutions that might be possible to borrow from, e.g. the Referenceable interface and the ObjectFactory/ObjectFactoryBuilder.
Regards, --mike On Thu, 20 Jun 2002, Robert Mouat wrote: > here is a proposal that will allow us to: > > - have a well defined relationship between the container and > component managers [though it doesn't touch on the issue of > component resolving] > > + you could write component managers that will work in any > container - and be specified at assembly time. > > + these new component managers will work alongside the existing > component managers (allowing for a gentle upgrade path). > > - create dynamic proxies, for example: > > + tracing of component level method calls. > > + aaa (authentication, authorisation, and accounting), an aaa > proxy could intercept component level method calls. > > + release() via the VM's garbage collector. > > + sessions could be implemented this way (with only slight > modifications from my recent email). > > - possibly satisfy some of the need for custom markers (as long as > they are called after initialize). [sessions would probably fit this > category] > > - chain together any of the above (at the whim of the assembler). > > this will work with version 4 (and 5) of the framework and shouldn't > break anything currently in existence. > > > ==== proposal: CustomLookup interface ==== > > the proposal is simply that we add the following interface to the > framework: > > interface CustomLookup > { > public Object lookup(); > } > > with the contract: > > if a component implements the CustomLookup interface then upon > ServiceManager.lookup() a reference to the component is not > returned, but instead the result of the CustomLookup.lookup() > method is returned. > > e.g. inside the ServiceManager the following: > > return component; > > could be replaced with: > > if ( component instanceof CustomLookup ) > { > return ((CustomLookup) component).lookup(); > } else { > return component; > } > > Note: the CustomLookup should probably have a release() method that > is deprecated/removed with the ServiceManager.release(). > > Note: the CustomLookup.lookup() has no args (to prevent it from > being used as a selector/directory/resolver) > > I'd also like to make the following recommendation: > > in the absence of any other lifestyle indicator a component > implementing CustomLookup should be a singleton, otherwise a new > instance should be created upon every lookup. > > Note: the container will still have to be able to handle these two > lifestyles (single and per-lookup) but all others can be managed by > CustomLookup components. > > It shouldn't take much effort to implement this change. > > > ==== example: component manager ==== > > note: component managers get the benefits of the lifecycle methods... > > for simplicity: not dealing with synchronization, exceptions, and > assuming that release() will get called. > > class PoolingComponentManager > implements CustomLookup, Parameterizable, Composable, Initializable > { > static final DEFAULT_SIZE = 5; > String m_role; > int m_size; > List m_pool; > ComponentManager m_cm; > > public void parameterize( Parameters parameters ) > { > m_size = parameters.getParameterAsInteger( "size", DEFAULT_SIZE ); > m_role = parameters.getParameter( "role", null ); > } > > public void Compose( ComponentManager cm ) > { > m_cm = cm; > } > > public void initialize() > { > m_pool = new ArrayList( m_size ); > } > > public Object lookup() > { > if (! m_pool.isEmpty() ) > return m_pool.remove( 0 ); > else > return m_cm.lookup( m_role ); > } > > public void release( Object component ) > { > if ( m_pool.size() < m_size ) > { > if ( component instanceof Recyclable ) > ((Recyclable) component).recycle(); > m_pool.add( component ); > } > else > m_cm.release( component ); > } > > } > > To use the PoolingComponentManager on a component X the assembler > could do the following... > > 1. configure the pooling component manager so that it has parametes > role=X-role size=5 > > 2. configure the component locater so that a lookup that would have > resolved to X now resolves to the pooling component manager. And > that when the pooling component manager looks up X-role it gets X. > > Now whenever a client makes a request that would resolve to X, the > request will go to the pooling component manager which will return a > component from its pool or request X-role from the ComponentManager > (if the pool is empty). > > ==== example: dynamic proxy ==== > > here is an example of how a tracing proxy could be implemented (minus > exception handling and synchronization)... > > class TracingProxy extends AbstractLogEnabled > implements CustomLookup, InvocationHandler, Composable, Parameterizable > { > String m_role; > String m_name; > ComponentManager m_cm; > Map m_ids = new WeakHashMap(); > int count = 0; > > public void parameterize( Parameters parameters ) > { > m_role = parameters.getParameter( "role", null ); > m_name = parameters.getParameter( "name", "tracingProxy" ); > } > > public void compose( ComponentManager cm ) > { > m_cm = cm; > } > > public Object invoke( Object proxy, Method method, Object[] args ) > throws Throwable > { > Object ret; > Object id = m_ids.get( proxy ); > info( "Enter: " + method + " for " + m_name + "-" + id ); > try > { > ret = method.invoke( m_component, args ); > } > catch ( InvocationTargetException ite ) > { > warn( "Error in: " + method " for " + m_name + "-" + id, ite ); > throw ite.getTargetException(); > } > info( "Leave: " + method + " for " + m_name + "-" + id ); > return ret; > } > > public Object lookup() > { > Object component = m_cm.lookup( m_role ); > Class[] interfaces = component.getClass().getInterfaces(); > ClassLoader classLoader = component.getClass().getClassLoader(); > Object proxy = java.lang.reflect.Proxy.newInstance( > classLoader, interfaces, this > ); > m_ids.put( proxy, new Integer( ++m_count ) ); > return proxy; > } > > } > > > To activate the tracing on a component X the assembler could do the > following... > > 1. configure the tracing proxy so that it has parameters: > role=X-role, name=X-trace > > 2. give the tracing proxy its own logger. > > 3. configure the component locator so that a lookup that would have > resolved to X now resolves to the tracing proxy. And that whenever > the tracing proxy looks up X-role it gets X. > > Now whenever a client makes a request that would resolve to X they > will get a proxy that will log all method calls, before passing them > on. > > ==== > > a SessionManagingProxy proxy can be created in a similar fashion to my > recent email, with the change that the Proxy now runs the show (and > the SessionEnabled component should probably let m_SessionManager > default to an instance of SimpleSessionManager in case > setSessionManager() isn't called). > > ==== issues ==== > > - it is now possible for the assembler to specify cyclic > dependencies when chaining Customlookup components together, this > may cause lookup() to hang. > > - unless you have something like: > > public Object lookup() { return this; } > > no other component will ever get a direct reference to the > CustomLookup component. So I'm wondering if it is still correct to > refer to it as a component... perhaps meta-component might be > better... or since the dynamic proxies could fall into a broad > definition of component management, perhaps manager-component... > > - I don't know if 'CustomLookup' is a great name so feel free > to suggest others... MetaComponent? > > Robert. > > > -- > To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> > For additional commands, e-mail: <mailto:[EMAIL PROTECTED]> > -- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>