Author: buildbot
Date: Wed Jan 6 03:20:38 2016
New Revision: 977130
Log:
Production update by buildbot for tapestry
Modified:
websites/production/tapestry/content/cache/main.pageCache
websites/production/tapestry/content/exploring-the-project.html
Modified: websites/production/tapestry/content/cache/main.pageCache
==============================================================================
Binary files - no diff available.
Modified: websites/production/tapestry/content/exploring-the-project.html
==============================================================================
--- websites/production/tapestry/content/exploring-the-project.html (original)
+++ websites/production/tapestry/content/exploring-the-project.html Wed Jan 6
03:20:38 2016
@@ -112,107 +112,126 @@ of where to look for pages, components a
</div></div><p>This is short and sweet: you can see that the package name you
provided earlier shows up as the <code>tapestry.app-package</code> context
parameter; the TapestryFilter instance will use this information to locate the
Java classes for pages and components.</p><p>Tapestry operates as a <em>servlet
filter</em> rather than as a traditional <em>servlet</em>. In this way,
Tapestry has a chance to intercept all incoming requests, to determine which
ones apply to Tapestry pages (or other resources). The net effect is that you
don't have to maintain any additional configuration for Tapestry to operate,
regardless of how many pages or components you add to your
application.</p><p>Much of the rest of web.xml is configuration to match
Tapestry execution modes against module classes. An execution mode defines how
the application is being run: the default execution mode is "production", but
the web.xml defines two additional modes: "development" and "qa" (for "Quality
Assurance").
The module classes indicated will be loaded for those execution modes, and can
change the configuration of the application is various ways. We'll come back to
execution modes and module classes later in the tutorial.</p><p>Tapestry pages
minimally consist of an ordinary Java class plus a component template
file.</p><p>In the root of your web application, a page named "Index" will be
used for any request that specifies no additional path after the context
name.</p><h1 id="ExploringtheProject-IndexJavaClass">Index Java
Class</h1><p>Tapestry has very specific rules for where page classes go.
Tapestry adds a sub-package, "pages", to the root application package
("com.example.tutorial1"); the Java classes for pages goes there. Thus the full
Java class name is
<code>com.example.</code>tutorial<code>1.pages.Index</code>.</p><div
class="code panel pdl" style="border-width: 1px;"><div class="codeHeader
panelHeader pdl" style="border-bottom-width:
1px;"><b>src/main/java/com/example/tutorial/p
ages/Index.java</b></div><div class="codeContent panelContent pdl">
<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;">package com.example.tutorial1.pages;
-import java.util.Date;
-import org.apache.tapestry5.annotations.*;
-import org.apache.tapestry5.ioc.annotations.*;
-import org.apache.tapestry5.corelib.components.*;
+import org.apache.tapestry5.Block;
+import org.apache.tapestry5.EventContext;
import org.apache.tapestry5.SymbolConstants;
-import org.apache.tapestry5.alerts.AlertManager;
+import org.apache.tapestry5.annotations.InjectPage;
+import org.apache.tapestry5.annotations.Log;
+import org.apache.tapestry5.annotations.Property;
+import org.apache.tapestry5.ioc.annotations.Inject;
+import org.apache.tapestry5.ioc.annotations.Symbol;
+import org.apache.tapestry5.services.HttpError;
+import org.apache.tapestry5.services.ajax.AjaxResponseRenderer;
+import org.slf4j.Logger;
+
+import java.util.Date;
/**
* Start page of application tutorial1.
*/
public class Index
{
+ @Inject
+ private Logger logger;
+
+ @Inject
+ private AjaxResponseRenderer ajaxResponseRenderer;
+
@Property
@Inject
@Symbol(SymbolConstants.TAPESTRY_VERSION)
private String tapestryVersion;
- @InjectComponent
- private Zone zone;
-
- @Persist
- @Property
- private int clickCount;
+ @InjectPage
+ private About about;
@Inject
- private AlertManager alertManager;
+ private Block block;
- public Date getCurrentTime()
+ // Handle call with an unwanted context
+ Object onActivate(EventContext eventContext)
{
- return new Date();
+ return eventContext.getCount() > 0 ? new HttpError(404, "Resource
not found") : null;
}
- void onActionFromIncrement()
+ Object onActionFromLearnMore()
{
- alertManager.info("Increment clicked");
+ about.setLearn("LearnMore");
- clickCount++;
+ return about;
}
- Object onActionFromIncrementAjax()
+ @Log
+ void onComplete()
{
- clickCount++;
+ logger.info("Complete call on Index page");
+ }
- alertManager.info("Increment (via Ajax) clicked");
+ @Log
+ void onAjax()
+ {
+ logger.info("Ajax call on Index page");
- return zone;
+ ajaxResponseRenderer.addRender("middlezone", block);
+ }
+
+ public Date getCurrentTime()
+ {
+ return new Date();
}
}
</pre>
-</div></div><p>There's a bit going on in this listing, as the Index page
attempts to demonstrate a bunch of different ideas in Tapestry. Even so, the
class is essentially pretty simple: Tapestry pages and components have no base
classes to extend, no interfaces to implement, and are just a very pure POJO
(Plain Old Java Object) ... with some special naming conventions and
annotations for fields and methods.</p><p>You do have to meet the Tapestry
framework partway:</p><ul><li>You need to put the Java class in the expected
package, here com.example.tutorial.pages</li><li>The class must be
public</li><li>You need to make sure there's a public, no-arguments constructor
(here, the Java compiler has silently provided one for us)</li><li>All
non-static fields must be <strong>private</strong></li></ul><p>As we saw when
running the application, the page displays the current date and time, as well
as a couple of extra links. The <code>currentTime</code> property is where that
value comes from
; shortly we'll see how that value is referenced in the template, so it can be
extracted from the page and output.</p><p>Tapestry always matches a page class
to a template; neither is functional without the other. In fact, components
within a page are treated the same way (except that components do not always
have templates).</p><p>You will often hear about the <a class="external-link"
href="http://en.wikipedia.org/wiki/Model_view_controller"
rel="nofollow">Model-View-Controller pattern</a> (MVC). In Tapestry, the page
class acts as both the Model (the source of data) and the controller (the logic
that responds to user interaction). The template is the View in MVC. As a
model, the page exposes JavaBeans properties that can be referenced in the
template.</p><p>Let's look at how the component template builds on the Java
class to provide the full user interface.</p><h1
id="ExploringtheProject-ComponentTemplate">Component Template</h1><p>Tapestry
pages are the combination of a POJO Jav
a class with a Tapestry component template. The template has the same name as
the Java class, but has the extension <code>.tml</code>. Since the Java class
here is com.example.tutorial.pages.Index, the template file will be located at
src/main/resource/com/example/tutorial/pages/Index.tml. Ultimately, both the
Java class and the component template file will be stored in the same folder
within the deployed WAR file.</p><p>Tapestry component templates are
well-formed XML documents. This means that you can use any available XML
editor. Templates may even have a DOCTYPE or an XML schema to validate the
structure of the template page.</p><p><em>Note that Tapestry parses component
templates using a non-validating parser; it only checks for well-formedness:
proper syntax, balanced elements, attribute values are quoted, and so forth. It
is reasonable for your build process to perform some kind of template
validation, but Tapestry accepts the template as-is, as long as it parses
cleanly.</em
></p><p>For the most part, a Tapestry component template looks like ordinary
>XHTML:</p><div class="code panel pdl" style="border-width: 1px;"><div
>class="codeHeader panelHeader pdl" style="border-bottom-width:
>1px;"><b>src/main/resources/com/example/tutorial/pages/Index.tml</b></div><div
> class="codeContent panelContent pdl">
+</div></div><p>There's a bit going on in this listing, as the Index page
attempts to demonstrate a bunch of different ideas in Tapestry. Even so, the
class is essentially pretty simple: Tapestry pages and components have no base
classes to extend, no interfaces to implement, and are just a very pure POJO
(Plain Old Java Object) ... with some special naming conventions and
annotations for fields and methods.</p><p>You do have to meet the Tapestry
framework partway:</p><ul><li>You need to put the Java class in the expected
package, here com.example.tutorial1.pages</li><li>The class must be
public</li><li>You need to make sure there's a public, no-arguments constructor
(here, the Java compiler has silently provided one for us)</li><li>All
non-static fields must be <strong>private</strong></li></ul><p>As we saw when
running the application, the page displays the current date and time, as well
as a couple of extra links. The <code>currentTime</code> property is where that
value comes fro
m; shortly we'll see how that value is referenced in the template, so it can
be extracted from the page and output.</p><p>Tapestry always matches a page
class to a template; neither is functional without the other. In fact,
components within a page are treated the same way (except that components do
not always have templates).</p><p>You will often hear about the <a
class="external-link" href="http://en.wikipedia.org/wiki/Model_view_controller"
rel="nofollow">Model-View-Controller pattern</a> (MVC). In Tapestry, the page
class acts as both the Model (the source of data) and the controller (the logic
that responds to user interaction). The template is the View in MVC. As a
model, the page exposes JavaBeans properties that can be referenced in the
template.</p><p>Let's look at how the component template builds on the Java
class to provide the full user interface.</p><h1
id="ExploringtheProject-ComponentTemplate">Component Template</h1><p>Tapestry
pages are the combination of a POJO Ja
va class with a Tapestry component template. The template has the same name as
the Java class, but has the extension <code>.tml</code>. Since the Java class
here is com.example.tutorial.pages.Index, the template file will be located at
src/main/resource/com/example/tutorial/pages/Index.tml. Ultimately, both the
Java class and the component template file will be stored in the same folder
within the deployed WAR file.</p><p>Tapestry component templates are
well-formed XML documents. This means that you can use any available XML
editor. Templates may even have a DOCTYPE or an XML schema to validate the
structure of the template page.</p><p><em>Note that Tapestry parses component
templates using a non-validating parser; it only checks for well-formedness:
proper syntax, balanced elements, attribute values are quoted, and so forth. It
is reasonable for your build process to perform some kind of template
validation, but Tapestry accepts the template as-is, as long as it parses
cleanly.</e
m></p><p>For the most part, a Tapestry component template looks like ordinary
XHTML:</p><div class="code panel pdl" style="border-width: 1px;"><div
class="codeHeader panelHeader pdl" style="border-bottom-width:
1px;"><b>src/main/resources/com/example/tutorial1/pages/Index.tml</b></div><div
class="codeContent panelContent pdl">
<pre class="brush: xml; gutter: false; theme: Default"
style="font-size:12px;"><html t:type="layout" title="tutorial1 Index"
- t:sidebarTitle="Framework Version"
- xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd"
+ xmlns:t="http://tapestry.apache.org/schema/tapestry_5_4.xsd"
xmlns:p="tapestry:parameter">
- <!-- Most of the page content, including <head>,
<body>, etc. tags, comes from Layout.tml -->
-
- <p>${message:greeting}</p>
-
- <p>The current time is:
<strong>${currentTime}</strong></p>
- <!-- A Zone is a component that can be updated in place, triggered by
other components. -->
- <t:zone t:id="zone">
+ <div class="hero-unit">
<p>
- You have clicked the link
<strong>${clickCount}</strong> times.
+ <img src="${asset:context:images/tapestry.png}"
+ alt="${message:greeting}" title="${message:greeting}"/>
</p>
-
+ <h3>${message:greeting}</h3>
+ <p>The current time is:
<strong>${currentTime}</strong></p>
<p>
- [
- <t:actionlink t:id="increment">increment</t:actionlink>
- ]
- &nbsp;
- [
- <t:actionlink t:id="incrementAjax" zone="^">increment (via
Ajax)</t:actionlink>
- ]
+ This is a template for a simple marketing or informational
website. It includes a large callout called
+ the hero unit and three supporting pieces of content. Use it as a
starting point to create something
+ more unique.
</p>
+ <p><t:actionlink t:id="learnmore" class="btn btn-primary
btn-large">Learn more &raquo;</t:actionlink></p>
+ </div>
- </t:zone>
-
- <p:sidebar>
- <p>
- You are running Tapestry version
<strong>${tapestryVersion}</strong>.
- </p>
-
-
- <p>
- [
- <t:pagelink page="Index">refresh page</t:pagelink>
- ]
- </p>
- </p:sidebar>
-
-</html>
-</pre>
-</div></div><div class="confluence-information-macro
confluence-information-macro-tip"><span class="aui-icon aui-icon-small
aui-iconfont-approve confluence-information-macro-icon"></span><div
class="confluence-information-macro-body"><p>You do have to name your component
template file, Index.tml, with the <strong>exact same case</strong> as the
component class name, Index. If you get the case wrong, it may work on some
operating systems (such as Mac OS X, Windows) and not on others (Linux, and
most others). This can be really vexing, as it is common to develop on Windows
and deploy on Linux or Solaris, so be careful about case in this one
area.</p></div></div><p>The goal in Tapestry is for component templates, such
as Index.tml, to look as much as possible like ordinary, static HTML files. (By
static, we mean unchanging, as opposed to a dynamically generated Tapestry
page.)</p><p>In fact, the expectation is that in many cases, the templates will
start as static HTML files, created b
y a web developer, and then be <em>instrumented</em> to act as live Tapestry
pages.</p><p>Tapestry hides non-standard elements and attributes inside XML
namespaces. By convention, the prefix "t:" is used for the primary namespace,
but that is not a requirement, any prefix you want to use is fine.</p><p>This
short template demonstrates quite a few features of Tapestry.</p><div
class="confluence-information-macro confluence-information-macro-warning"><span
class="aui-icon aui-icon-small aui-iconfont-error
confluence-information-macro-icon"></span><div
class="confluence-information-macro-body"><p>Part of the concept of the
quickstart archetype is to demonstrate a bunch of different features,
approaches, and common patterns used in Tapestry. So yes, we're hitting you
with a lot all at once.</p></div></div><p>First of all, there are two XML
namespaces defined:</p><div class="code panel pdl" style="border-width:
1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: xml; gutter: false; theme: Default"
style="font-size:12px;">
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd"
+ <div class="row">
+ <div class="span4">
+ <h2>Normal link</h2>
+ <p>Clink the bottom link and the page refresh with event
<code>complete</code></p>
+ <p><t:eventlink event="complete" class="btn
btn-default">Complete&raquo;</t:eventlink></p>
+ </div>
+ <t:zone t:id="middlezone" class="span4">
+
+ </t:zone>
+ <div class="span4">
+ <h2>Ajax link</h2>
+ <p>Click the bottom link to update just the middle column
with Ajax call with event <code>ajax</code></p>
+ <p><t:eventlink event="ajax" zone="middlezone" class="btn
btn-default">Ajax&raquo;</t:eventlink></p>
+ </div>
+ </div>
+
+ <t:block t:id="block">
+ <h2>Ajax updated</h2>
+ <p>I'v been updated through AJAX call</p>
+ <p>The current time is:
<strong>${currentTime}</strong></p>
+ </t:block>
+
+</html></pre>
+</div></div><div class="confluence-information-macro
confluence-information-macro-tip"><span class="aui-icon aui-icon-small
aui-iconfont-approve confluence-information-macro-icon"></span><div
class="confluence-information-macro-body"><p>You do have to name your component
template file, Index.tml, with the <strong>exact same case</strong> as the
component class name, Index. If you get the case wrong, it may work on some
operating systems (such as Mac OS X, Windows) and not on others (Linux, and
most others). This can be really vexing, as it is common to develop on Windows
and deploy on Linux or Solaris, so be careful about case in this one
area.</p></div></div><p>The goal in Tapestry is for component templates, such
as Index.tml, to look as much as possible like ordinary, static HTML files. (By
static, we mean unchanging, as opposed to a dynamically generated Tapestry
page.)</p><p>In fact, the expectation is that in many cases, the templates will
start as static HTML files, created b
y a web developer, and then be <em>instrumented</em> to act as live Tapestry
pages.</p><p>Tapestry hides non-standard elements and attributes inside XML
namespaces. By convention, the prefix "t:" is used for the primary namespace,
but that is not a requirement, any prefix you want to use is fine.</p><p>This
short template demonstrates quite a few features of Tapestry.</p><div
class="confluence-information-macro confluence-information-macro-warning"><span
class="aui-icon aui-icon-small aui-iconfont-error
confluence-information-macro-icon"></span><div
class="confluence-information-macro-body"><p>Part of the concept of the
quickstart archetype is to demonstrate a bunch of different features,
approaches, and common patterns used in Tapestry. So yes, we're hitting you
with a lot all at once.</p></div></div><p>First of all, there are two XML
namespaces commonly defined:</p><div class="code panel pdl"
style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: xml; gutter: false; theme: Default"
style="font-size:12px;">
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_4.xsd"
xmlns:p="tapestry:parameter"
</pre>
</div></div><p>The first namespace, "t:", it used to identify
Tapestry-specific elements and attributes. Although there is an XSD (that is, a
XML schema definition), it is incomplete (for reasons explained
shortly).</p><p>The second namespace, "p:", is a way of marking a chunk of the
template as a parameter passed into another component. We'll expand on that
shortly.</p><p>A Tapestry component template consists mostly of standard XHTML
that will pass down to the client web browser unchanged. The dynamic aspects of
the template are represented by <em>components</em> and
<em>expansions</em>.</p><h1
id="ExploringtheProject-ExpansionsinTemplates">Expansions in
Templates</h1><p>Let's start with expansions. Expansions are an easy way of
including some dynamic output when rendering the page. By default, an expansion
refers to a JavaBeans property of the page:</p><div class="code panel pdl"
style="border-width: 1px;"><div class="codeContent panelContent pdl">
<pre class="brush: xml; gutter: false; theme: Default"
style="font-size:12px;"> <p>The current time is: ${currentTime}</p>
</pre>
-</div></div><div class="confluence-information-macro
confluence-information-macro-tip"><span class="aui-icon aui-icon-small
aui-iconfont-approve confluence-information-macro-icon"></span><div
class="confluence-information-macro-body"><p>If you are coming to Tapestry 5
from Tapestry 4 or earlier, expansions are a concise replacement for the Insert
component.</p></div></div><p>The value inside the curly braces is a
<em>property expression</em>. Tapestry uses its own property expression
language that is expressive, fast, and type-safe.</p><div
class="confluence-information-macro confluence-information-macro-note"><span
class="aui-icon aui-icon-small aui-iconfont-warning
confluence-information-macro-icon"></span><div
class="confluence-information-macro-body"><pre>Tapestry does NOT use reflection
to implement property expressions.</pre></div></div><p>More advanced property
expressions can traverse multiple properties (for example,
<code>user.address.city</code>), or even invoke public me
thods. Here the expansion simply reads the <code>currentTime</code> property
of the page.</p><p>Tapestry follows the rules defined by Sun's JavaBeans
specification: a property name of <code>currentTime</code> maps to two methods:
<code>getCurrentTime()</code> and <code>setCurrentTime()</code>. If you omit
one or the other of these methods, the property is either read only (as here),
or write only. (Keep in mind that as far as JavaBeans properties go, it's the
<em>methods</em> that count; the names of the instance variables, or even
whether they exist, is immaterial.)</p><p>Tapestry does go one step further: it
ignores case when matching properties inside the expansion to properties of the
page. In the template we could say ${currenttime} or ${CurrentTime} or any
variation, and Tapestry will <em>still</em> invoke the
<code>getCurrentTime()</code> method.</p><p>Note that in Tapestry it is not
necessary to configure what object holds the <code>currentTime</code> property;
a template an
d a page are always used in combination with each other; expressions are
always rooted in the page instance, in this case, an instance of the Index
class.</p><p>The Index.tml template includes a second expansion:</p><div
class="code panel pdl" style="border-width: 1px;"><div class="codeContent
panelContent pdl">
+</div></div><p>The value inside the curly braces is a <em>property
expression</em>. Tapestry uses its own property expression language that is
expressive, fast, and type-safe.</p><div class="confluence-information-macro
confluence-information-macro-note"><span class="aui-icon aui-icon-small
aui-iconfont-warning confluence-information-macro-icon"></span><div
class="confluence-information-macro-body"><pre>Tapestry does NOT use reflection
to implement property expressions.</pre></div></div><p>More advanced property
expressions can traverse multiple properties (for example,
<code>user.address.city</code>), or even invoke public methods. Here the
expansion simply reads the <code>currentTime</code> property of the
page.</p><p>Tapestry follows the rules defined by Sun's JavaBeans
specification: a property name of <code>currentTime</code> maps to two methods:
<code>getCurrentTime()</code> and <code>setCurrentTime()</code>. If you omit
one or the other of these methods, the property is eithe
r read only (as here), or write only. (Keep in mind that as far as JavaBeans
properties go, it's the <em>methods</em> that count; the names of the instance
variables, or even whether they exist, is immaterial.)</p><p>Tapestry does go
one step further: it ignores case when matching properties inside the expansion
to properties of the page. In the template we could say ${currenttime} or
${CurrentTime} or any variation, and Tapestry will <em>still</em> invoke the
<code>getCurrentTime()</code> method.</p><p>Note that in Tapestry it is not
necessary to configure what object holds the <code>currentTime</code> property;
a template and a page are always used in combination with each other;
expressions are always rooted in the page instance, in this case, an instance
of the Index class.</p><p>The Index.tml template includes a second
expansion:</p><div class="code panel pdl" style="border-width: 1px;"><div
class="codeContent panelContent pdl">
<pre class="brush: xml; gutter: false; theme: Default"
style="font-size:12px;"> <p>${message:greeting}</p>
</pre>
</div></div><p>Here <code>greeting</code> is not a property of the page; its
actually a localized message key. Every Tapestry page and component is allowed
to have its own message catalog. (There's also a global message catalog,
<em>which we'll describe later</em>.)</p><div class="code panel pdl"
style="border-width: 1px;"><div class="codeHeader panelHeader pdl"
style="border-bottom-width:
1px;"><b>src/main/resources/com/example/tutorial/pages/Index.properties</b></div><div
class="codeContent panelContent pdl">
@@ -223,30 +242,30 @@ public class Index
...
</html>
</pre>
-</div></div><p>But for the PageLink component, we've used an element in the
Tapestry namespace:</p><div class="code panel pdl" style="border-width:
1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: xml; gutter: false; theme: Default"
style="font-size:12px;"><t:pagelink page="Index">refresh
page</t:pagelink>
+</div></div><p>But for the EventLink component, we've used an element in the
Tapestry namespace:</p><div class="code panel pdl" style="border-width:
1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: xml; gutter: false; theme: Default"
style="font-size:12px;"><t:eventlink page="Index">refresh
page</t:eventlink>
</pre>
-</div></div><p>Which form you select is a matter of choice. In the vast
majority of cases, they are exactly equivalent.</p><p>As elsewhere, case is
ignored. Here the types ("layout" and "pagelink") were in all lower case; the
actual class names are Layout and PageLink. Further, Tapestry "blends" the core
library components in with the components defined by this application; thus
type "layout" is mapped to application component class
com.example.tutorial.components.Layout, but "pagelink" is mapped to Tapestry's
built-in org.apache.tapestry5.corelib.components.PageLink class.</p><p>Tapestry
components are configured using parameters; for each component, there is a set
of parameters, each with a specific type and purpose. Some parameters are
required, others are optional. Attributes of the element are used to
<em>bind</em> parameters to specific literal values, or to page properties.
Tapestry is flexible here as well; you can always place an attribute in the
Tapestry namespace (using t
he "t:" prefix), but in most cases, this is unnecessary.</p><div class="code
panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+</div></div><p>Which form you select is a matter of choice. In the vast
majority of cases, they are exactly equivalent.</p><p>As elsewhere, case is
ignored. Here the types ("layout" and "eventlink") were in all lower case; the
actual class names are Layout and EventLink. Further, Tapestry "blends" the
core library components in with the components defined by this application;
thus type "layout" is mapped to application component class
com.example.tutorial.components.Layout, but "eventlink" is mapped to Tapestry's
built-in org.apache.tapestry5.corelib.components.EventLink
class.</p><p>Tapestry components are configured using parameters; for each
component, there is a set of parameters, each with a specific type and purpose.
Some parameters are required, others are optional. Attributes of the element
are used to <em>bind</em> parameters to specific literal values, or to page
properties. Tapestry is flexible here as well; you can always place an
attribute in the Tapestry namespace (usi
ng the "t:" prefix), but in most cases, this is unnecessary.</p><div
class="code panel pdl" style="border-width: 1px;"><div class="codeContent
panelContent pdl">
<pre class="brush: xml; gutter: false; theme: Default"
style="font-size:12px;"><html t:type="layout" title="tutorial1 Index"
- t:sidebarTitle="Framework Version" ...
+ p:sidebarTitle="Framework Version" ...
</pre>
</div></div><p>This binds two parameters, <code>title</code> and
<code>sidebarTitle</code>, of the Layout component to the literal strings
"tutorial1 Index" and "Framework Version", respectively.</p><p>The Layout
component will actually provide the bulk of the HTML ultimately sent to the
browser; we'll look at its template in a later chapter. The point is, the
page's template is integrated into the Layout component's template. The
following diagram shows how parameters passed to the Layout component end up
rendered in the final page:</p><p>
-<span class="gliffy-container" id="gliffy-container-24346949-1964"
data-fullwidth="913" data-ceoid="24188263"
data-edit="${diagramEditLink.getLinkUrl()}"
data-full="${diagramZoomLink.getLinkUrl()}" data-filename="Templates and
Parameters">
+<span class="gliffy-container" id="gliffy-container-24346949-2001"
data-fullwidth="913" data-ceoid="24188263"
data-edit="${diagramEditLink.getLinkUrl()}"
data-full="${diagramZoomLink.getLinkUrl()}" data-filename="Templates and
Parameters">
- <map id="gliffy-map-24346949-8577" name="gliffy-map-24346949-8577"></map>
+ <map id="gliffy-map-24346949-1823" name="gliffy-map-24346949-1823"></map>
- <img class="gliffy-image gliffy-image-border"
id="gliffy-image-24346949-1964" width="304" height="300" data-full-width="913"
data-full-height="901"
src="https://cwiki.apache.org/confluence/download/attachments/24188263/Templates%20and%20Parameters.png?version=2&modificationDate=1371888025000&api=v2"
alt="Templates and Parameters" usemap="#gliffy-map-24346949-8577">
+ <img class="gliffy-image gliffy-image-border"
id="gliffy-image-24346949-2001" width="304" height="300" data-full-width="913"
data-full-height="901"
src="https://cwiki.apache.org/confluence/download/attachments/24188263/Templates%20and%20Parameters.png?version=2&modificationDate=1371888025000&api=v2"
alt="Templates and Parameters" usemap="#gliffy-map-24346949-1823">
- <map class="gliffy-dynamic" id="gliffy-dynamic-map-24346949-1964"
name="gliffy-dynamic-map-24346949-1964"></map>
+ <map class="gliffy-dynamic" id="gliffy-dynamic-map-24346949-2001"
name="gliffy-dynamic-map-24346949-2001"></map>
</span>
</p><p>The interesting point here (and this is an advanced concept in
Tapestry, one we'll return to later) is that we can pass a chunk of the
Index.tml template to the Layout component as the <code>sidebar</code>
parameter. That's what the tapestry:parameter namespace (the "p:" prefix) is
for; the element name is matched against a parameter of the component and the
entire block of the template is passed into the Layout component ... which
decides where, inside <em>its</em> template, that block gets rendered.</p><div
class="code panel pdl" style="border-width: 1px;"><div class="codeContent
panelContent pdl">
-<pre class="brush: xml; gutter: false; theme: Default"
style="font-size:12px;"><t:pagelink
page="Index">refresh</t:pagelink>
+<pre class="brush: xml; gutter: false; theme: Default"
style="font-size:12px;"><t:eventlink event="complete" class="btn
btn-default">Complete&raquo;</t:eventlink>
</pre>
</div></div><p>This time, it's the <code>page</code> parameter of the PageLink
component that is bound, to the literal value "Index" (which is the name of
this page). This gets rendered as a URL that re-renders the page, which is how
the current time gets updated. You can also create links to other pages in the
application and, as we'll see in later chapters, attach additional information
to the URL beyond just the page name.</p><h1
id="ExploringtheProject-AMagicTrick">A Magic Trick</h1><p>Now it's time for a
magic trick. Edit Index.java and change the <code>getCurrentTime()</code>
method to:</p><div class="code panel pdl" style="border-width: 1px;"><div
class="codeHeader panelHeader pdl" style="border-bottom-width:
1px;"><b>Index.java (partial)</b></div><div class="codeContent panelContent
pdl">
<pre class="brush: xml; gutter: false; theme: Default"
style="font-size:12px;"> public String getCurrentTime()