I am resending this--opologies if you already got it.

---------------------------------------------------------------

> From: Peter Donald [mailto:[EMAIL PROTECTED]]
> 
> On Mon, 3 Jun 2002 22:30, Berin Loritsch wrote:
> > > From: Peter Donald [mailto:[EMAIL PROTECTED]]
> > >
> > > > I think the key is to have the second lookup (to find the
> > >
> > > component B
> > >
> > > > that is contained in C) standardized via a interface.
> > >
> > > Personally I think the exact opposite ;)
> > >
> > > I HATE the ComponentSelector interface and think it is a huge
> > > mistake to use it. If the ComponentSelector is simply access to a 
> > > category of avalon components then I can't see why you 
> can't depend
> > > on/lookup a component
> > > directly.
> >
> > Keep in mind the purpose of the Selector/Manager relationship.
> 
> I recall - one of the time I wished I had kept arguing ;)

:)  Maybe it is something we can address for the next version of Avalon
framework....  In that case, I would like to drag Stefano into the midst
of the discussion--he's pretty smart.

I personally want to remove the necessity of string resolution, but I
haven't been able to come up with something that is happy for all of us
involved.  Strings are the major bottleneck of Avalon right now.  Esp.
for something like Cocoon where we we can expect over 1000 requests per
second in a heavy traffic site (that translates to 86,400,000 hits in a
day) and components are resolved at runtime.  That's a lot of string
opperations!

That's a lot of Generator.ROLE + "/fooo"!

But that is another subject entirely.


> > The selector is much better or more elegant when we have something
> > like Cocoon.
> 
> I sooooooooooooo disagree ;) The only person it is "elegant"
> for is the 
> container writer - a very small % of overall cocoon developers.

Ok.  I'll give you that.  The difference between the selector and the
appended name is largely like EJB binding to a JNDI context.

J2EE spec specifies that the components are mapped to the following root
(or something close):

java:/comp/mycomp
java:/comp/mycomp/first
java:/comp/mycomp/second

All of those are valid binding locations.  The mycomp would be like the
default implementation of "mycomp" and "/first" and "/second" would be
the more specific implementations.

What you are advocating is like that.  (BTW, I was moving toward a
default impl in Fortress).


> > The components available for Generation, Transformation,
> > or Serialization are many.  Plus it is hard to determine
> what should
> > be the actual mapping to the specified component.  For example:
> >
> > Generator.ROLE + "/file"
> > Generator.ROLE + "/stream"
> > Generator.ROLE + "/foo"
> >
> > Truth be told, the File and Stream options can both be used
> to get the
> > same results....
> 
> 
> dont see relevance of above ?

Maybe not, but their implementations overlap.  The Stream version would
be able to grab info from any stream--but at the cost of not being
cacheable. The file version is cacheable, but is limited to files.

So the container could theorhetically replace one for the other
depending on the URI.

The fact that they overlap would mean that really there shouldn't be
implementations bound to separate locations.  There should be one
location. They aren't distinct enough.  It would be like blocking IO vs.
non-blocking IO.  One scales better than the other, but they essentially
do the same thing.

> hmm then lets go with generators then. Lets say you have 10 generators
> 
> Generator.ROLE selects the default component in role while
> Generator + "/X" 
> selects the X generators - wheres e problem ?
> 
> >
> > > Much easier to do dependency checking, much easier for component
> > > implementer and gives the assembler much more choice in 
> assembling
> > > the system.
> >
> > And the more complex ways are having the container take
> care of it all
> > for you.
> 
> explain.

Even better.  Here is something that I have been thinking about lately.
How can we have our cake and eat it too?  How can we have a fast
performing component hash without the limitations of the String.

In high transaction environments, this is critical.  My previous
attempts at coming up with something that would work for everyone have
not been up to par.  I am still stuck on trying to come up with
something.  I think a query object is better than Strings.  Strings have
the limitation of being expensive to match, and expensive to hash.
Especially when most of the string is the same.  As a result, we can
solve the problem like this:

/**
 * Avalon 5 interface, so I can reuse the component manager name.  */
public interface ComponentManager {
    /**
     * These methods create a Request object for the CM.  It will
     * return <code>null</code> if the component does not exist.
     */
    Request createRequest( String role );
    Request createRequest( String role, Object hint );

    /**
     * No need for exceptions because the Request object originates
     * from the ComponentManager.  The only issue that might come up
     * is a Request object from a different CM--in that case a
     * RuntimeException is accpetable.
     */
    Object lookup( Request role );

    /**
     * Still can't be convinced that this isn't necessary as long as
     * we have pooled components.
     */
    void release(Object component );
}

public final class Request
{
     public final Object origination;
     public final long  key;

     public Request( Object parent, long key )
     {
         origination = parent;
         this.key = key;
     }

     public long hashCode()
     {
         return key;
     }

     public boolean equals( Object other )
     {
         if ( ! other instanceOf Request ) return false;

         Request test = (Request) other;

         if ( other.key != key ) return false;
         if ( other.origination != origination) return false;

         return true;
     }
}

This will perform better than strings will in high performance or
throughput situations, and it is easy to use.  Let's say the container
stores the Components in an array (or an ArrayList) instead of a
hashmap.  With this Request object, it is possible. A map would be used
to find the Request object, done during initialization.  The list would
be used to serve the components.

/**
 * example lookup
 */
public Object lookup( Request role )
{
    if ( role.origination != this )
        throw new InvalidRequestException; // extends RuntimeException

    return m_componentList.get(role.key);
}

/**
 * Example createRequest
 */
public Request createRequest( String role )
{
    return createRequest( role, null );
}

public Request createRequest( String role, Object hint )
{
    if ( null == role ) return null;

    Map specificMap = m_roles.get( role );

    if ( null == specificMap ) return null;

    Object test = hint;
    Request req = null;

    if ( null == test ) test = "default";

    req = (Request)specificMap.get( test );

    if ( null == component && ! test.equals( "default" ) )
    {
        req = (Request)specificMap.get( "default" );
    }

    return req;
}


An example component using it would look like this:

/**
 * Component Impl.
 */
public final class MyComponent implements Composable
{
    Request m_required = null;
    Request m_optional = null;
    ComponentManager m_manager = null;

    public void compose( ComponentManager manager )
        throws ComponentException;
    {
        m_manager = manager;
        m_required = manager.createRequest( EchoComponent.ROLE );
        m_optional = manager.createRequest( I18nComponent.ROLE,
"XML-bundle" );

        if ( null == m_required ) throw new ComponentException("Missing
component");
    }

    public return processRequest( String message )
    {
        EchoComponent echo = (EchoComponent)m_manager.lookup( m_required
);
        String newMessage = echo.echoMessage( message );

        if ( null != m_optional )
        {
            I18nComponent trans = (I18nComponent)m_manager.lookup(
m_optional );
            newMessage = trans.translateMessage( newMessage );
            m_manager.release( trans );
        }

        m_manager.release( echo );
        return newMessage;
    }
}


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

Reply via email to