<chapter id="Introductory-examples"> | |
<title>Introductory Examples</title> | |
<para> | |
This section provides a set of examples that show some of the fundamental aspects of | |
Tapestry. It begins with a discussion on Tapestry binding, which is the process by which you | |
as a developer link your objects to the components in the HTML page, or put another way - | |
it is how you provide to the compoents the values they need (think of methods that | |
need arguments), as well as a way for the component to change those values. | |
. Moving on, we | |
create a simple multiple page application using the &PageLink; component, and then show | |
how to respond to user actions (typically &Submit; buttons) via the &ActionLink; component. | |
</para> | |
<para> | |
More advanced examples can be found from <xref linkend="forms"/> onwards. | |
</para> | |
<section id="ex-propertybinding"> | |
<title>Introduction to Tapestry Binding</title> | |
<para> | |
Most components have more than a single property. For example, the &Form; component typically | |
requires that both <varname>listener</varname> and <varname>delegate</varname> properties be set to | |
something meaningful. | |
</para> | |
<para> | |
There are multiple ways to provide values for the component properties: | |
<variablelist> | |
<varlistentry> | |
<term>Property Binding</term> | |
<listitem><para> | |
Binds a component value to something, using an &OGNL; (Object Graph Navigation Language) expression. | |
This is the most flexible | |
binding type within Tapestry. These bindings in the most part look like JavaBean property names | |
strung together with dots. e.g: <varname>visit.name</varname>, would work against against | |
the following object graph: <function>this.getVisit().getName()</function>. | |
Virtually anything can be references by | |
an &OGNL; expression, including methods, JavaBean properties and static fields | |
(<function>Boolean.TRUE</function>).</para> | |
<para> | |
<para><emphasis>All OGNL expressions are evaluated in the context of a current object, and a chain | |
simply uses the result of the previous link in the chain as the current object for the next one. | |
You can extend a chain as long as you like. (from &OGNL; web site)</emphasis></para></para> | |
<figure> | |
<title>OGNL binding example</title> | |
<programlisting> | |
<binding> name="value" expression="visit.name"/> | |
</programlisting> | |
</figure> | |
<para> | |
In Tapestry, the current object that you start with is the object for the page | |
in question. For the 'hello world' application covered previously, this is the | |
OGNL expressions must begin their evaluation somewhere. In Tapestry, this is | |
the <classname>tutorial.hello.Home</classname> obect. | |
Lets run through a few quick examples: | |
<orderedlist> | |
<listitem>Use <emphasis>sometext</emphasis> to access <function>public String getSomeText()</function> from the example</listitem> | |
<listitem>Use <emphasis>sometext.length()</emphasis> to access the <function>length()</function> method of the <function>String</function> object returned by the <function>getSomeText()</function> methodd.</listitem> | |
<listitem>Use <emphasis>true</emphasis> to refer to the constant which equals 'true' or <function>Boolean.TRUE</function></listitem> | |
<listitem>Use <emphasis>user.listAllCustomers()</emphasis> to get the <function>Collection</function> from the method <function>currentPageObject.getUser().listAllCustomers()</function> which is a member of the current page object</listitem> | |
<listitem>Use <emphasis>@com.someplace.MyClass@interestingMethod("hello world")</emphasis> to return the value from the static method <function>com.someplace.MyClass.interestingMethod(String arg)</function></listitem> | |
<listitem>Use <emphasis>@Boolean@TRUE</emphasis> to refer to <function>Boolean.TRUE</function></listitem> | |
</orderedlist> | |
</para> | |
<para> | |
This section provides only a brief introduction to the use of OGNL. For a full explanation, see the &OGNL; website. | |
</para> | |
</listitem> | |
</varlistentry> | |
<varlistentry> | |
<term>Static Binding</term> | |
<listitem><para> | |
A completely static piece of text, hardcoded into the component specification. As a result, static | |
bindings are not dynamic (being static!) and are read only. | |
</para> | |
<figure> | |
<title>Static Binding example</title> | |
<programlisting> | |
<static-binding name="value">Click To Save</static-binding> | |
</programlisting> | |
</figure> | |
<para> | |
The example above would use the text <emphasis>Click to Save</emphasis> as | |
the value for the binding. Note that <varname>static</varname> when used to | |
refer to a binding type does not mean the same as <varname>static</varname> within | |
Java itself. In Tapestry, the meaning is that the value is constant, and will never | |
change. | |
</para> | |
</listitem> | |
</varlistentry> | |
<varlistentry> | |
<term>Field Binding</term> | |
<listitem><para> | |
Refers to a static member variable on some class, e.g: <function>Boolean.TRUE</function> | |
or <function>com.mycompany.myclass.MyObject.SOMEVAR</function>. Static bindings must use full qualified | |
object names, except if the property being referenced is within the <function>java.lang</function> package. | |
</para> | |
<para>Field bindings important Java code and referenced in pages, which ensures | |
that the code and pages are synchronized and that changes occur only in a single place.</para> | |
<para> | |
Note that field bindings can also be achieved using an OGNL expression and property binding. | |
The reason that field bindings reman is historic. It is likely that they will be removed | |
in the 3.0 release, because you can achieve exactly the same thing with an &OGNL; | |
binding. | |
</para> | |
<figure> | |
<title>Field Binding example (set the value to 'true')</title> | |
<programlisting> | |
<field-binding name="value" field-name="Boolean.TRUE"/> | |
</programlisting> | |
</figure> | |
</listitem> | |
</varlistentry> | |
<varlistentry> | |
<term>String Binding</term> | |
<listitem><para> | |
Used for localization, the value of this binding should refer to some localized string resource for this page ( | |
part of a resource bundle). The binding is read only. The example below shows a usage of a string=binding | |
to provide a value for an &Insert; component. It is assumed that the properties file for the component, | |
with at least a line along the lines of <varname>pageTitle=Super Application Title!</varname>. | |
</para> | |
<figure> | |
<title>String Binding example </title> | |
<programlisting> | |
<string-binding name="value" key="pageTitle"/> | |
</programlisting> | |
</figure> | |
</listitem> | |
</varlistentry> | |
</variablelist> | |
</para> | |
<para> | |
The next section takes you through the building of slightly more complex application. | |
</para> | |
</section> | |
&into-examples-pagelinking; | |
<section id="ex-actions"> | |
<title>Simple Actions</title> | |
<para> | |
You may notice a bunch more components on the second page than was really obvious | |
from the previous section. That's because I didn't want to complicate the previous | |
example. Also note that there is lots of detail on &Form;s and other components later on. | |
What we are going to do here is give a taste of the simplicity that is Tapestry :-) | |
</para> | |
<para> | |
Below is the full HTML template and application specification, and Java code. | |
You will note that the code itself is really really simple, which is very cool. | |
In order to have an action called | |
on a component. You just name the method. Done. | |
<tip> | |
The method must have a particular signature - as you will see by the code it takes | |
a single <varname>IRequestCycle</varname> argument and is capable of throwing | |
<varname>RequestCycleException</varname>s. | |
</tip> | |
</para> | |
<para> | |
Breaking from tradition, I will provide you the screenshot at the top of the section: | |
</para> | |
<figure> | |
<title>Second page, showing various Actions</title> | |
<mediaobject> | |
<imageobject> | |
<imagedata fileref="images/pagelinking-actions.png" format="PNG"/> | |
</imageobject> | |
</mediaobject> | |
</figure> | |
<figure> | |
<title>Full HTML Template (for second page)</title> | |
<programlisting> | |
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> | |
<html> | |
<head> | |
<title>Page Linking Tutorial (page 2)</title> | |
</head> | |
<body> | |
<h1>Page Two</h1> | |
<center> | |
<table border=0> | |
<tr><th>Well, here we are! Let have some Action!</th></tr> | |
<tr><td><hr></td></tr> | |
<tr><td>Click <span jwcid="homePage">here</span> to go back to the home page.</td></tr> | |
<tr><td>Click <span jwcid="linkListener">here</span> to invoke a <b>DirectLink</b> listener</td></tr> | |
<form jwcid="form"> | |
<tr><td>Click <span jwcid="buttonListener">here</span> to invoke a <b>Submit</b> listener</td></tr> | |
</form> | |
<!-- This part shows the 'result' of the listener --> | |
<tr><td><hr></td></tr> | |
<tr><td><span jwcid="result"/></td></tr> | |
</body> | |
</html> | |
</programlisting> | |
</figure> | |
<para> | |
The template contains one &PageLink; which takes you back to the Home page | |
, one &DirectLink; and one &Submit; button. The later two links just set some text | |
inside the Java object, which is then displayed at the bottom of the table (this is | |
just so that you can see that the action listeners are called). | |
Finally, you will note the use of a &Form; object in the template - this is | |
required for the &Submit; component to work. As mentioned above, don't worry to | |
much about how all this works - concentrate on the use of the &DirectLink; | |
and &Submit; listener methods. | |
</para> | |
<figure> | |
<title>Full Page Specification (for second page)</title> | |
<programlisting> | |
<?xml version="1.0" encoding="UTF-8"?> | |
<!-- $Id: Home.page,v 1.6 2002/05/13 14:00:37 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.pagelinking.SecondPage"> | |
<component id="homePage" type="PageLink"> | |
<static-binding name="page">Home</static-binding> | |
</component> | |
<component id="form" type="Form"> | |
<binding name="stateful" expression="false"/> | |
</component> | |
<component id="result" type="InsertText"> | |
<binding name="value" expression="result"/> | |
</component> | |
<component id="linkListener" type="DirectLink"> | |
<binding name="listener" expression="<emphasis>listeners.linkListener</emphasis>"/> | |
<binding name="stateful" expression="false"/> | |
</component> | |
<component id="buttonListener" type="Submit"> | |
<binding name="listener" expression="<emphasis>listeners.buttonListener</emphasis>"/> | |
</component> | |
</page-specification> | |
</programlisting> | |
</figure> | |
<para> | |
And now the Java object. You can see the listener definitions at the top - very simple. | |
The <varname>result</varname> variable and <varname>getResult()</varname> method are | |
just there to provide feedback to the user. Of course, now that we're in Java land, you | |
can imagine that doing something more complex like calling an EJB object, or some other | |
business related method is easy. Most likely, you would then use the result of the method | |
to affect the rendering - which is what all this is really about. | |
<footnote> <para> | |
Dynamic behavior, that is... | |
</para></footnote> | |
</para> | |
<figure> | |
<title>Java Object (for second page)</title> | |
<programlisting> | |
package tutorial.pagelinking; | |
import net.sf.tapestry.html.BasePage; | |
import net.sf.tapestry.IRequestCycle; | |
import net.sf.tapestry.RequestCycleException; | |
/** | |
* Provides the listeners and a place to store a simple 'result' string | |
* that can be shown back to the user. | |
*/ | |
public class SecondPage extends BasePage { | |
public void linkListener(IRequestCycle cycle) throws RequestCycleException { | |
result = "The link listener was called - which is a good thing."; | |
} | |
public void buttonListener(IRequestCycle cycle) throws RequestCycleException { | |
result = "The submit listener was called - which is also a good thing."; | |
} | |
public String getResult() { | |
return result; | |
} | |
/** Clean up */ | |
public void detach() { | |
super.detach(); | |
result = null; | |
} | |
private String result; | |
} | |
</programlisting> | |
</figure> | |
<para> | |
That should give you a taste of the ease by which Tapestry can be used to handle user | |
actions. The next section takes a break from components and describes the types | |
of pages that a Tapestry application can have. It also shows you how to override | |
the standard Exception page. | |
</para> | |
</section> | |
</chapter> | |