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

Edit this page


Referenced by
SpringControllers_it




JSPWiki v2.2.33

[RSS]


Hide Menu

ValidationAndListSpring_it


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 visualizzare 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, è molto 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>

Infine, per attivare la validazione in personForm.jsp, devi assicurarti che personForm.jsp contenga quanto segue:

<v: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

Per esser sicuro che tutto funzioni davvero come atteso, puoi provare a spegnere il JavaScript e controllare che la validazione server-side stia funzionando. Ciò è semplice in Mozilla Firefox (il mio browser preferito), basta che vai in Strumenti → Opzioni → Contenuti e deselezioni "Attiva JavaScript". Ora se azzeri i campi e invii il form, dovresti vedere quanto segue:

ValidationAndList/validation-required-nojs.png

Se vuoi solo la validazione lato server (senza JavaScript), puoi eliminare l'attributo onsubmit da <html:form> (in web/pages/personForm.jsp) ed anche i tag del Validator JavaScript a fine pagina.


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

Aggiungi i metodi testGetPeople ai Test di DAO e Manager [#3]

Per creare una schermata elenco (chiamata anche schermata master), dobbiamo creare i metodi che restituiranno tutte le righe dalla nostra tabella person. Iniziamo aggiungendo i test oer questi metodi alle nostre classi PersonDaoTest e PersonManagerTest. Di solito io chiamo questi metodi getEntities (i.e. getUsers), ma potresti usare anche getAll o search - si tratta davvero solo di una questione di preferenze personali.

Apri test/dao/**/dao/PersonDaoTest.java ed aggiungi un metodo testGetPeople:


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

Il motivo per cui sto passando un oggetto person al metodo getPeople è per permettere di filtrare (basandomi sui valori in person) in futuro. Aggiungendo questo parametro alla firma del tuo metodo getPeople() è opzionale, ma il resto di questo tutorial assume che tu lo abbia fatto.

Ora apri test/service/**/service/PersonManagerTest.java ed aggiungi un metodo testGetPeople:


    public void testGetPeople() throws Exception {
        List results = new ArrayList();
        person = new Person();
        results.add(person);

        // imposta il comportamento atteso sul dao
        personDao.expects(once()).method("getPeople")
            .will(returnValue(results));

        List people = personManager.getPeople(null);
        assertTrue(people.size() == 1);
        personDao.verify();
    }

Affinché questi test possano compilare, devi aggiungere il metodo getPeople() alle interfacce PersonDao e PersonManager, e la relativa implementazione.

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

Apri src/dao/**/dao/PersonDao.java ed aggiungi la firma del metodo getPeople():


    public List getPeople(Person person);

Ora aggiungi la stessa firma al metodo src/service/**/service/PersonManager.java. Registra tutti i tuoi file ed aggiusta gli import nei tuoi test. Dopo devi implementare il metodo getPeople() nelle tue classi di implementazione. Apri src/dao/**/dao/hibernate/PersonDaoHibernate.java ed aggiungi il seguente metodo:


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

Noterai qui che non si fa nulla con il parametro person. Per ora si tratta solo di un segnaposto - in futuro puoi voler filtrare sulle sue proprietà usando l'Hibernate Query Language (HQL) o le Criteria Queries.

Un esempio con uso di Criteria Query:


    Example example = Example.create(person)
                             .excludeZeroes()    // escludi proprietà con valore zero
                             .ignoreCase();      // esegui confronti fra stringhe case insensitive
    try {
        return getSession().createCriteria(Person.class)
                           .add(example)
                           .list();
    catch (Exception e) {
        throw new DataAccessException(e.getMessage());
    }
    return new ArrayList();

Ora implementa il metodo getPeople() in src/service/**/impl/PersonManagerImpl.java:


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

Dopo aver registrato tutte le tue modifiche, dovresti poter lanciare entrambi i test eseguendo quanto segue:

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

Se funziona tutto - ben fatto! Ora devi aggiungere questa funzione recupera tutto allo strato web.

Crea il PersonControllerTest [#5]

Nell'ultimo paio di tutorial, abbiamo lavorato con il PersonFormController per interagire con la nostra form HTML. Ora dobbiamo creare un nuovo Controller che gestirà semplicemente il recupero e la visualizzazione di un elenco di persone da database.
Potresti usare anche un MultiActionController per gestire tutte le tue schermate elenco.

Per iniziare, crea test/web/**/action/PersonControllerTest.java (extends BaseControllerTestCase) ed aggiungi il seguente metodo:


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

Questa classe non compilerà finché non (1) crei la classe PersonController ed (2) aggiungi la variabile PERSON_LIST al file src/dao/**/Constants.java. Alcuni hanno suggerito di chiamare questa classe PersonControllerList - a te la scelta del nome. Io preferisco Controller e FormController perché mi dice che una classe implementa Controller mentra la seconda SimpleFormController.

Di solito copio una variabile simile già esistente in questo file - i.e. USER_LIST.


    /**
     * L'attributo in request scope che contiene l'elenco delle persone
     */
    public static final String PERSON_LIST = "personList";

Ora registra tutte le tue modifiche. Non sarai ancora in grado di lanciare ant test-web -Dtestcase=PersonController in quanto PersonController non esiste (per ora). Aggiungiamolo.

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 come URL per questo controller. Per far 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 generato in questo esempio è "persons" e probabilmente dovrebbe essere people. Alla riga 31 o lì vicino, dovresti avere quanto segue:
<display:setProperty name="paging.banner.items_name" value="persons"/>

Modificalo in:

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

Infine, aggiungi le chiavi per titolo ed intestazione (personList.title e personList.heading) a web/WEB-INF/classes/ApplicationResources.properties. Apri questo file ed aggiungi quanto segue:

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

Come reminder, personList.title contiene ciò che finisce nella barra del titolo del browser (il tag <title>) e personList.heading verrà messo in un tag <h1> prima di qualsiasi contenuto della pagina. A questo punto, potresti riuscire ad eseguire "ant deploy", avviare Tomcat ed aprire la schermata elenco nel tuo browser.

Ora che abbiamo una schermata elenco, modifichiamo le pagina visualizzate dopo l'aggiunta e l'eliminazione di una Person. In web/WEB-INF/action-servlet.xml, modifica la property successView di personFormController in modo che valga "people.html".


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

Devi anche aggiornare i test Canoo "AddPerson" e "DeletePerson". Apri test/web/web-tests.xml e modifica la riga seguente nel target "AddPerson":

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

in:

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

Poi nel target "DeletePerson", modifica la riga seguente:

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

in:

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

Per verificare che la visualizzazione della pagina funzioni, puoi creare una nuovo test JSP 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>

Vorrai anche aggiungere il target "SearchPeople" al target "PersonTests" in modo che venga eseguito insieme a tutti gli altri test relativi alle persone.



    <!-- esegui i test relativi alle persone -->
    <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>

Ora puoi eseguire ant deploy test-canoo -Dtestcase=SearchPeople (o ant test-jsp se Tomcat non è avviato) e se va bene tutto il risultato sarà "BUILD SUCCESSFUL". Se è cosi - ottimo lavoro!

Aggiungi il link al menu [#8]

L'ultimo passo è rendere visibili all'utente le funzioni elenco, aggiungi, modifica e cancella. Il modo più semplice è aggiungere un nuovo link all'elenco di link in web/pages/mainMenu.jsp:


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

Dove menu.viewPeople è una voce in web/WEB-INF/classes/ApplicationResources.properties.

menu.viewPeople=View People

L'altra (più probabile) alternative è che tu voglia aggiungerlo al menu. Per farlo, aggiungi quanto segue a web/WEB-INF/menu-config.xml:


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

Assicurati che l'XML sopra sia all'interno del tag <Menus>, ma non dentro un altro tag <Menu>. Poi aggiungi questo nuovo menu a web/common/menu.jsp - che ora dovrebbe vedersi come segue:


<%@ 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>

Se ora esegui ant clean deploy, avvii Tomcat e vai su http://localhost:8080/appfuse/mainMenu.html, dovresti vedere qualcosa di analogo allo screenshot sotto.

ValidationAndList/new-menu-item.png

Nota che c'è un nuovo link sul lato sinistro (da mainMenu.jsp) a sulla destra nel nostro menu (da menu.jsp).

È tutto!

Hai completato un ciclo di sviluppo intero di un insieme di pagine master-detail con AppFuse e il framework MVC di Spring - Congratulazioni! Ora il test vero è se puoi eseguire tutti i test nella tua applicazione senza che falliscano. Per verificare, ferma tomcat ed esegui ant clean test-all. Ciò esegue tutti gli unit test all'interno del progetto. Come promemoria, dovrebbe essere semplice impostare e testare AppFuse da zero usando ant setup-db setup-tomcat test-all. Inoltre, se stai cercando degli esempi più consistenti - guarda Struts Resume.

Buona Giornata!

BUILD SUCCESSFUL
Total time: 4 minutes 21 seconds



Go to top   Edit this page   More info...   Attach file...
This page last changed on 17-Jul-2008 18:56:38 MDT by MarcelloTeodori.