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