> 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