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 Sat Feb 3
13:21:04 2018
@@ -27,6 +27,16 @@
</title>
<link type="text/css" rel="stylesheet" href="/resources/space.css" />
+ <link href='/resources/highlighter/styles/shCoreCXF.css'
rel='stylesheet' type='text/css' />
+ <link href='/resources/highlighter/styles/shThemeCXF.css' rel='stylesheet'
type='text/css' />
+ <script src='/resources/highlighter/scripts/shCore.js'
type='text/javascript'></script>
+ <script src='/resources/highlighter/scripts/shBrushJava.js'
type='text/javascript'></script>
+ <script src='/resources/highlighter/scripts/shBrushXml.js'
type='text/javascript'></script>
+ <script src='/resources/highlighter/scripts/shBrushPlain.js'
type='text/javascript'></script>
+ <script>
+ SyntaxHighlighter.defaults['toolbar'] = false;
+ SyntaxHighlighter.all();
+ </script>
<link href="/styles/style.css" rel="stylesheet" type="text/css"/>
@@ -67,7 +77,8 @@
</div>
<div id="content">
- <div id="ConfluenceContent"><p>The layout of the project
follows the sensible standards promoted by Maven:</p><ul><li>Java source files
under <code>src/main/java</code></li><li>Web application files under
<code>src/main/webapp</code> (including
<code>src/main/webapp/WEB-INF</code>)</li><li>Java test sources under
<code>src/test/java</code></li><li>Non-code resources (including Tapestry page
and component templates) under <code>src/main/resources</code> and
<code>src/test/resources</code></li></ul><p>Let's look at what Maven has
created from the archetype, starting with the web.xml configuration
file:</p><parameter ac:name="language">xml</parameter><parameter
ac:name="title">src/main/webapp/WEB-INF/web.xml</parameter><plain-text-body><?xml
version="1.0" encoding="UTF-8"?>
+ <div id="ConfluenceContent"><p>The layout of the project
follows the sensible standards promoted by Maven:</p><ul><li>Java source files
under <code>src/main/java</code></li><li>Web application files under
<code>src/main/webapp</code> (including
<code>src/main/webapp/WEB-INF</code>)</li><li>Java test sources under
<code>src/test/java</code></li><li>Non-code resources (including Tapestry page
and component templates) under <code>src/main/resources</code> and
<code>src/test/resources</code></li></ul><p>Let's look at what Maven has
created from the archetype, starting with the web.xml configuration
file:</p><div class="code panel pdl" style="border-width: 1px;"><div
class="codeHeader panelHeader pdl" style="border-bottom-width:
1px;"><b>src/main/webapp/WEB-INF/web.xml</b></div><div class="codeContent
panelContent pdl">
+<pre class="brush: xml; gutter: false; theme: Default"
style="font-size:12px;"><?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
@@ -105,7 +116,9 @@ of where to look for pages, components a
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
-</plain-text-body><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
Assuran
ce"). 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><parameter
ac:name="language">java</parameter><parameter
ac:name="title">src/main/java/com/example/tutorial/pages/Index.java</parameter><plain-text-body>package
c
om.example.tutorial1.pages;
+</pre>
+</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 org.apache.tapestry5.Block;
import org.apache.tapestry5.EventContext;
@@ -175,7 +188,9 @@ public class Index
return new Date();
}
}
-</plain-text-body><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 com
es 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 P
OJO Java 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 clean
ly.</em></p><p>For the most part, a Tapestry component template looks like
ordinary XHTML:</p><parameter ac:name="language">xml</parameter><parameter
ac:name="lang">xml</parameter><parameter
ac:name="title">src/main/resources/com/example/tutorial1/pages/Index.tml</parameter><plain-text-body><html
t:type="layout" title="tutorial1 Index"
+</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.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"
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_4.xsd"
xmlns:p="tapestry:parameter">
@@ -216,27 +231,59 @@ public class Index
<p>The current time is:
<strong>${currentTime}</strong></p>
</t:block>
-</html></plain-text-body><rich-text-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></rich-text-body><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 by 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, th
e 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><rich-text-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></rich-text-body><p>First of all, there
are two XML namespaces commonly defined:</p><parameter
ac:name="language">xml</parameter><parameter
ac:name="lang">xml</parameter><plain-text-body>
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_4.xsd"
+</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"
-</plain-text-body><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><parameter
ac:name="language">xml</parameter><parameter
ac:name="lang">xml</parameter><plain-text-body> <p>The curre
nt time is: ${currentTime}</p>
-</plain-text-body><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><rich-text-body><pre>Tapestry does NOT use
reflection to implement property expressions.</pre></rich-text-body><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 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, i
s 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><parameter
ac:name="language">xml</parameter><parameter
ac:name="lang">xml</parameter><plain-text-body>
<p>${message:greeting}</p>
-</plain-text-body><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><parameter
ac:name="title">src/main/resources/com/example/tutorial/pages/Index.properties</parameter><plain-text-body>greeting=Welcome
to Tapestry 5! We hope that this project template will get you going in style.
-</plain-text-body><p>Message catalogs are useful for storing repeating strings
outside of code or templates, though their primary purpose is related to
localization of the application (which will be described in more detail in a
later chapter). Messages that may be used across multiple pages can be stored
in the application's global message catalog,
src/main/webapp/WEB-INF/app.properties, instead.</p><p>This "message:" prefix
is not some special case; there are actually quite a few of these <em>binding
prefixes</em> built into Tapestry, each having a specific purpose. In fact,
omitting a binding prefix in an expansion is exactly the same as using the
"prop:" binding prefix, which means to treat the binding as a property
expression.</p><p>Expansions are useful for extracting a piece of information
and rendering it out to the client as a string, but the real heavy lifting of
Tapestry occurs inside components.</p><h1
id="ExploringtheProject-ComponentsInsideTemplates">Components Inside
Templates</h1><p>Components can be represented inside a component template in
two ways:</p><ul><li>As an ordinary element, but with a t:type attribute to
define the type of component.</li></ul><ul><li>As an element in the Tapestry
namespace, in which case the element name determines the type.</li></ul><p>Here
we've used an <html> element to represent the application's Layout
component.</p><parameter ac:name="language">xml</parameter><parameter
ac:name="lang">xml</parameter><plain-text-body><html t:type="layout" ...>
+</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><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">
+<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;">greeting=Welcome to Tapestry 5! We hope that this
project template will get you going in style.
+</pre>
+</div></div><p>Message catalogs are useful for storing repeating strings
outside of code or templates, though their primary purpose is related to
localization of the application (which will be described in more detail in a
later chapter). Messages that may be used across multiple pages can be stored
in the application's global message catalog,
src/main/webapp/WEB-INF/app.properties, instead.</p><p>This "message:" prefix
is not some special case; there are actually quite a few of these <em>binding
prefixes</em> built into Tapestry, each having a specific purpose. In fact,
omitting a binding prefix in an expansion is exactly the same as using the
"prop:" binding prefix, which means to treat the binding as a property
expression.</p><p>Expansions are useful for extracting a piece of information
and rendering it out to the client as a string, but the real heavy lifting of
Tapestry occurs inside components.</p><h1
id="ExploringtheProject-ComponentsInsideTemplates">Components Inside Templa
tes</h1><p>Components can be represented inside a component template in two
ways:</p><ul><li>As an ordinary element, but with a t:type attribute to define
the type of component.</li></ul><ul><li>As an element in the Tapestry
namespace, in which case the element name determines the type.</li></ul><p>Here
we've used an <html> element to represent the application's Layout
component.</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" ...>
...
</html>
-</plain-text-body><p>But for the EventLink component, we've used an element in
the Tapestry namespace:</p><parameter
ac:name="language">xml</parameter><parameter
ac:name="lang">xml</parameter><plain-text-body><t:eventlink
page="Index">refresh page</t:eventlink>
-</plain-text-body><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 namespac
e (using the "t:" prefix), but in most cases, this is
unnecessary.</p><parameter ac:name="language">xml</parameter><parameter
ac:name="lang">xml</parameter><plain-text-body><html t:type="layout"
title="tutorial1 Index"
+</pre>
+</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 "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"
p:sidebarTitle="Framework Version" ...
-</plain-text-body><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><parameter
ac:name="border">false</parameter><parameter
ac:name="size">S</parameter><parameter ac:name="name">Templates and
Parameters</parameter></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><parameter
ac:name="language">xml</parameter><parameter
ac:name="lang">xml</parameter><plain-text-body><t:eventlink event="complete"
class="btn btn-default">Complete&raquo;</t:eventlink>
-</plain-text-body><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><parameter ac:name="language">xml</parameter><parameter
ac:name="lang">java</parameter><parameter ac:name="title">Index.java
(partial)</parameter><plain-text-body> public String getCurrentTime()
+</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-9257"
data-fullwidth="913" data-ceoid="24188263"
data-edit="${diagramEditLink.getLinkUrl()}"
data-full="${diagramZoomLink.getLinkUrl()}" data-filename="Templates and
Parameters">
+
+ <map id="gliffy-map-24346949-7684" name="gliffy-map-24346949-7684"></map>
+
+ <img class="gliffy-image gliffy-image-border"
id="gliffy-image-24346949-9257" 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-7684">
+
+ <map class="gliffy-dynamic" id="gliffy-dynamic-map-24346949-9257"
name="gliffy-dynamic-map-24346949-9257"></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: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()
{
return "A great day to learn Tapestry";
}
-</plain-text-body><p>Make sure you save changes; then click the refresh link
in the web browser:</p><p><span class="confluence-embedded-file-wrapper
confluence-embedded-manual-size"><img class="confluence-embedded-image"
width="700"
src="exploring-the-project.data/app-live-reload.png"></span><plain-text-body>{float:right|width=30%}
-{note}
-If Live Class Reloading isn't working for you, check the Troubleshooting
section at [Class Reloading].
-{note}
-{float}</plain-text-body>This is one of Tapestry's early <em>wow factor</em>
features: changes to your component classes are picked up immediately (a
feature we call Live Class Reloading). No restart. No re-deploy. Make the
changes and see them <em>now</em>. Nothing should slow you down or get in the
way of you getting your job done.</p><p>But ... what if you make a mistake?
What if you got the name in the template wrong. Give it a try; in the template,
change ${currentTime} to, say, ${currenTime}, and see what you get:</p><p><span
class="confluence-embedded-file-wrapper confluence-embedded-manual-size"><img
class="confluence-embedded-image" width="700"
src="exploring-the-project.data/app-error-1.png"></span></p><p>This is
Tapestry's exception report page. It's quite detailed. It clearly identifies
what Tapestry was doing, and relates the problem to a specific line in the
template, which is shown in context. Tapestry always expands out the entire
stack of exceptions, because it is s
o common for exceptions to be thrown, caught, and re-thrown inside other
exceptions. In fact, if we scroll down just a little bit, we see more detail
about this exception, plus a little bit of help:</p><p><span
class="confluence-embedded-file-wrapper confluence-embedded-manual-size"><img
class="confluence-embedded-image" width="700"
src="exploring-the-project.data/app-error-2.png"></span></p><p>This is part of
Tapestry's way: it not only spells out exactly what it was doing and what went
wrong, but it even helps you find a solution; here it tells you the names of
properties you could have used.</p><rich-text-body><p>This level of detail
reflects that the application has been configured to run in <em>development
mode</em> instead of <em>production mode</em>. In production mode, the
exception report would simply be the top level exception message. However, most
production applications go further and customize how Tapestry handles and
reports exceptions.</p></rich-text-body><p>Tapestry
displays the stack trace of the deepest exception, along with lots of details
about the run-time environment: details about the current request, the
HttpSession (if one exists), and even a detailed list of all JVM system
properties. Scroll down to see all this information.</p><p>Next: <a
href="implementing-the-hi-lo-guessing-game.html">Implementing the Hi-Lo
Guessing Game</a></p><p> </p><p></p></div>
+</pre>
+</div></div><p>Make sure you save changes; then click the refresh link in the
web browser:</p><p><span class="confluence-embedded-file-wrapper
confluence-embedded-manual-size"><img class="confluence-embedded-image
confluence-external-resource" width="700"
src="https://cwiki-test.apache.org/confluence/download/attachments/24188263/app-live-reload.png?version=5&modificationDate=1416707986000&api=v2"
data-image-src="https://cwiki-test.apache.org/confluence/download/attachments/24188263/app-live-reload.png?version=5&modificationDate=1416707986000&api=v2"></span></p><div
class="navmenu" style="float:right; width:30%; background:white; margin:3px;
padding:3px">
+<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">
+<p>If Live Class Reloading isn't working for you, check the Troubleshooting
section at <a href="class-reloading.html" title="Class Reloading">Class
Reloading</a>.</p></div></div></div>This is one of Tapestry's early <em>wow
factor</em> features: changes to your component classes are picked up
immediately (a feature we call Live Class Reloading). No restart. No re-deploy.
Make the changes and see them <em>now</em>. Nothing should slow you down or get
in the way of you getting your job done.<p>But ... what if you make a mistake?
What if you got the name in the template wrong. Give it a try; in the template,
change ${currentTime} to, say, ${currenTime}, and see what you get:</p><p><span
class="confluence-embedded-file-wrapper confluence-embedded-manual-size"><img
class="confluence-embedded-image confluence-external-resource" width="700"
src="https://cwiki-test.apache.org/confluence/download/attachments/24188263/app-error-1.png?version=3&modificationDate=1416707595000&api=v2"
d
ata-image-src="https://cwiki-test.apache.org/confluence/download/attachments/24188263/app-error-1.png?version=3&modificationDate=1416707595000&api=v2"></span></p><p>This
is Tapestry's exception report page. It's quite detailed. It clearly
identifies what Tapestry was doing, and relates the problem to a specific line
in the template, which is shown in context. Tapestry always expands out the
entire stack of exceptions, because it is so common for exceptions to be
thrown, caught, and re-thrown inside other exceptions. In fact, if we scroll
down just a little bit, we see more detail about this exception, plus a little
bit of help:</p><p><span class="confluence-embedded-file-wrapper
confluence-embedded-manual-size"><img class="confluence-embedded-image
confluence-external-resource" width="700"
src="https://cwiki-test.apache.org/confluence/download/attachments/24188263/app-error-2.png?version=4&modificationDate=1416707595000&api=v2"
data-image-src="https://cwiki-test.apac
he.org/confluence/download/attachments/24188263/app-error-2.png?version=4&modificationDate=1416707595000&api=v2"></span></p><p>This
is part of Tapestry's way: it not only spells out exactly what it was doing
and what went wrong, but it even helps you find a solution; here it tells you
the names of properties you could have used.</p><div
class="confluence-information-macro
confluence-information-macro-information"><span class="aui-icon aui-icon-small
aui-iconfont-info confluence-information-macro-icon"></span><div
class="confluence-information-macro-body"><p>This level of detail reflects that
the application has been configured to run in <em>development mode</em> instead
of <em>production mode</em>. In production mode, the exception report would
simply be the top level exception message. However, most production
applications go further and customize how Tapestry handles and reports
exceptions.</p></div></div><p>Tapestry displays the stack trace of the deepest
exception, along
with lots of details about the run-time environment: details about the
current request, the HttpSession (if one exists), and even a detailed list of
all JVM system properties. Scroll down to see all this information.</p><p>Next:
<a href="exploring-the-project.html">Exploring the
Project</a></p><p> </p><p></p></div>
</div>
<div class="clearer"></div>
Modified: websites/production/tapestry/content/getting-started.html
==============================================================================
--- websites/production/tapestry/content/getting-started.html (original)
+++ websites/production/tapestry/content/getting-started.html Sat Feb 3
13:21:04 2018
@@ -138,7 +138,7 @@
<p> </p><p>Getting started with Tapestry is easy, and you have lots of
ways to begin: watch a video, browse the source code of a working demo app,
create a skeleton app using Maven, or step through the tutorial.</p><h2
id="GettingStarted-Watchashortvideo">Watch a short video</h2><p>For a
fast-paced introduction, watch Mark W. Shead's <a class="external-link"
href="http://blog.markshead.com/900/tapestry-5-10-minute-demo/"
rel="nofollow">10 Minute Demo</a>. This video shows how to set up a simple
Tapestry application, complete with form validation, Hibernate-based
persistence, and Ajax. The video provides a preview of the development speed
and productivity that experienced Tapestry users enjoy.</p><h2
id="GettingStarted-Playwithaworkingdemoapp">Play with a working demo
app</h2><p>You can also play with Tapestry via our live demonstration
applications. To start, have a look at the <a class="external-link"
href="https://tapestry-app.apache.org/hotels/">Hotel Booking Demo</a>. The
<a class="external-link"
href="http://github.com/bobharner/tapestry5-hotel-booking-5.4/"
rel="nofollow">source code</a> is provided so you can download and play with
it.</p><h2 id="GettingStarted-CreateyourfirstTapestryproject">Create your first
Tapestry project</h2><p>The easiest way to start a new app is to use <a
class="external-link" href="http://maven.apache.org">Apache Maven</a> to create
your initial project; Maven can use an <em>archetype</em> (a kind of project
template) to create a bare-bones Tapestry application for you.</p><p>Once you
have Maven installed, execute the following command:</p><div
class="preformatted panel" style="border-width: 1px;"><div
class="preformattedContent panelContent">
<pre>mvn archetype:generate -DarchetypeCatalog=http://tapestry.apache.org</pre>
-</div></div><p><span style="line-height: 1.4285715;">(Alternatively, <span> if
you want to get an archetype for a not-yet-released version of Tapestry</span>
– most users don't – you can use the staging URI, <code><span
class="nolink"><span
class="nolink">https://repository.apache.org/content/repositories/staging</span></span></code>
).<br clear="none"></span></p><p><span style="line-height:
1.4285715;"><span>Maven will prompt you for the archetype to create ("Tapestry
5 Quickstart Project") and the exact version number (e.g., "5.4.3"). It also
asks you for a group id, an artifact id, and a version number.</span> You can
see this in the following transcript:</span></p><div class="code panel pdl"
style="border-width: 1px;"><div class="codeContent panelContent pdl">
+</div></div><p><span>(Alternatively, <span> if you want to get an archetype
for a not-yet-released version of Tapestry</span> – most users
don't – you can use the staging URI, <code><span
class="nolink"><span class="nolink"><a class="external-link"
href="https://repository.apache.org/content/repositories/staging">https://repository.apache.org/content/repositories/staging</a></span></span></code>
).<br clear="none"></span></p><p><span><span>Maven will prompt you for the
archetype to create ("Tapestry 5 Quickstart Project") and the exact version
number (e.g., "5.4.3"). It also asks you for a group id, an artifact id, and a
version number.</span> You can see this in the following
transcript:</span></p><div class="code panel pdl" style="border-width:
1px;"><div class="codeContent panelContent pdl">
<pre class="brush: text; gutter: false; theme: Default"
style="font-size:12px;">$ mvn archetype:generate
-DarchetypeCatalog=http://tapestry.apache.org
[INFO] Scanning for projects...
[INFO]
@@ -197,7 +197,7 @@ package: com.example.newapp
[INFO] ------------------------------------------------------------------------
</pre>
-</div></div><p><span style="line-height: 1.4285715;"><br
clear="none"></span></p><p>Maven will (after performing a number of one-time
downloads) create a skeleton project ready to run. Because we specified an
artifactId of "newapp", the project is created in the <code>newapp</code>
directory. (Note: if you get "Unable to get resource" warnings at this stage,
you may be behind a firewall which blocks outbound HTTP requests to Maven
repositories.)</p><p>To run the skeleton application, change to the
<code>newapp</code> directory and execute the <code>"mvn jetty:run"</code>
command to start the Jetty app server:</p><div class="code panel pdl"
style="border-width: 1px;"><div class="codeContent panelContent pdl">
+</div></div><p><span><br clear="none"></span></p><p>Maven will (after
performing a number of one-time downloads) create a skeleton project ready to
run. Because we specified an artifactId of "newapp", the project is created in
the <code>newapp</code> directory. (Note: if you get "Unable to get resource"
warnings at this stage, you may be behind a firewall which blocks outbound HTTP
requests to Maven repositories.)</p><p>To run the skeleton application, change
to the <code>newapp</code> directory and execute the <code>"mvn
jetty:run"</code> command to start the Jetty app server:</p><div class="code
panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
<pre class="brush: bash; gutter: false; theme: Default"
style="font-size:12px;">$ cd newapp
$ mvn jetty:run
[INFO] Scanning for projects...
@@ -217,7 +217,7 @@ Application 'app' (version 1.0-SNAPSHOT-
[INFO] Started [email protected]:8080
[INFO] Started Jetty Server</pre>
-</div></div><p> </p><p>After some more one-time downloads you can open
your browser to <a class="external-link" href="http://localhost:8080/newapp"
rel="nofollow">http://localhost:8080/newapp</a> to see the application
running:</p><p><span class="confluence-embedded-file-wrapper
image-center-wrapper confluence-embedded-manual-size"><img
class="confluence-embedded-image confluence-content-image-border image-center"
height="488" width="500"
src="getting-started.data/newapp_Index.png"></span></p><p>The application
consists of three pages sharing a common look and feel. The initial page,
Index, allows you to perform some basic operations.</p><p>You can also load the
newly-created project it into any IDE and start coding. See the next section on
where to find the different components of the application.</p><h2
id="GettingStarted-Exploringthegeneratedproject">Exploring the generated
project</h2><p>The archetype creates the following files:</p><div
class="preformatted panel" style="b
order-width: 1px;"><div class="preformattedContent panelContent">
+</div></div><p> </p><p>After some more one-time downloads you can open
your browser to <a class="external-link" href="http://localhost:8080/newapp"
rel="nofollow">http://localhost:8080/newapp</a> to see the application
running:</p><p><span class="confluence-embedded-file-wrapper
image-center-wrapper confluence-embedded-manual-size"><img
class="confluence-embedded-image confluence-external-resource
confluence-content-image-border image-center" height="488" width="500"
src="https://cwiki-test.apache.org/confluence/download/attachments/23334911/newapp_Index.png?version=1&modificationDate=1428074330000&api=v2"
data-image-src="https://cwiki-test.apache.org/confluence/download/attachments/23334911/newapp_Index.png?version=1&modificationDate=1428074330000&api=v2"></span></p><p>The
application consists of three pages sharing a common look and feel. The
initial page, Index, allows you to perform some basic operations.</p><p>You can
also load the newly-created project it
into any IDE and start coding. See the next section on where to find the
different components of the application.</p><h2
id="GettingStarted-Exploringthegeneratedproject">Exploring the generated
project</h2><p>The archetype creates the following files:</p><div
class="preformatted panel" style="border-width: 1px;"><div
class="preformattedContent panelContent">
<pre>newapp/
├── build.gradle
├── gradle
@@ -289,7 +289,7 @@ Application 'app' (version 1.0-SNAPSHOT-
└── resources
└── PLACEHOLDER
30 directories, 39 files</pre>
-</div></div><p>A Tapestry application is composed of pages, each page
consisting of one template file and one Java class.</p><p>Tapestry page
templates have the .tml extension and are found within
src/main/<strong>resources</strong>/ under the app's <strong>pages</strong>
package (src/main/resources/com/example/newapp/pages, in this example).
Templates are essentially HTML with some special markup to reference properties
in the corresponding Java class and to reference ready-made or custom
components.</p><p>Similarly, Tapestry page classes are found in within the
src/main/<strong>java</strong> under the app's <em><strong>pages</strong></em>
package (src/main/java/com/example/newapp/pages, in this example) and their
name matches their template name (Index.tml -> Index.java).</p><p>In the
skeleton project, most of the HTML is not found on the pages themselves but in
a Layout component which acts as a global template for the whole site. Java
classes for components live in src/main/<
strong>java</strong>/com/example/newapp/<strong>components</strong> and
component templates go in
src/main/<strong>resources</strong>/com/example/newapp/<strong>components</strong>.</p><p>The
archetype includes a few optional extras:</p><ul><li>The bundled version of
the <a class="external-link" href="http://getbootstrap.com/"
rel="nofollow">Bootstrap CSS library</a> has a per-project override. You can
see the files in src/webapp/context/mybootstrap, and the overrides to enable
that in AppModule.java.</li><li>By default, Tapestry users <a
class="external-link" href="http://prototypejs.org/"
rel="nofollow">Prototype</a> as its client-side library, the archetype
overrides this to <a class="external-link" href="https://jquery.org/"
rel="nofollow">jQuery</a>, which is preferred for new projects.</li><li>The
archetype adds a simple filter that shows the timing of each
request.</li><li>The archetype sets up not just for builds with Maven, but also
via <a class="external-link" href="ht
tp://gradle.org/" rel="nofollow">Gradle</a>.</li></ul><h2
id="GettingStarted-What'snext?">What's next?</h2><p>To deepen your
understanding, step through the <a href="tapestry-tutorial.html">Tapestry
Tutorial</a>, which goes into much more detail about setting up your project as
well as loading it into Eclipse... then continues on to teach you more about
Tapestry.</p><p>Be sure to read about the core <a
href="principles.html">Tapestry Principles</a>, and browse the extensive <a
href="user-guide.html">User Guide</a>.</p><h2
id="GettingStarted-ObtainHelp">Obtain Help</h2><p>Tapestry has an active user
mailing list on which you can find a lot of valuable support, commonly within
just a few minutes. You can subscribe by sending e-mail to <a
class="external-link" href="mailto:[email protected]"
rel="nofollow">[email protected]</a> or look for an answer in
the <a class="external-link"
href="http://markmail.org/search/list:org.apache.tapestry.users"
rel="nofollow">archives</a>. <a href="mailing-lists.html">More
Options</a>...</p><p>Having trouble? Try our <a
href="frequently-asked-questions.html">Frequently Asked
Questions</a>.</p><hr><p> </p><p> </p></div>
+</div></div><p>A Tapestry application is composed of pages, each page
consisting of one template file and one Java class.</p><p>Tapestry page
templates have the .tml extension and are found within
src/main/<strong>resources</strong>/ under the app's <strong>pages</strong>
package (src/main/resources/com/example/newapp/pages, in this example).
Templates are essentially HTML with some special markup to reference properties
in the corresponding Java class and to reference ready-made or custom
components.</p><p>Similarly, Tapestry page classes are found in within the
src/main/<strong>java</strong> under the app's <em><strong>pages</strong></em>
package (src/main/java/com/example/newapp/pages, in this example) and their
name matches their template name (Index.tml -> Index.java).</p><p>In the
skeleton project, most of the HTML is not found on the pages themselves but in
a Layout component which acts as a global template for the whole site. Java
classes for components live in src/main/<
strong>java</strong>/com/example/newapp/<strong>components</strong> and
component templates go in
src/main/<strong>resources</strong>/com/example/newapp/<strong>components</strong>.</p><p>The
archetype includes a few optional extras:</p><ul><li>The bundled version of
the <a class="external-link" href="http://getbootstrap.com/"
rel="nofollow">Bootstrap CSS library</a> has a per-project override. You can
see the files in src/webapp/context/mybootstrap, and the overrides to enable
that in AppModule.java.</li><li>By default, Tapestry users <a
class="external-link" href="http://prototypejs.org/"
rel="nofollow">Prototype</a> as its client-side library, the archetype
overrides this to <a class="external-link" href="https://jquery.org/"
rel="nofollow">jQuery</a>, which is preferred for new projects.</li><li>The
archetype adds a simple filter that shows the timing of each
request.</li><li>The archetype sets up not just for builds with Maven, but also
via <a class="external-link" href="ht
tp://gradle.org/" rel="nofollow">Gradle</a>.</li></ul><h2
id="GettingStarted-What'snext?">What's next?</h2><p>To deepen your
understanding, step through the <a href="getting-started.html">Getting
Started</a>, which goes into much more detail about setting up your project as
well as loading it into Eclipse... then continues on to teach you more about
Tapestry.</p><p>Be sure to read about the core <a
href="getting-started.html">Tapestry Principles</a>, and browse the extensive
<a href="getting-started.html">Getting Started</a>.</p><h2
id="GettingStarted-ObtainHelp">Obtain Help</h2><p>Tapestry has an active user
mailing list on which you can find a lot of valuable support, commonly within
just a few minutes. You can subscribe by sending e-mail to <a
class="external-link" href="mailto:[email protected]"
rel="nofollow">[email protected]</a> or look for an answer in
the <a class="external-link"
href="http://markmail.org/search/list:org.apache.tapes
try.users" rel="nofollow">archives</a>. <a href="getting-started.html">More
Options</a>...</p><p>Having trouble? Try our <a
href="getting-started.html">Getting
Started</a>.</p><hr><p> </p><p> </p></div>
</div>
<div class="clearer"></div>