| <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> |
| <?xml version="1.0" encoding="UTF-8"?> |
| <!DOCTYPE application PUBLIC |
| "-//Howard Lewis Ship//Tapestry Specification 1.3//EN" |
| "http://tapestry.sf.net/dtd/Tapestry_1_3.dtd"> |
| <application |
| name="Hello World Tutorial" |
| engine-class="net.sf.tapestry.engine.&SimpleEngine;"> |
| <page name="Home" specification-path="/tapestry/tutorial/hello/Home.page"/> |
| </application> |
| </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> |
| <web-app> |
| <display-name>Tapestry Tutorial</display-name> |
| <servlet> |
| <servlet-name>hello</servlet-name> |
| <servlet-class>tutorial.hello.HelloWorldServlet</servlet-class> |
| <load-on-startup>0</load-on-startup> |
| </servlet> |
| |
| <servlet-mapping> |
| <servlet-name>hello</servlet-name> |
| <url-pattern>/hello</url-pattern> |
| </servlet-mapping> |
| |
| <session-config> |
| <session-timeout>15</session-timeout> |
| </session-config> |
| |
| <welcome-file-list> |
| <welcome-file>index.html</welcome-file> |
| </welcome-file-list> |
| </web-app> |
| </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> |
| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> |
| <html> |
| <head> |
| <title>Hello World</title> |
| </head> |
| <body> |
| Welcome to your first <b>Tapestry Application</b> |
| <p> |
| <h1> |
| <span jwcid="insertSomeText">This text will be replaced by Tapesty</span> |
| </h1> |
| </body> |
| </html> |
| </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> |
| <?xml version="1.0" encoding="UTF-8"?> |
| <!-- $Id: tutorial-chapter-two.xml,v 1.5 2002/09/30 22:54:21 scornflake Exp $ --> |
| <!DOCTYPE page-specification PUBLIC |
| "-//Howard Lewis Ship//Tapestry Specification 1.3//EN" |
| "http://tapestry.sf.net/dtd/Tapestry_1_3.dtd"> |
| |
| <page-specification class="tutorial.hello.Home"> |
| <component id="insertSomeText" type="Insert"> |
| <binding name="value" expression="someText"/> |
| </component> |
| </page-specification> |
| </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 <text> 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> |
| |