Thanks! Let me put it this way ... this tutorial is going to cost me $1K -
$2K in lost billable time.

On Thu, Nov 18, 2010 at 5:42 PM, Josh Canfield <[email protected]>wrote:

> I meant "great article but..." :)
> On 18 Nov 2010 17:23, "Josh Canfield" <[email protected]> wrote:
> > I'm pretty sure that the footnote "Tapestry does _not_ use reflection to
> > implement property expressions." is incorrect.
> >
> > As I understand it, property expressions are built using the
> > PropertyConduitSource which uses reflection to determine the type and
> > available properties for each step in the expression. Right or wrong, I'm
> > not sure why the distinction is made here anyway...
> >
> > Josh
> >
> > On Thu, Nov 18, 2010 at 4:46 PM, <[email protected]> wrote:
> >
> >> First <https://cwiki.apache.org/confluence/display/TAPESTRY/First> Page
> >> *edited* by Howard M. Lewis Ship<
> https://cwiki.apache.org/confluence/display/~hlship>
> >> Changes (39)
> >> ...
> >> Tapestry pages minimally consist of an ordinary Java class plus a
> component
> >> template file.
> >>
> >> 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.
> >> h3. Index Java Class
> >>
> >> The final piece of the puzzle is the Java class for the page. Tapestry
> has
> >> very specific rules for where page classes go. Remember the package name
> >> (configured inside web.xml)? Tapestry adds a sub-package, "pages", to it
> and
> >> the Java class goes there. Thus the full Java class name is
> >> org.apache.tapestry5.tutorial.pages.Index.
> >>
> >> {code:title=src/main/java/com/example/tutorial/pages/Index.java}
> >> package org.apache.tapestry5.tutorial.pages;
> >>
> >> import java.util.Date;
> >>
> >> /**
> >> * Start page of application tutorial1.
> >> */
> >> public class Index
> >> {
> >> public Date getCurrentTime()
> >> {
> >> return new Date();
> >> }
> >> }
> >> {code}
> >>
> >> That's pretty darn simple: No classes to extend, no interfaces to
> >> implement, just a very pure POJO (Plain Old Java Object). You do have to
> >> meet the Tapestry framework halfway:
> >>
> >> * You need to put the Java class in the expected package,
> >> org.apache.tapestry5.tutorial.pages
> >> * The class must be public
> >> * You need to make sure there's a public, no-arguments constructor
> (here,
> >> the Java compiler has silently provided one for us)
> >>
> >> As we saw when running the application, this page displays the current
> date
> >> and time. the {{currentTime}} property is where that value comes from;
> >> shortly we'll see how that value is extracted from the page and output.
> >>
> >> Tapestry always matches a page class to a template; neither is
> functional
> >> without the other. In fact, components within a page are treated the
> same
> >> way (except that components do not always have templates).
> >>
> >> You will often hear about the [Model-View-Controller pattern|
> >> http://en.wikipedia.org/wiki/Model_view_controller] (MVC). In Tapestry,
> >> the page class acts as both the Model (the source of data) and the
> >> controller (the logic that responds to user interaction). The template
> is
> >> the View in MVC. As a model, the page exposes JavaBeans properties that
> can
> >> be referenced in the template.
> >>
> >> Let's look at how the component template builds on the Java class to
> >> provide the full user interface.
> >>
> >> h3. Component Template
> >>
> >> 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. Ultimately, both
> the
> >> Java class and the component template file will be stored in the same
> folder
> >> within the deployed WAR.
> >>
> >> 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.
> >>
> >> ...
> >> {code}
> >>
> >> {warning}
> >> You do have to name your component template file, Index.tml, with the
> >> *exact same case* as the component class name, Index. If you get the
> case
> >> wrong, it may work on some operating systems (such as Windows) and not
> on
> >> others (Mac OS X, Linux, and most others). This can be really vexing, as
> it
> >> is common to develop on Windows and deploy on Linux or Solaris, so be
> >> careful about case in this one area.
> >> {warning}
> >>
> >> 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.{footnote}. 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 elements and attributes inside the XML
> >> namespaces. By convention, the prefix "t:" is used for the primary
> >> namespace, but that is not a requirement.
> >>
> >> This short template demonstrates quite a few features of Tapestry.
> >> ...
> >> 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:
> >> h2. Expansions in Templates
> >>
> >> Let's start with expansions. Expansions are an easy way of including
> some
> >> dynamic output when rendering the page. By default, an expansion refers
> to a
> >> JavaBeans property of the page:
> >>
> >> {code:lang=xml}
> >> <p>The current time is: ${currentTime}</p>
> >> {code}
> >>
> >> {info}
> >> If you are coming to Tapestry 5 from Tapestry 4 or earlier, expansions
> are
> >> a concise replacement for the Insert component.
> >> {info}
> >>
> >> The value inside the curly braces is a _property expression_. Tapestry
> uses
> >> its own property expression language that is expressive, fast, and
> >> type-safe{footnote}Tapestry does _not_ use reflection to implement
> property
> >> expressions.{footnote}. More advanced property expressions can traverse
> >> multiple properties (for example, {{user.address.city}}), or even invoke
> >> public methods. Here the expansion simply reads the {{currentTime}}
> property
> >> of the page.
> >>
> >> Tapestry follows the rules defined by Sun's JavaBeans specification: a
> >> property name of {{currentTime}} maps to two methods:
> {{getCurrentTime()}}
> >> and {{setCurrentTime()}}. If you omit one or the other of these methods,
> the
> >> property is either read only (as here), or write only{footnote}Keep in
> mind
> >> that as far as JavaBeans properties go, it's the _methods_ that count;
> the
> >> names of the instance variables, or even whether they exist, is
> >> immaterial.{footnote}.
> >>
> >> Tapestry does go one step further: it ignores case when matching
> properties
> >> inside the expansion to properties of the page. In the template we could
> say
> >> $\{currenttime\} or $\{CurrentTime\} or any variation, and Tapestry will
> >> _still_ invoke the {{getCurrentTime()}} method.
> >>
> >> Note that in Tapestry it is not necessary to configure what object holds
> >> the {{currentTime}} property; a template and a page are always used in
> >> concert with each other; expressions are always rooted in the page
> instance,
> >> in this case, an instance of the Index class.
> >>
> >> The Index.tml template includes a second expansion:
> >>
> >> {code:lang=xml}
> >> <p>${message:greeting}</p>
> >> {code}
> >>
> >> Here {{greeting}} is not a property of the page; its actually a
> localized
> >> message key. Every page and component is allowed to have its own message
> >> catalog.
> >>
> >>
> {code:title=src/main/resources/com/example/tutorial/pages/Index.properties}
> >>
> >> greeting=Welcome to Tapestry 5! We hope that this project template will
> get
> >> you going in style.
> >> {code}
> >>
> >> Message catalogs are useful for storing repeating strings outside of
> code
> >> or templates, though their primary purpose is related to localization of
> the
> >> application (which will be described in more detail later). Messages
> that
> >> may be used across multiple pages can be stored in the application's
> global
> >> message catalog, src/main/webapp/WEB-INF/app.properties, instead.
> >>
> >> This "message:" prefix is not some special case; there are actually
> quite
> a
> >> few of these "binding prefixes" built into Tapestry, each having a
> specific
> >> purpose. In fact, omitting a binding prefix in an expansion is exactly
> the
> >> same as using the "prop:" binding prefix.
> >>
> >> Expansions are useful for extracting a piece of information and
> rendering
> >> it out to the client as a string, but the real heavy lifting of Tapestry
> >> occurs inside components.
> >>
> >> h2. Components Inside Templates
> >>
> >> Components can be represented inside a component template in two
> >> ways{footnote}Ok, there's a third way as well, which will be discussed
> in
> >> good time.{footnote}:
> >>
> >> * 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}
> >>
> >> Which form you use select is a matter of choice. In the vast majority of
> >> cases, they are exactly equivalent.
> >>
> >> {note}
> >> ...
> >> This binds two parameters, {{title}} and {{sidebarTitle}} of the Layout
> >> component, to the literal strings "tutorial1 Index" and "Current Time",
> >> respectively.
> >>
> >> The Layout component will actually provide the bulk of the HTML
> ultimately
> >> sent to the browser; we'll look at its template in a bit. The point is,
> the
> >> page's template is integrated into the Layout components. The following
> >> diagram shows how parameters passed to the Layout component end up
> rendered
> >> in the final page:
> >>
> >> {gliffy:name=Templates and Parameters|align=center|version=2}
> >>
> >> The interesting point here (and this is an advanced concept in Tapestry,
> >> one we'll return to later) is that we can pass a chunk of the Index.tml
> >> template to the Layout component as the {{sidebar}} parameter. That's
> what
> >> the tapestry:parameter namespace (the "p:" prefix) is for; the element
> name
> >> is matched against a parameter of the component and the entire block of
> the
> >> template is passed into the Layout component ... which decides where,
> inside
> >> _its_ template, that block gets rendered.
> >>
> >> {code:lang=xml}
> >>
> >>
> >>
> >> 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.
> >>
> >> The other dynamic element is the link used to refresh the page. We're
> >> specifying a component as an XML _element_ within the Tapestry
> namespace.
> >> The element name, "pagelink", defines the type of component. PageLink
> >> (Tapestry is case insensitive) is a component built into the framework;
> it
> >> is part of the Tapestry core component library. The attribute, page, is
> a
> >> string - the name of the page to link to. Here, we're linking back to
> the
> >> same page, page "Index".
> >>
> >> This is how Tapestry works; the Index page contains an _instance_ of the
> >> PageLink component. The PageLink component is configured via its
> parameters,
> >> which controls what it does and how it behaves.
> >>
> >> The URL that the PageLink component will render out is [
> >> http://localhost:8080/tapestry-tutorial1/]. "Index" pages are special
> and
> >> are identified just by the folder name. In later examples, when we link
> to
> >> pages besides "Index", the page name will be part of the URL.
> >>
> >> Tapestry ignores case where ever it can. Inside the template, we
> configured
> >> the PageLink component's page parameter with the name of the page,
> "Index".
> >> Here too we could be fuzzy on case. Feel free to use "index" if that
> works
> >> for you.
> >>
> >> {warning}
> >> You do have to name your component template file, Index.tml, with the
> >> *exact same case* as the component class name, Index. If you get the
> case
> >> wrong, it may work on some operating systems (such as Windows) and not
> on
> >> others (Mac OS X, Linux, and most others). This can be really vexing, as
> it
> >> is common to develop on Windows and deploy on Linux or Solaris, so be
> >> careful about case in this one area.
> >> {warning}
> >>
> >> Clicking the link in the web browser sends a request to re-render the
> page;
> >> the template and Java object are re-used to generate the HTML sent to
> the
> >> browser, which results in the updated time showing up in the web
> browser.
> >>
> >> The final piece of the puzzle is the Java class for the page. Tapestry
> has
> >> very specific rules for where page classes go. Remember the package name
> >> (configured inside web.xml)? Tapestry adds a sub-package, "pages", to it
> and
> >> the Java class goes there. Thus the full Java class name is
> >> org.apache.tapestry5.tutorial.pages.Index.
> >>
> >>
> {code:title=src/main/java/org/apache/tapestry5/tutorial/pages/Index.java}
> >> package org.apache.tapestry5.tutorial.pages;
> >>
> >> import java.util.Date;
> >>
> >> /**
> >> * Start page of application tutorial1.
> >> */
> >> public class Index
> >> {
> >> public Date getCurrentTime()
> >> {
> >> return new Date();
> >> }
> >> }
> >> <t:pagelink page="Index">refresh</t:pagelink>
> >> {code}
> >>
> >> That's pretty darn simple: No classes to extend, no interfaces to
> >> implement, just a very pure POJO (Plain Old Java Object). You do have to
> >> meet the Tapestry framework halfway:
> >> This time, it's the {{page}} parameter of the PageLink component that is
> >> bound, to the literal value "Index" (which is the name of this page).
> This
> >> gets rendered as a URL that re-renders the page, which is how the
> current
> >> time gets updated. You can also create links to other pages in the
> >> application and, as we'll see in later chapters, attach additional
> >> information to the URL beyond just the page name.
> >>
> >> * You need to put the Java class in the expected package,
> >> org.apache.tapestry5.tutorial.pages
> >> * The class must be public
> >> * You need to make sure there's a public, no-arguments constructor
> (here,
> >> the Java compiler has silently provided one for us)
> >> h2. Running the Application inside Eclipse
> >>
> >> The template referenced the property {{currentTime}} and we're providing
> >> that as a property, as a _synthetic property_, a property that is
> computed
> >> on the fly (rather than stored in an instance variable).
> >>
> >> This means that every time the page renders, a fresh Date instance is
> >> created, which is just what we want.
> >>
> >> As the page renders, it generates the HTML markup that is sent to the
> >> client web browser. For most of the page, that markup is exactly what
> came
> >> out of the component template: this is called the _static content_
> (we're
> >> using the term "static" to mean "unchanging").
> >>
> >> The expansion, $\{currentTime\}, is _dynamic:_ different every time.
> >> Tapestry will read that property and convert the result into a string,
> and
> >> that string is mixed into the stream of markup sent to the client.
> \_We'll
> >> often talk about the "client" and we don't mean the people you send your
> >> invoices to: we're talking about the client web browser. Of course, in a
> >> world of web spiders and other screen scrapers, there's no guarantee
> that
> >> the thing on the other end of the HTTP pipe is really a web
> >> browser.{footnote}You'll often see low-level HTML and HTTP documentation
> >> talk about the "user agent" rather than the "browser".{footnote}.
> Likewise,
> >> the PageLink component is dynamic, in that it generates a URL that is
> >> (potentially) different every time.
> >>
> >> Tapestry follows the rules defined by Sun's JavaBeans specification: a
> >> property name of {{currentTime}} maps to two methods:
> {{getCurrentTime()}}
> >> and {{setCurrentTime()}}. If you omit one of the other of these methods,
> the
> >> property is either read only (as here), or write only{footnote}Keep in
> mind
> >> that as far as JavaBeans properties go, it's the _methods_ that count;
> the
> >> names of the instance variables, or even whether they exist, is
> >> immaterial.{footnote}.
> >>
> >> Tapestry does go one step further: it ignores case when matching
> properties
> >> inside the expansion to properties of the page. In the template we could
> say
> >> $\{currenttime\} or $\{CurrentTime\} or any variation, and Tapestry will
> >> _still_ invoke the {{getCurrentTime()}} method.
> >>
> >> In the next chapter, we'll start to build a simple hi-lo guessing game,
> but
> >> we've got one more task before then, plus a magic trick.
> >>
> >> ...
> >> Choose the *Run ...* item from the Eclipse *Run* menu to get the launch
> >> configuration dialog:
> >>
> >> !eclipse-run.png!
> >> !eclipse-run.png|align=center,thumbnail!
> >>
> >> Select Jetty Web and click the _New_ button:
> >> Select *Jetty Webapp* and click the *New* button, then fill in a few
> >> values:
> >>
> >> !eclipse-launch.png!
> >> !eclipse-launch.png|align=center,thumbnail!
> >>
> >> Make sure you clear the field labeled *HTTPS*.
> >>
> >> We've filled in a name for our launch configuration, and identified the
> >> project. We've also told Jetty Launcher where our Jetty installation is.
> >> We've identified the web context as src/main/webapp, and we've turned on
> >> NCSA logging for good measure.
> >> You can then click *Run* and Jetty will launch (it takes only a few
> >> seconds):
> >>
> >> In addition, we've set up the context as "/tutorial1", which matches
> what
> >> our eventual WAR file, tutorial1.war, would be deployed as inside an
> >> application server.
> >>
> >> Once you click Run, Jetty will start up and launch (it should take about
> >> two seconds).
> >>
> >> You may now start the application with the URL [
> >> http://localhost:8080/tutorial1/|http://localhost:8080/tutorial1/<
> http://localhost:8080/tutorial1/%7Chttp://localhost:8080/tutorial1/>].
> >>
> >> !eclipse-jetty.png|align=center,thumbnail!
> >>
> >> You may now start the application with the URL [
> >> http://localhost:8080/tutorial1/].
> >>
> >> h2. A Magic Trick
> >>
> >> Now it's time for the magic trick. Edit Index.java and change the
> >> {{getCurrentTime()}} method to:
> >>
> >> {code:lang=java|title=Index.java (partial)}
> >> public String getCurrentTime()
> >> {
> >> ...
> >> Make sure you save changes; then click the refresh link in the web
> browser:
> >>
> >>
> >> !app-live-reload.png!
> >> !app-live-reload.png|align=center,thumbnail!
> >>
> >> This is one of Tapestry's early _wow factor_ features: changes to your
> >> component classes are picked up immediately. No restart. No re-deploy.
> Make
> >> the changes and see them _now_. Nothing should slow you down or get in
> the
> >> way of you getting your job done.
> >>
> >> But ... what if you make a mistake? What if you got the name in the
> >> template wrong. Give it a try; in the template, change $\{currentTime\}
> to,
> >> say, $\{currenTime\}, and see what you get:
> >>
> >> !app-error-1.png|align=center,thumbnail!
> >>
> >> This is Tapestry's exception report page. It's quite detailed. It
> clearly
> >> identifies what Tapestry was doing, and relates the problem to a
> specific
> >> line in the template, which is shown in context. Tapestry always expands
> out
> >> the entire stack of exceptions, because it is so common for exceptions
> to
> be
> >> thrown, caught, and re-thrown inside other exceptions. In fact, if we
> scroll
> >> down just a little bit, we see more detail about this exception, plus a
> >> little bit of help:
> >>
> >> !app-error-2.png|align=center,thumbnail!
> >>
> >> This is part of Tapestry's way: it not only spells out exactly what it
> was
> >> doing and what went wrong, but it even helps you find a solution; here
> it
> >> tells you the names of properties you could have used.
> >>
> >> Tapestry displays the stack trace of the deepest exception, along with
> lots
> >> of details about the runtime environment: details about the current
> request,
> >> the HttpSession (if one exists), and even a detailed list of all JVM
> system
> >> properties. Scroll down to see all this information.
> >>
> >>
> >> {info}
> >> This level of detail reflects that the application has been configured
> to
> >> run in _development mode_ instead of _production mode_. In production
> mode,
> >> the exception report would simply be the top level exception message.
> >> However, most production applications go further and customize how
> Tapestry
> >> handles and reports exceptions.
> >> {info}
> >>
> >>
> >> Now that we have our basic application set up, and ready to run (or
> debug)
> >> directly inside Eclipse, we can start working on implementing our Hi/Lo
> game
> >> in earnest.
> >>
> >> ...
> >> Full Content
> >> Chapter 2: Your First Tapestry Application
> >> This chapter may look long, but almost all of it is one-time setup for
> >> Maven and Eclipse. The actual Tapestry part is really small and simple.
> >> Enjoy!
> >>
> >> Before we can get down to the fun, we have to create an empty
> application.
> >> Tapestry uses a feature of Maven to do this: *archetypes* (a too-clever
> >> way of saying "project templates").
> >>
> >> What we'll do is create an empty shell application using Maven, then
> import
> >> the application into Eclipse to do the rest of the work.
> >>
> >> For the tutorial, I've used a fresh install of Eclipse and an empty
> >> workspace at /Users/Howard/Documents/workspace 1
> >> <https://cwiki.apache.org/confluence#Footnote1> . You may need to
> adjust
> a
> >> few things for other operating systems or local paths.
> >>
> >> From my workspace directory, I'll use Maven to create a skeleton
> Tapestry
> >> project.
> >>
> >> Before proceeding, we have to decide on four things: A Maven *group
> id*and
> >> *artifact id* for our project, a *version*, and a *base package name*.
> >>
> >> Maven uses the group id and artifact id to provide a unique identity for
> >> the application, and Tapestry needs to have a base package name so it
> knows
> >> where to look for pages and components.
> >>
> >> For this example, we'll use the group id *com.example*, artifact id *
> >> tutorial1*, version *1.0-SNAPSHOT* and we'll use *com.example.tutorial*
> as
> >> the base package.
> >>
> >> Our final command line is:
> >>
> >> mvn archetype:generate -DarchetypeCatalog=http://tapestry.apache.org
> >>
> >> It will then prompt you to pick the archetype - choose *Tapestry 5.2.4
> >> Quickstart Project*, enter the group id, artifact id, version and
> package
> >> when prompted.
> >>
> >> ~/Documents/workspace
> >> $ mvn archetype:generate -DarchetypeCatalog=http://tapestry.apache.org
> >> [INFO] Scanning for projects...
> >> [INFO] Searching repository for plugin with prefix: 'archetype'.
> >> [INFO]
> ------------------------------------------------------------------------
> >> [INFO] Building Maven Default Project
> >> [INFO] task-segment: [archetype:generate] (aggregator-style)
> >> [INFO]
> ------------------------------------------------------------------------
> >> [INFO] Preparing archetype:generate
> >> [INFO] No goals needed for project - skipping
> >> [INFO] [archetype:generate {execution: default-cli}]
> >> [INFO] Generating project in Interactive mode
> >> [INFO] No archetype defined. Using maven-archetype-quickstart
> (org.apache.maven.archetypes:maven-archetype-quickstart:1.0)
> >> Choose archetype:
> >> 1: http://tapestry.apache.org -> quickstart (Tapestry 5.2.4 Quickstart
> Project)
> >> 2: http://tapestry.apache.org -> tapestry-archetype (Tapestry 4.1.6
> Archetype)
> >> Choose a number: : 1
> >> Choose version:
> >> 1: 5.1.0.5
> >> 2: 5.0.19
> >> 3: 5.2.4
> >> Choose a number: 3: 3
> >> Define value for property 'groupId': : com.example
> >> Define value for property 'artifactId': : tutorial1
> >> Define value for property 'version': 1.0-SNAPSHOT:
> >> Define value for property 'package': com.example: com.example.tutorial
> >> Confirm properties configuration:
> >> groupId: com.example
> >> artifactId: tutorial1
> >> version: 1.0-SNAPSHOT
> >> package: com.example.tutorial
> >> Y:
> >> [INFO]
> ------------------------------------------------------------------------
> >> [INFO] BUILD SUCCESSFUL
> >> [INFO]
> ------------------------------------------------------------------------
> >> [INFO] Total time: 1 minute 41 seconds
> >> [INFO] Finished at: Wed Nov 17 17:00:16 PST 2010
> >> [INFO] Final Memory: 16M/81M
> >> [INFO]
> ------------------------------------------------------------------------
> >> ~/Documents/workspace
> >> $
> >>
> >> The first time you use Maven, you'll see quite a bit more output, mostly
> >> about downloading all sorts of JARs and other files. These downloaded
> files
> >> are cached locally and will not need to be downloaded again, but you do
> have
> >> to be patient on first use.
> >>
> >> After executing the command, you'll see a new directory, tutorial1.
> >> *Maven Behind a Firewall*
> >> If you are behind a firewall, before running any "mvn" commands, you
> will
> >> need to configure your proxy settings in settings.xml. Here is an
> example:
> >> *settings.xml*
> >>
> >> <settings>
> >> <proxies>
> >> <proxy>
> >> <active>true</active>
> >> <protocol>http</protocol>
> >> <host>myProxyServer.com</host>
> >> <port>8080</port>
> >> <username>joeuser</username>
> >> <password>myPassword</password>
> >> <nonProxyHosts></nonProxyHosts>
> >> </proxy>
> >> </proxies>
> >> <localRepository>C:/Documents and
> Settings/joeuser/.m2/repository</localRepository>
> >> </settings>
> >>
> >> Of course, adjust the localRepository element to match the correct path
> >> for your computer.
> >> Running the New Application in Jetty
> >>
> >> One of the first things you can do is use Maven to run Jetty directly.
> >>
> >> Change into the newly created directory, and execute the command:
> >>
> >> mvn jetty:run
> >>
> >> Again, the first time, there's a dizzying number of downloads, but
> before
> >> you know it, the Jetty servlet container is up and running.
> >>
> >> Once Jetty is initialized (which only takes a few seconds), you'll see
> the
> >> following in your console:
> >>
> >> URLRewriter: DEFINED
> >> UpdateListenerHub: REAL
> >> ValidateBindingFactory: DEFINED
> >> ValidationConstraintGenerator: DEFINED
> >> ValidationMessagesSource: DEFINED
> >> ValidatorMacro: DEFINED
> >> ValueEncoderSource: DEFINED
> >>
> >> 85.00% unrealized services (153/180)
> >>
> >> 2010-11-17 17:06:30.630::INFO: Started
> [email protected]:8080
> >> [INFO] Started Jetty Server
> >>
> >> You can now open a web browser to http://localhost:8080/tutorial1/ to
> see
> >> the running application:
> >>
> >>
> >> <
>
> https://cwiki.apache.org/confluence/download/attachments/23340356/startpage.png
> >
> >>
> >> The date and time in the middle of the page proves that this is a live
> >> application.
> >>
> >> This is a complete little application; it doesn't do much, but it
> >> demonstrate how to create a number of pages sharing a common layout, and
> >> demonstrates some simple navigation.
> >> Loading the Project into Eclipse
> >>
> >> Let's look at what Maven has generated for us. To do this, we're going
> to
> >> load the project inside Eclipse and continue from there.
> >>
> >> Start by hitting Control-C in the Terminal window to close down Jetty.
> >>
> >> Next, we'll ask Maven to create our Eclipse project for us:
> >>
> >> $ mvn eclipse:eclipse -DdownloadSources=true
> >> [INFO] Scanning for projects...
> >> [INFO] Searching repository for plugin with prefix: 'eclipse'.
> >> [INFO] org.apache.maven.plugins: checking for updates from
> apache-snapshots
> >> [INFO] org.codehaus.mojo: checking for updates from apache-snapshots
> >> [INFO] artifact org.apache.maven.plugins:maven-eclipse-plugin: checking
> for updates from apache-snapshots
> >> [INFO] snapshot
> org.apache.maven.plugins:maven-eclipse-plugin:2.9-SNAPSHOT: checking for
> updates from apache-snapshots
> >> Downloading:
>
> http://repository.apache.org/snapshots//org/apache/maven/plugins/maven-eclipse-plugin/2.9-SNAPSHOT/maven-eclipse-plugin-2.9-20101117.070458-148.pom
> >> 11K <
>
> http://repository.apache.org/snapshots//org/apache/maven/plugins/maven-eclipse-plugin/2.9-SNAPSHOT/maven-eclipse-plugin-2.9-20101117.070458-148.pom11K
> >
> downloaded (maven-eclipse-plugin-2.9-20101117.070458-148.pom)
> >> Downloading:
>
> http://repository.apache.org/snapshots//org/apache/maven/plugins/maven-eclipse-plugin/2.9-SNAPSHOT/maven-eclipse-plugin-2.9-20101117.070458-148.jar
> >> 194K <
>
> http://repository.apache.org/snapshots//org/apache/maven/plugins/maven-eclipse-plugin/2.9-SNAPSHOT/maven-eclipse-plugin-2.9-20101117.070458-148.jar194K
> >
> downloaded (maven-eclipse-plugin-2.9-20101117.070458-148.jar)
> >> [INFO]
> ------------------------------------------------------------------------
> >> [INFO] Building tutorial1 Tapestry 5 Application
> >> [INFO] task-segment: [eclipse:eclipse]
> >> [INFO]
> ------------------------------------------------------------------------
> >> [INFO] Preparing eclipse:eclipse
> >> [INFO] No goals needed for project - skipping
> >> [INFO] [eclipse:eclipse {execution: default-cli}]
> >> [INFO] Using Eclipse Workspace: /Users/Howard/Documents/workspace
> >> [INFO] Adding default classpath container:
> org.eclipse.jdt.launching.JRE_CONTAINER
> >> [INFO] Wrote settings to
>
> /Users/Howard/Documents/workspace/tutorial1/.settings/org.eclipse.jdt.core.prefs
> >> [INFO] Wrote Eclipse project for "tutorial1" to
> /Users/Howard/Documents/workspace/tutorial1.
> >> [INFO]
> >> [INFO]
> ------------------------------------------------------------------------
> >> [INFO] BUILD SUCCESSFUL
> >> [INFO]
> ------------------------------------------------------------------------
> >> [INFO] Total time: 5 seconds
> >> [INFO] Finished at: Wed Nov 17 17:13:11 PST 2010
> >> [INFO] Final Memory: 21M/81M
> >> [INFO]
> ------------------------------------------------------------------------
> >> ~/Documents/workspace/tutorial1
> >> $
> >>
> >> At this point, Maven has created the Eclipse .project and
> .classpathfiles, and we can import the project.
> >>
> >> Launch Eclipse and switch over to the Java Perspective.
> >>
> >> Right click inside the Package Explorer view and select *Import ...*
> >>
> >>
> >> <
>
> https://cwiki.apache.org/confluence/download/attachments/23340356/eclipse-java-persp.png
> >
> >>
> >> Choose the "existing projects" option:
> >>
> >>
> >> <
>
> https://cwiki.apache.org/confluence/download/attachments/23340356/eclipse-import.png
> >
> >>
> >> Now select the folder created by Maven:
> >>
> >>
> >> <
>
> https://cwiki.apache.org/confluence/download/attachments/23340356/eclipse-import-folder.png
> >
> >>
> >> When you click the Finish button, the project will be imported into the
> >> Eclipse workspace.
> >>
> >>
> >> <
>
> https://cwiki.apache.org/confluence/download/attachments/23340356/eclipse-project-errors.png
> >
> >>
> >> 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*:
> >>
> >>
> >> <
>
> https://cwiki.apache.org/confluence/download/attachments/23340356/eclipse-classpath-vars.png
> >
> >>
> >> Click the *New* button, and enter the new variable (you'll have to
> adjust
> >> this for your operating system and local paths):
> >>
> >>
> >> <
>
> https://cwiki.apache.org/confluence/download/attachments/23340356/eclipse-new-var.png
> >
> >>
> >> Eclipse will ask to perform a clean build, and the errors will be gone
> once
> >> it has done so.
> >> Investigating the Generated Artifacts
> >>
> >> Maven dictates the layout of the project:
> >>
> >> - Java source files under src/main/java
> >> - Web application files under src/main/webapp (including
> >> src/main/webapp/WEB-INF)
> >> - Java test sources under src/test/java
> >> - Non-code resources under src/main/resources and src/test/resources
> >>
> >> Tapestry uses a number of non-code resources, such as template files and
> >> message catalogs, which will ultimately be packaged into the WAR file
> >> alongside the Java classes.
> >>
> >> Let's look at what the archetype has created for us, starting with the
> >> web.xml configuration file:
> >> *src/main/webapp/WEB-INF/web.xml*
> >>
> >> <?xml version="1.0" encoding="UTF-8"?>
> >> <!DOCTYPE web-app
> >> PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "
> http://java.sun.com/dtd/web-app_2_3.dtd";><web-app>
> >> <display-name>tutorial1 Tapestry 5 Application</display-name>
> >> <context-param>
> >> <!-- The only significant configuration for Tapestry 5, this informs
> Tapestry
> >> of where to look for pages, components and mixins. -->
> >> <param-name>tapestry.app-package</param-name>
> >> <param-value>com.example.tutorial</param-value>
> >> </context-param>
> >> <filter>
> >> <filter-name>app</filter-name>
> >> <filter-class>org.apache.tapestry5.TapestryFilter</filter-class>
> >> </filter>
> >> <filter-mapping>
> >> <filter-name>app</filter-name>
> >> <url-pattern>/*</url-pattern>
> >> </filter-mapping>
> >> </web-app>
> >>
> >> 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
> >> for 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.
> >>
> >> Tapestry pages minimally consist of an ordinary Java class plus a
> component
> >> template file.
> >>
> >> 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.
> >> Index Java Class
> >>
> >> The final piece of the puzzle is the Java class for the page. Tapestry
> has
> >> very specific rules for where page classes go. Remember the package name
> >> (configured inside web.xml)? Tapestry adds a sub-package, "pages", to it
> and
> >> the Java class goes there. Thus the full Java class name is
> >> org.apache.tapestry5.tutorial.pages.Index.
> >> *src/main/java/com/example/tutorial/pages/Index.java*
> >>
> >> package org.apache.tapestry5.tutorial.pages;
> >> import java.util.Date;
> >>
> >> /**
> >> * Start page of application tutorial1.
> >> */public class Index
> >> {
> >> public Date getCurrentTime()
> >> {
> >> return new Date();
> >> }
> >> }
> >>
> >> That's pretty darn simple: No classes to extend, no interfaces to
> >> implement, just a very pure POJO (Plain Old Java Object). You do have to
> >> meet the Tapestry framework halfway:
> >>
> >> - You need to put the Java class in the expected package,
> >> org.apache.tapestry5.tutorial.pages
> >> - The class must be public
> >> - You need to make sure there's a public, no-arguments constructor
> >> (here, the Java compiler has silently provided one for us)
> >>
> >> As we saw when running the application, this page displays the current
> date
> >> and time. the currentTime property is where that value comes from;
> shortly
> >> we'll see how that value is extracted from the page and output.
> >>
> >> Tapestry always matches a page class to a template; neither is
> functional
> >> without the other. In fact, components within a page are treated the
> same
> >> way (except that components do not always have templates).
> >>
> >> You will often hear about the Model-View-Controller pattern<
> http://en.wikipedia.org/wiki/Model_view_controller>(MVC). In Tapestry, the
> page class acts as both the Model (the source of
> >> data) and the controller (the logic that responds to user interaction).
> The
> >> template is the View in MVC. As a model, the page exposes JavaBeans
> >> properties that can be referenced in the template.
> >>
> >> Let's look at how the component template builds on the Java class to
> >> provide the full user interface.
> >> Component Template
> >>
> >> 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. Ultimately, both
> the
> >> Java class and the component template file will be stored in the same
> folder
> >> within the deployed WAR.
> >>
> >> 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.
> >> Tapestry parses component templates 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.
> >>
> >> For the most part, the template looks like ordinary XHTML:
> >> *src/main/resources/com/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";
> >> xmlns:p="tapestry:parameter">
> >> <!-- Most of the page content, including <head>, <body>, etc. tags,
> comes
> from Layout.tml -->
> >>
> >> <p>${message:greeting}</p>
> >>
> >> <p:sidebar>
> >>
> >> <p>
> >> Just to prove this is live:
> >> </p>
> >>
> >> <p>The current time is: ${currentTime}.</p>
> >>
> >>
> >> <p>
> >> [<t:pagelink page="Index">refresh</t:pagelink>]
> >> </p>
> >> </p:sidebar>
> >> </html>
> >>
> >> You do have to name your component template file, Index.tml, with the
> *exact
> >> same case* as the component class name, Index. If you get the case
> wrong,
> >> it may work on some operating systems (such as Windows) and not on
> others
> >> (Mac OS X, Linux, and most others). This can be really vexing, as it is
> >> common to develop on Windows and deploy on Linux or Solaris, so be
> careful
> >> about case in this one area.
> >>
> >> The goal in Tapestry is for component templates, such as Index.tml, to
> look
> >> as much as possible like ordinary, static HTML files 2
> >> <https://cwiki.apache.org/confluence#Footnote2> . 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 elements and attributes inside XML
> namespaces.
> >> By convention, the prefix "t:" is used for the primary namespace, but
> that
> >> is not a requirement.
> >>
> >> This short template demonstrates quite a few features of Tapestry.
> >> Part of the concept of the quickstart archetype is to demonstrate a
> bunch
> >> of different features, approaches and common patterns used in Tapestry,
> thus
> >> we're hitting you with a lot all at once.
> >>
> >> First of all, there are two XML namespaces defined:
> >>
> >> 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*.
> >> Expansions in Templates
> >>
> >> Let's start with expansions. Expansions are an easy way of including
> some
> >> dynamic output when rendering the page. By default, an expansion refers
> to a
> >> JavaBeans property of the page:
> >>
> >> <p>The current time is: ${currentTime}</p>
> >>
> >> If you are coming to Tapestry 5 from Tapestry 4 or earlier, expansions
> >> are a concise replacement for the Insert component.
> >>
> >> The value inside the curly braces is a *property expression*. Tapestry
> >> uses its own property expression language that is expressive, fast, and
> >> type-safe 3 <https://cwiki.apache.org/confluence#Footnote3> . More
> >> advanced property expressions can traverse multiple properties (for
> example,
> >> user.address.city), or even invoke public methods. Here the expansion
> >> simply reads the currentTime property of the page.
> >>
> >> Tapestry follows the rules defined by Sun's JavaBeans specification: a
> >> property name of currentTime maps to two methods: getCurrentTime() and
> >> setCurrentTime(). If you omit one or the other of these methods, the
> >> property is either read only (as here), or write only 4
> >> <https://cwiki.apache.org/confluence#Footnote4> .
> >>
> >> Tapestry does go one step further: it ignores case when matching
> properties
> >> inside the expansion to properties of the page. In the template we could
> say
> >> ${currenttime} or ${CurrentTime} or any variation, and Tapestry will *
> >> still* invoke the getCurrentTime() method.
> >>
> >> Note that in Tapestry it is not necessary to configure what object holds
> >> the currentTime property; a template and a page are always used in
> concert
> >> with each other; expressions are always rooted in the page instance, in
> this
> >> case, an instance of the Index class.
> >>
> >> The Index.tml template includes a second expansion:
> >>
> >> <p>${message:greeting}</p>
> >>
> >> Here greeting is not a property of the page; its actually a localized
> >> message key. Every page and component is allowed to have its own message
> >> catalog.
> >> *src/main/resources/com/example/tutorial/pages/Index.properties*
> >>
> >> greeting=Welcome to Tapestry 5! We hope that this project template will
> get you going in style.
> >>
> >> Message catalogs are useful for storing repeating strings outside of
> code
> >> or templates, though their primary purpose is related to localization of
> the
> >> application (which will be described in more detail later). Messages
> that
> >> may be used across multiple pages can be stored in the application's
> global
> >> message catalog, src/main/webapp/WEB-INF/app.properties, instead.
> >>
> >> This "message:" prefix is not some special case; there are actually
> quite
> a
> >> few of these "binding prefixes" built into Tapestry, each having a
> specific
> >> purpose. In fact, omitting a binding prefix in an expansion is exactly
> the
> >> same as using the "prop:" binding prefix.
> >>
> >> Expansions are useful for extracting a piece of information and
> rendering
> >> it out to the client as a string, but the real heavy lifting of Tapestry
> >> occurs inside components.
> >> Components Inside Templates
> >>
> >> Components can be represented inside a component template in two ways 5
> >> <https://cwiki.apache.org/confluence#Footnote5> :
> >>
> >> - 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.
> >>
> >> Here we've used an <html> element to represent the application's Layout
> >> component.
> >>
> >> <html t:type="layout">
> >> ...</html>
> >>
> >> But for the PageLink component, we've used an element in the Tapestry
> >> namespace:
> >>
> >> <t:pagelink> ... </t:pagelink>
> >>
> >> Which form you select is a matter of choice. In the vast majority of
> >> cases, they are exactly equivalent.
> >> 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
> >> application 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.
> Some
> >> parameters are required, others are optional. Attributes 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.
> >>
> >> <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",
> >> respectively.
> >>
> >> The Layout component will actually provide the bulk of the HTML
> ultimately
> >> sent to the browser; we'll look at its template in a bit. The point is,
> the
> >> page's template is integrated into the Layout components. The following
> >> diagram shows how parameters passed to the Layout component end up
> rendered
> >> in the final page:
> >> [image: A Gliffy Diagram named: Templates and Parameters]
> >>
> >> The interesting point here (and this is an advanced concept in Tapestry,
> >> one we'll return to later) is that we can pass a chunk of the Index.tml
> >> template to the Layout component as the sidebar parameter. That's what
> the
> >> tapestry:parameter namespace (the "p:" prefix) is for; the element name
> is
> >> matched against a parameter of the component and the entire block of the
> >> template is passed into the Layout component ... which decides where,
> inside
> >> *its* template, that block gets rendered.
> >>
> >> <t:pagelink page="Index">refresh</t:pagelink>
> >>
> >> This time, it's the page parameter of the PageLink component that is
> >> bound, to the literal value "Index" (which is the name of this page).
> This
> >> gets rendered as a URL that re-renders the page, which is how the
> current
> >> time gets updated. You can also create links to other pages in the
> >> application and, as we'll see in later chapters, attach additional
> >> information to the URL beyond just the page name.
> >> Running the Application inside Eclipse
> >>
> >> In the next chapter, we'll start to build a simple hi-lo guessing game,
> but
> >> we've got one more task before then, plus a magic trick.
> >>
> >> The task is to set up Jetty to run our application directly out of our
> >> Eclipse workspace. This is a great way to develop web applications,
> since
> we
> >> don't want to have to use Maven to compile and run the application ...
> or
> >> worse yet, use Maven to package and deploy the application. That's for
> >> later, when we want to put the application into production. For
> development,
> >> we want a fast, agile environment that can keep up with our changes, and
> >> that means we can't wait for redeploys and restarts.
> >>
> >> Choose the *Run ...* item from the Eclipse *Run* menu to get the launch
> >> configuration dialog:
> >>
> >>
> >> <
>
> https://cwiki.apache.org/confluence/download/attachments/23340356/eclipse-run.png
> >
> >>
> >> Select *Jetty Webapp* and click the *New* button, then fill in a few
> >> values:
> >>
> >>
> >> <
>
> https://cwiki.apache.org/confluence/download/attachments/23340356/eclipse-launch.png
> >
> >>
> >> Make sure you clear the field labeled *HTTPS*.
> >>
> >> You can then click *Run* and Jetty will launch (it takes only a few
> >> seconds):
> >>
> >> Once you click Run, Jetty will start up and launch (it should take about
> >> two seconds).
> >>
> >>
> >> <
>
> https://cwiki.apache.org/confluence/download/attachments/23340356/eclipse-jetty.png
> >
> >>
> >> You may now start the application with the URL
> >> http://localhost:8080/tutorial1/.
> >> A Magic Trick
> >>
> >> Now it's time for the magic trick. Edit Index.java and change the
> >> getCurrentTime() method to:
> >> *Index.java (partial)*
> >>
> >> public String getCurrentTime()
> >> {
> >> return "A great day to learn Tapestry";
> >> }
> >>
> >> Make sure you save changes; then click the refresh link in the web
> >> browser:
> >>
> >>
> >> <
>
> https://cwiki.apache.org/confluence/download/attachments/23340356/app-live-reload.png
> >
> >>
> >> This is one of Tapestry's early *wow factor* features: changes to your
> >> component classes are picked up immediately. No restart. No re-deploy.
> Make
> >> the changes and see them *now*. Nothing should slow you down or get in
> the
> >> way of you getting your job done.
> >>
> >> But ... what if you make a mistake? What if you got the name in the
> >> template wrong. Give it a try; in the template, change ${currentTime}
> to,
> >> say, ${currenTime}, and see what you get:
> >>
> >>
> >> <
>
> https://cwiki.apache.org/confluence/download/attachments/23340356/app-error-1.png
> >
> >>
> >> This is Tapestry's exception report page. It's quite detailed. It
> clearly
> >> identifies what Tapestry was doing, and relates the problem to a
> specific
> >> line in the template, which is shown in context. Tapestry always expands
> out
> >> the entire stack of exceptions, because it is so common for exceptions
> to
> be
> >> thrown, caught, and re-thrown inside other exceptions. In fact, if we
> scroll
> >> down just a little bit, we see more detail about this exception, plus a
> >> little bit of help:
> >>
> >>
> >> <
>
> https://cwiki.apache.org/confluence/download/attachments/23340356/app-error-2.png
> >
> >>
> >> This is part of Tapestry's way: it not only spells out exactly what it
> was
> >> doing and what went wrong, but it even helps you find a solution; here
> it
> >> tells you the names of properties you could have used.
> >>
> >> Tapestry displays the stack trace of the deepest exception, along with
> lots
> >> of details about the runtime environment: details about the current
> request,
> >> the HttpSession (if one exists), and even a detailed list of all JVM
> system
> >> properties. Scroll down to see all this information.
> >> This level of detail reflects that the application has been configured
> to
> >> run in *development mode* instead of *production mode*. In production
> >> mode, the exception report would simply be the top level exception
> message.
> >> However, most production applications go further and customize how
> Tapestry
> >> handles and reports exceptions.
> >>
> >> Now that we have our basic application set up, and ready to run (or
> debug)
> >> directly inside Eclipse, we can start working on implementing our Hi/Lo
> game
> >> in earnest.
> >> ------------------------------
> >>
> >> Footnotes Reference Notes 1
> >> <https://cwiki.apache.org/confluence#FootnoteMarker1> Yes, I'm on a
> Mac.
> >> Get one. 2 <https://cwiki.apache.org/confluence#FootnoteMarker2> By
> >> static, we mean unchanging, as opposed to a dynamically generated
> Tapestry
> >> page. 3 <https://cwiki.apache.org/confluence#FootnoteMarker3> Tapestry
> >> does *not* use reflection to implement property expressions. 4
> >> <https://cwiki.apache.org/confluence#FootnoteMarker4> Keep in mind that
> >> as far as JavaBeans properties go, it's the *methods* that count; the
> >> names of the instance variables, or even whether they exist, is
> immaterial. 5
> >> <https://cwiki.apache.org/confluence#FootnoteMarker5> Ok, there's a
> third
> >> way as well, which will be discussed in good time.
> >>
> >> Continue on to chapter 3: Implementing The Hi/Lo Game<
> https://cwiki.apache.org/confluence/display/TAPESTRY/Hilo>
> >> Change Notification Preferences<
> https://cwiki.apache.org/confluence/users/viewnotifications.action>
> >> View Online <https://cwiki.apache.org/confluence/display/TAPESTRY/First
> >
> |
> >> View Changes<
>
> https://cwiki.apache.org/confluence/pages/diffpagesbyversion.action?pageId=23340356&revisedVersion=13&originalVersion=12
> >
> >>
>



-- 
Howard M. Lewis Ship

Creator of Apache Tapestry

The source for Tapestry training, mentoring and support. Contact me to learn
how I can get you up and productive in Tapestry fast!

(971) 678-5210
http://howardlewisship.com

Reply via email to