I want to throw out some ideas about the upcoming work on Tapestry 5. Everyone wants T4.1 and T5 to happen a lot quicker than T4 did. I'm focusing on T5 in the hopes that getting some discussion going will help grease the wheels.
I'm not putting this on the wiki at this time. First, I made some statements here http://wiki.apache.org/jakarta-tapestry/Tapestry5LookupDebate which I now think are somewhat flawed as I was approaching the topic from a T4 pov which is not applicable as I think T5 is a whole different beast. I'm looking again as the statements Howard made in http://www.nabble.com/forum/ViewPost.jtp?post=2687072&framed=y and at the resulting responses and it looks like: - The scope for T4.1 is a 'tweaking' of T4. - T5 is a world changer and the changes will vastly alter what Tapestry 'is' without much thought given to backwards compatibility. Assuming the following as a starting point for T5: (from Howards post) - Annotations based. JDK 1.5. - No XML for pages and components. Just HTML and Annotations. - Concrete, not abstract, page and component classes - No inheritance imposition - Transforming class loader driven by annotations (i.e., @Persist on the field, not the method) - Change detection; automatic invalidate and reload of changed objects (including Java classes) - "Modern" templates: Templates as well formed XML, using a namespace for Tapestry attributes and elements - A "preview" mode for pages - Partial rendering of pages (for Ajax operations) - Improved management of page state (including dynamic state during the render) - Vastly simplified API - Clear deliniation between public/stable and private/internal/unstable APIs I want to initiate some discussion based on a subset of the above: - Annotations based. JDK 1.5. - No XML for pages and components. Just HTML and Annotations. - Concrete, not abstract, page and component classes - No inheritance imposition (I have an case for keeping a (modified) form of the xml for pages/components as an optional item but that's an argument for a later time) So we are talking about Tapestry developers writing concrete Pojos instead of abstract classes that inherit from Tapestry classes. A __ good idea__. In T5, in a statement similar to Sun's "the network is the computer", the goal is that "the class is the page/component". Howard has said this was the goal he was working towards when building T4. In T4 the implementation of that goal is incomplete. The java class is not the main actor in T4, the actual class *used* is ambiguous depending on the name used to reference a page or component. It was also possible for the same name to resolve to different classes in some contexts. In a world where "the class is the page/component" the name used to reference the page or component is irrelevant. All 'namings' that resolve to one class are referring the same page/component. (It would be nice to have a few namings as possible!). Sidebar - as I progress it will become clear that the various Tapestry "lookup rules" will move from a complex task to a much simpler one as the whole lookup mechanism was designed in T3 to find xml files (gone?) and was just tweaked in T4 in the move towards "the class is the page/component". So, in T5 a page/component is a concrete pojo and there is no inheritance requirement. Let's ignore the concept of namespaces for a moment. Now that "the class is the page/component" there is a natural naming for any T5 page/component. That naming is the fully qualified name of the class! (Don't freak out yet, remember we are ignoring namespaces right now). How does T5 decide that a particular Pojo is a page/component? I would suggest the following (obvious) requirement: "Pojos are Tapestry pages/components if and only if they contain, directly, an @Component or @Page annotation" In T4 a component class need not have the @Component annotation and there is no @Page annotation. The 'componentness" or "pageness" of a class was based on the results of the "lookup" and even the @Component annoation was optional to maintain compatibility for developers not using JDK1.5. There is need to make @Component or @Page optional in T5 as JDK 1.3/1.4 will not be supported. In the spirit of "start of strict and relax things later" I would suggest that the statement I made previously: "All 'namings' that resolve to one class are referring to the same page/component" be implemented in a strict fashion in T5. What does this mean? Well, in T4 it's possible to specify no class at all and (with customization possible) BaseComponent or BasePage would be used as the class. Or, use the same class for more than one page or component. In Pojo world the former sentence is gone anyways as BaseComponent and BasePage make no sense if there is no inheritance from Tapestry classes. The latter sentence is not possible since the "the class *is* the page/component". So what if a developer creates a component Pojo and wants to base many other components on the same pojo? Subclass it and add an @Component annotation. What if the developer doesn't want to write a class at all? Too bad, "the class is the page/component". The act of creating a class (perhaps by subclassing) "creates" an new component in our, currently global, namespace. I think this is simpler and better than what's been done to date. What have we gotten rid of? - BaseComponent and BasePage are already gone (No inheritance imposition) - There is no ambiguity as to what *exactly* is a Page or Component in the system. - Resolving a name to a page/component is simplified - no need for org.apache.tapestry.default-page-class - Resolving a name to a page/component is even more simplified - no need to check an xml file for a 'class' tag - indeed no need to find the xml file at all (if they are still around). I think this would also make tools easier. Need to find everything to generate a Component Reference? Just write an AnnotationProcessor that gobbles up all the classes that have a @Component annotation. The fact that one class relates to one component (and only one component) means that such a tool no longer needs to re implement the old "lookup rules" in order to find all the components. Now we have a global namespace containing a bunch of pages/components identified by the fully qualified name of their classes. This: <span jwcid="@/org/apache/tapestry/contrib/ajax/XTile"/> is an awful way to have to refer to a component! In T4, the "lookup rules" provide the ability to refer to pages and components by nicer, shorter, names. If anyone has paid any attention to my recent ramblings the current facility for doing this leaves the door open for components and pages to "cross namespace boundaries" and a lot of fun (not) can occur when this happens. Howard has mused about adding code to check to disallow these situations. I think that, in T4 anyways, it would be hard to do and pretty hacky to boot. Since "simple names" are the main culprit in boundary crossing issues, lets visit namespaces in T5 and see if we can't prevent it from ever happening or at least make it easier to detect and disallow. First that global namespace of fqns, T5 should not allow anyone to refer to a component in this way. period. Well, there is an exception described later. By definition a global namespace crosses all boundaries so let's stomp on that. That means the current T4 "rule" that looks for a name relative to the default package is out altogether or at least severely restricted. OPTION 1 Each namespace should declare it's boundaries and no other namespace is allowed to cross them. That declaration would be in the form of a package. "A package?" you say? Why not, isn't the word "package" a pretty good description of a "container of stuff" which is what a namespace really is anyway? Now, because each namespace declares a package as it's own, let's say for now that every page/component class in that package or it's descendant is 'owned' by that namespace. Checking for boundary crossing becomes easier, just check all the packages of the namespaces in the app - if they overlap you have a boundary crossing situation. This is radical and I don't think people will like it. It restricts what packages they can use to locate thier Pojos. Plus, T5 I assume will continue the tradition of being very lazy and not load up all the namespaces up front so that "easy" check isn't really all that easy. OPTION 2 "Make each page/component declare it's namespace" Something like @Component{ns="contrib"} @Page{ns="tacos"} Ok, that sounds as bad as the first option. But is it really? Every class declares it's package. Every xml file that exists in Tapestry today declares it's dtd (that's a kind of namespace too). Plus it removes any need to impose draconian "rules" like OPTION 1. The trick is to make it a painless as possible. The first thing to do it make it optional for applications. If a page/component does not declare it's namespace it's considered to be part of the application namespace. This does leave the door open to namespace boundary crossing in war files containing more than one T5 app, but what can you do? A sacrifice for usability. The apps will still run ok in most cases. This could be avoided if a developer chose to declare the namespace for all of their application pages/components. If the last paragraph is accepted we do know that the application namespace and any library namespaces won't overlap since it's implied that a namespace declaration is required for a library component or page. We now have a scheme that allows developers to put their pojos anywhere they like and Tapestry can easily check for an illegal (boundary crossing) access: <span jwcid="@contrib:inspector/Inspector"/> (legal in T4!) Would be illegal as Inspector would report it's namespace as "inspector" and that's not "contrib". Pls, no complicated "rules" for determining the namespace of a page/component based on it's location in the classpath. Is it really that onerous to type ns="contrib"? Stay strict at first and relax later. Like after I retire :-) Where does the "tacos" in @Page{ns="tacos"} come from? The <application-specification> tag currently has a 'name' attribute, why not add that to the <library-specification> too? Should keep it optional for applications and make it required for libraries. A neat side effect is that if Tapestry could discover all the .library files at runtime then the <library> tag could become optional as each library would declare it's 'name'. If we had this: <libary-specification name="contrib"/> then it would be possible to make: <libary name="contrib" specification-path="/org/apache/tapestry/contrib/Contrib.library"/> optional. [ ok i'm off on a tangent now. How does tapestry discover all the libraries? Steal an idea from HiveMind and do this for any "public" libraries: /META-INF/tapestry-library.properties (or xml or whatever). library=/org/apache/tapestry/contrib/Contrib.library or to borrow xml from Mike Henderson's Palette: <library id="groovestry" label="Groovestry" preferredNamespace="groovestry" specificationPath="/org/apache/tapestry/contrib/groovestry/Groovestry.library" downloadURL="http://www.mjhenderson.com/tapestry/components/groovestry/groovestry-0.7.jar" version="0.7"> If T5 grabs all the tapestry-library files the same way HM grabs all the /META_INF/hivemodule.xml files, it has "discovered" all the libraries in the app. ] We have put somewhat strict checks on namespace crossing but have not yet made it possible to refer to a page or component by a nice simple name. 1. Add the <page-alias>/<component-alias> tags I described in http://wiki.apache.org/jakarta-tapestry/Tapestry5LookupDebate. These would be replacements for <page> and <component-type> which were only used to find xml anyways. 2. Do the same thing Tapestry does now with the "lookup" rules. It would be much simpler as we are not looking for xml specs any more ( we'd still use org.apache.tapestry.page-class-packages and all that guff). Ok, this message is already wayyyy to long. But I did mention that I saw a case for keeping a (modified) version of the page/component xml files. There is only one case: keeping cruft out of the templates. On the project I'm working on now we have an amazing HTML/CSS developer and we try as hard as possible to make her life easier by not using the @ syntax for components in our templates. This: <component id="tree" type="AjaxTree"> <binding name="ajaxListener" expression="listeners.ajaxRequestStart"/> <binding name="ajaxParameters" expression="ajaxPageState"/> <binding name="cssclass" expression="currentCSS"/> <binding name="label" expression="currentLabel"/> <binding name="labelProvider" expression="beans.datasource.labelProvider"/> <binding name="selection" expression="selectedTreeNodes"/> <binding name="labelSelection" expression="labelSelection"/> <binding name="treeManager" expression="beans.datasource.treeManager"/> <binding name="treeProvider" expression="beans.datasource.treeContentProvider"/> <binding name="showingCheckboxes" expression="true"/> <binding name="labelsSelectable" expression="contentType == @...long class name [EMAIL PROTECTED]"/> </component> Is much better for her than the template alternative. I say keep the xml, but collapse it so that only <component> and <meta> tags are allowed. Simplify the "rules" for finding these new xml files. Find the class *first* and if it's in a library the xml must be in the same package. If it's in the app namespace it must either be in the same package as the class or at a point relative to the app xml location. Just two rules! If you made it this far, thanks for your patience. Geoff -- The Spindle guy. http://spindle.sf.net Get help with Spindle: http://lists.sourceforge.net/mailman/listinfo/spindle-user Blog: http://jroller.com/page/glongman Feature Updates: http://spindle.sf.net/updates --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
