ITPub博客

首页 > Linux操作系统 > Linux操作系统 > IBM Records Manager 逻辑扩展实现和部署示例

IBM Records Manager 逻辑扩展实现和部署示例

原创 Linux操作系统 作者:ArtCode 时间:2009-04-27 15:43:22 0 删除 编辑

IBM Records Manager 概述

IBM Records Manager 提供了物理的(Physical)和电子的(Electronic)记录(Records)的生命周期管理。它可以为各种主机应用(Host Applications),如电子邮件,文档管理,工作流和群件等,提供记录的生命周期管理,与其他记录管理应用(Records Manager Application)不同的是, IBM Records Manager 并不是一个独立的应用(Application),它是一个可以嵌入到各种主机应用中的引擎(Engine)。主机应用(Host Applications)提供记录的产生,存储和查询等,而 IBM Records Manager 为主机应用提供了的记录的生命周期管理。 IBM Records Manager 并不预定生命周期管理的规则,如记录何时进入生命周期,何时被销毁等。每个主机应用可以基于组织的法规,规章,业务逻辑和策略定制自己独一无二的规则。

IBM Records Manager 包含如下组件:

  • 引擎(Engine):提供了生命周期管理的所有业务逻辑(Business Logic)
  • 应用编程接口(API): 用来将 IBM Records Manager 嵌入到主机应用(Host Applications)中
  • 基于Web的管理客户端(Web Administrator Client): 一个管理用户接口,用来设计,构建和维护主机应用的文档归档计划(File Plan)

IBM Records Manager 应用标准的 J2EE 设计模式。引擎用 Enterprise Java Beans(EJB)编写, 使用 Java Messaging Service(JMS) 来支持组件间通信和异步的体系结构。它与 IBM Records Manager 数据库通过JDBC来通信。引擎支持 JAVA Internet Inter-ORB Protocol(IIOP)、远程方法调用(Remote Method Invocation,RMI)和简单对象访问协议(Simple Object Access Protocol,SOAP)。客户机可以使用 IIOP/RMI 或 SOAP 协议与引擎进行通信。

主机应用使用API(包含在IRMAPI.jar包)与引擎通信,每个主机应用必须实现接口主机服务接口(Host Service Interface)实现与引擎的双通信。

基于 Web 的管理客户端调用 IBM Records Manager API 访问引擎, 用户完全可以使用 API, 重新定义和实现管理客户端的外。

IBM Records Manager 逻辑扩展

用户可以通过逻辑扩展(Logic Extension)来扩展 IBM Records Manager 的业务逻辑(Business Logic)。 IBM Records Manager 在 IRMAPI.jar 中定义了一个接口 FilePlanComponentListener(在包 com.ibm.gre.engine.extension 里),用户通过实现这个接口,来变更IRMger某些业务对象(Business Objects)的行为,达到扩展业务逻辑的目的。可被影响的业务对象有接口 FilePlanComponentController 的如下方法(Methods):

  • addFilePlanComponent
  • deleteFilePlanComponent
  • getFilePlanComponentByID
  • getFilePlanComponentByBarCode
  • getFilePlanComponentField
  • setFilePlanComponentField
  • updateFilePlanComponent
  • supercede
  • Transitioning File Plan Components

接口 FilePlanComponentController 定义了对文档归档组件(File Plan Component)的操作。所以,逻辑扩展可以影响的组件对象是 IBM Records Manager 文档归档组件,可以影响的业务对象是 IBM Records Manager 文档归档组件上的由以上方法定义的操作。

与逻辑扩展相随的定制商业逻辑(Custom Business Logic)可以被加到到所选的文档归档组件的方法中。而且与一个文档归档组件关联的逻辑扩展的数目并没有限制。

每一个不同类型的文档归档组件都可以和一组唯一的逻辑扩展相关联。例如,对于一类称作“Series”的文档归档组件,人们可以定义仅适用于该类组件(“Series”)的文件归档组件方法的逻辑扩展。而对另一类称作“Folder”的组件,那么,也可以为其创建一组完全不同的逻辑扩展。

一个逻辑扩展有两个组件: before-action 事件(Event)和 after-action 事件(Event)。 IBM Records Manager 对要进行修改的每个业务对象使用一个简单的侦听器模式。该模式需要 Pre Action 和 Post Action 定制逻辑扩展(Custom Logic Extension)。也就是说在某些事件发生前和发生后,逻辑扩展会被调用。逻辑扩展可以用于接收和修改传递给文档归档组件方法的数据,或者将该数据传递给后续方法,执行客户应用程序相关函数,或者回调(Call back) IBM Records Manager 接收或修改数据。如图 1.所示,任意数量的逻辑扩展可以以任意的顺序加到一个核心逻辑之上,并实现数据的传递。


图 1. 多个逻辑扩展的逻辑流程
多个逻辑扩展的逻辑流程 

接口 FilePlanComponentListener

开发人员通过实现接口 FilePlanComponentListener 来创建逻辑扩展。与逻辑扩展可以影响的业务对象相对应,接口 FilePlanComponentListener 定义了一系列扩展方法(Extension Methods),某一个业务对象会触发相应的扩展方法。


表 1. 扩展方法及与其相应的触发方法

触发逻辑扩展事件的方法 扩展方法
addFilePlanComponent beforeAddEvent, afterAddEvent
deleteFilePlanComponent beforeDeleteEvent, afterDeleteEvent
getFilePlanComponentByID beforeGetByIDEvent, afterGetByIDEvent
getFilePlanComponentByBarCode beforeGetByBarCodeEvent, afterGetByBarCodeEvent
getFilePlanComponentField beforeGetFieldEvent, afterGetFieldEvent
setFilePlanComponentField beforeSetFieldEvent, afterSetFieldEvent
updateFilePlanComponent beforeUpdateEvent, afterUpdateEvent
supercede beforeTransitionEvent, afterTransitionEvent
Transitioning File Plan Components beforeSupercedeEvent, afterSupercedeEvent

每个扩展方法都具有一个 EventObject 参数。这个参数封装了一个传递一组对象集合(Objects Collection)的哈希图(HashMap)。这些扩展方法的 EventObject 参数可以被读取和修改,那么业务对象,也就是文档归档组件的方法,在调用这些扩展方法时,就达到了扩展业务逻辑的目的。

限于篇幅,下表只列出了本文实现的两个扩展方法 afterAddEvent 和 beforeTransitionEvent 的对象集合或者说是参数:


表 2. 扩展方法参数列表

扩展方法 参数 类型 注释
afterAddEvent STATE_MACHINE StateMachine Used to call back into Records Manager
FILE_PLAN_COMPONENT_XML String The Fields Collection XML containing the components metadata
PARENT_FILE_PLAN_COMP_ID Long The FilePlanComponent ID of the Source (Parent) of the Component being Created
ADD Long The return value from the addFilePlanComponent method (the unique computer generated ID identifying the newly created component)
beforeTransitionEvent STATE_MACHINE StateMachine Used to call back into Records Manager
FILE_PLAN_COMPONENT_ID Long The unique ID of the FilePlanComponent
PHASE_ID Long The ID of the phase this component is transitioning into

当一个与逻辑扩展方法关联的业务对象,也就是文档归档组件的方法,被调用时,下列事件会发生:

  • 初始化程序(Routine)被处理
  • 扩展方法的参数被初始化。以 FilePlanComponentController 的 AddFilePlanComponent 方法为例,参数 File_Plan_Component_XML 和 Parent_File_Plan_COMP_ID 的值被加到哈希图中,这个哈希图会被传递给扩展方法
  • 组件(Component)的 StateMachine 对象被加到哈希图中,这个对象允许客户应用程序创建本地接口来回调 IBM Records Manager
  • 扩展方法的 before-action 事件被调用。注意,每个扩展方法是可以更改某些参数的
  • 从扩展方法的 before-action 事件返回,输出参数的值被赋给 IBM Records Manager 相应的变量
  • IBM Records Manager 执行业务逻辑程序,注意,如果扩展方法更改了某些输出参数,这些更改后的值会被使用
  • 扩展方法的参数再次被初始化。以 FilePlanComponentController 的 AddFilePlanComponent 方法为例,参数 File_Plan_Component_XML 的值,Parent_File_Plan_COMP_ID 的值和参数 Add 被加到哈希图中,这个哈希图会被传递给扩展方法
  • 扩展方法的after-action事件被调用
  • 从扩展方法的 after-action事件返回,输出参数的值被赋给 IBM Records Manager 相应的变量
  • 结束程序(Routine)被调用

    问题定义

    下面我们以一个简单的场景为例,来介绍如何设计和实现逻辑扩展,并配置 IBM Records Manager 来部署定制的逻辑扩展。

    用户在他/她的文档归档计划(File Plan)中定义了“Document”类型的文档归档组件。这一类型的文档归档组件用来存储客户应用程序声明的记录,这些记录在不同的生命周期阶段(Life Cycle Phase)转换(Transition), 当这些记录完成它们的生命周期(Life Cycle),它们会最终被销毁(Destroyed)。

    上述过程由 IBM Records Manager 引擎的业务逻辑即可实现。现在用户计划扩展其业务逻辑如下:

    • 在记录生成之后, 回调 IBM Records Manager 获得新创建的记录的HostID,写入逻辑扩展日志
    • 在记录转换到下一个生命周期阶段之前,获得这一新的生命周期阶段的信息,写入逻辑扩展日志

      实现逻辑扩展

      检查 IBM Records Manager 逻辑扩展的方法表,我们知道要实现如下方法 afterAddEvent and beforeTransitionEvent。

      工具和先决条件

      由于我们要创建一个 Java 应用程序,首先要有一个 Java 应用程序的开发环境,这里我们使用 eclipse 3.2 作为我们的开发环境。此外,我们还需要 IBM Records Manager API,它包含在 IRMAPI.jar 中。

      在开始运行之前,这里假定一套可工作的 IBM Records Manager 系统(数据库,引擎,基于 Web 的管理客户端)已经搭建好。

      代码清单


      清单 1. 代码清单
                      
      
      package com.ibm.gre.irmsamples.irmlogicextensions;import java.util.EventObject;
      
      import java.util.HashMap;
      import javax.ejb.CreateException;
      import javax.naming.NamingException;
      import javax.rmi.PortableRemoteObject;
      import org.apache.log4j.Logger;
      import com.ibm.gre.engine.ejb.facade.FilePlanComponentControllerEJBLocal;
      import com.ibm.gre.engine.ejb.facade.FilePlanComponentControllerEJBLocalHome;
      import com.ibm.gre.engine.extension.FilePlanComponentListener;
      import com.ibm.gre.engine.util.BusinessComponentsJNDINames;
      import com.ibm.gre.engine.util.BusinessLayerError;
      import com.ibm.gre.engine.util.ExtensionParamKeys;
      import com.ibm.gre.engine.util.RecordManagerException;
      import com.ibm.gre.engine.util.RecordManagerExceptionTypes;
      import com.ibm.gre.engine.util.ServiceLocator;
      import com.ibm.gre.engine.value.StateMachine;
      
      public class IRMLogicExtension implements FilePlanComponentListener
      {
      	
         private static final long serialVersionUID = 1L;
         private static Logger logger = Logger.getLogger("EXTENSION");		
         public void afterAddEvent(EventObject e) throws RecordManagerException
         {
      
            logger.info("   ");
            logger.info("starting afterAddEvent Listener...");
            HashMap map = (HashMap) e.getSource();
            long id = ((Long) map.get(ExtensionParamKeys.PARENT_FILE_PLAN_COMP_ID)).longValue();
            logger.info("Parent File Plan ComponentId " + id);
            StateMachine stateMachine = (StateMachine) map.get(ExtensionParamKeys.
                STATE_MACHINE);
            Long newFilePlanComponentID = (Long) map.get(ExtensionParamKeys.ADD);
            logger.info("Newly added File Plan Component ID " + newFilePlanComponentID);
            try{	
      	  ServiceLocator locator = ServiceLocator.getInstance();
      	  Object bj = locator.lookup("local:ejb/" +
      	      BusinessComponentsJNDINames.FILE_PLAN_COMPONENT_CONTROLLER_JNDI);
      	  FilePlanComponentControllerEJBLocalHome uch = 
      	      (FilePlanComponentControllerEJBLocalHome)PortableRemoteObject.narrow(obj, 
      	          FilePlanComponentControllerEJBLocalHome.class);
      	  FilePlanComponentControllerEJBLocal ucl = null;
      	  ucl = uch.create(stateMachine);			
      	  logger.debug("host id for newly added file plan component:" + 
      	      ucl.getFilePlanComponentField(newFilePlanComponentID.longValue(),
                                 "RecHsID"));
                  } 
            catch(NamingException ex)
                  {
      	  RecordManagerException rme = new RecordManagerException(BusinessLayerError.
      	      JNDI_LOOKUP_FAILED,ex.getMessage(), getClass().getName(), 
      	          RecordManagerExceptionTypes.BUSINESS_LOGIC, ex);
      	  rme.addMessageParameter(ex.getMessage());
      	  throw rme;
                   }
            catch(CreateException ce)
                   {
      	  logger.debug("Extension exception:", ce);			
      	  throw new RecordManagerException(BusinessLayerError.UNKNOWN, ce.getMessage(), 
      	      getClass().getName(), RecordManagerExceptionTypes.SYSTEM, ce);
                    }
      		
      	  logger.info("The end of afterAddEvent Listener...");
           }
      
         public void beforeTransitionEvent(EventObject e) throws RecordManagerException
          {
            logger.info("   ");
            logger.info("starting beforeTransitionEvent Listener...");
            HashMap map = (HashMap) e.getSource();
            long id = ((Long) map.get(ExtensionParamKeys.FILE_PLAN_COMPONENT_ID)).longValue();
            logger.info("File Plan ComponentId to be transitioned " + id);
            Long phaseID = (Long) map.get(ExtensionParamKeys.PHASE_ID);
            logger.info("The next phase is" + phaseID);            
            logger.info("The end of beforeTransitionEvent Listener...");
         }
      }
            

      步骤1

      首先逻辑扩展 IRMLogicExtension 要实现 IBM Records Manager 定义的接口 FilePlanComponentListener


      图 2. 实现接口 FilePlanComponentListener
      实现接口

      步骤2

      当新建文档归档组件时,FilePlanComponentController 的 addFilePlanComponent 方法触发了 afterAddEvent,并初始化 EventObject 类型的参 e,传递给 afterAddEvent


      图 3. afterAddEvent方法被初始化
      初始化

      步骤3

      EventObject 参数 e 封装了一个哈希图(HashMap),哈希图传递了一组对象集合(Objects Collection)。对方法 afterAddEvent 而言,参数 PARENT_FILE_PLAN_COMP_ID,STATE_MACHINE,ADD 已被初始化,其值可获得


      图 4. 获得参数值
      获得参数值

      步骤4

      首先,从 JNDI 服务器获得 FilePlanComponentControllerEJBLocalHome 工厂信息,并由参数值 StateMachine 获得对 IBM Records Manager 的回调入口。最后获得新建文档归档组件的 HostID 信息。


      图 5. 回调 IBM Records Manager
      回调

      部署逻辑扩展

      当上述代码完成调试编译,在 eclipse 里将之导出为 IRMLogicExtension.jar 文件,现在我们要完成如下步骤:

      • 将逻辑扩展和某一类型的文档归档组件关联起来,使当用户对这一类型的文档归档组件作相应操作时,逻辑扩展可以被触发
      • 将 IRMLogicExtension.jar 添加到 IBM Records Manager 的 Classpath,使逻辑扩展被触发时, IBM Records Manager 可以定位它的实现代码

      步骤1

      登陆 IBM Records Manager Web Administrator Client, 在Tools->Extensions页面,点击 Add 按钮后,在打开的 Logic Extension Class - New 页面中:在 Component Definition 的下拉列表里选择你要为之扩展逻辑的文档归档组件类型,这里,我们选择 Document。对 Fully Qualified Logic Extension Class Name 中输入 com.ibm.gre.irmsamples.irmlogicextensions.IRMLogicExtension 而不是 IRMLogicExtension。如果希望使这个逻辑扩展确实被调用,则选择 Enabled。因为我们这里只实现了一个逻辑扩展,在 Execution Order 中输入 1。


      图 6. 在 IBM Records Manager 中配置逻辑扩展
      配置逻辑扩展

      步骤2

      将 IRMLogicExtension.jar 文件拷贝到安装 IBM Records Manager 引擎(不是 IBM Records Manager Web Administrator Client)的机器上。由于 IBM Records Manager 引擎作为一个 J2EE 的应用部署到 IBM WebSphere Application Server(WAS),首先在 WAS 上新建一个共享库 logicextension。将 logicextension 添加到 IBM Records Manager 引擎的 Classpath。


      图 7. 新建共享库
      新建共享库

      图 8. 添加到 IBM Records Manager 的Classpath
      配置Classpath

      运行逻辑扩展

      在运行逻辑扩展之前,请执行下列步骤准备测试环境:

      • 修改 IRMLogConfig.properties 来更新逻辑扩展的日志级别,默认是 ERROR, 改为 INFO
      • 重新启动 IBM Records Manager 引擎

      图 9. 更新逻辑扩展日志级别
      日志级别

      执行如下步骤运行和验证逻辑扩展

      • 新建一个 Document 类型的文档归档组件
      • 检查日志 record_manager_extensions.log,日志内容应如图 10.所示

      图 10. 逻辑扩展日志
      日志 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/15082138/viewspace-591945/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2008-08-05

  • 博文量
    269
  • 访问量
    560799