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
Articles
CreateActions_it
CreateDAO_it
SpringControllers_it




JSPWiki v2.2.33

[RSS]


Hide Menu

CreateManager_it


Parte II: Creare nuovi Manager - Un HowTo sulla creazione di Business Façade che parlino con il livello del database (DAO) e si occupino della gestione delle transazioni.

Questo tutorial dipende da Parte I: Creare nuovi DAO ed Object in AppFuse.

Informazioni su questo Tutorial

Questo tutorial ti mostrerà come creare una classe di Business Façade (ed un Test JUnit) per parlare con il DAO che abbiamo creato nella Parte I.

Nel contesto di AppFuse, questa viene denominata una classe Manager. La sua responsibilità principale è comportarsi da ponte fra il layer di persistenza (DAO) ed il layer web. È anche utile per disaccoppiare lo strato di presentazione dallo strato database (i.e. per applicazioni Swing). I Manager dovrebbero inoltre essere il luogo deputato nel quale mettere la business logic della tua applicazione.

Ti dirò come si fanno le cose nel Mondo Reale in un testo come questo.

Iniziamo con il creare un nuovo ManagerTest ed un nuovo Manager nell'architettura di AppFuse.

Indice

  • [1] Crea un nuovo ManagerTest per eseguire test JUnit sul Manager
  • [2] Crea un nuovo Manager per parlare con il DAO
  • [3] Configura Spring per questo Manager e relative Transaction
  • [4] Esegui il ManagerTest

Crea un nuovo ManagerTest per eseguire test JUnit sul Manager [#1]

Nella Parte I, abbiamo creato un oggetto Person ed un PersonDao - pertanto continuiamo a sviluppare questa entità. Per primp, creiamo un test JUnit per il PersonManager. Crea PersonManagerTest nella directory test/service/**/service. Ora vogliamo verificare gli stessi metodi di base (get, save, remove) che possiede il nostro DAO.
Ciò potrebbe sembrare ridondante (ma perché scrivere tutti i test!), ma è una GRAN cosa avere questi test quando sono passati 6 mesi dall'inizio dello sviluppo.

Questa classe dovrebbe estendere BaseManagerTestCase, che è già presente nel package service. La classe base (BaseManagerTestCase) fornisce funzionalità analoghe al BaseDaoTestCase.

Di solito io copio (open → save as) un test esistente (i.e. UserManagerTest.java) e faccio un find/replace [Uu]ser con [Pp]erson, o quale che sia il nome del mio oggetto.

Il codice qui sotto è tutto ciò di cui hai bisogno per un test JUnit di base del tuo Manager. Diversamente dal DaoTest, questo test usa jMock per isolare il Manager dalle sue dipendenze e renderlo un vero "unit" test. Ciò può essere di grande aiuto perché ti permette di verificare la tua business logic senza preoccuparti delle altre dipendenze. Il codice sottostante semplicemente inizializza il Manager e le sue dipendenze (come Mock) per effettuare i test.


package org.appfuse.service;

import java.util.List;
import java.util.ArrayList;

import org.appfuse.dao.PersonDao;
import org.appfuse.model.Person;
import org.appfuse.service.impl.PersonManagerImpl;

import org.jmock.Mock;
import org.springframework.orm.ObjectRetrievalFailureException;

public class PersonManagerTest extends BaseManagerTestCase {
    private final String personId = "1";
    private PersonManager personManager = new PersonManagerImpl();
    private Mock personDao = null;
    private Person person = null;

    protected void setUp() throws Exception {
        super.setUp();
        personDao = new Mock(PersonDao.class);
        personManager.setPersonDao((PersonDaopersonDao.proxy());
    }

    protected void tearDown() throws Exception {
        super.tearDown();
        personManager = null;
    }
}

Ora che lo scheletro della classe è fatto, devi aggiungervi la carne: i metodi di test per far sì che tutto funzioni. Qui c'è un frammento tratto dal Tutorial su DAO che ti aiuterà a caipre cosa stiamo per fare.

...crea dei metodi che inizino con "test" (tutto minuscolo). Se questi metodi sono pubblici, hanno un valore di ritorno void e non prendono argomenti, verranno richiamati dal task <junit> del build.xml di Ant. Qui sotto ci sono alcuni semplici test per verificare il CRUD. Una cosa importante da ricordare è che ogni metodo (noto anche come test), deve essere autonomo.

Aggiungi i metodi seguenti al tuo file PersonManagerTest.java:


    public void testGetPerson() throws Exception {
        // set expected behavior on dao
        personDao.expects(once()).method("getPerson")
            .will(returnValue(new Person()));
        person = personManager.getPerson(personId);
        assertTrue(person != null);
        personDao.verify();
    }

    public void testSavePerson() throws Exception {
        // set expected behavior on dao
        personDao.expects(once()).method("savePerson")
            .with(same(person)).isVoid();

        personManager.savePerson(person);
        personDao.verify();
    }    

    public void testAddAndRemovePerson() throws Exception {
        person = new Person();

        // set required fields
        person.setFirstName("firstName");
        person.setLastName("lastName");

        // set expected behavior on dao
        personDao.expects(once()).method("savePerson")
            .with(same(person)).isVoid();
        personManager.savePerson(person);
        personDao.verify();

        // reset expectations
        personDao.reset();

        personDao.expects(once()).method("removePerson").with(eq(new Long(personId)));
        personManager.removePerson(personId);
        personDao.verify();

        // reset expectations
        personDao.reset();
        // remove
        Exception ex = new ObjectRetrievalFailureException(Person.class, person.getId());
        personDao.expects(once()).method("removePerson").isVoid();            
        personDao.expects(once()).method("getPerson").will(throwException(ex));
        personManager.removePerson(personId);
        try {
            personManager.getPerson(personId);
            fail("Person with identifier '" + personId + "' found in database");
        catch (ObjectRetrievalFailureException e) {
            assertNotNull(e.getMessage());
        }
        personDao.verify();
    }

A questo punto questa classe non compilerà perché non abbiamo ancora creato la nostra interfaccia PersonManager.

Credo sia divertente il fatto che abbia seguito così tanti pattern per permettere l'estensibilità in AppFuse. In realtà, nella maggior parte dei progetti sui quali sono stato - imparo così tanto in un anno che non voglio estendere l'archiettura - la voglio riscrivere. Sperabilmente mantenendo aggiornato AppFuse con quelle che io ritengo le best practices, ciò non succederà così spesso. Ogni anno sarà solo un aggiornamento alla versione più recente di AppFuse, piuttosto che una sua riscrittura. ;-)

Crea un nuovo Manager per parlare con il DAO [#2]

Per primo, crea un'interfaccia PersonManager.java nella directory src/service/**/service e specifica i metodi CRUD di base in tutte le classi che la implementano. Ho rimosso i JavaDoc nella classe sotto per motivi di visualizzazione. Il metodo setPersonDao() nella maggior parte dei casi non è usato - esiste giusto per permettere al PersonManagerTest di poter impostare il DAO sull'interfaccia.

Come sempre, io di solito duplico (apri → registra come) un file esistente (i.e. UserManager.java).


package org.appfuse.service;

import org.appfuse.model.Person;
import org.appfuse.dao.PersonDao;

public interface PersonManager {
    public void setPersonDao(PersonDao dao);
    public Person getPerson(String id);
    public void savePerson(Person person);
    public void removePerson(String id);
}

Ora creiamo una classe PersonManagerImpl che implementi i metodi in PersonManager. Per far questo, crea una nuova classe in src/service/**/service/impl e chiamala PersonManagerImpl.java. Deve estendere BaseManager ed implementare PersonManager.


package org.appfuse.service.impl;

import org.appfuse.model.Person;
import org.appfuse.dao.PersonDao;
import org.appfuse.service.PersonManager;

public class PersonManagerImpl extends BaseManager implements PersonManager {
    private PersonDao dao;

    public void setPersonDao(PersonDao dao) {
        this.dao = dao;
    }

    public Person getPerson(String id) {
        return dao.getPerson(Long.valueOf(id));
    }

    public void savePerson(Person person) {
        dao.savePerson(person);
    }

    public void removePerson(String id) {
        dao.removePerson(Long.valueOf(id));
    }
}

Una cosa da notare è il metodo setPersonDao(). Questo è usato da Spring per legare il PersonDao a questo Manager. Ciò è configurato nel flie applicationContext-service.xml. Arriveremo a configurare quello nel Passo 3[3]. Dovresti riuscire a compilare tutto ora con "ant compile-service".

Ora devi modificare il file di configurazione di Spring per il nostro strato servizi in modo che sappia dell'esistenza di questo nuovo Manager.

Configura Spring per questo Manager e relative Transaction [#3]

Per notificare a Spring l'esistenza della nostra interfaccia PersonManager e della relativa implementazione, apri il file src/service/**/service/applicationContext-service.xml. Aggiungi quanto segue al termine di questo file.


    <bean id="personManager" class="org.appfuse.service.impl.PersonManagerImpl">
        <property name="personDao" ref="personDao"/>
    </bean>

Questo bean deve avere un nome che termina con "Manager". Deve essere così, in quanto esiste un advice AOP che viene applicato su questo file per tutti i bean *Manager.

<aop:advisor id="managerTx" advice-ref="txAdvice" pointcut="execution(* *..service.*Manager.*(..))" order="2"/>
Per ulteriori informazioni sulle transazioni con Spring, vedi la documentazione di Spring.

Esegui il ManagerTest [#4]

Registra tutti i file da te modificati e prova ad eseguire ant test-service -Dtestcase=PersonManager.

Yeah Baby, Yeah: BUILD SUCCESSFUL
Total time: 9 seconds


I file che sono stati modificati ed aggiunti fino a questo punto sono disponibili in download.

Prossima Puntata: Parte III: Creare Action e JSP - Un HowTo per la creazione di Action e JSP nell'architettura di AppFuse.



Go to top   Edit this page   More info...   Attach file...
This page last changed on 06-Nov-2006 13:53:00 MST by MarcelloTeodori.