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
SpringControllers_it




JSPWiki v2.2.33

[RSS]


Hide Menu

ValidationAndListSpring_it


This is version 2. It is not the current version, and thus it cannot be edited.
[Back to current version]   [Restore this version]


Parte IV: Aggiungere Validazione e Schermata Elenco - Aggiungere logica di convalida all'oggetto Person in modo che firstName e lastName siano campi obbligatori ed aggiungere una schermata elenco per visualizzare tutti i record nel database.
Questo tutorial dipende da Parte III: Creazione Controller e JSP.

Info su questo Tutorial

Questo tutorial mostra come aggiungere la logica di validazione (sia client che server-side) all'oggetto Person usando Commons Validator. Verrà creata anche una schermata di elenco usando la Display Tag Library per mostrare tutte le persone nel database.
Ti dirò come faccio le cose nel Mondo Reale in un testo come questo.

Indice

  • [1] Aggiungi i tag XDoclet per il Validator a Person.java
  • [2] Vedi JSP con la validazione aggiunta e verifica
  • [3] Aggiungi i metodi testGetPeople ai test di DAO e Manager
  • [4] Aggiungi i metodi getPeople a PersonDao e Manager
  • [5] Crea il PersonControllerTest
  • [6] Crea il PersonController
  • [7] Crea personList.jsp ed il test Canoo
  • [8] Aggiungi un collegamento al menu

Aggiungi i tag XDoclet per il Validator a Person.java [#1]

Per usare Commons Validator con Spring MVC normalmente devi scrivere un file validation.xml a mano. Tuttavia, grazie a XDoclet, è nolto più semplice - devi solo aggiungere un paio di tag @spring.validator al tuo POJO (Person.java). Apriamo il file (src/dao/**/dao/Person.java) e modifichiamo i metodi setFirstName e setLastName come segue:


    /**
     * @spring.validator type="required"
     */
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    /**
     * @spring.validator type="required"
     */
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

Va inoltre menzionato che puoi anche aggiungere un attributo msgkey a questo tag per effettuare l'override della chiave messaggio predefinita per questo errore.


@spring.validator type="required" msgkey="errors.required"

La chiave predefinita per type="required" è già errors.required, per cui io di solito la lascio al default. Questa chiave è definita in web/WEB-INF/classes/ApplicationResources_*.properties.

Ora se registri Person.java ed esegui ant clean webdoclet, verrà generato un file validation.xml in build/appfuse/WEB-INF/. Il contenuto dovrebbe avere un elemento per "person".


      <form name="person">
              <field property="firstName"
                     depends="required">

                  <arg0 key="person.firstName"/>
              </field>
              <field property="lastName"
                     depends="required">

                  <arg0 key="person.lastName"/>
              </field>
      </form>

Per attivare la validazione in personForm.jsp, devi assicurarti che personForm.jsp contenga alla fine quanto segue:

<html:javascript formName="person" cdata="false"
      dynamicJavascript="true" staticJavascript="false"/>
<script type="text/javascript" 
      src="<c:url value="/scripts/validator.jsp"/>"></script>

Devi anche decommentare la property "validator" che abbiamo commentato prima. Controlla che il <bean> "personFormController" in web/WEB-INF/action-servlet.xml abbia il seguente XML:


    <bean id="personFormController" class="org.appfuse.webapp.action.PersonFormController">
        <property name="commandName"><value>person</value></property>
        <property name="commandClass"><value>org.appfuse.model.Person</value></property>
        <property name="validator"><ref bean="beanValidator"/></property>
        <property name="formView"><value>personForm</value></property>
        <property name="successView"><value>mainMenu.html</value></property>
        <property name="personManager"><ref bean="personManager"/></property>
    </bean>

Vedi JSP con la validazione aggiunta e verifica [#2]

Ora che abbiamo la validazione configurata su questo form, assicuriamoci che funzioni. Esegui ant db-load deploy, avvia Tomcat e vai su http://localhost:8080/appfuse/editPerson.html?id=1. Un'altra cosa che potresti notare è che le label "First Name" e "Last Name" ora hanno degli asterischi vicino - che indicano i campi come obbligatori. Ciò è ottenuto tramite un LabelTag che legge le regole di validazione da Commons Validator.

Se cancelli i valori nei campi firstName e lastName e fai clic sul bottone registra, dovresti avere il seguente JavaScript.

ValidationAndList/validation-required.png

To make sure things are really working as expected, you can turn off JavaScript and ensure the server-side validation is working. This is easy in Mozilla Firebird (my favorite browser), just go to Tools → Options → Web Features and uncheck "Enable JavaScript". Now if you clear the fields and save the form, you should see the following:

ValidationAndList/validation-required-nojs.png

If you only want server-side validation (no JavaScript), you can remove the onsubmit attribute of <html:form> (in web/pages/personForm.jsp) as well as the Validator JavaScript tags at the bottom of the page.


<html:javascript formName="personForm" cdata="false"
      dynamicJavascript="true" staticJavascript="false"/>
<script type="text/javascript" 
      src="<html:rewrite page="/scripts/validator.jsp"/>"></script>

Add testGetPeople methods to DAO and Manager Tests [#3]

To create a List screen (also called a master screen), we need to create methods that will return all the rows from our person table. Let's start by adding tests for these methods to our PersonDaoTest and PersonManagerTest classes. I usually name this method getEntities (i.e. getUsers), but you could also use getAll or search - it's really just a matter of personal preference.

Open test/dao/**/dao/PersonDaoTest.java and add a testGetPeople method:


    public void testGetPeople() {
        person = new Person();
        List results = dao.getPeople(person);
        assertTrue(results.size() 0);
    }

The reason I'm passing in a person object to the getPeople method is to allow for filtering (based on values in person) in the future. Adding this parameter in your getPeople() method signature is optional, but the rest of this tutorial assumes you have done this.

Now open test/service/**/service/PersonManagerTest.java and add a testGetPeople method:


    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();
    }

In order for these tests to compile, you need to add the getPeople() method to the PersonDao and PersonManager interfaces, and their implementations.

Aggiungi il metodo getPeople() a DAO e Manager [#4]

Open src/dao/**/dao/PersonDao.java and add the getPeople() method signature:


    public List getPeople(Person person);

Now add the same method signature to src/service/**/service/PersonManager.java. Save all your files and adjust the imports in your tests. Next you need to implement the getPeople() method in your implementation classes. Open src/dao/**/dao/hibernate/PersonDaoHibernate.java and add the following method:


    public List getPeople(Person person) {
        return getHibernateTemplate().find("from Person");
    }

You'll notice here that nothing is being done with the person parameter. This is just a placeholder for now - in the future you may want to filter on it's properties using Hibernate's Query Language (HQL) or using Criteria Queries.

An example using a Criteria Query:


    Example example = Example.create(person)
                             .excludeZeroes()    // exclude zero valued properties
                             .ignoreCase();      // perform case insensitive string comparisons
    try {
        return getSession().createCriteria(Person.class)
                           .add(example)
                           .list();
    catch (Exception e) {
        throw new DataAccessException(e.getMessage());
    }
    return new ArrayList();

Now implement the getPeople() method in src/service/**/impl/PersonManagerImpl.java:


    public List getPeople(Person person) {
        return dao.getPeople(person);
    }

After saving all your changes, you should be able to run both tests by executing the following:

  • ant test-dao -Dtestcase=PersonDao
  • ant test-service -Dtestcase=PersonManager

If everything works - nice job! Now you need to add this retrieve all functionality to the web tier.

Crea il PersonControllerTest [#5]

In the last couple of tutorials, we've been working with the PersonFormController to interact with our HTML form. Now we need to create a new Controller that'll simply handle getting and displaying a list of people in the database.
You could also use a MultiActionController to handle all your List screens.

To begin, create test/web/**/action/PersonControllerTest.java (extends BaseControllerTestCase) and add the following method:


package org.appfuse.webapp.action;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.appfuse.Constants;
import org.springframework.web.servlet.ModelAndView;

public class PersonControllerTest extends BaseControllerTestCase {
    
    public void testHandleRequest() throws Exception {
        PersonController c = (PersonControllerctx.getBean("personController");
        ModelAndView mav = c.handleRequest((HttpServletRequestnull,
                                           (HttpServletResponsenull);
        Map m = mav.getModel();
        assertNotNull(m.get(Constants.PERSON_LIST));
        assertEquals(mav.getViewName()"personList");
    }
}

This class will not compile until you (1) create the PersonController class and (2) add the PERSON_LIST variable to the src/dao/**/Constants.java file. Some folks have suggested that this class be named PersonControllerList - the name choice is up to you. I prefer Controller and FormController because it tells me one implements Controller while the latter extends SimpleFormController.

I usually copy a similar variable that already exists in this file - i.e. USER_LIST.


    /**
     * The request scope attribute that holds the person list
     */
    public static final String PERSON_LIST = "personList";

Now save all your changes. You won't be able to run ant test-web -Dtestcase=PersonController yet since PersonController does not exist (yet). Let's add it.

Crea il PersonController [#6]

Crea il file src/web/**/action/PersonController.java. Dovrebbe implementare org.springframework.web.servlet.mvc.Controller e leggersi come segue:


package org.appfuse.webapp.action;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.appfuse.Constants;
import org.appfuse.model.Person;
import org.appfuse.service.PersonManager;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

public class PersonController implements Controller {
    private final Log log = LogFactory.getLog(PersonController.class);
    private PersonManager mgr = null;

    public void setPersonManager(PersonManager personManager) {
        this.mgr = personManager;
    }

    public ModelAndView handleRequest(HttpServletRequest request,
                                      HttpServletResponse response)
    throws Exception {
        if (log.isDebugEnabled()) {
            log.debug("entering 'handleRequest' method...");
        }

        return new ModelAndView("personList", Constants.PERSON_LIST,
                                mgr.getPeople(new Person()));
    }
}

Ora aggiungi una definizione a web/WEB-INF/action-servlet.xml per questo Controller.


    <bean id="personController" class="org.appfuse.webapp.action.PersonController">
        <property name="personManager"><ref bean="personManager"/></property>
    </bean>

Ora se esegui ant test-web -Dtestcase=PersonController, il test dovrebbe passare. Successivamente, crea il mapping su URL per questo controller. Per fare ciò, cerca il bean "urlMapping" in web/WEB-INF/action-servlet.xml ed aggiungi la riga seguente alla proprietà "mappings":


    <prop key="/people.html">personController</prop>

Crea personList.jsp ed il test Canoo [#7]

Apri il file personList.jsp nella cartella web/pages del tuo progetto. Una cosa che vorrai probabilmente modificare è la forma plurale degli elementi che stai elencando. Il nome generati in questo esempio è "persons" è probabilmente dovrebbe essere people. At or near line 31, you should have the following line:
<display:setProperty name="paging.banner.items_name" value="persons"/>

Change it to:

<display:setProperty name="paging.banner.items_name" value="people"/>

Finally, add the title and heading keys (personList.title and personList.heading) to web/WEB-INF/classes/ApplicationResources.properties. Open this file and add the following:

# -- person list page --
personList.title=Person List
personList.heading=All People

As a reminder, the personList.title is what ends up in the brower's title bar (the <title> tag) and personList.heading will be put into an <h1> tag before any page content. At this point, you could be able to run "ant deploy", start Tomcat and open the list screen in your browser.

Now that we have a List Screen, let's change the pages that are displayed after adding and deleting a new Person. In web/WEB-INF/action-servlet.xml, change the personFormController's successView property to be "people.html".


    <property name="successView"><value>people.html</value></property>

You will also need to update the Canoo tests "AddPerson" and "DeletePerson". Open test/web/web-tests.xml and change the following line in the "AddPerson" target:

<verifytitle description="Main Menu appears if save successful" 
    text=".*${mainMenu.title}.*" regex="true"/>

to:

<verifytitle description="Person List appears if save successful" 
    text=".*${personList.title}.*" regex="true"/>

Then in the "DeletePerson" target, change the following line:

<verifytitle description="display Main Menu" text=".*$(mainMenu.title}.*" regex="true"/>

to:

<verifytitle description="display Person List" text=".*${personList.title}.*" regex="true"/>

To test that displaying this page works, you can create a new JSP test in test/web/web-tests.xml:


    <!-- Verify the people list screen displays without errors -->
    <target name="SearchPeople" 
        description="Tests search for and displaying all people">
        <webtest name="searchPeople">
            &config;
            <steps>
                &login;
                <invoke description="click View People link" url="/people.html"/>
                <verifytitle description="we should see the personList title" 
                    text=".*${personList.title}.*" regex="true"/>
            </steps>
        </webtest>
    </target>

You'll also want to add the "SearchPeople" target to the "PersonTests" target so it will be executed along with all the other person-related tests.



    <!-- runs person-related tests -->
    <target name="PersonTests" 
        depends="SearchPeople,EditPerson,SavePerson,AddPerson,DeletePerson"
        description="Call and executes all person test cases (targets)">
        <echo>Successfully ran all Person JSP tests!</echo>
    </target>

Now you can run ant deploy test-canoo -Dtestcase=SearchPeople (or ant test-jsp if Tomcat isn't running) and hopefully it will result in "BUILD SUCCESSFUL". If so - nice work!

Add link to menu [#8]

The last step is to make the list, add, edit and delete functions visible to the user. The simplest way is to add a new link to the list of links in web/pages/mainMenu.jsp:


    <li>
        <a href="<c:url value="/people.html"/>"><fmt:message key="menu.viewPeople"/></a>
    </li>

Where menu.viewPeople is an entry in web/WEB-INF/classes/ApplicationResources.properties.

menu.viewPeople=View People

The other (more likely) alternative is that you'll want to add it to the menu. To do this, add the following to web/WEB-INF/menu-config.xml:


<Menu name="PeopleMenu" title="menu.viewPeople" page="/people.html"/>

Make sure the above XML is inside the <Menus> tag, but not within another <Menu>. Then add this new menu to web/common/menu.jsp - which should now looks as follows:


<%@ include file="/common/taglibs.jsp"%>

<div id="menu">
<menu:useMenuDisplayer name="ListMenu" permissions="rolesAdapter">
    <menu:displayMenu name="AdminMenu"/>
    <menu:displayMenu name="UserMenu"/>
    <menu:displayMenu name="PeopleMenu"/>
    <menu:displayMenu name="FileUpload"/>
    <menu:displayMenu name="FlushCache"/>
    <menu:displayMenu name="Clickstream"/>
</menu:useMenuDisplayer>
</div>

Now if you run ant clean deploy, start Tomcat and go to http://localhost:8080/appfuse/mainMenu.html, you should see something like the screenshot below.

ValidationAndList/new-menu-item.png

Notice that there is a new link on the left side (from mainMenu.jsp) and on the right in our menu (from menu.jsp).

That's it!

You've completed the full lifecycle of developing a set of master-detail pages with AppFuse and Spring's MVC framework - Congratulations! Now the real test is if you can run all the tests in your app without failure. To test, stop tomcat and run ant clean test-all. This will run all the unit tests within your project. As a reminder, it should be easy to setup and test AppFuse from scratch using ant setup-db setup-tomcat test-all. Also, if you're looking for more robust examples - checkout Struts Resume.

Happy Day!

BUILD SUCCESSFUL
Total time: 4 minutes 21 seconds



Go to top   More info...   Attach file...
This particular version was published on 16-Jun-2008 07:55:19 MDT by MarcelloTeodori.