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]

Reply via email to