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