Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

You can now open a web browser to http://localhost:8080/tutorial1/ to see the running application:

Image RemovedImage Added

The date and time in the middle of the page proves that this is a live application.

...

Right click inside the Package Explorer view and select Import ...

Image RemovedImage Added

Choose the "existing projects" option:

Image RemovedImage Added

Now select the folder created by Maven:

Image RemovedImage Added

When you click the Finish button, the project will be imported into the Eclipse workspace.

Image RemovedImage Added

However; there are many errors. Maven expects that you will configure a classpath variable, M2_REPO, that points at your local repository; a directory in your home directory that stores all those downloaded JARs and other files. Open Eclipse's preferences panel and navigate to Java > Build Path > Classpath Variables:

Image RemovedImage Added

Click the New button, and enter the new variable (you'll have to adjust this for your operating system and local paths):

Image RemovedImage Added

Eclipse will ask to perform a clean build, and the errors will be gone once it has done so.

...

This is short and sweet: you can see that the package name you provided earlier shows up as the tapestry.app-package context parameter; the TapestryFilter instance will use this information to locate the Java classes we'll look at nextfor pages and components.

Tapestry 5 operates as a servlet filter rather than as a traditional servlet. 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.

...

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. Tapestry expects pages to be stored in the pages package under your root package; in this case, the class name will be com.example.tutorial.pages.Index.

Tapestry pages are the combination of a POJO Java class with a Tapestry component template. The has the same name as the Java class, but has the extension .tml. 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.

Tapestry component templates are well-Let's start with the template, which is stored in the webapp's WEB-INF folder. 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.That is,

Note

Tapestry parses documents 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.

may use a tool to validate your templates. At runtime, when Tapestry reads the template, it does not use a validating parser.For the most part, the template looks like ordinary XHTML:

Code Block
langxml
titlesrc/main/resources/webapp/Indexcom/example/tutorial/pages/Index.tml
<html t:type="layout" title="tutorial1 Index"
      t:sidebarTitle="Current Time"
      xmlns:t="http://tapestry.apache.org/schema/tapestry_5_1_0.xsd">
    <head>
  xmlns:p="tapestry:parameter">
      <title>tutorial1 Start Page</title>
    </head>
    <body>
        <h1>tutorial1 Start Page</h1> <!-- Most of the page content, including <head>, <body>, etc. tags, comes from Layout.tml -->

    <p>${message:greeting}</p>

    <p:sidebar>

    <p> This is the start page for this application, a good place to start your modifications. <p>
            Just to prove this is live:
        </p>

        <p> The<p>The current time is: ${currentTime}. </p>


        <p>
            [<t:pagelink t:page="Index">refresh</t:pagelink>]
        </p>
    </body>p:sidebar>

</html>

The goal in Tapestry is for component templates, such as Index.tml, to look as much as possible like ordinary, static HTML files

Footnote

By static, we mean unchanging, as opposed to a dynamically generated Tapestry page.

. 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 instrumented to act as live Tapestry pages.

Tapestry hides non-standard element and attributes inside the XML namespace. By convention, the prefix "t:" is used for this the primary namespace, but that is not a requirement.

This short template demonstrates quite a few features of Tapestry.

First of all, there are two XML namespaces defined:

Code Block
langxml

  xmlns:t="http://tapestry.apache.org/schema/tapestry_5_1_0.xsd"
  xmlns:p="tapestry:parameter"

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).

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.

A Tapestry 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 components and expansions.

Components can be represented two ways:

  • As an ordinary element, but with a t:type attribute to define the type of component.
  • As an element in the Tapestry namespace, in which case the element name determines the type.

In nearly all cases, the two approaches are equivalent.

Here we've used an <html> element to represent the application's Layout component.

Code Block
langxml

<html t:type="layout"> 
  ...
</html>

But for the PageLink component, we've used an element in the Tapestry namespace:

Code Block
langxml

<t:pagelink> ... </t:pagelink>

Which form you use is a matter of choice. In the vast majority of cases, they are exactly equivalent.

Note

As elsewhere, case is ignored. Here the types ("layout" and "pagelink") were in all lower case; the actual class names are Layout and PageLink. Further, Tapestry "blends" the core library components in with the components defined by this application; thus type "layout" is mapped to component class com.example.tutorial.components.Layout, but "pagelink" is mapped to Tapestry's built-in org.apache.tapestry5.corelib.components.PageLink class.

Tapestry components are configured using parameters; for each component, there is a set of parameters, each with a specific type and purpose. Attribute of the element are used to bind parameters to values, or to page properties. Tapestry is flexible here as well; you can always place an attribute in the Tapestry namespace (using the "t:" prefix), but in most cases, this is unecessary.

Code Block
langxml

<html t:type="layout" title="tutorial1 Index"
      t:sidebarTitle="Current Time"

This binds two parameters, title and sidebarTitle of the Layout component, to the literal strings "tutorial1 Index" and "Current Time", respectivelyThere only two bits of Tapestry instrumentation on this page.

First is the way we display the current date and time: ${currentTime}. This syntax is used to access a property of the page object, a property named currentTime. Tapestry calls this an expansion. The value inside the braces is the name of a standard JavaBeans property supplied by the page. As we'll see in later chapters, this is just the tip of the iceberg for what is possible using expansions.

...