tapestry-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From build...@apache.org
Subject svn commit: r977130 - in /websites/production/tapestry/content: cache/main.pageCache exploring-the-project.html
Date Wed, 06 Jan 2016 03:20:38 GMT
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() &gt; 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;">&lt;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"&gt;
-        &lt;!-- Most of the page content, including &lt;head&gt;, &lt;body&gt;,
etc. tags, comes from Layout.tml --&gt;
-
-    &lt;p&gt;${message:greeting}&lt;/p&gt;
-
-    &lt;p&gt;The current time is: &lt;strong&gt;${currentTime}&lt;/strong&gt;&lt;/p&gt;
 
-    &lt;!-- A Zone is a component that can be updated in place, triggered by other components.
--&gt;
-    &lt;t:zone t:id="zone"&gt;
+    &lt;div class="hero-unit"&gt;
         &lt;p&gt;
-            You have clicked the link &lt;strong&gt;${clickCount}&lt;/strong&gt;
times.
+            &lt;img src="${asset:context:images/tapestry.png}"
+                 alt="${message:greeting}" title="${message:greeting}"/&gt;
         &lt;/p&gt;
-
+        &lt;h3&gt;${message:greeting}&lt;/h3&gt;
+        &lt;p&gt;The current time is: &lt;strong&gt;${currentTime}&lt;/strong&gt;&lt;/p&gt;
         &lt;p&gt;
-            [
-            &lt;t:actionlink t:id="increment"&gt;increment&lt;/t:actionlink&gt;
-            ]
-            &amp;nbsp;
-            [
-            &lt;t:actionlink t:id="incrementAjax" zone="^"&gt;increment (via Ajax)&lt;/t:actionlink&gt;
-            ]
+            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.
         &lt;/p&gt;
+        &lt;p&gt;&lt;t:actionlink t:id="learnmore" class="btn btn-primary btn-large"&gt;Learn
more &amp;raquo;&lt;/t:actionlink&gt;&lt;/p&gt;
+    &lt;/div&gt;
 
-    &lt;/t:zone&gt;
-
-    &lt;p:sidebar&gt;
-        &lt;p&gt;
-            You are running Tapestry version &lt;strong&gt;${tapestryVersion}&lt;/strong&gt;.
-        &lt;/p&gt;
-
-
-        &lt;p&gt;
-            [
-            &lt;t:pagelink page="Index"&gt;refresh page&lt;/t:pagelink&gt;
-            ]
-        &lt;/p&gt;
-    &lt;/p:sidebar&gt;
-
-&lt;/html&gt;
-</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"
+    &lt;div class="row"&gt;
+        &lt;div class="span4"&gt;
+            &lt;h2&gt;Normal link&lt;/h2&gt;
+            &lt;p&gt;Clink the bottom link and the page refresh with event &lt;code&gt;complete&lt;/code&gt;&lt;/p&gt;
+            &lt;p&gt;&lt;t:eventlink event="complete" class="btn btn-default"&gt;Complete&amp;raquo;&lt;/t:eventlink&gt;&lt;/p&gt;
+        &lt;/div&gt;
+        &lt;t:zone t:id="middlezone" class="span4"&gt;
+
+        &lt;/t:zone&gt;
+        &lt;div class="span4"&gt;
+            &lt;h2&gt;Ajax link&lt;/h2&gt;
+            &lt;p&gt;Click the bottom link to update just the middle column with
Ajax call with event &lt;code&gt;ajax&lt;/code&gt;&lt;/p&gt;
+            &lt;p&gt;&lt;t:eventlink event="ajax" zone="middlezone" class="btn
btn-default"&gt;Ajax&amp;raquo;&lt;/t:eventlink&gt;&lt;/p&gt;
+        &lt;/div&gt;
+    &lt;/div&gt;
+
+    &lt;t:block t:id="block"&gt;
+        &lt;h2&gt;Ajax updated&lt;/h2&gt;
+        &lt;p&gt;I'v been updated through AJAX call&lt;/p&gt;
+        &lt;p&gt;The current time is: &lt;strong&gt;${currentTime}&lt;/strong&gt;&lt;/p&gt;
+    &lt;/t:block&gt;
+
+&lt;/html&gt;</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;">  &lt;p&gt;The
current time is: ${currentTime}&lt;/p&gt;
 </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;">   
&lt;p&gt;${message:greeting}&lt;/p&gt;
 </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
   ...
 &lt;/html&gt;
 </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;">&lt;t:pagelink
page="Index"&gt;refresh page&lt;/t:pagelink&gt;
+</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;">&lt;t:eventlink
page="Index"&gt;refresh page&lt;/t:eventlink&gt;
 </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;">&lt;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&amp;modificationDate=1371888025000&amp;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&amp;modificationDate=1371888025000&amp;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;">&lt;t:pagelink
page="Index"&gt;refresh&lt;/t:pagelink&gt;
+<pre class="brush: xml; gutter: false; theme: Default" style="font-size:12px;">&lt;t:eventlink
event="complete" class="btn btn-default"&gt;Complete&amp;raquo;&lt;/t:eventlink&gt;
 </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()



Mime
View raw message