Dynamic Content</> <para> In this chapter, we'll create a new web application that will show some dynamic content. We'll also begin to show some interactivity by adding a link to the page. Our dynamic content will simply be to show the current date and time. The interactivity will be a link to refresh the page. It all looks like this: </> <figure> <title>Dynamic Application</> <mediaobject> <imageobject> <imagedata fileref="images/dynamic.jpg" format="jpg"> </imageobject> </> </figure> <para> Clicking the word "here" will update the page showing the new data and time. Not incredibly interactive, but it's a start. </> <para> The code for this section of the tutorial is in the package <classname>tutorial.simple</>. </> <para> We need to create a new servlet, but its almost identical to our earlier one. The real action in this section will be the new version of the home page. </> <figure> <title>SimpleServlet.java</> <programlisting><![CDATA[package tutorial.simple; import com.primix.tapestry.*; import com.primix.tapestry.app.*; public class SimpleServlet extends ApplicationServlet { protected String getApplicationSpecificationPath() { return "/tutorial/simple/Simple.application"; } }]]></></> <para> The application specification is also straight forward: </> <figure> <title>Simple.application</> <programlisting><![CDATA[<?xml version="1.0"?> <!DOCTYPE application PUBLIC "-//Primix Solutions//Tapestry Specification 1.0//EN" "http://tapestry.sourceforge.net/dtd/Tapestry_1_0.dtd"> <application> <name>Simple Tutorial</name> <engine-class>com.primix.tapestry.engine.SimpleEngine</engine-class> <page> <name>Home</name> <specification-path>/tutorial/simple/Home.jwc </specification-path> </page> </application>]]></></> <para> Things only begin to get more interesting when we look at the HTML template for the home page: </> <figure> <title>Home.html</> <programlisting><![CDATA[<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title>Simple This application demonstrates some dynamic behavior using Tapestry components.

The current date and time is:

Click here to refresh. ]]> This looks like ordinary HTML, except for the special &jwc-tag; tags. "jwc" is an abbreviation for "Java Web Component"; these tags are placeholders for the dynamic content provided by Tapestry components. We have two components. The first inserts the current date and time into the HTML response. The second component creates a hyperlink that refreshes the page when clicked. One of the goals of Tapestry is that the HTML should have the minimum amount of special markup. This is demonstrated here ... the &jwc-tag; tags blend into the standard HTML of the template. We also don't confuse the HTML by explaining exactly what an insertDate or refresh is; that comes out of the specification (described shortly). The ids used here are meaningful only to the developer Of course, good and consistent naming is important. , the particular type and configuration of each component is defined in the component specification. Very significant is the fact that a Tapestry component can wrap around other elements of the template. The refresh component wraps around the word "here". What this means is that the refresh component will get a chance to emit some HTML (an a hyperlink tag), then emit the HTML it wraps (the word "here"), then get a chance to emit more HTML (the a closing tag). What's more important is that the component can not only wrap static HTML from the template (as shown in this example), but may wrap around other Tapestry components and those components may themselves wrap text and components, to whatever depth is required. And, as we'll see in later chapters, a Tapestry component itself may have a template and more components inside of it. In a real application, the single page of HTML produced by the framework may be the product of dozens of components, effectively "woven" from dozens of HTML templates. Again, the HTML template doesn't define what the components are, it is simply a mix of static HTML that will be passed directly back to the client web browser, with a few placeholders (the &jwc-tag; tags) for where dynamic content will be plugged in. The page's component specification defines what types of components are used and how data moves between the application, page and any components.

Home.jwc</> <programlisting><![CDATA[<?xml version="1.0"?> <!DOCTYPE specification PUBLIC "-//Primix Solutions//Tapestry Specification 1.0//EN" "http://tapestry.sourceforge.net/dtd/Tapestry_1_0.dtd"> <specification> <class>tutorial.simple.Home</class> <components> <component> <id>insertDate</id> <type>Insert</type> <bindings> <binding> <name>value</name> <property-path>currentDate</property-path> </binding> </bindings> </component> <component> <id>refresh</id> <type>Page</type> <bindings> <static-binding> <name>page</name> <value>Home</value> </static-binding> </bindings> </component> </components> </specification>]]></programlisting></figure> <para> Here's what all that means: The <varname>Home</> page is implemented with a custom class, <classname>tutorial.simple.Home</>. It contains two components, <varname>insertDate</> and <varname>refresh</>. </> <para> The two components used within this page are provided by the Tapestry framework. </> <para> The <varname>insertDate</> component is type <classname>Insert</>. <classname>Insert</> components have a <varname>value</> parameter used to specify what should be inserted into the HTML produced by the page. The <varname>insertDate</> component has its <varname>value</> parameter bound to a JavaBeans property of its container (the page), the <varname>currentDate</> property. </> <para> The <varname>refresh</> component is type <classname>Page</>, meaning it creates a link to some other page in the application. <classname>Page</> components have a parameter, named <varname>page</>, which defines the name of the page to navigate to. The name is matched against a page named in the application specification. </> <para> In this case, we only have one page in our application (named "Home"), so we can use a static binding for the page parameter. A static binding provides a value for the component parameter statically, the same value every time. The value is defined right in the specification. </> <para> That just leaves the implementation of the Home page component: </> <figure> <title>Home.java</> <programlisting><![CDATA[ package tutorial.simple; import java.util.*; import com.primix.tapestry.*; public class Home extends BasePage { public Date getCurrentDate() { return new Date(); } }]]></programlisting></figure> <para> <classname>Home</> implements a read-only JavaBeans property, <varname>currentDate</>. This is the same <varname>currentDate</> that the <varname>insertDate</> component needs. When asked for the current date, the <varname>Home</> object returns a new instance of the <classname>java.util.Date</> object. </> <para> The <varname>insertDate</> component converts objects into strings by invoking <function>toString()</> on the object. </> <para> Now all the bits and pieces are working together. </> <para> Run the application, and use the View Source command to examine the HTML generated by by framework. </> <figure> <title>HTML generated for Home page</> <programlisting><![CDATA[<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title>Simple This application demonstrates some dynamic behavior using Tapestry components.

The current date and time is: Thu Nov 09 17:23:31 EST 2000

Click here to refresh. ]]>

This should look very familiar, in that it is mostly the same as the HTML template for the page. Tapestry not only inserted simple text (the current date and time, obtained from an java.util.Date object), but the refresh component inserted the a and a tags, and created an appropriate URL for the href attribute.