| Raible's Wiki
    Raible Designs AppFuseHomepage- Korean - Chinese - Italian - Japanese QuickStart Guide User Guide Tutorials Other ApplicationsStruts ResumeSecurity Example Struts Menu 
 
    
    
         
        Set your name in UserPreferences 
 
 Referenced by 
   JSPWiki v2.2.33 
    
 Hide Menu | 
 
      
         
      
      
         
             This is version 24.  
            It is not the current version, and thus it cannot be edited. Part II: Creating new Managers - A HowTo for creating Business Delegates  that talk to the database tier (DAOs) and the web tier (Struts Actions). About this TutorialThis tutorial will show you how to create a Business Delegate class (and a JUnit Test) to talk to the DAO we created in Part I.In the context of AppFuse, this is called a Manager class.  It's main responsibility is converting backend data (POJOs) into front-end data (Struts ActionForms).  The main reason I even use Managers, rather than just calling the DAOs directly is testability.  It's nice to be able to populate a Form manually (in the test) and call the DAO to persist it, and verify the database gets the proper results.  The Business Delegate 
 Let's get started by creating a new ManagerTest and Manager in AppFuse's architecture. Table of Contents
 Create a new ManagerTest to run JUnit tests on the Manager [#1]In Part I, we created a Person object and PersonDao - so let's continue developing this entity. First, let's create a JUnit test for the PersonManager. Create PersonManagerTest in the test/web/**/service directory. We'll want to test the same basic methods (get, save, remove) that our DAO has.
 This class should extend BaseManagerTestCase 
 The code below is what we need for a basic JUnit test of our Managers.  It created and destroys our PersonManager. The "conn" object is initialized (and obtains a connection) in the BaseManagerTestCase 
package org.appfuse.webapp.service;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.appfuse.webapp.form.PersonForm;
public class PersonManagerTest extends BaseManagerTestCase {
    //~ Instance fields ========================================================
    private PersonManager mgr = null;
    private Log log = LogFactory.getLog(PersonManagerTest.class);
    private PersonForm personForm;
    //~ Constructors ===========================================================
    public PersonManagerTest(String name) {
        super(name);
    }
    //~ Methods ================================================================
    protected void setUp() throws Exception {
        super.setUp();
        mgr = new PersonManagerImpl(conn);
    }
    protected void tearDown() throws Exception {
        super.tearDown();
        mgr = null;
    }
    public static void main(String[] args) {
        junit.textui.TestRunner.run(PersonManagerTest.class);
    }
}
Now that we have the JUnit framework down for this class, let's add the meat: the test methods to make sure everything works in our Manager.  Here's a snippet from the DAO Tutorial tutorial to help you understand what we're about to do.
 Add the following methods to your PersonManagerTest.java file: 
    public void testGetPerson() throws Exception {
        personForm = (PersonForm) mgr.getPerson("1");
        if (log.isDebugEnabled()) {
            log.debug(personForm);
        }
        assertTrue(personForm != null);
        assertTrue(personForm.getFirstName() != null);
    }
    public void testSavePerson() throws Exception {
        personForm = (PersonForm) mgr.getPerson("1");
        personForm.setFirstName("Joe");
        if (log.isDebugEnabled()) {
            log.debug("saving person with updated firstName: " + personForm);
        }
        personForm = (PersonForm) mgr.savePerson(personForm);
        assertTrue(personForm.getFirstName().equals("Joe"));
    }
    public void testAddAndRemovePerson() throws Exception {
        personForm = new PersonForm();
        // call populate method in super class to populate test data
        // from a properties file matching this class name
        personForm = (PersonForm) populate(personForm);
        personForm = (PersonForm) mgr.savePerson(personForm);
        assertTrue(personForm.getLastName().equals("Raible"));
        if (log.isDebugEnabled()) {
            log.debug("removing person...");
        }
        mgr.removePerson(personForm);
        try {
            personForm = (PersonForm) mgr.getPerson("1");
            fail("Expected 'Exception' not thrown");
        } catch (Exception e) {
            if (log.isDebugEnabled()) {
                log.debug(e);
            }
            assertTrue(e != null);
        }
    }
This class won't compile at this point because we have not created our PersonManager nor the PersonManagerImpl.  Unlike the DAO class, I'm not using a Factory pattern.  Rather, I'm instantiating new Managers using:Manager mgr = new ManagerImp(conn);If I followed recommended patterns a bit more, I'd do: Manager mgr = ManagerFactory.getInstance(conn, PersonManager.class);I don't have any reason for not doing the factory pattern on Managers, I just simply haven't done it. I am creating Interfaces for the Managers - in case I decide I need new ManagerImpls someday. Then it'd be easy to create a Factory and different implementations. I also hope to look into Spring for determining Managers for clients (Tests and Actions). 
 Create a new Manager to talk to the DAO [#2]First off, create a PersonManager.java interface in the src/web/**/service directory and specify the basic CRUD methods for any implementation classes. I've eliminated the JavaDocs in the class below for display purposes.
 
package org.appfuse.webapp.service;
public interface PersonManager {
    public Object getPerson(String id) throws Exception;
    public Object savePerson(Object person) throws Exception;
    public void removePerson(Object Person) throws Exception;
}
Now let's create a PersonManagerImpl class that implements the methods in PersonManager and uses BeanUtils.copyProperties to convert POJOs → ActionForms and ActionForms → POJOs. To do this, create a new class in src/web/**/service and name it PersonManagerImpl.java. It should extend BaseManager and implement PersonManager. 
 
package org.appfuse.webapp.service;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.appfuse.persistence.DAOFactory;
import org.appfuse.persistence.Person;
import org.appfuse.persistence.PersonDao;
import org.appfuse.webapp.form.PersonForm;
public class PersonManagerImpl extends BaseManager implements PersonManager {
    //~ Instance fields ========================================================
    private Log log = LogFactory.getLog(PersonManagerImpl.class);
    private PersonDao dao;
    private Person person;
    private PersonForm personForm;
    //~ Constructors ===========================================================
    public PersonManagerImpl(Object conn)
    throws Exception {
        dao = (PersonDao) DAOFactory.getInstance(conn, PersonDao.class);
    }
    //~ Methods ================================================================
    public Object getPerson(String id) throws Exception {
        person = dao.getPerson(Long.valueOf(id));
        
        personForm = new PersonForm();
        BeanUtils.copyProperties(personForm, person);
        
        return personForm;
    }
    public Object savePerson(Object obj) throws Exception {
        if (person == null) {
            person = new Person();
        }
        personForm = (PersonForm) obj;
        
        // copy form properties to person
        try {
            BeanUtils.copyProperties(person, personForm);
        } catch (IllegalArgumentException i) {
            log.error("Exception occured copying properties", i);
            throw new ConversionException();
        }
        // BeanUtils.copyProperties converts empty Strings to 
        // Longs with a value of 0 to prevent a NPE.
        // Setting the defaultLong to null (in BaseManager) is another solution 
        if (ObjectUtils.equals(person.getId(), new Long(0))) {
            person.setId(null);
        }
        dao.savePerson(person);
        return getPerson(person.getId().toString());
    }
    public void removePerson(Object obj) throws Exception {
        if (person == null) {
            person = new Person();
        }
        personForm = (PersonForm) obj;
        if (log.isDebugEnabled()) {
            log.debug("removing person: " + 
                      personForm.getFirstName() + " " + 
                      personForm.getLastName());
        }
        dao.removePerson(person);
    }
You should be able to compile everything now using "ant compile-web".  Doh!  I guess not:
PersonManagerImpl.java:11: cannot resolve symbol
    [javac] symbol  : class PersonForm 
    [javac] location: package form
    [javac] import org.appfuse.webapp.form.PersonForm;
We need to add XDoclet tags to the Person.java Object to create our Struts ActionForm.  In the JavaDoc for the Person.java file, add the following @struts.form tags (use User.java if you need an example):* @struts.form include-all="true" extends="BaseForm" 
 Now, running "ant compile-web" should work just fine. Finally, we need to create the PersonManagerTest.properties file in test/web/**/service so that personForm = (PersonForm) populate(personForm); will work in our test. 
 id=1 firstName=Matt lastName=Raible Run the ManagerTest [#3]Save all your edited files and try running "ant test-web -Dtestcase=PersonManager" one more time. Yeah Baby, Yeah:
BUILD SUCCESSFUL 
 Next Up: Part II: Creating new Managers - A HowTo for creating Business Delegates 
 | ||||||