It's saturday and I'm working on the tutorial. So your appreciation is
appreciated.

The main thing holding Tapestry 3 and 4 back a couple of years ago,
when they were clearly superior technologically, was documentation.
The reference documentation is a bit of a brain dump, but will be good
for those in-depth questions.  The tutorial is very important for
people getting started.

It's important to hook people in their first hour using Tapestry.

On 2/24/07, Mike D Pilsbury <[EMAIL PROTECTED]> wrote:
Of course. It should have been obvious.

Thanks again for the great T5 docs. They're much appreciated.


Howard Lewis Ship wrote:
> If there's a form or a link on the page, back to the same page, the
> context will be maintained.
>
> On 2/23/07, Mike D Pilsbury <[EMAIL PROTECTED]> wrote:
>> Very nice explanation.
>>
>> One small question. In the last scenario (Render Requests Only), why is
>> the passivation method required?
>>
>>
>> [EMAIL PROTECTED] wrote:
>> > Author: hlship
>> > Date: Thu Feb 22 16:19:45 2007
>> > New Revision: 510729
>> >
>> > URL: http://svn.apache.org/viewvc?view=rev&rev=510729
>> > Log:
>> > Add some detailed documentation concerning page navigation,
>> including component request context and page activation context.
>> >
>> > Added:
>> >
>> tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/pagenav.apt
>> > Modified:
>> >     tapestry/tapestry5/tapestry-core/trunk/src/site/apt/index.apt
>> >     tapestry/tapestry5/tapestry-core/trunk/src/site/site.xml
>> >
>> > Added:
>> tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/pagenav.apt
>> > URL:
>> 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/pagenav.apt?view=auto&rev=510729
>>
>> >
>> 
==============================================================================
>>
>> > ---
>> tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/pagenav.apt
>> (added)
>> > +++
>> tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/pagenav.apt
>> Thu Feb 22 16:19:45 2007
>> > @@ -0,0 +1,293 @@
>> > + ----
>> > + Page Navigation
>> > + ----
>> > +
>> > +Page Navigation
>> > +
>> > +  In essense, a Tapestry application is a number of related pages,
>> working together.  To some degree, each page is like an application
>> unto itself.
>> > +
>> > +  Any individual request will be targetted at a single page.
>> Requests come in two forms:
>> > +
>> > +  * <action> requests target a specific component on a specific
>> page, triggering an event within that component
>> > +
>> > +  * <render> requests target a specific page, and stream the HTML
>> markup for that page back to the client
>> > +
>> > +  []
>> > +
>> > +  This dictomy between action requests
>> > +  and render requests is new in Tapestry 5. It is in some ways
>> based on ideas from the Portlet specification and differentiating
>> > +  the two types of requests alleviates a number of problems in
>> traditional web applications related to the browser back button, or
>> to the user hitting the
>> > +  refresh button in their browser.
>> > +
>> > +Action Requests
>> > +
>> > +  Action requests may take the form of hyperlinks
>> > +
>> 
({{{../component-parameters.html#org.apache.tapestry.corelib.components.actionlink}ActionLink}})
>> or form submissions
>> > +
>> 
({{{../component-parameters.html#org.apache.tapestry.corelib.components.form}Form}}).
>>
>> > +
>> > +  In both cases, the value returned from an {{{event.html}event
>> handler method}} controls the response sent to the client web browser.
>> > +
>> > +  The URL for an action request identifies the name of the page,
>> the nested id of the component, and the name of the event to trigger
>> on the component (this is usually "action").
>> > +  Further, an action request may contain additional context
>> information, which will be provided to the event handler method.
>> > +
>> > +  These URLs expose a bit of the internal structure of the
>> application.  Over time, as an application grows and is maintained,
>> the ids of components may change. This means that
>> > +  action request URLs should not be bookmarked.  Fortunately,
>> users will rarely have the chance to do so (see below).
>> > +
>> > +* Null response
>> > +
>> > +  If the event handler method returns no value, or returns null,
>> then the current page (the page containing the component) will render
>> the response.
>> > +
>> > +  A page render link for the current page is created and sent to
>> the client as a client side redirect.  The client browser will
>> automatically submit a new request
>> > +  to generate the page.
>> > +
>> > +  The user will see the newly generated content in their browser.
>> In addition, the URL in the browser's address bar will be a render
>> request URL.  Render request URLs are
>> > +  shorter and contain less application structure (for instance,
>> they don't include component ids or event types).  Render requests
>> URLs are what your users will bookmark. The action request URLs
>> > +  are transitory, meaningful only while the application is
>> actively engaged, and not meant to be used in later sessions.
>> > +
>> > +* String response
>> > +
>> > +  When a string is returned, it is expected to be the logical name
>> of a page (as opposed to the page's
>> > +  fully qualified class name).  As elsewhere, the name of the page
>> is case insensitive.
>> > +
>> > +  Again, a render request URL will be constructed and sent to the
>> client as a redirect.
>> > +
>> > +* Page response
>> > +
>> > +  You may also return an instance of a page, rather than the name
>> of a page.
>> > +
>> > +  A page may be injected via the
>> {{{../apidocs/org/apache/tapestry/annotations/InjectPage.html}InjectPage}}
>> annotation.
>> > +
>> > +  Often, you will configure the page in some way before returning
>> the page (examples below).
>> > +
>> > +  You can also return a component within the page, but this will
>> generate a runtime warning.
>> > +
>> > +* Link response
>> > +
>> > +  An event handler method may return a
>> > +  {{{../apidocs/org/apache/tapestry/Link.html}Link}} instance
>> directly.  The Link is converted into a URL and a client redirect to
>> that URL is sent to the client.
>> > +
>> > +  The
>> 
{{{../apidocs/org/apache/tapestry/ComponentResources.html}ComponentResources}}
>> object that is injected into your pages (and components) has methods
>> > +  for creating action and page links (they are actually defined in
>> > +
>> 
{{{../apidocs/org/apache/tapestry/ComponentResourcesCommon.html}ComponentResourcesCommon}}).
>>
>> > +
>> > +* Stream response
>> > +
>> > +  An event handler can also return a
>> {{{../apidocs/org/apache/tapestry/StreamResponse.html}StreamResponse}}
>> object, which encapsulates a stream to
>> > +  be sent directly to the client browser.  This is useful for
>> compnents that want to, say, generate an image or PDF and provide it
>> to the client.
>> > +
>> > +* Object response
>> > +
>> > +  Any other type of object returned from an event handler method
>> is an error.
>> > +
>> > +Page Render Requests
>> > +
>> > +  Render requests are simpler in structure and behavior than
>> action requests. In the simplest case, the URL is simply the
>> > +  logical name of the page.
>> > +
>> > +  Pages may have an <activation context>.  The activation context
>> represents persistent information about the state of the page.  In
>> practical terms,
>> > +  the activation context is usually the id of some
>> database-persistent object.
>> > +
>> > +  When a page has an activation context, the values of the context
>> are appended to the URL path.
>> > +
>> > +  Not all pages have an activation context.
>> > +
>> > +  The activation context may be explicitly set when the render
>> request link is created (the PageLink component has a context
>> parameter for this purpose).
>> > +  When no explicit activation context is provided, the page itself
>> is queried for its activation context.
>> > +
>> > +  This querying takes the form of an event trigger. The event name
>> is "passivate" (as we'll see shortly, there's a corresponding
>> "activate").  The
>> > +  return value of the method is used as the context.  For example:
>> > +
>> > ++---+
>> > +public class ProductDetail
>> > +{
>> > +  private Product _product;
>> > +
>> > +  . . .
>> > +
>> > +  long onPassivate() { return _product.getId(); }
>> > +}
>> > ++----+
>> > +
>> > +  The activation context may consist of a series of values, in
>> which case the return value of the method should be an array or a List.
>> > +
>> > +* Page activation
>> > +
>> > +  When a page render request arrives, the page is activated before
>> it is rendered.
>> > +
>> > +  Activation serves two purposes:
>> > +
>> > +  * It allows the page to restore its internal state from data
>> encoded into the URL (the activation context discussed above).
>> > +
>> > +  * It provides coarse approach to validating access to the page.
>> > +
>> > +  []
>> > +
>> > +  The later case, validation, is generally concerned with user
>> identity and access; if you have pages that may only be accessed by
>> certain users,
>> > +  you may use the page's activate event handler responsible for
>> verifying that access.
>> > +
>> > +  A page's activate event handler mirrors its passivate handler:
>> > +
>> > ++----+
>> > +  . . .
>> > +
>> > +  void onActivate(long productId)
>> > +  {
>> > +     _product = _productDAO.getById(productId);
>> > +  }
>> > +
>> > +  . . .
>> > ++-----+
>> > +
>> > +  Here's the relevant part: when the page renders, it is likely to
>> include more action request URLs (links and forms). The action requests
>> > +  for those links and forms will <also> start by activating the
>> page, before performing other work. This forms an unbroken chain of
>> requests
>> > +  that include the same activation context.
>> > +
>> > +  To some degree, this same effect could be accomplished using a
>> {{{persist.html}persistent page value}}, but that requires an active
>> session,
>> > +  and the result is not bookmarkable.
>> > +
>> > +  The activate event handler may also return a value, which is
>> treated identically to a return value of an action request event
>> trigger.  This will typically
>> > +  be used in an access validation scenario.
>> > +
>> > +Page Navigation Patterns
>> > +
>> > +  This combination of action links and context and page context
>> can be put together in any number of ways.
>> > +
>> > +  Let's take a typical master/detail relationship using the
>> concept of a product catalog page.  In this example, the
>> > +  ProductListing page is a list of products, and the
>> ProductDetails page must display the details for a specific product.
>> > +
>> > +* Action Requests / Persistent Data
>> > +
>> > +  In this pattern, the ProductListing page uses action events and
>> a persistent field on the ProductDetails page.
>> > +
>> > +  ProductListing.html:
>> > +
>> > ++---+
>> > +  <t:comp id="loop" source="products" value="product">
>> > +    <a t:type="actionlink" t:id="select"
>> context="product.id">${product.name}</a>
>> > +  </t:comp>
>> > ++---+
>> > +
>> > +  ProductListing.java:
>> > +
>> > ++---+
>> > +  @InjectPage
>> > +  private ProductDetails _details;
>> > +
>> > +  Object onActionFromSelect(long productId)
>> > +  {
>> > +    _details.setProductId(productId);
>> > +
>> > +    return _details;
>> > +  }
>> > ++---+
>> > +
>> > +  ProductDetails.java:
>> > +
>> > ++----+
>> > +  @Inject
>> > +  private ProductDAO _dao;
>> > +
>> > +  private Product _product;
>> > +
>> > +  @Persist
>> > +  private long _productId;
>> > +
>> > +  public void setProductId(long productId) { _productId =
>> productId; }
>> > +
>> > +  void onActivate()
>> > +  {
>> > +    _product = _dao.getById(_productId);
>> > +  }
>> > ++----+
>> > +
>> > +  This is a minimal approach, perhaps good enough for a prototype.
>> > +
>> > +  When the user clicks a link, the action request URL will
>> initially be something like
>> "http://.../productlisting/select.action/99"; and the final
>> > +  render request URL will be something like
>> "http://.../productdetails";.  Notice that the product id ("99") does
>> not appear in the render request URL.
>> > +
>> > +  It has some minor flaws:
>> > +
>> > +  * It requires a session (to store the _productId field between
>> requests).
>> > +
>> > +  * It may fail if the ProductDetails page is accessed before a
>> valid product id is set.
>> > +
>> > +  * The URL does not indicate the identity of the product; if the
>> user bookmarks the URL and comes back later, they will trigger the
>> previous case (no valid product id).
>> > +
>> > +* Action Requests / Persistent Data
>> > +
>> > +  We can improve the previous example without changing the
>> ProductListing page,  using a passivation and activation context
>> > +  to avoid the session and make the links more bookmarkable.
>> > +
>> > +  ProductDetails.java:
>> > +
>> > ++----+
>> > +  @Inject
>> > +  private ProductDAO _dao;
>> > +
>> > +  private Product _product;
>> > +
>> > +  private long _productId;
>> > +
>> > +  public void setProductId(long productId) { _productId =
>> productId; }
>> > +
>> > +  void onActivate(long productId)
>> > +  {
>> > +    _productId = productId;
>> > +
>> > +    _product = _dao.getById(_productId);
>> > +  }
>> > +
>> > +  long onPassivate() { return _productId; }
>> > ++----+
>> > +
>> > +  This change ensures that the render request URL will include the
>> product id, i.e., "http://.../productdetails/99";.
>> > +
>> > +  It has the advantage that the connection from page to page
>> occurs in typesafe Java code, inside the onActionFromSelect method of
>> ProductListing.
>> > +  It has the disadvantage that clicking a link requires two round
>> trips to the server.
>> > +
>> > +* Render Requests Only
>> > +
>> > +  This is the most common version of this master/detail relationship.
>> > +
>> > +  ProductListing.html:
>> > +
>> > ++---+
>> > +  <t:comp id="loop" source="products" value="product">
>> > +    <a t:type="pagelink" page="productdetails"
>> context="product.id">${product.name}</a>
>> > +  </t:comp>
>> > ++---+
>> > +
>> > +  ProductListing.java:
>> > +
>> > +  No code is needed to support the link.
>> > +
>> > +  ProductDetails.java:
>> > +
>> > ++----+
>> > +  @Inject
>> > +  private ProductDAO _dao;
>> > +
>> > +  private Product _product;
>> > +
>> > +  private long _productId;
>> > +
>> > +  void onActivate(long productId)
>> > +  {
>> > +    _productId = productId;
>> > +
>> > +    _product = _dao.getById(_productId);
>> > +  }
>> > +
>> > +  long onPassivate() { return _productId; }
>> > ++----+
>> > +
>> > +  The setProductId() method is no longer needed.
>> > +
>> > +* Limitations
>> > +
>> > +  As your application's workflow expands, you may find that there
>> is not a reasonable way to avoid storing some data persistently
>> between requests, outside
>> > +  of the page activation context.  For example, if from the
>> ProductDetails page, the user is allowed to navigate to related pages
>> and then back to ProductDetails, it
>> > +  starts to become necessary to keep passing that product id
>> around from page to page to page.
>> > +
>> > +  At some point, persistent values make more sense.  In the near
>> future, there will be a client-side persistence strategy that will
>> encode persistent data, such as
>> > +  the product id field, into query parameters (and hidden form
>> fields) automatically.
>> > \ No newline at end of file
>> >
>> > Modified:
>> tapestry/tapestry5/tapestry-core/trunk/src/site/apt/index.apt
>> > URL:
>> 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/index.apt?view=diff&rev=510729&r1=510728&r2=510729
>>
>> >
>> 
==============================================================================
>>
>> > --- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/index.apt
>> (original)
>> > +++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/index.apt
>> Thu Feb 22 16:19:45 2007
>> > @@ -80,6 +80,8 @@
>> >
>> >    * Component parameters may have default values.
>> >
>> > +  * The @ComponentClass anntotation, seen in the earlier
>> {{{../screencast.html}screencasts}} has been removed.
>> > +
>> >  Adaptive API
>> >
>> >    A key feature of Tapestry 5 is <adaptive API>.
>> >
>> > Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/site.xml
>> > URL:
>> 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/site.xml?view=diff&rev=510729&r1=510728&r2=510729
>>
>> >
>> 
==============================================================================
>>
>> > --- tapestry/tapestry5/tapestry-core/trunk/src/site/site.xml
>> (original)
>> > +++ tapestry/tapestry5/tapestry-core/trunk/src/site/site.xml Thu
>> Feb 22 16:19:45 2007
>> > @@ -61,6 +61,7 @@
>> >              <item name="Component Classes"
>> href="guide/component-classes.html"/>
>> >              <item name="Component Templates"
>> href="guide/templates.html"/>
>> >              <item name="Component Parameters"
>> href="guide/parameters.html"/>
>> > +            <item name="Page Navigation" href="guide/pagenav.html"/>
>> >              <item name="Input Validation"
>> href="guide/validation.html"/>
>> >              <item name="Component Events" href="guide/event.html"/>
>> >              <item name="Page Lifecycle" href="guide/lifecycle.html"/>
>> >
>> >
>> >
>>
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: [EMAIL PROTECTED]
>> For additional commands, e-mail: [EMAIL PROTECTED]
>>
>>
>
>



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




--
Howard M. Lewis Ship
TWD Consulting, Inc.
Independent J2EE / Open-Source Java Consultant
Creator and PMC Chair, Apache Tapestry
Creator, Apache HiveMind

Professional Tapestry training, mentoring, support
and project work.  http://howardlewisship.com

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

Reply via email to