14.TimeTrackingService定义
我们现在处于迭代2阶段。这个迭代的目标是要构建搜索结果界面。要刷新我们的内存,下面是搜索屏幕的模型。搜索结果界面是时间卡显示的右面的内容。
Value Objects
要支持搜索结果面板,服务层必须提供根据匹配的特定规则获取timecard列表的能力。让我们决定我们创建一个service叫做TimeTrackingService,提供需要的功能:
public interface TimeTrackingService
{
public TimecardSummaryVO[] findTimecards(TimecardSearchCriteriaVO criteria);
}
有一个TimecardSearchCriteriaVO是value object,timecard包搜索条件-如果在这个类中的一个字段被指定,这个搜索条件就被应用了;如果这个filed被保留为null,则那个查询条件不会被用到。TimecardSummaryVO是另外的一个VO,在summary information包中。基于在Search屏幕中的条件,让我们来设计这两个VO。注意,我们需要一个状态field,在所有的Value Object中包含。因此首先,创建一个项目叫做TimecardStatus在org.andromda.timetracker.domain包中。在”Domain Objects”图中创建一个类,把sterotype设置为Enumeration。像下面显示的那样,这些被增加到属性中。确认enumeration被创建在org.andromda.timetracker.domain包中。
TimecardStatus被定义了,我们能定义被findTimecards()服务方法使用的两个value object。创在org.andromda.timetracker.vo包中建立TimecardSearchCriteriaVO和TimecardSummaryVO。在”Value Objects”图中创建这些value object。在TimecardSearchCriteriaVO中的每个属性的多重性被设置为0..1-指出他们的值可以有或没有。要指定一个属性的多重性,你必须在属性上双击打开它的描述,然后选择正确的多重性。在另外的两个value objects,创建一个类叫做TimecardSummaryVO[]来表现timecard summary数组。确保这三个类被创建在org.andromda.timetracker.vo包中。
TimeTrackingService
我们现在已经有了定义我们的TimeTrackingService的任何东西。在org.andromda.timetracker.service包中创建这个服务。在”Services”图中创建并且确保服务被创建在org.andromda.timetracker.service包中。已经确保findTimecards方法的返回类型为TimecardSummaryVO[]。
现在,让我们要求AndroMDA来生成代码:
1.在命令提示符中,执行mvn install。确保你看到了BUILD SUCCESSFUL消息。验证下面的文件会被生成:
- common/target/src/org/andromda/timetracker/domain/TimecardStatus.java
- common/target/src/org/andromda/timetracker/vo/TimecardSummaryVO.java
- common/target/src/org/andromda/timetracker/vo/TimecardSearchCriteriaVO.java
- common/target/src/org/andromda/timetracker/service/TimeTrackingService.java
- core/target/src/org/andromda/timetracker/service/TimeTrackingServiceBase.java
- core/src/main/java/org/andromda/timetracker/service/TimeTrackingServiceImpl.java
TimeTrackingService Test
像UserService一样,我们首先要给TimeTrackingService写一个测试用例并且写实现来使测试通过。下面的步骤用来创建TimeTrackingServiceTest并且运行:
1.
从C:/timetracker-completed/core/src/test/java/org/andromda/timetracker/service
位置拷贝TimeTrackingServiceTest.java在你的实现的位置中。这个文件包括对findTimecards()方法的两个测试,testFindAllTimecards()和testFindTimecardsForSubmitter。确保你确认和理解这些测试。
2.
编辑在C:/timetracker/core/src/test/resources目录下的testng.xml,取消注释TimeTrackingServiceTest以便能执行。
3.
执行下面的命令,在C:/timetracker目录来运行测试。
Mvn –f core/pom.xml test
你可以看到下面的错误信息,说明了测试失败:
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running Services Test
Tests run: 3, Failures: 2, Errors: 0, Skipped: 0, Time elapsed: 0.661 sec <<< FAILURE!
Results :
Tests run: 3, Failures: 2, Errors: 0, Skipped: 0
[INFO] ------------------------------------------------------------------------
[ERROR] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] There are test failures.
[INFO] ------------------------------------------------------------------------
[INFO] For more information, run Maven with the -e switch
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 19 seconds
[INFO] Finished at: Sun Aug 06 18:38:26 EDT 2006
[INFO] Final Memory:
4.让我们看测试结果,看看发生了什么。打开c:/timetracker/core/target/surefire-reports/Services Test.txt。你可以看到下面的日志:
-------------------------------------------------------------------------------
Test set: Services Test
-------------------------------------------------------------------------------
Tests run: 3, Failures: 2, Errors: 0, Skipped: 0, Time elapsed: 0.661 sec <<< FAILURE!
testFindAllTimecards Time elapsed: 0.31 sec <<< FAILURE!
java.lang.NullPointerException
at ...(TimeTrackingServiceTest.java:58)
at ...(TimeTrackingServiceTest.java:41)
testFindTimecardsForSubmitter Time elapsed: 0.01 sec <<< FAILURE!
java.lang.NullPointerException
at ...(TimeTrackingServiceTest.java:58)
at ...(TimeTrackingServiceTest.java:50)
很明显,服务当前返回了null而不是TimecardSummaryVO[]。这个问题会当我们实现服务后被纠正。
15.TimeTrackingServcie实现
在这一章,我们会实现TimeTrackingService并且确保能通过测试。
我们会首先需要增强我们的领域模型来支持新value object TimecardSearchCriteriaVO并且TimecardSummaryVO。注意TimecardSearchCriteriaVO是一个简单的数据传输对象,来指定搜索参数。没有领域实体被需要表达这个概念。然而TimecardSummaryVO代表了timecard实体并且必须被增加到领域模型中。这个图如下面的显示:
Timecard与User实体有两个关系:
1. submitter:提交timecard的人。
2. approver:审核timecard的人。
两个关联关系的箭头指出了从Timecard到Person的方向。例如,timecard保持了对submitter和approver的饮用。在关联末端的数字和型号指明了多重性。顶端的关联指出timecard能有一个submitter,但是submitter能提交多个timecard(用*显示)。相似的,地下的关系指出了有0或1个审批者,一个审批者可以审批多个timecard。我们允许0审批者,以便审批是与提交延迟的。
我们在Timecard实体中增加一个方法叫做findByCriteria()。TimeTrackingService会使用这个方法来查找timecard。注意在findByCriteria()方法的下划线-他表示在UML中的”classifier”范围。如果在方法上没有下划线,会实现”instance”范围。这是在AndroMDA中重要的概念,特别注意。
一个带classifier scope的方法是一种一般目的的工具方法,操作一个或更多的实体。这样的方法在DAO类中被生成。带