You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2008/05/06 18:47:44 UTC

svn commit: r653834 - in /tapestry/tapestry5/trunk/tapestry-tutorial1: ./ src/main/java/org/apache/tapestry/tutorial/entities/ src/main/java/org/apache/tapestry/tutorial/pages/ src/main/java/org/apache/tapestry/tutorial/pages/address/ src/main/resource...

Author: hlship
Date: Tue May  6 09:47:43 2008
New Revision: 653834

URL: http://svn.apache.org/viewvc?rev=653834&view=rev
Log:
Update the Tutorial:
- Use simple field name (no leading underscore)
- Fill out page forms2, to discuss the submit event and configuring Hibernate
- Introduce the Grid component

Added:
    tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/java/org/apache/tapestry/tutorial/entities/
    tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/java/org/apache/tapestry/tutorial/entities/Address.java
      - copied, changed from r647587, tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/java/org/apache/tapestry/tutorial/data/Address.java
    tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/resources/hibernate.cfg.xml
Removed:
    tapestry/tapestry5/trunk/tapestry-tutorial1/src/site/resources/address-v4.png
Modified:
    tapestry/tapestry5/trunk/tapestry-tutorial1/pom.xml
    tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/java/org/apache/tapestry/tutorial/pages/GameOver.java
    tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/java/org/apache/tapestry/tutorial/pages/Guess.java
    tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/java/org/apache/tapestry/tutorial/pages/Index.java
    tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/java/org/apache/tapestry/tutorial/pages/address/CreateAddress.java
    tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/resources/log4j.properties
    tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/webapp/Index.tml
    tapestry/tapestry5/trunk/tapestry-tutorial1/src/site/apt/forms.apt
    tapestry/tapestry5/trunk/tapestry-tutorial1/src/site/apt/forms2.apt
    tapestry/tapestry5/trunk/tapestry-tutorial1/src/site/apt/hilo.apt
    tapestry/tapestry5/trunk/tapestry-tutorial1/src/site/resources/address-v6.png
    tapestry/tapestry5/trunk/tapestry-tutorial1/src/site/resources/address-v7.png
    tapestry/tapestry5/trunk/tapestry-tutorial1/src/site/resources/address-v8.png

Modified: tapestry/tapestry5/trunk/tapestry-tutorial1/pom.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-tutorial1/pom.xml?rev=653834&r1=653833&r2=653834&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-tutorial1/pom.xml (original)
+++ tapestry/tapestry5/trunk/tapestry-tutorial1/pom.xml Tue May  6 09:47:43 2008
@@ -25,10 +25,48 @@
     <dependencies>
         <dependency>
             <groupId>org.apache.tapestry</groupId>
-            <artifactId>tapestry-core</artifactId>
+            <artifactId>tapestry-hibernate</artifactId>
             <version>${project.version}</version>
         </dependency>
 
+        <dependency>
+            <groupId>org.apache.geronimo.specs</groupId>
+            <artifactId>geronimo-jta_1.0.1B_spec</artifactId>
+            <version>1.1.1</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.hibernate</groupId>
+            <artifactId>hibernate</artifactId>
+            <version>3.2.2.ga</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>javax.transaction</groupId>
+                    <artifactId>jta</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>org.hibernate</groupId>
+            <artifactId>hibernate-annotations</artifactId>
+            <version>3.2.1.ga</version>
+        </dependency>
+
+
+        <dependency>
+            <groupId>javax.persistence</groupId>
+            <artifactId>persistence-api</artifactId>
+            <version>1.0</version>
+        </dependency>
+
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <version>5.1.5</version>
+        </dependency>
+
+
         <!-- A dependency on either JUnit or TestNG is required, or the surefire plugin (which runs the tests)
 will fail, preventing Maven from packaging the WAR. Tapestry includes a large number
 of testing facilities designed for use with TestNG (http://testng.org/), so it's recommended. -->

Copied: tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/java/org/apache/tapestry/tutorial/entities/Address.java (from r647587, tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/java/org/apache/tapestry/tutorial/data/Address.java)
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/java/org/apache/tapestry/tutorial/entities/Address.java?p2=tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/java/org/apache/tapestry/tutorial/entities/Address.java&p1=tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/java/org/apache/tapestry/tutorial/data/Address.java&r1=647587&r2=653834&rev=653834&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/java/org/apache/tapestry/tutorial/data/Address.java (original)
+++ tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/java/org/apache/tapestry/tutorial/entities/Address.java Tue May  6 09:47:43 2008
@@ -1,4 +1,4 @@
-// Copyright 2007 The Apache Software Foundation
+// Copyright 2007, 2008 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -12,134 +12,157 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package org.apache.tapestry.tutorial.data;
+package org.apache.tapestry.tutorial.entities;
 
+import org.apache.tapestry.beaneditor.NonVisual;
 import org.apache.tapestry.beaneditor.Validate;
+import org.apache.tapestry.tutorial.data.Honorific;
 
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+
+@Entity
 public class Address
 {
-    private Honorific _honorific;
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+
+    private Honorific honorific;
+
+    private String firstName;
+
+    private String lastName;
 
-    private String _firstName;
+    private String street1;
 
-    private String _lastName;
+    private String street2;
 
-    private String _street1;
+    private String city;
 
-    private String _street2;
+    private String state;
 
-    private String _city;
+    private String zip;
 
-    private String _state;
+    private String email;
 
-    private String _zip;
+    private String phone;
 
-    private String _email;
+    @NonVisual
+    public Long getId()
+    {
+        return id;
+    }
 
-    private String _phone;
+    public void setId(Long id)
+    {
+        this.id = id;
+    }
 
     public Honorific getHonorific()
     {
-        return _honorific;
+        return honorific;
     }
 
     @Validate("required")
     public String getFirstName()
     {
-        return _firstName;
+        return firstName;
     }
 
     public String getLastName()
     {
-        return _lastName;
+        return lastName;
     }
 
     @Validate("required")
     public String getStreet1()
     {
-        return _street1;
+        return street1;
     }
 
     public String getStreet2()
     {
-        return _street2;
+        return street2;
     }
 
     @Validate("required")
     public String getCity()
     {
-        return _city;
+        return city;
     }
 
     @Validate("required")
     public String getState()
     {
-        return _state;
+        return state;
     }
 
     @Validate("required,regexp")
     public String getZip()
     {
-        return _zip;
+        return zip;
     }
 
     public String getEmail()
     {
-        return _email;
+        return email;
     }
 
     public String getPhone()
     {
-        return _phone;
+        return phone;
     }
 
     public void setCity(String city)
     {
-        _city = city;
+        this.city = city;
     }
 
     public void setEmail(String email)
     {
-        _email = email;
+        this.email = email;
     }
 
     public void setFirstName(String firstName)
     {
-        _firstName = firstName;
+        this.firstName = firstName;
     }
 
     public void setHonorific(Honorific honorific)
     {
-        _honorific = honorific;
+        this.honorific = honorific;
     }
 
     public void setLastName(String lastName)
     {
-        _lastName = lastName;
+        this.lastName = lastName;
     }
 
     public void setPhone(String phone)
     {
-        _phone = phone;
+        this.phone = phone;
     }
 
     public void setState(String state)
     {
-        _state = state;
+        this.state = state;
     }
 
     public void setStreet1(String street1)
     {
-        _street1 = street1;
+        this.street1 = street1;
     }
 
     public void setStreet2(String street2)
     {
-        _street2 = street2;
+        this.street2 = street2;
     }
 
     public void setZip(String zip)
     {
-        _zip = zip;
+        this.zip = zip;
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/java/org/apache/tapestry/tutorial/pages/GameOver.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/java/org/apache/tapestry/tutorial/pages/GameOver.java?rev=653834&r1=653833&r2=653834&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/java/org/apache/tapestry/tutorial/pages/GameOver.java (original)
+++ tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/java/org/apache/tapestry/tutorial/pages/GameOver.java Tue May  6 09:47:43 2008
@@ -11,6 +11,19 @@
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
+// Copyright 2007, 2008 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
 
 package org.apache.tapestry.tutorial.pages;
 
@@ -21,11 +34,11 @@
 {
     @Persist
     @Property
-    private int _count;
+    private int count;
 
     Object initialize(int count)
     {
-        _count = count;
+        this.count = count;
 
         return this;
     }

Modified: tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/java/org/apache/tapestry/tutorial/pages/Guess.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/java/org/apache/tapestry/tutorial/pages/Guess.java?rev=653834&r1=653833&r2=653834&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/java/org/apache/tapestry/tutorial/pages/Guess.java (original)
+++ tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/java/org/apache/tapestry/tutorial/pages/Guess.java Tue May  6 09:47:43 2008
@@ -14,52 +14,52 @@
 
 package org.apache.tapestry.tutorial.pages;
 
-import org.apache.tapestry.annotations.Property;
 import org.apache.tapestry.annotations.InjectPage;
 import org.apache.tapestry.annotations.Persist;
+import org.apache.tapestry.annotations.Property;
 
 public class Guess
 {
     @Persist
-    private int _target;
+    private int target;
 
     @Property
-    private int _guess;
+    private int guess;
 
     @Persist
     @Property
-    private String _message;
+    private String message;
 
     @Persist
-    private int _count;
+    private int count;
 
     @InjectPage
-    private GameOver _gameOver;
+    private GameOver gameOver;
 
     Object onActionFromLink(int guess)
     {
-        _count++;
+        count++;
 
-        if (guess == _target) return _gameOver.initialize(_count);
+        if (guess == target) return gameOver.initialize(count);
 
-        if (guess < _target)
-            _message = String.format("%d is too low.", guess);
+        if (guess < target)
+            message = String.format("%d is too low.", guess);
         else
-            _message = String.format("%d is too high.", guess);
+            message = String.format("%d is too high.", guess);
 
         return null;
     }
 
     Object initialize(int target)
     {
-        _target = target;
-        _count = 0;
+        this.target = target;
+        count = 0;
 
         return this;
     }
 
     public int getTarget()
     {
-        return _target;
+        return target;
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/java/org/apache/tapestry/tutorial/pages/Index.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/java/org/apache/tapestry/tutorial/pages/Index.java?rev=653834&r1=653833&r2=653834&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/java/org/apache/tapestry/tutorial/pages/Index.java (original)
+++ tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/java/org/apache/tapestry/tutorial/pages/Index.java Tue May  6 09:47:43 2008
@@ -15,20 +15,33 @@
 package org.apache.tapestry.tutorial.pages;
 
 import org.apache.tapestry.annotations.InjectPage;
+import org.apache.tapestry.ioc.annotations.Inject;
+import org.apache.tapestry.tutorial.entities.Address;
+import org.hibernate.Session;
 
+import java.util.List;
 import java.util.Random;
 
 public class Index
 {
-    private final Random _random = new Random();
+    private final Random random = new Random();
 
     @InjectPage
-    private Guess _guess;
+    private Guess guess;
+
+    @Inject
+    private Session session;
 
     Object onAction()
     {
-        int target = _random.nextInt(10) + 1;
+        int target = random.nextInt(10) + 1;
+
+        return guess.initialize(target);
+    }
 
-        return _guess.initialize(target);
+    @SuppressWarnings({ "unchecked" })
+    public List<Address> getAddresses()
+    {
+        return session.createCriteria(Address.class).list();
     }
 }
\ No newline at end of file

Modified: tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/java/org/apache/tapestry/tutorial/pages/address/CreateAddress.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/java/org/apache/tapestry/tutorial/pages/address/CreateAddress.java?rev=653834&r1=653833&r2=653834&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/java/org/apache/tapestry/tutorial/pages/address/CreateAddress.java (original)
+++ tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/java/org/apache/tapestry/tutorial/pages/address/CreateAddress.java Tue May  6 09:47:43 2008
@@ -1,4 +1,4 @@
-// Copyright 2007 The Apache Software Foundation
+// Copyright 2007, 2008 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -14,11 +14,30 @@
 
 package org.apache.tapestry.tutorial.pages.address;
 
+import org.apache.tapestry.annotations.InjectPage;
 import org.apache.tapestry.annotations.Property;
-import org.apache.tapestry.tutorial.data.Address;
+import org.apache.tapestry.hibernate.annotations.CommitAfter;
+import org.apache.tapestry.ioc.annotations.Inject;
+import org.apache.tapestry.tutorial.entities.Address;
+import org.apache.tapestry.tutorial.pages.Index;
+import org.hibernate.Session;
 
 public class CreateAddress
 {
     @Property
-    private Address _address;
+    private Address address;
+
+    @Inject
+    private Session session;
+
+    @InjectPage
+    private Index index;
+
+    @CommitAfter
+    Object onSuccess()
+    {
+        session.persist(address);
+
+        return index;
+    }
 }

Added: tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/resources/hibernate.cfg.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/resources/hibernate.cfg.xml?rev=653834&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/resources/hibernate.cfg.xml (added)
+++ tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/resources/hibernate.cfg.xml Tue May  6 09:47:43 2008
@@ -0,0 +1,23 @@
+<!DOCTYPE hibernate-configuration PUBLIC
+        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
+        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
+<hibernate-configuration>
+    <session-factory>
+        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
+        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/t5_tutorial1</property>
+        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
+
+        <!--
+
+        To create user, login a root and:
+
+            grant all on t5_tutorial1.* to 't5tutorialuser'@'localhost' identified by 'secret';
+
+        -->
+        <property name="hibernate.connection.username">t5tutorialuser</property>
+        <property name="hibernate.connection.password">secret</property>
+        <property name="hbm2ddl.auto">update</property>
+        <property name="hibernate.show_sql">true</property>
+        <property name="hibernate.format_sql">true</property>
+    </session-factory>
+</hibernate-configuration>

Modified: tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/resources/log4j.properties
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/resources/log4j.properties?rev=653834&r1=653833&r2=653834&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/resources/log4j.properties (original)
+++ tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/resources/log4j.properties Tue May  6 09:47:43 2008
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-log4j.rootCategory=WARN, A1
+log4j.rootCategory=info, A1
 
 # A1 is set to be a ConsoleAppender. 
 log4j.appender.A1=org.apache.log4j.ConsoleAppender

Modified: tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/webapp/Index.tml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/webapp/Index.tml?rev=653834&r1=653833&r2=653834&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/webapp/Index.tml (original)
+++ tapestry/tapestry5/trunk/tapestry-tutorial1/src/main/webapp/Index.tml Tue May  6 09:47:43 2008
@@ -14,6 +14,8 @@
 
         <h1>Address Book</h1>
 
+        <t:grid source="addresses"/>
+
         <ul>
             <li>
                 <t:pagelink page="address/create">Create new address</t:pagelink>

Modified: tapestry/tapestry5/trunk/tapestry-tutorial1/src/site/apt/forms.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-tutorial1/src/site/apt/forms.apt?rev=653834&r1=653833&r2=653834&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-tutorial1/src/site/apt/forms.apt (original)
+++ tapestry/tapestry5/trunk/tapestry-tutorial1/src/site/apt/forms.apt Tue May  6 09:47:43 2008
@@ -10,135 +10,138 @@
   Form support in Tapestry is deep and rich, more than can be covered in a single chapter. However, we can show the basics, including
   some very common development patterns. To get started, let's create a simple address book application.
   
-  We'll start with the data, a simple object to store the information we'll need. By convention, these classes go in a <<<data>>> sub-package.  Unlike
-  the use of the <<<pages>>> sub-package (for page component classes), this is not enforced by Tapestry; it's just a convention.
+  We'll start with the entity data, a simple object to store the information we'll need. These classes go in an <<<entities>>> sub-package.  Unlike
+  the use of the <<<pages>>> sub-package (for page component classes), this is not enforced by Tapestry; it's just a convention (but
+  as we'll see shortly, a handy one).
   
   
-  <<src/main/java/org/apache/tapestry/tutorial/data/Address.java:>>
+  <<src/main/java/org/apache/tapestry/tutorial/entities/Address.java:>>
   
 ----
-package org.apache.tapestry.tutorial.data;
+package org.apache.tapestry.tutorial.entities;
+
+import org.apache.tapestry.tutorial.data.Honorific;
 
 public class Address
 {
-  private Honorific _honorific;
+  private Honorific honorific;
 
-  private String _firstName;
+  private String firstName;
 
-  private String _lastName;
+  private String lastName;
 
-  private String _street1;
+  private String street1;
 
-  private String _street2;
+  private String street2;
 
-  private String _city;
+  private String city;
 
-  private String _state;
+  private String state;
 
-  private String _zip;
+  private String zip;
 
-  private String _email;
+  private String email;
 
-  private String _phone;
+  private String phone;
 
   public String getCity()
   {
-    return _city;
+    return city;
   }
 
   public String getEmail()
   {
-    return _email;
+    return email;
   }
 
   public String getFirstName()
   {
-    return _firstName;
+    return firstName;
   }
 
   public Honorific getHonorific()
   {
-    return _honorific;
+    return honorific;
   }
 
   public String getLastName()
   {
-    return _lastName;
+    return lastName;
   }
 
   public String getPhone()
   {
-    return _phone;
+    return phone;
   }
 
   public String getState()
   {
-    return _state;
+    return state;
   }
 
   public String getStreet1()
   {
-    return _street1;
+    return street1;
   }
 
   public String getStreet2()
   {
-    return _street2;
+    return street2;
   }
 
   public String getZip()
   {
-    return _zip;
+    return zip;
   }
 
   public void setCity(String city)
   {
-    _city = city;
+    this.city = city;
   }
 
   public void setEmail(String email)
   {
-    _email = email;
+    this.email = email;
   }
 
   public void setFirstName(String firstName)
   {
-    _firstName = firstName;
+    this.firstName = firstName;
   }
 
   public void setHonorific(Honorific honorific)
   {
-    _honorific = honorific;
+    this.honorific = honorific;
   }
 
   public void setLastName(String lastName)
   {
-    _lastName = lastName;
+    this.lastName = lastName;
   }
 
   public void setPhone(String phone)
   {
-    _phone = phone;
+    this.phone = phone;
   }
 
   public void setState(String state)
   {
-    _state = state;
+    this.state = state;
   }
 
   public void setStreet1(String street1)
   {
-    _street1 = street1;
+    this.street1 = street1;
   }
 
   public void setStreet2(String street2)
   {
-    _street2 = street2;
+    this.street2 = street2;
   }
 
   public void setZip(String zip)
   {
-    _zip = zip;
+    this.zip = zip;
   }
 }
 ----
@@ -219,7 +222,7 @@
 
    Another note:  Index pages work in folders as well.  A class named org.apache.tapestry.tutorial.pages.address.AddressIndex would be given the name
    "address/Index".  However, Tapestry has special rules for pages named "Index" and the render URL would be
-   <<<http://localhost:8080/tutorial1/address"/>>>.  In other words, you can place Index pages in any folder and Tapestry will
+   http://localhost:8080/tutorial1/address/ .  In other words, you can place Index pages in any folder and Tapestry will
    build a short URL for that page ... and you <don't> have to keep naming the classes Index (it's confusing to have many classes with the same
    name, even across multiple packages); instead, you can name each index page after the package
    that contains it.  Tapestry users a smart <convention> to keep it all straight and generate short, to the point URLs.
@@ -238,15 +241,18 @@
   And match that up with a property in the CreateAddress class:
   
 ----
-  @GenerateAcessors
-  private Address _address
+  @Property
+  private Address address
 ----
    
    When you refresh the page, you'll see the following:
    
 [address-v1.png] Initial version of the create address form
 
-  Tapestry's done quite a bit of work here.  Its created a form that includes a field for each property.  Further, its seen that the
+  <There have been minor changes to the default CSS since this screenshot was taken; for example, the labels are a bit
+   wider now.  In addition, the Honorific field (being optional) would include a blank option, rather than the first real selection, "Mr".>
+
+  Tapestry's done quite a bit of work here.  It has created a form that includes a field for each property.  Further, its seen that the
   honorific property is an enumerated type, and presented that as a drop-down list.
   
   In addition, Tapestry has converted the property names ("city", "email", "firstName") to user presentable labels ("City", "Email", "First Name").
@@ -312,28 +318,10 @@
 phone-label=Phone Number
 ----
 
-  Since this is a <new> file (and not a change to an existing file), you will have to restart Jetty to force Tapestry to pick up the change.
+  Since this is a <new> file (and not a change to an existing file), you may have to restart Jetty to force Tapestry to pick up the change.
   
 [address-v3.png] Create Address form with field labels corrected
   
-  However, things are getting a little crowded in the form.  That too is easy to fix: we can just provide our own overriding
-  Cascading Style Sheet (CSS) rules.  Tapestry has automatically injected a built-in CSS style sheet to provide the fonts and colors in the page, we
-  just need to tweak it a bit.  Add the following to CreateAddress.html:
-  
-----
-<style>
-  DIV.t-beaneditor LABEL { 
-    width: 200px;
-  }
-</style>
-----    
-
-  The "t-beaneditor" CSS class refers to a \<div\> element around the \<label\> element.  Tapestry's style classes are all prefixed with "t-" (for "Tapestry") so that
-  they don't conflict with anything your own web designers may decide to use.  In any case, this CSS rule forces the label to be 200 pixels wide (rather than
-  the default, which is 10% of the overall page width).
-  
-[address-v4.png] Corrected width on labels
-
    We can also customize the options in the drop down list.  All we have to do is add some more entries to the message catalog matching the enum names to the desired labels.
    Update CreateAddress.properties and add:
    
@@ -344,7 +332,7 @@
 ----
 
   Notice that we don't have to include an option for MISS, because that is converted to "Miss" anyway.  You might just want to include it for
-  consistencie's sake ... the point is, each option label is searched for seperately.
+  sake of consistency ... the point is, each option label is searched for seperately.
 
   Lastly, the default label on the submit button is "Create/Update" (BeanEditForm doesn't know how it is being used). Let's change that to "Create Address".
   
@@ -370,7 +358,7 @@
   label will go in the message catalog. 
   
   In Tapestry, when binding a parameter, the value you provide may include a prefix.  The prefix guides Tapestry in how to interpret the rest of the
-  the parameter value ... is it the name of a property?  The id of a component? A message key?  Most fields have a default prefix, usually "prop:" that
+  the parameter value ... is it the name of a property?  The id of a component? A message key?  Most fields have a default prefix, usually "prop:", that
   is used when you fail to provide one (this helps to make the templates as terse as possible).
   
   Here we want to reference a message from the catalog, so we use the "message:" prefix:
@@ -402,7 +390,7 @@
   @Validate("required")
   public String getFirstName()
   {
-    return _firstName;
+    return firstName;
   }
 ----
 
@@ -416,14 +404,15 @@
     
 [address-v6.png] Form with client side validations visible
 
-  <<TODO: Update this with a more recent image showing the new pop-up bubbles style of displaying client-side error messages.>>
+  This is a shot just after hitting the submit button; all the fields have been validated and pop-up error bubbles are displayed.  This looks a bit cluttered, but all the bubbles, except for the one
+  for the focus field (the field the user is actively typing into), will fade out after a moment.  As you tab from field to field, Tapestry will validate your input and briefly display the error bubble.  And <all> of this
+  is taking place on the client side, without any communication with the application.
 
-  What this picture doesn't show is that the validation occurred entirely <on the client side>, using JavaScript. Look what's happened: a summary of <all> the
-  errors in the form has scrolled down at the top of the form, and each form in error has been highlighted (it's a bit subtle) and marked with a red "X".  Further, the label
+  Each field in error has been highlighted (it's a bit subtle) and marked with a red "X".  Further, the label
   for each of the fields has also been highlighted in red, to even more clearly identify what's in error.  The cursor has also been moved to the first field
   that's in error.
   
-  Again, all of this validation occured entirely on the client side, no request was sent to the server.  However, once all the errors are corrected, and the form does submit,
+  Once all the errors are corrected, and the form does submit,
   all validations are performed on the server side as well (just in
   case the client has JavaScript disabled).
 
@@ -434,7 +423,7 @@
   @Validate("required,regexp=\\d{5}(-\\d{4})?")
   public String getZip()
   {
-    return _zip;
+    return zip;
   }    
 ----
 
@@ -442,7 +431,12 @@
   
 [address-v7.png] Regexp validation
 
-  That's the right behavior, but it's the wrong message.  Fortunately, it's easy to customize validation messages.  All we need to know is the name of the
+  This is what you'll see after typing "abc" and tabbing out of the field, then tabbing back in. It's a little hard to capture all the animation
+  effects in a still photo.
+
+  In any case, that's the right validation behavior, but it's the wrong message. Your users are not going to know or care about regular expressions.
+
+  Fortunately, it's easy to customize validation messages.  All we need to know is the name of the
   property ("zip") and the name of the validator ("regexp").  We can then put an entry into the CreateAddress message catalog:
   
 ----
@@ -456,18 +450,18 @@
   This trick isn't limited to just the regexp validator, it works equally well with <any> validator.
   
   Let's go one step further.  Turns out, we can move the
-  regexp pattern to the message catalog as well.  If you only provide the name of the validator in the @Validator annotation, Tapestry will search the containing
+  regexp pattern to the message catalog as well.  If you only provide the name of the validator in the @Validate annotation, Tapestry will search the containing
   page's message catalog of the constraint value, as well as the validation message.  The constraint value for the regexp validator is the regular expression to match against.
   
 ----
   @Validate("required,regexp")
   public String getZip()
   {
-    return _zip;
+    return zip;
   }
 ----
 
-  Now, just put the value into the CreateAddress message catalog:
+  Now, just put the regular expression  into the CreateAddress message catalog:
   
 ----
 zip-regexp=\\d{5}(-\\d{4})?

Modified: tapestry/tapestry5/trunk/tapestry-tutorial1/src/site/apt/forms2.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-tutorial1/src/site/apt/forms2.apt?rev=653834&r1=653833&r2=653834&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-tutorial1/src/site/apt/forms2.apt (original)
+++ tapestry/tapestry5/trunk/tapestry-tutorial1/src/site/apt/forms2.apt Tue May  6 09:47:43 2008
@@ -4,4 +4,470 @@
  
 Chapter 5: Forms in Tapestry (Part Two)
 
-  <Still working on it!>
+  So, you fill in all the fields, submit the form (without validation errors) and voila:  you get back the same
+  form, blanked out.  What happened, and where did the data go?
+
+  What happened is that we haven't told Tapestry what to do after the form is succesfully submitted (by succesful, we mean,
+  with no validation errors).  Tapestry's default behavior is to redisplay the active page, and that occurs in a new
+  request, with a new instance of the Address object (because the _address field is not a peristent field).
+
+  Well, since we're creating objects, we might as well store them somewhere ... in a database.  We're going to
+  quickly integrate Tapestry with {{{http://hibernate.org}Hibernate}} as the object/relational mapping layer,
+  and ultimately store our data inside a {{{http://www.mysql.com/}MySQL}} database.  You'll have to download
+  and install MySQL on your own.
+
+  In addition, we need to create the database and user.  The database will be "t5_tutorial1" and
+  the user will be "t5tutorialuser" with password "secret". This is accomplished from the
+  command line using the mysql shell.
+
+  The two commands are:
+
+  *   create database t5_tutorial1;
+
+  *   grant all on t5_tutorial1.* to 't5tutorialuser'@'localhost' identified by 'secret';
+
+  []
+
+  Log into the MySQL monitor shell as user root to execute the commands:
+
+----
+$ mysql -u root -p
+Enter password:
+Welcome to the MySQL monitor.  Commands end with ; or \g.
+Your MySQL connection id is 4
+Server version: 5.0.51a MySQL Community Server (GPL)
+
+Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
+
+mysql> create database t5_tutorial1;
+Query OK, 1 row affected (0.08 sec)
+
+
+mysql> grant all on t5_tutorial1.* to 't5tutorialuser'@'localhost' identified by 'secret';
+Query OK, 0 rows affected (0.00 sec)
+
+mysql>
+---
+
+Re-configuring the Project
+
+  We're going to bootstrap this project from a simple Tapestry project to one that uses Hibernate and MySQL.
+
+
+* Updating the Dependencies
+
+  First, we must update the POM to list a new set of dependencies, that includes Hibernate,
+  the Tapestry/Hibernate integration library, and the MySQL JDBC driver.
+
+  <<src/pom.xml (partial):>>
+
+----
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.tapestry</groupId>
+            <artifactId>tapestry-hibernate</artifactId>
+            <version>${tapestry-release-version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.geronimo.specs</groupId>
+            <artifactId>geronimo-jta_1.0.1B_spec</artifactId>
+            <version>1.1.1</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.hibernate</groupId>
+            <artifactId>hibernate</artifactId>
+            <version>3.2.2.ga</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>javax.transaction</groupId>
+                    <artifactId>jta</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>org.hibernate</groupId>
+            <artifactId>hibernate-annotations</artifactId>
+            <version>3.2.1.ga</version>
+        </dependency>
+
+        <dependency>
+            <groupId>javax.persistence</groupId>
+            <artifactId>persistence-api</artifactId>
+            <version>1.0</version>
+        </dependency>
+
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <version>5.1.5</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.testng</groupId>
+            <artifactId>testng</artifactId>
+            <version>5.1</version>
+            <classifier>jdk15</classifier>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.easymock</groupId>
+            <artifactId>easymock</artifactId>
+            <version>2.3</version>
+            <scope>test</scope>
+        </dependency>
+
+    </dependencies>
+----
+
+* Hibernate Configuration
+
+  Hibernate has a master configuration file used to store connection and other data.
+
+  <<src/main/resources/hibernate.cfg.xml:>>
+
+----
+<!DOCTYPE hibernate-configuration PUBLIC
+        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
+        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
+<hibernate-configuration>
+    <session-factory>
+        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
+        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/t5_tutorial1</property>
+        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
+        <property name="hibernate.connection.username">t5tutorialuser</property>
+        <property name="hibernate.connection.password">secret</property>
+        <property name="hbm2ddl.auto">update</property>
+        <property name="hibernate.show_sql">true</property>
+        <property name="hibernate.format_sql">true</property>
+    </session-factory>
+</hibernate-configuration>
+----
+
+
+  Most of the configuration is to identify the JDBC driver and connection URL.
+
+  In addition, we are configuring Hibernate to <update> the database schema; when Hibernate initializes
+  it will create or even modify tables to match the entities.  Finally, we are configuring Hibernate
+  to output any SQL it executes, which is very useful when initially building an application.
+
+  But what entities?  Normally, the available entities are listed inside hibernate.cfg.xml, but that's not necessary
+  with Tapestry; in another example of convention over configuration, Tapestry locates all entity classes
+  inside the entities package and adds them to the configuration. Currently, that is just the Address entity.
+
+Adding Hibernate Annotations
+
+  For an entity class to be used with Hibernate, some Hibernate annotations must be added to the class.
+
+  Below is the updated Address class, with the Hibernate annotations (as well as the Tapestry ones).  Hibernate
+  annotations can be applied to fields or to accessor methods, but the Tapestry annotations we use below
+  are for methods only.
+
+  <<src/main/java/org/apache/tapestry/tutorial/entities/Address.java:>>
+
+----
+package org.apache.tapestry.tutorial.entities;
+
+import org.apache.tapestry.beaneditor.NonVisual;
+import org.apache.tapestry.beaneditor.Validate;
+import org.apache.tapestry.tutorial.data.Honorific;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+
+@Entity
+public class Address
+{
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+
+    private Honorific honorific;
+
+    private String firstName;
+
+    private String lastName;
+
+    private String street1;
+
+    private String street2;
+
+    private String city;
+
+    private String state;
+
+    private String zip;
+
+    private String email;
+
+    private String phone;
+
+    @NonVisual
+    public Long getId()
+    {
+        return id;
+    }
+
+    public void setId(Long id)
+    {
+        this.id = id;
+    }
+
+    public Honorific getHonorific()
+    {
+        return honorific;
+    }
+
+    @Validate("required")
+    public String getFirstName()
+    {
+        return firstName;
+    }
+
+    public String getLastName()
+    {
+        return lastName;
+    }
+
+    @Validate("required")
+    public String getStreet1()
+    {
+        return street1;
+    }
+
+    public String getStreet2()
+    {
+        return street2;
+    }
+
+    @Validate("required")
+    public String getCity()
+    {
+        return city;
+    }
+
+    @Validate("required")
+    public String getState()
+    {
+        return state;
+    }
+
+    @Validate("required,regexp")
+    public String getZip()
+    {
+        return zip;
+    }
+
+    public String getEmail()
+    {
+        return email;
+    }
+
+    public String getPhone()
+    {
+        return phone;
+    }
+
+    public void setCity(String city)
+    {
+        this.city = city;
+    }
+
+    public void setEmail(String email)
+    {
+        this.email = email;
+    }
+
+    public void setFirstName(String firstName)
+    {
+        this.firstName = firstName;
+    }
+
+    public void setHonorific(Honorific honorific)
+    {
+        this.honorific = honorific;
+    }
+
+    public void setLastName(String lastName)
+    {
+        this.lastName = lastName;
+    }
+
+    public void setPhone(String phone)
+    {
+        this.phone = phone;
+    }
+
+    public void setState(String state)
+    {
+        this.state = state;
+    }
+
+    public void setStreet1(String street1)
+    {
+        this.street1 = street1;
+    }
+
+    public void setStreet2(String street2)
+    {
+        this.street2 = street2;
+    }
+
+    public void setZip(String zip)
+    {
+        this.zip = zip;
+    }
+}
+----
+
+Updating the Database
+
+  So we have a database up and running, and Hibernate is configured to connect to it.  Let's make use of that
+  to store our Address object in the database.
+
+  What we need is to provide some code to be executed when the form is submitted.  When a Tapestry form
+   is submitted, there is a whole series of events that get fired.  The event we are interested in is the "success"
+   event, which comes late in the process, after all the values have been pulled out of the request and
+   applied to the page properties, and after all server-side validations have occured.
+
+   The success event is only fired if there are no validation errors.
+
+  Our event handler must do two things:
+
+  * Use the Hibernate Session object to persist the new Address object.
+
+  * Commit the transaction to force the data to be written to the database.
+
+  []
+
+  <<src/main/java/org/apache/tapestry/tutorial/pages/address/CreateAddress.java:>>
+
+----
+package org.apache.tapestry.tutorial.pages.address;
+
+import org.apache.tapestry.annotations.InjectPage;
+import org.apache.tapestry.annotations.Property;
+import org.apache.tapestry.hibernate.annotations.CommitAfter;
+import org.apache.tapestry.ioc.annotations.Inject;
+import org.apache.tapestry.tutorial.entities.Address;
+import org.apache.tapestry.tutorial.pages.Index;
+import org.hibernate.Session;
+
+public class CreateAddress
+{
+    @Property
+    private Address address;
+
+    @Inject
+    private Session session;
+
+    @InjectPage
+    private Index index;
+
+    @CommitAfter
+    Object onSuccess()
+    {
+        session.persist(address);
+
+        return index;
+    }
+}
+----
+
+  The {{{../apidocs/org/apache/tapestry/ioc/annotations/Inject.html}Inject}} annotation tells Tapestry to inject a service into the
+  annotated field; 
+  Tapestry includes a sophisticated
+  Inversion of Control container (similar in many ways to Spring) that is very good at locating available services
+  by type, rather than by a string id.  In any case, the Hibernate Session object is exposed as a Tapestry IoC service,
+  ready to be injected (this is one of the things provided by the tapestry-hibernate module).
+
+  Tapestry automatically starts a transaction as necessary; however that transaction will be <aborted> at the end
+  of the request.  If we make changes to persistent objects, such as adding a new Address object,
+  then it is necessary to commit the transaction.
+
+  The {{{../apidocs/org/apache/tapestry/hibernate/annotations/CommitAfter.html}CommitAfter}} annotation can be applied to any component method; if the method completes normally, the transaction
+  will be committed (and a new transaction started to replace the committed transaction).
+
+  After persisting the new address, we return to the main Index page of the application.
+
+  <Note: In real applications, it is rare to have pages and components directly use the Hibernate Session. It
+  is generally a better approach to define your own Data Access Object layer to perform common update operations
+  and queries.>
+
+Showing Addresses
+
+  As a little preview of what's next, let's display all the Addresses entered by the user on the Index page
+  of the application.  After you enter a few names, it will look something like:
+
+[index-grid-v1.png] Adding the Grid to the Index page
+
+  So, how is this implemented?  Primarily, its accomplished by the
+  {{{../tapestry-core/ref/org/apache/tapestry/corelib/components/Grid.html}Grid}} component.
+
+  The Grid component is based on the same concepts as the BeanEditForm component; it can pull apart
+  a bean into columns. The columns are sortable, and when there are more entries than will fit on a single
+  page, page navigation is automatically added.
+
+  A minimal Grid is very easy to add to the template:
+
+  <<src/main/webapp/Index.tml (partial):>>
+
+----
+  <t:grid source="addresses"/>
+----
+
+  And all we have to do is supply the addresses property in the Java code:
+
+  <<src/main/java/org/apache/tapestry/tutorial/pages/Index.java (partial):>>
+
+----
+    @Inject
+    private Session session;
+
+    public List<Address> getAddresses()
+    {
+        return session.createCriteria(Address.class).list();
+    }
+----
+
+What's Next?
+
+  We have lots more to talk about: more components, more customizations, built-in Ajax support,
+  more common design and implementation patterns,
+  and event writing your own components (which is easy!).
+
+  ... but Tapestry and this tutorial are a work in progress, so stay patient, and check out
+  the other Tapestry tutorials and resources available on the
+  {{{../index.html}Tapestry 5 home page}.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

Modified: tapestry/tapestry5/trunk/tapestry-tutorial1/src/site/apt/hilo.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-tutorial1/src/site/apt/hilo.apt?rev=653834&r1=653833&r2=653834&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-tutorial1/src/site/apt/hilo.apt (original)
+++ tapestry/tapestry5/trunk/tapestry-tutorial1/src/site/apt/hilo.apt Tue May  6 09:47:43 2008
@@ -77,11 +77,11 @@
 
 public class Guess
 {
-  private int _target;
+  private int target;
 
   Object initialize(int target)
   {
-    _target = target;
+    this.target = target;
 
     return this;
   }
@@ -92,14 +92,11 @@
    method is package private, not public;
   it is only expected to be invoked from the Index page (as we'll see in a moment), so there's no need to make it public.  Later we'll see that
   there's more initialization to be done
-  than just storing a value into the _target instance variable (which is why we don't simply name the method setTarget() ).
-  
-  <The naming convention, using leading underscores for fields, is NOT a requirement of Tapestry; that's
-   just my personal coding style.>
+  than just storing a value into the target instance variable (which is why we don't simply name the method setTarget() ).
 
   Now we can move back to the Index page.  What we want is to have the ActionLink component invoke a method on the Index page. We can then generate
   a random target number. We'll tell the Guess page what the target number is and then make sure that it is  the Guess page, and not the
-   Index page,
+  Index page,
   that renders the response into the user's web browser.  That's actually quite a few concepts to take in all at once.
   
   Let's start with the code, and break it down:
@@ -115,16 +112,16 @@
 
 public class Start
 {
-  private final Random _random = new Random();
+  private final Random random = new Random();
 
   @InjectPage
-  private Guess _guess;
+  private Guess guess;
 
   Object onAction()
   {
-    int target = _random.nextInt(10) + 1;
+    int target = random.nextInt(10) + 1;
 
-    return _guess.initialize(target);
+    return guess.initialize(target);
   }
 }
 ----
@@ -142,7 +139,7 @@
 
   Injection can be a somewhat nebulous concept.  In terms of Tapestry, it means that some cooperating object needed by one class is provided to it.  The other
   object is often referred to as a "dependency"; in this case, the Index page <depends on> the Guess page to be fully functional, and an instance of the Guess
-  page is made available as the _guess instance variable.  The Index page doesn't, and can't, <create> the Guess page, it can only
+  page is made available as the guess instance variable.  The Index page doesn't, and can't, <create> the Guess page, it can only
   advertise, to Tapestry, that it needs the Guess page.  Tapestry will take care of the rest.
     
   Let's see what we do with this injected page.  It's used inside onAction().  You might guess that this method is invoked when the link ("Start guessing") is clicked.  But
@@ -204,7 +201,7 @@
 ---
   public int getTarget()
   {
-    return _target;
+    return target;
   }
 ---
 
@@ -248,7 +245,7 @@
   The same page instance will be used for request after request. 
   
   So, inside the action request, the code inside the onAction() event handler method <did> call the
-  initialize() method, and a value between 1 and 10 was stored in the _target instance variable. But
+  initialize() method, and a value between 1 and 10 was stored in the target instance variable. But
   at the end of that request, the value was lost, and in the subsequent render request for the Guess page,
   the value was zero.
   
@@ -257,7 +254,7 @@
   
 ----
   @Persist
-  private int _target;
+  private int target;
 ----
 
   Now we can use the browser back button to return to the Start page, and click the link again.
@@ -317,7 +314,7 @@
   
 ---
   @Property
-  private int _guess;
+  private int guess;
 ---
 
   Tapestry will automatically create the methods needed so that the guess property (it's smart
@@ -340,16 +337,16 @@
 ---
   @Persist
   @Property
-  private String _message;
+  private String message;
 
   String onActionFromLink(int guess)
   {
-    if (guess == _target) return "GameOver";
+    if (guess == target) return "GameOver";
 
-    if (guess < _target)
-      _message = String.format("%d is too low.", guess);
+    if (guess < target)
+      message = String.format("%d is too low.", guess);
     else
-      _message = String.format("%d is too high.", guess);
+      message = String.format("%d is too high.", guess);
 
     return null;
   }
@@ -361,7 +358,7 @@
   method parameter.
   We can then compare the guess from the user to the secret target number.
 
-  Notice how Tapestry adapts to the return value.  Here is may be null ... Tapestry interprets that
+  Notice how Tapestry adapts to the return value.  Here it may be null ... Tapestry interprets that
   as "stay on the same page".  You may also return a string ("GameOver"); Tapestry interprets <that>
   as the name of the page to render the response.
   
@@ -421,17 +418,17 @@
 ---
   @Persist
   @Property
-  private int _count;
+  private int count;
 ---
 
-  Next we modified initialize() to ensure that _count is set to 0.  This is a safety
+  Next we modified initialize() to ensure that count is set to 0.  This is a safety
   precaution in case we add logic to play the game again.
   
 ---
   Object initialize(int target)
   {
-    _target = target;
-    _count = 0;
+    this.target = target;
+    this.count = 0;
 
     return this;
   }
@@ -444,14 +441,14 @@
 ---
   Object onActionFromLink(int guess)
   {
-    _count++;
+    count++;
 
-    if (guess == _target) return _gameOver.initialize(_count);
+    if (guess == target) return gameOver.initialize(count);
 
-    if (guess < _target)
-      _message = String.format("%d is too low.", guess);
+    if (guess < target)
+      message = String.format("%d is too low.", guess);
     else
-      _message = String.format("%d is too high.", guess);
+      message = String.format("%d is too high.", guess);
 
     return null;
   }
@@ -474,11 +471,11 @@
 {
   @Persist
   @Property
-  private int _count;
+  private int count;
 
   Object initialize(int count)
   {
-    _count = count;
+    this.count = count;
 
     return this;
   }

Modified: tapestry/tapestry5/trunk/tapestry-tutorial1/src/site/resources/address-v6.png
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-tutorial1/src/site/resources/address-v6.png?rev=653834&r1=653833&r2=653834&view=diff
==============================================================================
Binary files - no diff available.

Modified: tapestry/tapestry5/trunk/tapestry-tutorial1/src/site/resources/address-v7.png
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-tutorial1/src/site/resources/address-v7.png?rev=653834&r1=653833&r2=653834&view=diff
==============================================================================
Binary files - no diff available.

Modified: tapestry/tapestry5/trunk/tapestry-tutorial1/src/site/resources/address-v8.png
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-tutorial1/src/site/resources/address-v8.png?rev=653834&r1=653833&r2=653834&view=diff
==============================================================================
Binary files - no diff available.