Hi guys,


Normally I would send separate emails for these things, but they are so
interconnected to each other that I think it is best if they come in one
package. Sorry for the lenght...



Please indicate what you think about them. If there are no overly negative
comments or modification suggestions, I will start adding them soon.





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.




It was logical to some extent for pages not to have parameters earlier.
Contrast pages with components: the parameters for components were in the
application code and if, for example, a required parameter is not passed,
that is a clear bug that comes within the application. Its fix can be relied
upon in the future.



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.



On the other hand, it seems to me that it is easy to invoke an exception in
the application anyway by simply generating a URL that does not provide a
parameter in the proper squeezing format. Thus, I do not see a reason for
required parameters to be removed here. Perhaps an easy page-specific
exception handler may be helpful, although the general exception handler
could be overridden to do a good job as well.





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.



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. Instead, in the interest of world peace and backward
compatibility, I think namespaces should be used here.



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>



<transition name="address" page="ShowAddress">
    <binding name="user" expression="user.name"/>
    <binding name="email" expression="user.email"/>
</transition>



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.



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.



A similar property-setting scheme could be applied to ExternalLink, etc.





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.





Note that since Tapestry parameters are read/write, the return values, such
as 'product', are also defined as parameters of the page - there is no need
for a different specification type.





STACK



In order for call transitions to work, it is necessary for the framework to
keep a stack in order to determine where to return from a call. The
explanation of how everything would work so that it is Back-button resistant
turned out to be rather long, so I am cutting that part out - may post
another message about it if there is interest. Here are the important points
however:



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





Some other things that are a bit further in the pipeline:





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



What I think is necessary is something very similar, at the very least
because it allows pages to be combined in units and the unit to be treated
as a "black box". This is particularly important with transitions and call
transitions.



Here is another reason why: Pages are typically placed in a wrap that has
links to pages like Home or ContactUs or some other such generic parts of
the site. If the user goes to those pages, it is as if he starts his
experience anew and the stack should not be dragged across as well.



Units allow us to determine the group of pages related to a particular
action. If the control leaves that group, then a 'return' will simply not
happen and the stack can be discarded as a result (at least on the client
side).



Pages are units of one by default - no definition is needed there. Units
need only to be defined if multiple pages take part in a particular action.



Note that the concept of units may also be used to determine the lifetime of
properties persisted in the URL as well.







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



Best regards,

-mb





---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to