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 26.
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. Someday I hope to dig into Spring to see if it can be my Factory to determine 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
|
||||||