blob: a4f05968af38254c0351cd93378af61807cbabd6 [file] [log] [blame]
<chapter id="getting-started">
<title>Getting Started</title>
<para>
This section provides your first introduction on how to write a Tapestry
application. This is followed with an example, and finally a more in depth
discussion on the various parts that make up an application.
</para>
<section id="tapestry-requirements">
<title>Requirements</title>
<para>
For this tutorial, you need only Tapestry and the included
contributed components. Of course, we expect that you have already
deployed the example development environment or tutorial into
a container.
</para>
<para>
The next section provide a brief summary of how Tapestry works, including
a little detail on how it processes your request, as well as an introduction
into the different parts that make up a Tapestry application.
Feel free to skip this section and proceed to
<xref linkend="Introductory-examples"/>
if you already understand what a Page is, and how &OGNL; fits into the picture.
</para>
</section>
<section id="how-does-it-work">
<title>How does it work?</title>
<para>
In a standard Java Web application (using the Servlet API), a request is
processed as follows:
<orderedlist>
<listitem>User agent (browser) sends request over HTTP to server (Servlet Engine)</listitem>
<listitem>Servlet Engine receives request, and routes it to your servlet</listitem>
<listitem>Your servlet(s) examine the HTTP content</listitem>
<listitem>Servlet(s) and JSP are combined to produce the desired result</listitem>
<listitem>The result is sent back to the user agent (browser)</listitem>
</orderedlist>
</para>
<para>
This is a somewhat simplified view, as it does not take into account the myriad
of things that as a developer you are responsible for. For anything but the simplest
(and hence, not very useful) web application, you will need to consider the
implementation of:
<orderedlist>
<listitem>Session management</listitem>
<listitem>Implementation of business logic and/or integration with existing 'back end' logic</listitem>
<listitem>Presentation and 'rendering' of the site or application</listitem>
<listitem>Maintenance over time</listitem>
<listitem>Performance</listitem>
<listitem>Scalability</listitem>
<listitem>...</listitem>
</orderedlist>
</para>
<para>
The list goes on. Tapestry provides almost all of the glue to make a Web Application
happen, so that you can concentrate on implementing the actual logic. Here's how it works:
</para>
<para>
A Tapestry Application consists of a number of Pages, where each page consists of some
HTML, some Java code, and what is known as a <emphasis>page specification</emphasis>.
The page specification is what allows you define the dynamic content that makes it's way
from various Java object into the HTML.
</para>
<para>
When responding to a request, Tapestry does the following:
<orderedlist>
<listitem>User agent (browser) sends request over HTTP to server (Servlet Engine)</listitem>
<listitem>Servlet Engine receives request, and routes it to
<emphasis>the Tapestry Application</emphasis> servlet</listitem>
<listitem>The users previous session is restored or created, as appropriate</listitem>
<listitem>The Application Servlet decodes the request, and calls the
relevant Java code (defined by you) to both get/set variables or take
an action (if the request was a form POST, for example)</listitem>
<listitem>Your application executes code (a method), and sets object
state.</listitem>
<listitem>Tapestry inserts the appropriate responses <emphasis>in
place of</emphasis> the existing HTML, using <emphasis>Components</emphasis></listitem>
<listitem>The result is sent back to the user agent (browser)</listitem>
</orderedlist>
Tapestry is doing much more 'glue' work for you
than with the standard Servlet/JSP model. An important concept here
is that in terms of Java code, you only need to provide the
<emphasis>data</emphasis> and <emphasis>actions</emphasis> for the web page.
The actual rendering of this into HTML is put together by Tapestry, using
the HTML for the page as a basis, with the relevant parts of the page
being replaced with dynamic content.
</para>
<para>
Finally, Tapestry abstracts the rendering of content from the content
itself. For example, data for a web based shopping system may be extracted
by a Java component via JDBC, and presented to Tapestry as a Collection
of business objects. Tapestry is then able to take that collection and
render it into HTML in a way that the page designer (the person who
create the Pages HTML) specified.
</para>
<para>
The next section shows the simplest Tapestry application - a single page.
</para>
</section>
<section id="simplest-app">
<title>The Simplest Application</title>
<para>
You're close to being able to write some code!
</para>
<para>
Not mentioned in the previous section, but important, is that
Tapestry applications have at least one mandatory page - called <emphasis>Home</emphasis>.
This is the page that Tapestry will route new requests to.
</para>
<para>
The following example
will construct a 'Hello World' application, where the text is
retreived a Java object. This example will build up the
application specification, basic HTML tempalte (for the Home page),
and finally a simple Java object to return the 'hello world' string.
</para>
<para>
You will see more on this later, but it is worth explaining now that most
Tapestry pages you write will consist of an HTML template, a page specification
and a Java object (this is exactly what we're going to do below). If it sounds confusing
don't worry - it will be explained in detail later - just follow on for now :-)
</para>
<para>
The example code supplied contains a full implementation of this tutorial.
Feel free to recreate the tutorial as you go along, using the supplied development
environment.
<note>
For each major part of this tutorial, you will find full source code within
<filename class="directory">c:\Tapestry-x.x\examples\Tutorial\src</filename>. So, if
you don't want to construct your own version of the tutorial, you can just run
the examples provided.
</note>
</para>
<para>
The code for this example is in
<filename class="directory">c:\Tapestry-x.x\examples\Tutorial\src\tutorial\hello</filename>.
</para>
<section id="simplest-app-setup">
<title>Setup the Application</title>
<para>
Every Tapestry Application must have at least a single <emphasis>Application Servlet</emphasis>,
where the applications pages and other engine services are defined. For this example, create
a package in your source tree with the name <classname>tutorial.hello</classname>.
Within this package, create a file called <filename>HelloWorld.application</filename>. This
is the application specification file.
</para>
<para>
The application specification is a file that is located on the Java class path.
In a deployed Tapestry application, the specification lives with the application's
class files, in the <filename class="directory">WEB-INF/classes</filename> directory
of a War file.
</para>
<figure>
<title>HelloWorld.application</title>
<programlisting>
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE application PUBLIC
"-//Howard Lewis Ship//Tapestry Specification 1.3//EN"
"http://tapestry.sf.net/dtd/Tapestry_1_3.dtd"&gt;
&lt;application
name="Hello World Tutorial"
engine-class="net.sf.tapestry.engine.&SimpleEngine;"&gt;
&lt;page name="Home" specification-path="/tapestry/tutorial/hello/Home.page"/&gt;
&lt;/application&gt;
</programlisting>
</figure>
<para>
This specification defines a Tapestry Application using the standard Tapestry Engine
(documented later), and a single page called <emphasis>Home</emphasis>,
which Tapestry expects to find at <filename>/tapestry/tutorial/hello/Home.page</filename>
on the classpath.
</para>
<para>
The last <emphasis>application related</emphasis> configuration we need (before we can work on
the page content itself), is to provide the Servlet engine configuration.
Within the <filename class="directory">WEB-INF</filename> directory is a
file called <filename>web.xml</filename>. This file should have at least the following
content:
<figure>
<title>Servet Configuration (web.xml)</title>
<programlisting>
&lt;web-app&gt;
&lt;display-name&gt;Tapestry Tutorial&lt;/display-name&gt;
&lt;servlet&gt;
&lt;servlet-name&gt;hello&lt;/servlet-name&gt;
&lt;servlet-class&gt;tutorial.hello.HelloWorldServlet&lt;/servlet-class&gt;
&lt;load-on-startup&gt;0&lt;/load-on-startup&gt;
&lt;/servlet&gt;
&lt;servlet-mapping&gt;
&lt;servlet-name&gt;hello&lt;/servlet-name&gt;
&lt;url-pattern&gt;/hello&lt;/url-pattern&gt;
&lt;/servlet-mapping&gt;
&lt;session-config&gt;
&lt;session-timeout&gt;15&lt;/session-timeout&gt;
&lt;/session-config&gt;
&lt;welcome-file-list&gt;
&lt;welcome-file&gt;index.html&lt;/welcome-file&gt;
&lt;/welcome-file-list&gt;
&lt;/web-app&gt;
</programlisting>
</figure>
Depending on the <filename>web.xml</filename> you are looking at, there may be
more than this (specifically, the definition of further servlets). That's fine - as long
as there is a definition for the <classname>HelloWorldServlet</classname>.
</para>
</section>
<section id="simplest-app-thehtml">
<title>The Home Page HTML</title>
<para>
With the basic application specification itself complete, we can now define the
HTML on the main page. This HTML file is a Tapestry resource, and for this tutorial
should reside in the source directory for the application.
<footnote>
<para>The tutorial is setup to copy .html, .page and .application files to the classpath - as
such, these files will be loadable by Tapestry at runtime</para>
</footnote>
It should have the same filename as the Page name, in this case it is called <filename>
Home.html</filename>, and is in
<filename class="directory">c:\Tapestry-x.x\examples\Tutorial\src\tutorial\hello</filename>.
<figure>
<title>The HTML Content (Home.html)</title>
<programlisting>
&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"&gt;
&lt;html&gt;
&lt;head&gt;
&lt;title&gt;Hello World&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
Welcome to your first &lt;b&gt;Tapestry Application&lt;/b&gt;
&lt;p&gt;
&lt;h1&gt;
&lt;span jwcid="insertSomeText"&gt;This text will be replaced by Tapesty&lt;/span&gt;
&lt;/h1&gt;
&lt;/body&gt;
&lt;/html&gt;
</programlisting>
</figure>
</para>
<para>
You will notice that the page is completely normal, apart from the single
<emphasis>span </emphasis> tag, which contains an attribute with name
<varname>jwcid</varname>. This is how Tapestry inserts dynamic data
into a page. In this example, Tapestry will completely replace
the <emphasis>span </emphasis>
tag, including whatever it wraps when it renders the page -
that is, you will not see the text <emphasis>This text will be
replaced by Tapestry</emphasis>, but rather the value that is
returned by the <varname>getSomeText()</varname> method.
<footnote>
<para>The tag does not have to be a span tag. Don't worry about it now, it will be covered later.</para>
</footnote>
</para>
<para>
You may be wondering how Tapestry calls the <varname>getSomeText()</varname>
method. In the specification above, we have used an &OGNL; binding.
This type of binding uses an expression, which can be read like
a JavaBean name. For the above, it means that the expression "someText"
relates to the <varname>getSomeText()</varname> and <varname>setSomeText()</varname>
method respectively. In the case of the &Insert; component, only
<varname>getSomeText()</varname> is required, so &Insert; will not try to
change the value. Also note that the example here is very simple,
and returns a constant String. There is no reason why the value could
not come from a Database, or some other dynamic source. There is no
restriction on what you can do in the method. Finally, if you do change
the code to return the value a different way, you don't need to change
the specification or HTML template.
</para>
</section>
<section id="simplest-app-thejavaobject">
<title>The Java Object</title>
<para>
With the page definition completed, we will create the Java Object that
is related to this page. This object will simply supply some static text
to the HTML template.
</para>
<figure>
<title>The Java Object (Home.java)</title>
<programlisting>
package tutorial.hello;
import net.sf.tapestry.html.BasePage;
public class Home extends BasePage
{
public String getSomeText()
{
return "It's a brave new world!";
}
}
</programlisting>
</figure>
</section>
<section id="simplest-app-pagespec">
<title>The Page Specification</title>
<para>
Almost there! The last step is to tie the capabilities of the Java Object,
into the HTML. The final piece of the puzzle is the <emphasis>page
specification</emphasis>.
</para>
<para>
Again, this file should be with the .html and .java files, in the source directory
for this tutorial example.
</para>
<figure>
<title>The Page Specification (Home.page)</title>
<programlisting>
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!-- $Id: tutorial-chapter-two.xml,v 1.5 2002/09/30 22:54:21 scornflake Exp $ --&gt;
&lt;!DOCTYPE page-specification PUBLIC
"-//Howard Lewis Ship//Tapestry Specification 1.3//EN"
"http://tapestry.sf.net/dtd/Tapestry_1_3.dtd"&gt;
&lt;page-specification class="tutorial.hello.Home"&gt;
&lt;component id="insertSomeText" type="Insert"&gt;
&lt;binding name="value" expression="someText"/&gt;
&lt;/component&gt;
&lt;/page-specification&gt;
</programlisting>
</figure>
<para>
Note that Tapestry Components are different from JSP tags.
Specifically, a Tapestry component takes typed values (the
type is defined in the property binding part of the specification,
at the top of the specification file). Secondly, the values of a
component can be read only, or read/write. In the later case, the
component Java code is able to change the value, which causes whatever
was <emphasis>bound</emphasis> to that property to be changed.
Lastly, components can be nested.
A component may itself be made up of many other
components (which themselves might be made up of other components, and so on),
and can bind the properties of those contained
components to properties of itself.
</para>
<para>
Whew! Thats it! You can execute <emphasis>ant run</emphasis> to both
compile, package and run the Web Application. Go to
<ulink url="http://localhost:8081/learn-tapestry/hello">
<filename>http://localhost:8081/learn-tapestry/hello</filename>
</ulink> to see the result.
<figure>
<title>Hello World Application</title>
<mediaobject>
<imageobject>
<imagedata fileref="images/helloworld-example.png" format="PNG"/>
</imageobject>
</mediaobject>
</figure>
</para>
</section>
<section id="simplest-app-summary">
<title>Summary</title>
<para>
What have we done?
<orderedlist>
<listitem>We have seen that an application requires a specification file, which lists
the pages of the application. The application specification is required for any Tapestry
app.</listitem>
<listitem>That pages are defined in terms of an HTML file (the content), a Page file
(which ties the content to the Java Object) and finally the Java Object for the page
logic.</listitem>
<listitem>That a Tapestry application, consisting of any number of pages is
controlled by a single servlet</listitem>
<listitem>Built an example which uses both static content, and content
from a java object</listitem>
</orderedlist>
</para>
<para>
The next section details the separate parts of a Tapestry application in more detail.
</para>
</section>
</section>
<section id="diff-parts">
<title>Different Parts of a Tapestry Application</title>
This last section outlines in a little more detail the separate parts of
a Tapestry application. <footnote><para>The Developer Reference is the definitive
manual for this information</para></footnote>
<section id="part-servlet">
<title>The Servlet</title>
<para>
The part most obvious if you have previous Java Web experience is the Servlet.
In Tapestry, only a single servlet is required per application in most cases. The
servlet becomes the glue between the web server itself, and the rest of tapestry.
It is otherwise known as a <emphasis>Controller</emphasis> servlet,
since it takes care of farming out whatever request is given to it to the right
part of the Tapestry application.
</para>
</section>
<section id="part-app-comp">
<title>Application Engine</title>
<para>
As each new client connects to the application, an instance of the
application engine is created for them. The application engine is used to
track that client's activity within the application.
</para>
<para>
The application engine is an instance, or subclass of, the Tapestry class
&SimpleEngine;.
In these first example, we have no additional behavior to add to the provided base class, so
we simply use &SimpleEngine; directly.
</para>
</section>
<section id="part-pages">
<title>Pages</title>
<para>
Pages make up the visible content of the application. Each page consists
of a page template (The HTML) and page logic (the Java). Tapestry links these
together using a '.page' specification.
</para>
<para>
One of the goals of Tapestry is that the HTML should have the minimum amount
of special markup. As you saw in the example presented above, the page
was completely standard HTML, without any additional markup. This idea is
carried across to other parts as well - when editing a Java object, you hardly
ever see any HTML (which keeps the java <emphasis>clean</emphasis>),
and when editing a page specification - you are editing straight XML, with no
Java or HTML in sight.
</para>
<para>
Tapestry inserts content in the HTML at points that you define using the
<varname>jwcid</varname> attributes on elements.
</para>
<para>Tapestry doesn't really care what HTML tag you use, as long as you balance
the tag correctly. In fact, it ignores the tag entirely: the <varname>insertSomeText</varname>
component above could just has easily been identified with a &lt;text&gt; tag,
or any other tag for that matter. Tapestry is only interested in the <emphasis>structure</emphasis>
of the HTML template. The fact that you can use meaningful tags is a convienience;
it allows a Tapestry HTML template to be previewed in a <acronym>WYSIWYG</acronym>
HTML editor, such as HomeSite. Additionally, Tapestry edits out the content of tags
for components that don't wrap around other content.
This allows a preview values to be kept in the template.
</para>
</section>
<section id="part-components">
<title>Components</title>
<para>
Tapesty components provide the core building blocks for the application. They can
be thought of as 'black boxes' that both render HTML and respond to user actions.
</para>
<para>
Pages are typically built using multiple components. Components may either
exist on their own (non-wrapping, &Insert;) or may enclose some other number of
components (wrapping, e.g: &Form;). Within a page, the HTML refers to various
components by name. Component names are defined in the page specification.
</para>
<para>
The component specification includes both name, type and some bound properties.
The properties define where the component gets its data from, and what other
objects it interacts with.
For example, in the 'Hello World' application above, a component
with name <varname>insertSomeText</varname> was defined to be an &Insert;,
and was bound to the <varname>someText</varname> property of the
page object. In this example, there is no real interaction, as the &Insert;
component does not provide any links for the user to click, nor forms to subnmit.
</para>
</section>
<section id="part-logic">
<title>Application Logic</title>
<para>
The last part of the page is the logic - which is simply a standard Java class
having the same name as the page (e.g: the Home page has a class called
<classname>Home.java</classname>.
</para>
</section>
</section>
</chapter>