Raible's Wiki

Raible Designs
Wiki Home
News
Recent Changes

AppFuse

Homepage
  - Korean
  - Chinese
  - Italian
  - Japanese

QuickStart Guide
  - Chinese
  - French
  - German
  - Italian
  - Korean
  - Portuguese
  - Spanish
  - Japanese

User Guide
  - Korean
  - Chinese

Tutorials
  - Chinese
  - German
  - Italian
  - Korean
  - Portuguese
  - Spanish

FAQ
  - Korean

Latest Downloads

Other Applications

Struts Resume
Security Example
Struts Menu

Set your name in
UserPreferences


Referenced by
Articles
Articles_cn
Articles_de
Articles_pt
Articles_zh
TapestryPages




JSPWiki v2.2.33

[RSS]


Hide Menu

ValidationAndListTapestry


Difference between version 20 and version 1:

At line 12 changed 1 line.
* [2] View JSP with validation added and test
* [2] View HTML with validation added and test
At line 21 changed 1 line.
To implement validation with Tapestry is quite simple. Rather than using a [TextField|http://jakarta.apache.org/tapestry/doc/ComponentReference/TextField.html] component, you use a [ValidField|http://jakarta.apache.org/tapestry/doc/ComponentReference/ValidField.html] components. The validation integration for the personForm.html page is already done by AppGen in the personForm.page. If you open web/pages/personForm.page, you should see the following XML. I've highlighted the portions that are relevant to validation.
Implementing validation with Tapestry is quite simple. All you need to do is configure a "validators" property on your [TextField|http://jakarta.apache.org/tapestry/doc/ComponentReference/TextField.html] components. The validation integration for the personForm.html page is already done by AppGen in the personForm.page. If you open web/pages/personForm.page, you should see the following XML.
At line 23 changed 8 lines.
<pre>
&lt;?xml version="1.0"?&gt;
&lt;!DOCTYPE page-specification PUBLIC
"-//Apache Software Foundation//Tapestry Specification 3.0//EN"
"http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd"&gt;
&lt;page-specification class="org.appfuse.webapp.action.PersonForm"&gt;
<span style="background-color: yellow">&lt;bean name="delegate" class="org.appfuse.webapp.action.Validator"/&gt;</span>
{{{<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE page-specification PUBLIC
"-//Apache Software Foundation//Tapestry Specification 4.0//EN"
"http://jakarta.apache.org/tapestry/dtd/Tapestry_4_0.dtd">
At line 32 changed 4 lines.
<span style="background-color: yellow">&lt;bean name="requiredValidator" class="org.apache.tapestry.valid.StringValidator"&gt;</span>
<span style="background-color: yellow">&lt;set-property name="required" expression="true"/&gt;</span>
<span style="background-color: yellow">&lt;set-property name="clientScriptingEnabled" expression="true"/&gt;</span>
<span style="background-color: yellow">&lt;/bean&gt;</span>
<page-specification class="org.appfuse.webapp.action.PersonForm">
<inject property="engineService" object="engine-service:page"/>
<inject property="request" object="service:tapestry.globals.HttpServletRequest"/>
<inject property="response" object="service:tapestry.globals.HttpServletResponse"/>
<inject property="personManager" type="spring" object="personManager"/>
At line 37 changed 5 lines.
&lt;property-specification name="person" type="org.appfuse.model.Person"/&gt;
&lt;property-specification name="manager" type="org.appfuse.service.Manager"&gt;
global.appContext.getBean("manager")
&lt;/property-specification&gt;
&lt;property-specification name="message" type="java.lang.String"/&gt;
<bean name="delegate" class="org.appfuse.webapp.action.Validator"/>
<property name="message" persist="flash"/>
At line 43 changed 5 lines.
<span style="background-color: yellow">&lt;component id="firstNameField" type="ValidField"&gt;</span>
<span style="background-color: yellow">&lt;binding name="value" expression="person.firstName"/&gt;</span>
<span style="background-color: yellow">&lt;binding name="validator" expression="beans.requiredValidator"/&gt;</span>
<span style="background-color: yellow">&lt;message-binding name="displayName" key="person.firstName"/&gt;</span>
<span style="background-color: yellow">&lt;/component&gt;</span>
<component id="personForm" type="Form">
<binding name="delegate" value="ognl:beans.delegate"/>
<binding name="clientValidationEnabled" value="true"/>
</component>
At line 49 changed 7 lines.
<span style="background-color: yellow">&lt;component id="lastNameField" type="ValidField"&gt;</span>
<span style="background-color: yellow">&lt;binding name="value" expression="person.lastName"/&gt;</span>
<span style="background-color: yellow">&lt;binding name="validator" expression="beans.requiredValidator"/&gt;</span>
<span style="background-color: yellow">&lt;message-binding name="displayName" key="person.lastName"/&gt;</span>
<span style="background-color: yellow">&lt;/component&gt;</span>
&lt;/page-specification&gt;
</pre>
<component id="firstNameField" type="TextField">
<binding name="value" value="person.firstName"/>
<binding name="validators" value="validators:required"/>
<binding name="displayName" value="message:person.firstName"/>
</component>
<component id="lastNameField" type="TextField">
<binding name="value" value="person.lastName"/>
<binding name="validators" value="validators:required"/>
<binding name="displayName" value="message:person.lastName"/>
</component>
At line 53 added 2 lines.
</page-specification>}}}
At line 59 changed 1 line.
There are a [number of different validators|http://jakarta.apache.org/tapestry/doc/ComponentReference/ValidField.html] you can use, this example just shows a way to validate Strings are entered. All input fields generated by AppGen are required by default. You can change this by modifying the extras/appgen/src/**/*_page.xdt files.
There are a [number of different validators|http://jakarta.apache.org/tapestry/UsersGuide/validation.html] you can use, this example just shows a way to validate Strings are entered. The userForm.page has examples of an EmailValidator and a PatternValidator. All input fields generated by AppGen are required by default. You can change this by modifying the extras/appgen/src/**/*_page.xdt files.
At line 65 changed 1 line.
if (getValidationDelegate().getHasErrors()) {
if (getDelegate().getHasErrors()) {
At line 71 changed 1 line.
Since validation is configured in the page-specification file (a.k.a. personForm.page), whenever a field uses the ValidField component, it will get validated. For those fields that don't have validation, make sure and use the @Label component for its label. Below is a non-validated field example from web/pages/userForm.html.
Since validation is configured in the page-specification file (a.k.a. personForm.page), whenever a field specifies a "validators" property. For those fields that don't have validation, make sure and use the @Label component for its label. Below is a non-validated field example from web/pages/userForm.html.
At line 121 changed 3 lines.
public void testGetPeople() {
List results = mgr.getPeople(new Person());
assertTrue(results.size() > 0);
public void testGetPeople() throws Exception {
List results = new ArrayList();
person = new Person();
results.add(person);
// set expected behavior on dao
personDao.expects(once()).method("getPeople")
.will(returnValue(results));
List people = personManager.getPeople(null);
assertTrue(people.size() == 1);
personDao.verify();
At line 187 changed 1 line.
To begin, create test/web/**/action/PersonListTest.java (extends BasePage implements PageRenderListener) and add two methods. The first, {{pageBeginRender()}} is executed when the page first loads. The second, {{edit()}} is a listener method that's invoked when you click to edit a row. This is pretty much the same as the {{edit()}} method on PersonForm. The one on PersonForm was mainly added for demonstration purposes. AppGen will won't generate an "edit" listener on the form class if you use it to generate your page classes.
To begin, create test/web/**/action/PersonListTest.java and add test methods for editing and searching. The {{edit()}} method is a listener method that's invoked when you click to edit a row. This is pretty much the same as the {{edit()}} method on PersonForm. The one on PersonForm was mainly added for demonstration purposes. AppGen will won't generate an "edit" listener on the form class if you use it to generate your page classes.
At line 193 changed 1 line.
import org.appfuse.model.Person;
import org.apache.tapestry.engine.RequestCycle;
At line 202 added 1 line.
import org.appfuse.model.Person;
At line 204 added 3 lines.
import java.util.HashMap;
import java.util.Map;
At line 199 changed 4 lines.
protected void setUp() throws Exception {
super.setUp();
page = (PersonList) getPage(PersonList.class);
protected void onSetUpBeforeTransaction() throws Exception {
super.onSetUpBeforeTransaction();
At line 204 changed 2 lines.
page.setManager((Manager) ctx.getBean("manager"));
page.setRequestCycle(getCycle(request, response));
Map map = new HashMap();
map.put("personManager", (Manager) applicationContext.getBean("personManager"));
page = (PersonList) getPage(PersonList.class, map);
At line 208 changed 2 lines.
protected void tearDown() throws Exception {
super.tearDown();
protected void onTearDownAfterTransaction() throws Exception {
super.onTearDownAfterTransaction();
At line 214 changed 3 lines.
MockRequestCycle cycle = (MockRequestCycle) page.getRequestCycle();
cycle.addServiceParameter(new Long(1));
RequestCycle cycle = new MockRequestCycle();
cycle.setServiceParameters(new Object[] {new Long("1")});
At line 218 removed 1 line.
At line 223 changed 3 lines.
PageEvent event = new PageEvent(page, page.getRequestCycle());
page.pageBeginRender(event);
assertTrue(page.getPeople().size() >= 1);
assertTrue(page.getPersons().size() >= 1);
At line 232 changed 2 lines.
!!Create PersonController [#6]
Create src/web/**/action/PersonList.java. It should implement [PageRenderListener|http://jakarta.apache.org/tapestry/doc/api/org/apache/tapestry/event/PageRenderListener.html] and read as follows:
!!Create PersonList [#6]
Create src/web/**/action/PersonList.java. It should implement [PageBeginRenderListener|http://jakarta.apache.org/tapestry/tapestry/apidocs/org/apache/tapestry/event/PageBeginRenderListener.html] and read as follows:
At line 242 removed 2 lines.
import org.apache.tapestry.event.PageEvent;
import org.apache.tapestry.event.PageRenderListener;
At line 248 changed 1 line.
public abstract class PersonList extends BasePage implements PageRenderListener {
public abstract class PersonList extends BasePage {
At line 250 removed 3 lines.
public abstract void setPersonManager(PersonManager manager);
public abstract List getPeople();
public abstract void setPeople(List people);
At line 254 changed 2 lines.
public void pageBeginRender(PageEvent event) {
setPeople(getPersonManager().getPeople(null));
public List getPersons() {
return getPersonManager().getPeople();
At line 257 changed 1 line.
At line 259 changed 2 lines.
Object[] parameters = cycle.getServiceParameters();
Long id = (Long) parameters[0];
Object[] parameters = cycle.getListenerParameters();
Long personId = (Long) parameters[0];
At line 263 changed 1 line.
log.debug("fetching person with id: " + id);
log.debug("fetching person with personId: " + personId);
At line 266 changed 2 lines.
Person person = getPersonManager().getPerson(id.toString());
Person person = getPersonManager().getPerson(personId);
At line 288 removed 4 lines.
Change it in personList.page too:
{{{<property-specification name="people" type="java.util.List"/>}}}
At line 298 changed 1 line.
You should already have the title and heading keys (personList.title and personList.heading) for the personList.html page in web/WEB-INF/classes/ApplicationResources_en.properties. You should've added these keys in the previous tutorial. The column names automatically resolve to i18n messages based on their identifier (with the . in them).
You should already have the title and heading keys (personList.title and personList.heading) for the personList.html page in web/WEB-INF/classes/ApplicationResources.properties. You should've added these keys in the previous tutorial. The column names automatically resolve to i18n messages based on their identifier (with the . in them).
At line 308 changed 1 line.
In the last tutorial, the Canoo tests verify that the user sees the Main Menu after saving/editing a user. Since you've changed that logic, and now you're activating the PersonList, you need to update the tests. Open test/web/web-tests.xml and change any "mainMenu" references in the "PersonsTests" to be go to the people list.
In the last tutorial, the Canoo tests verify that the user sees the Main Menu after saving/editing a person. Since you've changed that logic, and now you're activating the PersonList, you need to update the tests. Open test/web/web-tests.xml and change any "mainMenu" references in the "PersonsTests" to be go to the people list.
At line 310 changed 1 line.
{{{<verifytitle description="display Main Menu" text=".*${mainMenu.title}.*" regex="true"/>}}}
{{{<verifyTitle description="display Main Menu" text=".*${mainMenu.title}.*" regex="true"/>}}}
At line 314 changed 1 line.
{{{<verifytitle description="we should see the personDetail title" text=".*${personDetail.title}.*" regex="true"/>}}}
{{{{{{<verifyTitle description="Person List appears if save successful" text=".*${personList.title}.*" regex="true"/>}}}}}}
At line 315 added 1 line.
At line 322 changed 2 lines.
{{{
<invoke description="View People" url="/people.html"/>
{{{<invoke description="View People" url="/people.html"/>
At line 371 changed 1 line.
Where ''menu.viewPeople'' is an entry in web/WEB-INF/classes/ApplicationResources_en.properties.
Where ''menu.viewPeople'' is an entry in web/WEB-INF/classes/ApplicationResources.properties.
At line 380 changed 1 line.
<Menu name="PeopleMenu" title="menu.viewPeople" forward="viewPeople"/>
<Menu name="PeopleMenu" title="menu.viewPeople" page="/people.html"/>
At line 407 changed 1 line.
Notice that there is a new link on the left side (from mainMenu.jsp) and on the right in our menu (from menu.jsp).
Notice that there is a new link on the left side (from mainMenu.html) and on the right in our menu (from menu.jsp).

Back to ValidationAndListTapestry, or to the Page History.