> From: news [mailto:[EMAIL PROTECTED] On Behalf Of Leo Simons
> 
> Wake up thinking about this! (Yes, I have a sick mind :D) 
>
> There's just a 
> few characters of less typing to be squeezed out 
> here.....let's make it 
> a little more complete...

OK, have read what you wrote and it's pretty much what I meant.

Just a couple of things regarding "how stuff works":

= STATEFUL/STATELESS =

This not-so-RT splits all component interfaces (not components)
into stateful and stateless sets. The stateless interfaces are
passed to the client as-is, while the stateful are passed to
the client as a factory, which is then used by the client to
obtain actual instances of the required component.

So, it is then a property of the component interface whether it
is stateful or stateless.

    /**
     * @@Stateful()
     */
    public interface MyInterface { ... }

    /**
     * @@Stateless()
     */
    public interface MyInterface { ... }

Then we have the implementation. Some implementations can handle
more than one client simultaneously, and some only one. Some
are used up after one use, and some can be re-used. (This corresponds
to the ThreadSafe, SingleThreaded/Poolable, SingleThreaded and Poolable,
respectively of ECM.)

For simplicity's sake, we'll assume that if an interface is stateful,
then the implementation cannot handle multiple clients.

So implementations are then either:

 + Single client, not reusable

 + Single client, reusable

 + Multiple client

The two single client implementations can be collapsed into one, since
the only difference is internal handling at end-of-life.

Since we pass stateful interfaces via a factory and stateless interfaces
as-is to the client, we have to be able to adapt any implementation of
a stateless interface to that interface. For example, you can have a 
stateless interface, but pooled implementation. I just read your email
about the uselessness of this kind of decomposition, and I will address
it
below in the summary, but for now the matrix is thus:

              Single     Multiple

   Stateful     1           2

  Stateless     3           4

1. These are the SAXTransformers. They are stateful and are passed in
   via a Factory. Client code:

        Factory f;

        public void service (ServiceManager manager) {
            f = (Factory) manager.lookup(MyComponent.ROLE);
        }

        public void doStuff () {
            MyComponent comp = (MyComponent) f.get ();
            try {
                comp.doStuff ();
            } finally {
                f.release (comp);
            }
        }

        public void dispose ()
            manager.release (f);
        }

2. Not existing - a stateful component has only one client. (The client
   code can of course get around this and share the instance among
   several threads, but it does so at its own risk.)

3. Stateless interface, but can only handle a single client. We wrap a
   proxy around the ServiceManager that, for each method call, looks up
   an instance, executes the method call, and returns the instance.
   Client code:

        MyComponent comp;

        public void service (ServiceManager manager) {
            comp = (MyComponent) manager.lookup(MyComponent.ROLE);
        }

        public void doStuff () {
            comp.doStuff();
        }

        public void dispose ()
            manager.release (comp);
        }

4. Stateless interface, impl can handle multiple clients. Client code
   same as (3):

        MyComponent comp;

        public void service (ServiceManager manager) {
            comp = (MyComponent) manager.lookup(MyComponent.ROLE);
        }

        public void doStuff () {
            comp.doStuff();
        }

        public void dispose ()
            manager.release (comp);
        }

So we need to annotate the implementation with:

 @@MultipleClient()

or

 @@SingleClient(), optionally with an "implements Recyclable"
 to indicate that it can be pooled.

== Summary ==

Four new attributes, two for the interface, and two for the impl:

    Interface:
        Stateful
        Stateless
   
    Implementation:
        SingleClient
        MultipleClient

Whether we agree on the decomposition or not, one thing is inherent
in this scheme - the interfaces are either stateful or stateless, and
the container (or some plugin) must provide adapters from different 
implementations of those interfaces to the required interface (where 
such an adapter makes sense - see (2) above).

So we have the following domain objects:

 + Stateful interfaces

 + Stateless interfaces

 + Plugins

= Plugin =

Each component type is managed by a plugin.

    public interface Plugin {
        public Object get ();
        public void put (Object o);
    }

The role of a plugin is to provide an instance of the component
interface
if the interface is stateless, or a Factory for the interface if the 
interface is stateful.

= Code to adapt a stateless single-client impl to a stateless interface
=

public class StatelessTransientAdapter 
    implements InvocationHandler {
    
    private final ServiceManager manager;
    private final String role;
    
    public StatelessTransientAdapter (
        ServiceManager manager, 
        String role) {

        this.handler = handler;
        this.role = role;
    }
    
    public Object invoke (
        Object proxy, 
        Method method, 
        Object[] args) 
        throws Throwable {

        Object comp = null;
        try {
            try {
                comp = manager.lookup (role);
            } catch (ServiceException ce) {
                // ?
                throw new Error ();
            }
            
            return method.invoke (comp, args);
        } finally {
            manager.release (comp);
        }
    }
    
    public static Object createAdapter (
        Class interfaceClass, 
        ServiceManager manager, 
        String role) {

        return createAdapter (
            Thread.currentThread ().getContextClassLoader (), 
            interfaceClass, 
            manager, 
            role);
    }
    
    public static Object createAdapter (
        ClassLoader loader, 
        Class interfaceClass, 
        ServiceManager manager, 
        String role) {

        return Proxy.newProxyInstance (
            loader, 
            new Class[]{ interfaceClass }, 
            new StatelessTransientAdapter (manager, role));  
    }
}

/LS


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to