Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Fix next link

...

Scrollbar

...

In the previous chapters, we saw how Tapestry can handle simple links, even links that pass information in the URL. In this chapter, we'll see how Tapestry can do the same, and quite a bit more, for HTML forms.

...

Code Block
languagejava
titlesrc/main/java/com/example/tutorial/entities/Address.java
package com.example.tutorialtutorial1.entities;

import com.example.tutorialtutorial1.data.Honorific;

public class Address
{
    public Honorific honorific;
    public String firstName;
    public String lastName;
    public String street1;
    public String street2;
    public String city;
    public String state;
    public String zip;
    public String email;
    public String phone;
}

...

Code Block
languagejava
titlesrc/main/java/com/example/tutorial/data/Honorific.java
package com.example.tutorialtutorial1.data;

public enum Honorific
{
    MR, MRS, MISS, DR
}

...

Code Block
languagejava
titlesrc/main/java/com/example/tutorial/pages/address/CreateAddress.java
package com.example.tutorialtutorial1.pages.address;

public class CreateAddress
{

}

So ... why is the class named "CreateAddress" and not simply "Create"? Actually, we could have named it "Create", and the application would still work, but the longer class name is equally valid. Tapestry noticed the redundancy in the class name (com.example.tutorialtutorial1.pages.address.CreateAddress) and just stripped out the redundant suffix.

Tapestry actually creates a bunch of aliases for you pages; any of these aliases are valid and can appear in URLs or in the page parameter of PageLink.  You can see the list in the console:

Code Block
[INFO] TapestryModule.ComponentClassResolver Available pages (12):
              (blank): com.example.tutorialtutorial1.pages.Index
   ComponentLibraries: org.apache.tapestry5.corelib.pages.ComponentLibraries
             Error404: com.example.tutorialtutorial1.pages.Error404
      ExceptionReport: org.apache.tapestry5.corelib.pages.ExceptionReport
             GameOver: com.example.tutorialtutorial1.pages.GameOver
                Guess: com.example.tutorialtutorial1.pages.Guess
                Index: com.example.tutorialtutorial1.pages.Index
          PageCatalog: org.apache.tapestry5.corelib.pages.PageCatalog
PropertyDisplayBlocks: org.apache.tapestry5.corelib.pages.PropertyDisplayBlocks
   PropertyEditBlocks: org.apache.tapestry5.corelib.pages.PropertyEditBlocks
        ServiceStatus: org.apache.tapestry5.corelib.pages.ServiceStatus
          T5Dashboard: org.apache.tapestry5.corelib.pages.T5Dashboard
       address/Create: com.example.tutorialtutorial1.pages.address.CreateAddress
address/CreateAddress: com.example.tutorialtutorial1.pages.address.CreateAddress

Tapestry users the shortest alias when constructing URLs.

Eventually, your application will probably have more entities: perhaps you'll have a "user/Create" page and a "payment/Create" page and an "account/Create" page. You could have a bunch of different classes all named Create spread across a number of different packages. That's legal Java, but it isn't ideal. You may find yourself accidentally editing the Java code for creating an Account when you really want to be editing the code for creating a Payment.

Tapestry is encouraging you to use a more descriptive name: CreateAddress, not just Create, but it isn't making you pay the cost (in terms of longer, uglier URLs). The URL to access the page will still be http://localhost:8080/tutorial1/address/create.

...

Info

Index pages work in folders as well. A class named com.example.tutorialtutorial1.pages.address.AddressIndex would be given the name "address/Index". However, Tapestry has special rules for pages named "Index" and the rendered URL would be 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.

...

When you refresh the page, you may see a warning like the following at the top of the page:

Image RemovedImage Added

If you see that, it means you need to invent an HMAC passphrase for your app. Just edit your AppModule.java class (in your services package), adding a couple of lines to the contributeApplicationDefaults method like the following:

...

After you do that, stop the app and restart it, and click on the Create new address link again, and you'll see something like this:

Image Modified

Tapestry has done quite a bit of work here. It has created a form that includes a field for each property. Further, it has seen that the honorific property is an enumerated type, and presented that as a drop-down list.

...

Code Block
languagexml
titleCreateAddress.tml (partial)
    <t:beaneditform object="address"
        reorder="honorific,firstName,lastName,street1,street2,city,state,zip,email,phone" />

Image Modified

Customizing labels

...

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.

Image Modified

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:

...

The final result shows the reformatting and relabelling:

Image Modified

Before continuing on to validation, a side note about message catalogs. Message catalogs are not just for re-labeling fields and options; we'll see in later chapters how message catalogs are used in the context of localization and internationalization.

...

Restart the application, and refresh your browser, then hit the Create Address button.

Image Modified

This is a shot just after hitting the Create Address button; all the fields have been validated and errors displayed. Each field in error has been highlighted in red and had an error message added. 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. And all of this is taking place on the client side, without any communication with the application.

...

Let's give it a try; restart the application and enter an "abc" for the zip code.

Image Modified

This is what you'll see after typing "abc" and clicking the Create Address button.

...

Refresh the page and submit again:

Image Modified

This trick isn't limited to just the regexp validator, it works equally well with any validator.

...

By now you are likely curious about what happens after the form submits successfully (without validation errors), so that's what we'll focus on next.

Next: Using Tapestry With Hibernate

 

...

Scrollbar

...