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
Articles
Articles_pt
CreateActions
CreateDAO
CreateDAO_sp
CreateDAOiBATIS
CreateDAOiBATIS_ko
CreateManager_es
JSFBeans
SpringControllers
...and 3 more




JSPWiki v2.2.33

[RSS]


Hide Menu

CreateManager


Difference between version 33 and version 32:

At line 17 added 1 line.
* [3] Configure Spring for this Manager and Transactions
At line 20 changed 1 line.
In [Part I|CreateDAO], 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.
In [Part I|CreateDAO], 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/service/**/service directory. We'll want to test the same basic methods (get, save, remove) that our DAO has.
At line 24 changed 1 line.
This class should extend [BaseManagerTestCase|http://raibledesigns.com/downloads/appfuse/api/org/appfuse/webapp/service/BaseManagerTestCase.java.html], which already exists in the ''service'' package. The parent class (BaseManagerTestCase) serves the same functionality as the BaseDaoTestCase - to load a properties file that has the same name as your *Test.class.
This class should extend [BaseManagerTestCase|http://raibledesigns.com/downloads/appfuse/api/org/appfuse/service/BaseManagerTestCase.java.html], which already exists in the ''service'' package. The parent class (BaseManagerTestCase) serves the same functionality as the BaseDaoTestCase - to load a properties file that has the same name as your *Test.class, as well as to initialize Spring's ApplicationContext.
At line 28 changed 1 line.
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|http://raibledesigns.com/downloads/appfuse/api/org/appfuse/webapp/service/BaseManagerTestCase.java.html] class.
The code below is what we need for a basic JUnit test of our Managers. It created and destroys our PersonManager. The "ctx" object is initialized in the [BaseManagerTestCase|http://raibledesigns.com/downloads/appfuse/api/org/appfuse/service/BaseManagerTestCase.java.html] class.
At line 32 changed 1 line.
package org.appfuse.webapp.service;
package org.appfuse.service;
At line 40 added 1 line.
At line 42 added 4 lines.
//~ Static fields/initializers =============================================
private PersonForm personForm;
At line 44 removed 1 line.
private PersonForm personForm;
At line 46 removed 1 line.
//~ Constructors ===========================================================
At line 48 removed 4 lines.
public PersonManagerTest(String name) {
super(name);
}
At line 55 changed 2 lines.
super.setUp();
mgr = new PersonManagerImpl(conn);
mgr = (PersonManager) ctx.getBean("personManager");
At line 60 removed 1 line.
super.tearDown();
At line 81 changed 6 lines.
if (log.isDebugEnabled()) {
log.debug(personForm);
}
assertTrue(personForm != null);
assertTrue(personForm.getFirstName() != null);
assertTrue("person.firstName not null",
personForm.getFirstName() != null);
At line 91 changed 1 line.
personForm.setFirstName("Joe");
String name = personForm.getFirstName();
personForm.setFirstName("test");
At line 93 removed 4 lines.
if (log.isDebugEnabled()) {
log.debug("saving person with updated firstName: " + personForm);
}
At line 98 changed 1 line.
assertTrue(personForm.getFirstName().equals("Joe"));
assertTrue("name updated", personForm.getFirstName().equals("test"));
personForm.setFirstName(name);
mgr.savePerson(personForm);
At line 103 removed 3 lines.
// call populate method in super class to populate test data
// from a properties file matching this class name
At line 109 changed 1 line.
assertTrue(personForm.getLastName().equals("Raible"));
assertTrue(personForm.getFirstName().equals("Abbie"));
assertTrue(personForm.getId() != null);
At line 112 changed 1 line.
log.debug("removing person...");
log.debug("removing personForm, personId: " +
personForm.getId());
At line 116 changed 1 line.
At line 130 changed 1 line.
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:
This class won't compile at this point because we have not created our PersonManager interface.
At line 132 removed 14 lines.
[{Java2HtmlPlugin
Manager mgr = new ManagerImp(conn);
}]
If I followed recommended patterns a bit more, I'd do:
[{Java2HtmlPlugin
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 <a href="http://www.springframework.org/">Spring</a> to see if it can be my Factory to determine Managers for clients (Tests and Actions).
At line 149 removed 1 line.
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.''
At line 129 added 2 lines.
First off, create a PersonManager.java interface in the src/service/**/service directory and specify the basic CRUD methods for any implementation classes. ''I've eliminated the JavaDocs in the class below for display purposes.''
At line 155 changed 1 line.
package org.appfuse.webapp.service;
package org.appfuse.service;
At line 168 changed 1 line.
to convert POJOs &rarr; ActionForms and ActionForms &rarr; POJOs. To do this, create a new class in src/web/**/service and name it PersonManagerImpl.java. It should extend BaseManager and implement PersonManager.
to convert POJOs &rarr; ActionForms and ActionForms &rarr; POJOs. To do this, create a new class in src/service/**/service and name it PersonManagerImpl.java. It should extend BaseManager and implement PersonManager.
At line 170 changed 1 line.
;:''The [BaseManager|http://raibledesigns.com/downloads/appfuse/api/org/appfuse/webapp/service/BaseManager.java.html] is for registering different Converters (i.e. [DateConverter|http://raibledesigns.com/downloads/appfuse/api/org/appfuse/common/util/DateConverter.java.html]) so that BeanUtils.copyProperties knows how to convert Strings &rarr; Objects. It currently does not have any convenience methods, but does provide a nice place to add them for all your managers.''
;:''The [BaseManager|http://raibledesigns.com/downloads/appfuse/api/org/appfuse/service/BaseManager.java.html] is for registering different Converters (i.e. [DateConverter|http://raibledesigns.com/downloads/appfuse/api/org/appfuse/common/util/DateConverter.java.html]) so that BeanUtils.copyProperties knows how to convert Strings &rarr; Objects. It also provides a {{convert(Object)}} method that converts POJOs -&gt; Forms and vise-versa. If you have Lists on your POJOs (i.e. for parent-child relationships), you will need to manually convert those if you want to work with indexed properties (see UserManagerImpl.java and the conversion of Roles for an example).
At line 174 changed 1 line.
package org.appfuse.webapp.service;
package org.appfuse.service;
At line 176 removed 2 lines.
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.ObjectUtils;
At line 181 changed 2 lines.
import org.appfuse.persistence.DAOFactory;
import org.appfuse.persistence.Person;
import org.appfuse.model.Person;
At line 184 removed 1 line.
import org.appfuse.webapp.form.PersonForm;
At line 186 removed 2 lines.
public class PersonManagerImpl extends BaseManager implements PersonManager {
//~ Instance fields ========================================================
At line 163 added 1 line.
public class PersonManagerImpl extends BaseManager implements PersonManager {
At line 191 removed 2 lines.
private Person person;
private PersonForm personForm;
At line 194 changed 5 lines.
//~ Constructors ===========================================================
public PersonManagerImpl(Object conn)
throws Exception {
dao = (PersonDao) DAOFactory.getInstance(conn, PersonDao.class);
public void setPersonDao(PersonDao dao) {
this.dao = dao;
At line 201 removed 2 lines.
//~ Methods ================================================================
At line 204 changed 6 lines.
person = dao.getPerson(Long.valueOf(id));
personForm = new PersonForm();
BeanUtils.copyProperties(personForm, person);
return personForm;
Person person = dao.getPerson(Long.valueOf(id));
return convert(person);
At line 213 changed 20 lines.
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);
}
Person person = (Person) convert(obj);
At line 235 changed 2 lines.
return getPerson(person.getId().toString());
return convert(person);
At line 240 changed 10 lines.
if (person == null) {
person = new Person();
}
personForm = (PersonForm) obj;
if (log.isDebugEnabled()) {
log.debug("removing person: " +
personForm.getFirstName() + " " +
personForm.getLastName());
}
Person person = (Person) convert(obj);
At line 255 changed 1 line.
You should be able to compile everything now using "ant compile-web"...
One thing to note is the {{setPersonDao}} method. This is used by Spring to bind the PersonDao to this Manager. This is configured in the applicationContext-service.xml file. We'll get to configuring that in Step 3[3].
You should be able to compile everything now using "ant compile-service"...
At line 275 changed 1 line.
Finally, we need to create the PersonManagerTest.properties file in test/web/**/service so that {{personForm = (PersonForm) populate(personForm);}} will work in our test.
Finally, we need to create the PersonManagerTest.properties file in test/service/**/service so that {{personForm = (PersonForm) populate(personForm);}} will work in our test.
At line 277 changed 6 lines.
;:''Duplicating (and renaming) the PersonDaoTest.properties is the easy route. Alternatively, you could set the properties manually. Make sure and add an __id__ property.''
{{{
firstName=Bill
lastName=Joy
}}}
!!Run the ManagerTest [#3]
;:''Duplicating (and renaming) the PersonDaoTest.properties is the easy route. Alternatively, you could set the properties manually.''
At line 216 added 32 lines.
{{{firstName=Bill
lastName=Joy}}}
Now we need to edit Spring's config file for our services layer so it will know about this new Manager.
!!Configure Spring for this Manager and Transactions [#3]
To notify Spring of this our PersonManager interface and it's implementation, open the src/service/**/service/applicationContext-service.xml file. In here, you will see an existing configuration for the UserManager. You should be able to copy that and change a few things to get the XML fragment below. Add the following to the bottom of this file.
[{Java2HtmlPlugin
<!-- Person Manager: Struts implementation -->
<bean id="personManagerTarget" class="org.appfuse.service.PersonManagerImpl" singleton="false">
<property name="personDao"><ref local="personDAO"/></property>
</bean>
<!-- Transaction declarations for business services. To apply a generic transaction proxy to
all managers, you might look into using the BeanNameAutoProxyCreator -->
<bean id="personManager" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager"><ref local="transactionManager"/></property>
<property name="target"><ref local="personManagerTarget"/></property>
<property name="transactionAttributes">
<props>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="remove*">PROPAGATION_REQUIRED</prop>
<prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
}]
!!Run the ManagerTest [#4]

Back to CreateManager, or to the Page History.