At line 37 added 1 line. |
|
At line 50 changed 1 line. |
protected void setUp() throws Exception{ |
protected void setUp() throws Exception { |
At line 56 changed 1 line. |
protected void tearDown() { |
protected void tearDown() throws Exception { |
At line 60 removed 1 line. |
|
At line 63 added 1 line. |
Agora que temos o framework JUnit configurado para esta classe, vamos ao que interessa: os métodos de teste para nos certificar que tudo funciona no nosso Manager. Aqui está um exemplo do [Tutorial DAO|CreateDAO_pt] para ajudá-lo a entender o que estamos fazendo. |
At line 64 changed 1 line. |
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|CreateDAO] tutorial to help you understand what we're about to do. |
;:''...criamos métodos que começam com "test" (tudo em letra minúscula). Enquanto estes métodos forem públicos, possuírem um retorno void e não possuírem argumentos, serão chamados pela nossa task <junit> em nosso arquivo build.xml do Ant. Aqui estão alguns testes simples para testar operações CRUD. Uma coisa importante para relembrar é que cada método (conhecido como teste), deve ser autônomo.'' |
At line 66 changed 1 line. |
;:''...we create methods that begin with "test" (all lower case). As long as these methods are public, have a void return type and take no arguments, they will be called by our <junit> task in our Ant build.xml file. Here's some simple tests for testing CRUD. An important thing to remember is that each method (also known as a test), should be autonomous.'' |
Adicione os métodos seguintes ao seu arquivo PersonManagerTest.java: |
At line 68 removed 2 lines. |
Add the following methods to your PersonManagerTest.java file: |
|
At line 73 changed 4 lines. |
person = (Person) mgr.getPerson("1"); |
|
assertTrue("person.firstName not null", |
person.getFirstName() != null); |
// set expected behavior on dao |
personDao.expects(once()).method("getPerson") |
.will(returnValue(new Person())); |
person = personManager.getPerson(personId); |
assertTrue(person != null); |
personDao.verify(); |
At line 80 changed 3 lines. |
person = (Person) mgr.getPerson("1"); |
String name = person.getFirstName(); |
person.setFirstName("test"); |
// set expected behavior on dao |
personDao.expects(once()).method("savePerson") |
.with(same(person)).isVoid(); |
At line 84 changed 2 lines. |
person = (Person) mgr.savePerson(person); |
assertTrue("name updated", person.getFirstName().equals("test")); |
personManager.savePerson(person); |
personDao.verify(); |
} |
At line 87 removed 4 lines. |
person.setFirstName(name); |
mgr.savePerson(person); |
} |
|
At line 93 removed 1 line. |
person = (Person) populate(person); |
At line 95 changed 3 lines. |
person = (Person) mgr.savePerson(person); |
assertTrue(person.getFirstName().equals("Bill")); |
assertTrue(person.getId() != null); |
// set required fields |
person.setFirstName("firstName"); |
person.setLastName("lastName"); |
At line 99 changed 4 lines. |
if (log.isDebugEnabled()) { |
log.debug("removing person, personId: " + |
person.getId()); |
} |
// set expected behavior on dao |
personDao.expects(once()).method("savePerson") |
.with(same(person)).isVoid(); |
personManager.savePerson(person); |
personDao.verify(); |
At line 104 changed 1 line. |
mgr.removePerson(person.getId().toString()); |
// reset expectations |
personDao.reset(); |
At line 106 changed 1 line. |
assertNull(mgr.getPerson(person.getId().toString())); |
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(); |
At line 110 changed 1 line. |
This class won't compile at this point because we have not created our PersonManager interface. |
Esta classe não compilará neste ponto porque nós não criamos nossa interface PersonManager. |
At line 112 changed 1 line. |
;:%%(color: blue)''I think it's funny how I've followed so many patterns to allow __extendibility__ in AppFuse. In reality, on most projects I've been on - I learn so much in a year that I don't want to extend the architecture - I want to rewrite it. Hopefully by keeping AppFuse up to date with my perceived best practices, this won't happen as much. Each year will just be an upgrade to the latest AppFuse, rather than a re-write. ;-)'' |
;:%%(color: blue)''Acho engraçado como segui tantos padrões para permitir __extendibilidade__ no AppFuse. Na realidade, na maioria dos projetos que participei, aprendi tanto em um ano que não queria extender a arquitetura - queria reescrevê-la. Espero que isto não ocorra tanto, utilizando minhas melhores práticas para manter o AppFuse em dia. A cada ano haverá apenas um upgrade para uma nova versão do AppFuse, ao invés de ter de reescrevê-lo. ;-)'' |
At line 114 changed 1 line. |
!!Create a new Manager to talk to the DAO [#2] |
!!Criar um novo Manager para conversar com o DAO [#2] |
At line 116 changed 1 line. |
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.'' |
Primeiramente, crie uma interface PersonManager.java no diretório src/service/**/service, e especifique os métodos CRUD básicos para implementações posteriores. ''Eliminei os JavaDocs na classe abaixo para não poluir o código.'' |
At line 118 changed 1 line. |
;:%%(color: blue)''As usual, I usually duplicate (open → save as) an existing file (i.e. UserManager.java).''%% |
;:%%(color: blue)''Como sempre, duplico (open → save as) um arquivo existente (i.e. UserManager.java).''%% |
At line 141 added 1 line. |
import org.appfuse.dao.PersonDao; |
At line 126 removed 2 lines. |
import java.util.List; |
|
At line 129 changed 3 lines. |
|
public List getPeople(Person person); |
|
public void setPersonDao(PersonDao dao); |
At line 133 changed 3 lines. |
|
public Person savePerson(Object person); |
|
public void savePerson(Person person); |
At line 140 changed 1 line. |
Now let's create a PersonManagerImpl class that implements the methods in PersonManager. To do this, create a new class in src/service/**/service and name it PersonManagerImpl.java. It should extend BaseManager and implement PersonManager. |
Agora vamos criar uma classe PersonManagerImpl que implementa os métodos da interface PersonManager. Para fazer isto, crie uma nova classe em src/service/**/service com o nome PersonManagerImpl.java. Esta classe deve estender BaseManager e implementar PersonManager. |
At line 144 changed 1 line. |
package org.appfuse.service; |
package org.appfuse.service.impl; |
At line 146 removed 3 lines. |
import org.apache.commons.logging.Log; |
import org.apache.commons.logging.LogFactory; |
|
At line 159 added 1 line. |
import org.appfuse.service.PersonManager; |
At line 152 removed 6 lines. |
import java.util.List; |
|
/** |
* @author mraible |
* @version $Revision: $ $Date: May 25, 2004 11:46:54 PM $ |
*/ |
At line 159 removed 1 line. |
private static Log log = LogFactory.getLog(PersonManagerImpl.class); |
At line 166 removed 4 lines. |
public List getPeople(Person person) { |
return dao.getPeople(person); |
} |
|
At line 174 changed 1 line. |
public Person savePerson(Object person) { |
public void savePerson(Person person) { |
At line 176 removed 1 line. |
return (Person) person; |
At line 185 changed 2 lines. |
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"... |
Uma coisa que deve ser notada é o método {{setPersonDao}}. Este método é utilizado pelo Spring para ligar o PersonDao a este Gerente(Manager). Isto é configurado no arquivo applicationContext-service.xml. Veremos como se configura este arquivo no Passo 3[3]. |
Já nos é possível compilar tudo agora utilizando "ant compile-service"... |
At line 188 changed 1 line. |
Finally, we need to create the PersonManagerTest.properties file in test/service/**/service so that {{person = (Person) populate(person);}} will work in our test. |
Agora necessitamos editar o arquivo de configuração do Spring para nossa camada Service para lhe dizer da existência do novo Manager. |
At line 190 changed 1 line. |
;:''Duplicating (and renaming) the PersonDaoTest.properties is the easy route. Alternatively, you could set the properties manually.'' |
!!Configurar o Spring para este Manager e as Transações [#3] |
At line 192 changed 2 lines. |
{{{firstName=Bill |
lastName=Joy}}} |
Para notificar o Spring da nossa interface PersonManager e sua implementação, abra o arquivo src/service/**/service/applicationContext-service.xml. Nele, veremos uma configuração comentada para o bean "PersonManager". Retire o comentário, ou adicione o seguinte código ao final do arquivo. |
At line 195 removed 6 lines. |
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. |
|
At line 203 changed 3 lines. |
<!-- Person Manager --> |
<bean id="personManagerTarget" class="org.appfuse.service.PersonManagerImpl" singleton="false"> |
<property name="personDao"><ref bean="personDAO"/></property> |
<bean id="personManager" parent="txProxyTemplate"> |
<property name="target"> |
<bean class="org.appfuse.service.impl.PersonManagerImpl" autowire="byName"/> |
</property> |
At line 207 removed 8 lines. |
|
<!-- 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 bean="transactionManager"/></property> |
<property name="target"><ref local="personManagerTarget"/></property> |
<property name="transactionAttributeSource"><ref local="defaultTxAttributes"/></property> |
</bean> |
At line 217 changed 1 line. |
''Note: [I|DaveKeller] had SAX throw an error because defaultTxAttributes was not defined so I replaced the transactionAttributeSource with this instead, which allowed my unit test to run successfully.'' |
O atributo "parent" se refere a uma definição de bean para um [TransactionProxyFactoryBean|http://www.springframework.org/docs/api/org/springframework/transaction/interceptor/TransactionProxyFactoryBean.html], que possui todos os atributos de transação básicos inicializados. |
At line 219 changed 1 line. |
[{Java2HtmlPlugin |
!!Rodar o ManagerTest [#4] |
At line 221 changed 5 lines. |
<property name="transactionAttributes"> |
<props> |
<prop key="*">PROPAGATION_REQUIRED</prop> |
</props> |
</property> |
Salve todos os seus arquivos editados e tente rodar "ant test-service -Dtestcase=PersonManager" mais uma vez. |
At line 227 removed 7 lines. |
}] |
|
|
!!Run the ManagerTest [#4] |
|
Save all your edited files and try running "ant test-service -Dtestcase=PersonManager" one more time. |
|
At line 240 changed 1 line. |
''Next Up:'' __Part III:__ [Creating Actions and JSPs|CreateActions] - A HowTo for creating Actions and JSPs in the AppFuse architecture. |
Os arquivos modificados e adicionados nesta parte [podem ser baixados aqui|http://appfuse.dev.java.net/files/documents/1397/7484/appfuse-tutorial-managers-1.6.zip]. |
|
''Próxima:'' __Parte III:__ [Criando Actions e JSPs|CreateActions_pt] - Um tutorial para criação de Actions e JSPs na arquitetura AppFuse. |