A few quick thoughts inline to get the discussion rolling...
On May 15, 2005, at 11:31 AM, Mind Bridge wrote:
PAGE PARAMETERS
At the moment, pages cannot have parameters. In reality, however, pages do
have parameters even now.
Here is a frequent example. (for clarity, let's call the current page UserPage and let the code below be an excerpt of UserPage.java)
One very typical occurrence in Tapestry applications is code like this (usually in the listeners):
ShowAddress page = (ShowAddress) getPage("ShowAddress"); page.setUser(user); page.setEmail(email); cycle.activate(page);
Note that User and Email are essentially parameters of ShowAddress. They
could be declared in the ShowAddress.page file as parameters of that page
(this was not allowed until now):
<parameter name="user"/> <parameter name="email"/>
The above code is essentially a transition from UserPage to ShowAddress upon
a particular activity. That could be declared in UserPage like this:
<transition name="address" page="ShowAddress"> <binding name="user" expression="user.name"/> <binding name="email" expression="user.email"/> </transition>
That transition could then be invoked in a way similar to this:
<a jwcid="@DirectLink" listener="transition: address">...</a>
Nevertheless, I find the following approach more flexible and thus
preferable, even though it involves a new parameter to the link components:
<a jwcid="@DirectLink" listener="someListener" transition="address">...</a>
Here both 'listener' and 'transition' are optional. If both are defined,
then the listener is invoked before the specified transition is performed,
otherwise only one of them is called.
Page flow is an area where Tapestry has remained agnostic thus far, so this is breaking new ground for sure.
I'm having trouble coming up with an elaborate rationale for why I don't like the transition attribute, it just doesn't feel right to me. I'm trying to push the idea that the link components in Tapestry are already too numerous and confusing, and this adds another layer to the complexity. Would your transitions support client-side redirects? If so, how?
If listener methods had before/after hooks built-in, then page flow could be "aspected" in as an _after_ hook and various strategies could be employed, with my favorite being a client-side redirect. Your transition feature could be incorporated in this manner somehow, I'd think.
The page parameters will come from the outside however, specifically from
the request to the server. That means that such an exception can no longer
be labeled simply as a 'bug', but could be a malicious or accidental
tampering instead. This is particularly true of required parameters - they
may simply be omitted. As a result, it is necessary to think whether a page
can have required parameters.
In your example, the page parameters aren't quite coming from the request, but rather from the rewind after the initial page has had a chance to set those properties. Right?
It is an interesting point to consider parameters for pages, and something I feel is important. I'd like to be able to very cleanly map pieces of the URL to parameters (or properties, whatever we call them) of the page. Consider a blog-style URLs:
/2005/05/12
/category/entry_name
/2005/05
or del.icio.us-style (which is similar to the system I'm building now):
/UserName
/UserName/tag-expression
Consider the competition, Ruby on Rails routing:
<http://manuals.rubyonrails.com/read/chapter/65#page164>
I see this as related to your idea of pages with parameters. I'd love to be able to declaratively say that /UserName/tag-expression can go to the Display page with the "username" and "tagExpression" properties already set and usable. I could (and have in a limited sense) done this very thing with servlet filters, and this may be the right way to do what I'm after more generally yet this does so without access to Tapestry internals so I'm not really creating a page and setting properties, but rather fabricating a URL that is ExternalLink style with a request wrapper.
DIRECT LINK WITH PROPERTIES
Currently, DirectLink passes its parameters via an array and
getServiceParameters() needs to be invoked to the get them in the listener
(some improvements have been made in 4.0, but the principle is the same).
While there is a clear need for this approach, I would suggest DirectLink to
be able to store some parameters in the component's properties as well. No
listener should be required.
I'm not following why listener should be optional in the DirectLink case. In that case, it's simply a PageLink that sets parameters. In other words, I'm suggesting that the link components converge rather than getting more diverse.
Also, I do not think having a fixed list of informal parameters such as
onKeyPress to separate them from the parameters is a good idea for a number
of reasons.
It's a finite set of attributes. Why shouldn't Tapestry be smart about the output format?
Instead, in the interest of world peace and backward compatibility, I think namespaces should be used here.
I agree in general except in details....
For example, if UserPage was to provide the selection of a user out of a
list, the above example could be implemented like this:
<span jwcid="[EMAIL PROTECTED]" source="users">
<a jwcid="@DirectLink" property:user="components.for.value" transition="
ShowAddress"> . </a>
</span>
you probably meant transition="address" there, given the below snippet.
Re: namespaces - it should be a Tapestry namespace, in the formal XML sense, not just a conventional prefix like "property:user". What about "tap:user"?
To put the example in words, DirectLink will squeeze the currently iterated
user into the link it generates. If the link is invoked, it will set the
'user' property of the page and will then invoke the transition to the
ShowAddress page.
Again, I'd prefer the flow of where the page goes after a listener is invoked be decoupled from the link itself. The flow "aspect" can (and in your examples, should) be connected though.
As you can see, this is simple and no Java code is required. The 'transition
' here is just an example, this method for setting parameters could be used
in a number of different ways as well.
By a mapping from the hyperlink! :)
A similar property-setting scheme could be applied to ExternalLink, etc.
Let's coalesce the link components, not diverge them. Please!
CALL TRANSITIONS
Very often it is necessary for the user to perform an action, such as to
select an item from a list. This same action may be invoked from a number of
different places in the application, however, and the control has to return
to the place where it originally came from. In the programming world there
is a simple mechanism to achieve this - functions. In the web world,
however, there is no good way to that without custom code.
Let's use the name "call transitions" to denote a special type of
transitions that allow you to invoke a particular page and then return back
from it with results. Here is an example: suppose that you have a web store
application. On a number of different places in the application you would
want the user to select a product so that you can do something with it (view
its details, purchase it, etc).
Here is some simple code in pages like Basket that could achieve that:
<a jwcid="@DirectLink" transition="select">Add a product to basket</a>
<!-SelectProduct will return the selection in the 'product' property and the
handleSelectedProduct listener will be called when that happens -->
<call-transition name="select" page="SelectProduct" listener=" handleSelectedProduct">
<binding name="product" expression="product"/>
</transition>
In SelectProduct.page define:
<parameter name="product"/>
And when a product is selected in SelectProduct and you can get back to the
caller, simply invoke the predefined transition "return" to get back to the
page that called us in the first place, e.g.:
in SelectProduct.html:
<span jwcid="[EMAIL PROTECTED]" source="products">
<a jwcid="@DirectLink" property:product="components.for.value" transition="
return"> . </a>
</span>
SelectProduct could then be invoked whenever a particular part of the
application needs the user to select a product and the framework will return
to the invoker with the result.
This seems like something that could be done with clever use of ICallback. I like the idea, but again for some reason the transition specifics don't hit home with me.
STACK
A stack of ICallback's??
- The stack needs to be kept in some form both in the request (URL) and in
the session (if any) to avoid funny effects when Back is used. At the moment
only persistent properties may be placed in URL, but I would like us to have
a mechanism that allows a service to be injected and place relevant
information on the URL. The stack is one such service.
- pages on the stack may be forcibly "pop-ed out" (usually upon Back button
use). They may have a listener to be notified when that happens so that they
can clean up if they want to.
The back button doesn't bother me much, as I opt for client-side redirects for actions that POST'ed or for URL's that could be damaging if reloaded. Idempotent GET's!
UNITS
Units of pages have been mentioned before, specifically in the work of Geoff. He has put a very nice PPT of his work here:
http://spindle.sourceforge.net/OrcaWorkUnits.ppt
Interesting! I don't quite get it yet, so will let it get some background thinking before I have anything to say on this topic.
Note that the concept of units may also be used to determine the lifetime of
properties persisted in the URL as well.
This seems to relate to what Howard and Drew "OGNL" Davidson have discussed about the lifetime and scope of persistent properties and how Tapestry differs from WebObjects with WO having a nice feature to allow persistent properties to only be within the scope of a certain page flow path. I'd like to hear how Howard and/or Drew have contemplated the implementation of this.
And here are a few other topics related to the ones above that we need to
consider: transitions as parameters and integration with global transition
frameworks such as Web Flow. But let's see whether the above makes sense
first...
Your concepts make sense, but your examples seem to complicate things rather than making it simpler. Links are already a mess to work with for me, and surely for newbies even more so. I want cleaner/simpler ways to link to pages, hand them parameters, and be able to do so from the URL or from a listener code, or in an "aspect".
Erik
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
