技术开发 频道

基于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字段中指明。

0
相关文章