基于Jazz技术构建企业级Web2.0应用(3)
PetStore AOP实现
一个Jazz构件若需要Jazz Process的支持(或者说“向Process开放”),需要完成以下几个方面:
· 通过configurationPoints扩展点定义operation。operation是Jazz Process进行AOP的切入点。
· operation的实现。通常将业务逻辑(如对其它服务的调用)封装在一个com.ibm.team.process.common.advice.AdvisableOperation的run方法中,并通过Process构件提供的com.ibm.team.process.service.IServerProcess中的adviceAndExecute方法调用。注意:operation的定义与实现的绑定是在AdvisableOperation构造方法中,将参数operationId赋值为operation定义中的id。
· 通过operationAdvisors和operationParticipants扩展点定义针对operation的前置通知(advisor)和后置行为(participant)。
· advisor和participant的实现(分别实现com.ibm.team.process.common.advice.runtime. IOperationAdvisor和com.ibm.team.process.common.advice.runtime. IOperationParticipant接口)。
· 通过process定义文件将operation和它的advisors、participants关联起来(分别通过operation的preconditions和follow-up actions字段)。
下面将详细介绍如何在PetStore中利用Jazz Process机制实现上面设计的AOP功能。
第一步,添加对Process bundle的依赖
在插件项目com.ibm.petstore.service中添加对两个process bundle com.ibm.process.common和com.ibm.process.service的依赖。
第二步,定义和实现operation "buy"及其participant "buyParticipant"
在com.ibm.petstore.service的plugin.xml中通过configurationPoints扩展点定义operation "buy":
清单1. operation定义
<extension
point="com.ibm.team.process.service.configurationPoints">
<operation
id="com.ibm.petstore.service.buy"
name="Buy Pet">
</operation>
</extension>
注意:这里较为重要的是id的定义。在下面的步骤中将通过对此id引用这里定义的operation。
用一个继承自com.ibm.team.process.common.advice.AdvisableOperation的类BuyPetOperation实现operation "buy",在其run方法中封装用户付费的业务逻辑:
清单2. BuyPetOperation
public class BuyPetOperation extends AdvisableOperation {
private int accNo;
private String pw;
private int price;
private String email;
public BuyPetOperation(ITeamArea teamArea,
int accNo, String pw, int price, String email) {
super("com.ibm.petstore.service.buy", null, teamArea);
this.accNo=accNo;
this.pw=pw;
this.price=price;
this.email=email;
}
@Override
public IOperationReport run(IBehaviorConfiguration configuration,
IProgressMonitor monitor) throws TeamRepositoryException {
PayUtil payUtil=new PayUtil();
try {
payUtil.login(accNo, pw);
payUtil.pay(price);
payUtil.logout();
} catch (PayUtilException e) {
throw new TeamRepositoryException(e);
}
return null;
}
public String[] getActions() throws TeamRepositoryException {
return new String[] { "buy" };
}
public String getEmail() {
return email;
}
public int getPrice() {
return price;
}
}
注意:在BuyPetOperation的构造方法中通过引用plugin.xml中operation定义的id值将实现类与operation的定义绑定,该id值将作为参数被传给AdvisableOperation的构造方法以完成operation实例的构造。
在com.ibm.petstore.service的plugin.xml中通过operationParticipants扩展点定义针对operation "buy"的participant "buyParticipant":
清单3. participant定义
<extension
point="com.ibm.team.process.service.operationParticipants">
<operationParticipant
class="com.ibm.petstore.service.process.BuyPetParticipant"
id="com.ibm.petstore.service.buyParticipant"
name="Buy Pet Participant"
operationId="com.ibm.petstore.service.buy">
</operationParticipant>
</extension>
这里发生了两件事:1)定义了此participant的id;2)通过operationId标识此participant所针对的operation。
用一个实现IOperationParticipant接口的类BuyPetParticipant实现"buyParticipant",在其run方法中实现向用户发送email的功能:
清单4. BuyPetParticipant
public class BuyPetParticipant implements IOperationParticipant {
public void run(AdvisableOperation operation,
IProcessConfigurationElement participantConfig,
IParticipantInfoCollector collector, IProgressMonitor monitor)
throws TeamRepositoryException {
String email=((BuyPetOperation)operation).getEmail();
int price=((BuyPetOperation)operation).getPrice();
this.sendEmail(email,
"From PetStore: Amount "+price+" is paid by your account.");
}
public void sendEmail(String email, String content){
……
System.out.println("log: mail sent to \""+email+
"\" with content \""+content+"\".");
}
}
注意:同operation类似,一个participant也在其run方法中封装核心业务逻辑。在Jazz Process执行一个participant时,将把其对应的operation对象作为参数传递给run方法,本例中通过operation对象获取用户的email和购买宠物的价格信息。
在PetStore的process定义文件中将operation "buy"和participant "buyParticipant"关联起来:
清单5. operation和participant的关联
<process-specification xmlns="http://com.ibm.team.process">
<project-configuration>
……
</project-configuration>
<team-configuration>
<permissions>
……
</permissions>
<behavior>
<role id="default">
<operation id="com.ibm.petstore.service.buy">
<preconditions>
</preconditions>
<followup-actions>
<followup-action id="com.ibm.petstore.service.buyParticipant"
name="Buy Pet Participant"
description="Buy Pet Participant contains sending a email to notify user pay amount.">
</followup-action>
</followup-actions>
</operation>
</role>
</behavior>
</team-configuration>
</process-specification>
注意:在process定义中通过id引用一个已定义的operation,并在follow-up actions字段中通过id引用它对应的所有participant。类似的,如果它有对应advisor,则需要在preconditions字段中指明。