`

Dorado和Remedy整合可行性分析

阅读更多

        Dorado是一个专注于web表现层界面展现的开发框架,能与各种后台业务逻辑层实现无缝集成,Remedy AR System作为BMC提供的一个ITSM开发平台,为了提供给用户更多的灵活性,提供了一套Java API,这样为Remedy和Dorado进行整合提供了可能.
        Dorado 架构,原理,技术实现...省略字若干
        Remedy AR System组成元素,系统原理,具体用法...省略字若干
I)Dorado操作后台数据库,包含核心典型代码。
         首先这个提法有些问题,如果能直接用dorado来操作数据库了,那还要remedy AR System干嘛?所以应该是Dorado调用Remedy AR System后台业务逻辑层,我们知道所有涉及到数据库的信息管理系统,其业务逻辑归根结底都是对DBMS进行增加,删除,查找和修改操作(CURD), 作为开发平台Remedy AR System也不例外,只是它除了将所有操作的数据保存在数据库里面之外,它还将系统的所有的界面信息(这里主要指的是Forms),相关的操作信息(这里指的是Active Link, Filter, Escalation)也保存到了数据库中.
         MVC(model-view-control)是我们进行软件开发时通常的分层方法和设计模式,不过在Remedy AR System中,这种做法没有得到很好的实现,即其View和Model的分层并不明显,所以我们需要做这个工作:找出该表单中的model信息,然后加以定义,比如对一个城市的维护form中,我们需要从form中分离出关于城市的model信息,然后生成成相应的JavaBean.
         至此,我们将根据JavaBean信息以及Remedy AR System系统中的Form布局信息来创建Dorado所需要的view.xml文件(dataset+control),最终生成jsp文件.
         界面创建完毕之后,接下来就是调用Remedy Java API,在Dorado将通过使用dataset的监听器类以及DataModel类的相应方法,来处理从前台页面发出的CRUD请求以及实现相应的权限控制,这里也是我们调用Java API完成与后台业务层集成的结合点.
Remedy提供的Java API调用一般分为三个部分:根据当前登录用户信息创建ARServerUser对象;然后使用Server Object Factory创建Remedy Server Object,并为Server对象设置相应的参数;执行Server对象的方法(增删查改操作);最后销毁ARServerUser以及创建的Server Object.
         下面我们以Remedy自带的Sample中City信息的维护为例,来说明如何使用Dorado与Remedy AR System后台整合进行CRUD操作
(1)查询操作
          在dataset监听器的onInit方法中,使用当前登录用户信息实例化一个ARServerUser对象:

java 代码
  1. public void onInit(Dataset arg0) throws Exception {   
  2.  System.out.println("In Dataset Listener Connecting to AR Server...");   
  3.  context = new ARServerUser();   
  4.  context.setServer("bstek-macro");   
  5.  // 通常用户信息将从session中取得   
  6.  context.setUser(new AccessNameID("Demo"));   
  7.  context.setPassword(new AccessNameID(""));   
  8.  try {   
  9.   context.verifyUser(new VerifyUserCriteria());   
  10.  } catch (ARException e) {   
  11.   // This exception is triggered by a bad server, password or,   
  12.   // if guest access is turned off, by an unknown username.   
  13.   System.out.println("Error verifying user: " + e);   
  14.   // Clear memory used by our user context object   
  15.   context.clear();   
  16.   System.exit(1);   
  17.  }   
  18.  System.out.println("In Dataset Listener Connected to AR Server.");   
  19. }   

         接下来我们在afterLoadData()方法中根据jsp页面传过来的参数,构造操作参数调用Remedy AR System的Java API进行查询操作,Remedy Java API的查询参数非常类似于SQL语法,所以其用法相对来说也十分简单:

java 代码
  1. public void afterLoadData(Dataset dataset) throws Exception {   
  2.  ParameterSet parameters = dataset.parameters();   
  3.   
  4.  String qualStr = "";   
  5.  String city = parameters.getString("city");   
  6.  String code = parameters.getString("airPortCode");   
  7.  boolean andFlag = false;   
  8.  // 构造查询参数   
  9.  if (StringUtils.isNotEmpty(city)) {   
  10.   qualStr = "( \'City\' like \"%" + city + "%\" )";   
  11.   andFlag = true;   
  12.  }   
  13.  if (StringUtils.isNotEmpty(code)) {   
  14.   qualStr += (andFlag ? " and " : "")   
  15.     + "( \'Airport Code\' like \"%" + code + "%\" )";   
  16.  }   
  17.  //设置参数,执行查询操作   
  18.  List list = queryRecordsByQual(qualStr);   
  19.  //将查询结果返回给dataset,用于jsp页面进行展示   
  20.  dataset.fromDO(list);   
  21. }   
  22. private List queryRecordsByQual(String qualStr) {   
  23.  List result = new ArrayList();   
  24.  System.out.println("Retrieving records with qualification " + qualStr);   
  25.  try {   
  26.   // 查询参数包括两部分,以部分是列信息,另外一部分是行信息,在得到的结果中,Remedy AR System将自动执行权限控制,也就是说返回的数据是进行了权限约束的,只有当前用户有权限查看到的数据还会返回   
  27.   // 首先是根据当前登录用户信息,取得查询要返回数据的列,也就是制定form中的列信息   
  28.   FieldCriteria fCrit = new FieldCriteria();   
  29.   fCrit.setRetrieveAll(true);   
  30.   FieldListCriteria fListCrit = new FieldListCriteria(formName,   
  31.     new Timestamp(0), FieldType.AR_ALL_FIELD);   
  32.   // 这里的得到的field已经包含了权限信息,只有当前用户可见的列在查询结果中才会出现   
  33.   Field[] formFields = FieldFactory.findObjects(context, fListCrit,   
  34.     fCrit);   
  35.   
  36.   // 对查询行添加进行解析,类似于SQL中的where条件语句   
  37.   QualifierInfo myQual = Util.ARGetQualifier(context, qualStr,   
  38.     formFields, null, Constants.AR_QUALCONTEXT_DEFAULT);   
  39.   FieldFactory.getFactory().releaseInstance(formFields);   
  40.   // 下面是设置行信息,也就是对最终查询结果的行进行处理   
  41.   EntryListCriteria listCriteria = new EntryListCriteria();   
  42.   listCriteria.setSchemaID(formName);   
  43.   listCriteria.setQualifier(myQual);   
  44.   
  45.   EntryListFieldInfo[] entryListFieldList = new EntryListFieldInfo[3];   
  46.   // id   
  47.   entryListFieldList[0] = new EntryListFieldInfo(   
  48.     new FieldID(FIELD_ID), 15" ");   
  49.   // city   
  50.   entryListFieldList[1] = new EntryListFieldInfo(new FieldID(   
  51.     FIELD_CITY), 15" ");   
  52.   // code   
  53.   entryListFieldList[2] = new EntryListFieldInfo(new FieldID(   
  54.     FIELD_CODE), 25" ");   
  55.   
  56.   // Set the entry criteria   
  57.   EntryCriteria criteria = new EntryCriteria();   
  58.   criteria.setEntryListFieldInfo(entryListFieldList);   
  59.   
  60.   // 最终取得查询结果   
  61.   Integer nMatches = new Integer(0);   
  62.   Entry[] list = EntryFactory.findObjects(context, listCriteria,   
  63.     criteria, false, nMatches);   
  64.   System.out.println("Query returned " + nMatches + " matches.");   
  65.   if (nMatches.intValue() > 0) {   
  66.    for (int i = 0; i < list.length; i++) {   
  67.     EntryItem[] items = list[i].getEntryItems();   
  68.     result.add(new City(   
  69.       (String) items[0].getValue().getValue(),   
  70.       (String) items[1].getValue().getValue(),   
  71.       (String) items[2].getValue().getValue()));   
  72.    }   
  73.   }   
  74.   EntryFactory.getFactory().releaseInstance(list);   
  75.  } catch (ARException e) {   
  76.   handleException(e, "Problem while querying by qualifier: ");   
  77.  }   
  78.  // 清除销毁操作   
  79.  cleanup();   
  80.  return result;   
  81. }   
  82.   

         对于删除操作,则放到DataModel的实现类中处理,在DataModel实现类中(当然也可以放在dataset监听器中处理),与查询操作一样,在init()方法中实例化一个ARServerUser对象,删除操作在制定的方法中实现:

java 代码
  1. public void deleteCity(ParameterSet parameters,   
  2.   ParameterSet outParameters) throws Exception {   
  3.  // find then remove   
  4.  Dataset dsCity = getDataset("dsCity");   
  5.  Record record = dsCity.getCurrent();   
  6.  if (record != null) {   
  7.   String id = dsCity.getString("id");   
  8.   try {   
  9.    // 同所有的操作一样,创建要删除的记录实体对象,这里得到的实体对象也包含了权限信息,如果得到的实体没有删除操作的权限将导致删除失败   
  10.    EntryID entryID = new EntryID(id);   
  11.    EntryKey entryKey = new EntryKey(formName, entryID);   
  12.    Entry entry = EntryFactory.findByKey(context, entryKey, null);   
  13.    // 执行实体对象的操作   
  14.    entry.remove();   
  15.    System.out.println("Record #" + id + " delete successfully.");   
  16.   } catch (ARException e) {   
  17.    handleException(e, "Problem while modifying record: ");   
  18.   }   
  19.  }   
  20.  // 清除销毁创建对象   
  21.  cleanup();   
  22.  super.doUpdateData(parameters, outParameters);   
  23. }   

       新增和修改与删除基本类似,这里就不做详细说明,主要代码如下:

java 代码
  1. public void afterUpdateData(Dataset ds) throws Exception {   
  2.  List list = new ArrayList();   
  3.  ds.toDO(list);   
  4.  City city = (City) list.get(0);   
  5.  String id = city.getId();   
  6.  if (StringUtils.isNotEmpty(id)) {   
  7.   // edit   
  8.   try {   
  9.    EntryID entryID = new EntryID(id);   
  10.    EntryKey entryKey = new EntryKey(formName, entryID);   
  11.    Entry entry = EntryFactory.findByKey(userInfo, entryKey, null);   
  12.    EntryItem[] entryItems = new EntryItem[2];   
  13.    entryItems[0] = new EntryItem(new FieldID(FIELD_CITY),   
  14.      new Value(city.getCity()));   
  15.    entryItems[1] = new EntryItem(new FieldID(FIELD_CODE),   
  16.      new Value(city.getAirPortCode()));   
  17.    entry.setEntryItems(entryItems);   
  18.    entry.store();   
  19.    System.out.println("Record #" + id + " modified successfully.");   
  20.   } catch (ARException e) {   
  21.    handleException(e, "Problem while modifying record: ");   
  22.   }   
  23.  } else {   
  24.   // add   
  25.   try {   
  26.    EntryFactory entryFactory = EntryFactory.getFactory();   
  27.    Entry entryr = (Entry) entryFactory.newInstance();   
  28.    entryr.setContext(userInfo);   
  29.    entryr.setSchemaID(new NameID(formName));   
  30.   
  31.    EntryItem[] entryItems = new EntryItem[2];   
  32.    entryItems[0] = new EntryItem(new FieldID(FIELD_CITY),   
  33.      new Value(city.getCity()));   
  34.    entryItems[1] = new EntryItem(new FieldID(FIELD_CODE),   
  35.      new Value(city.getAirPortCode()));   
  36.   
  37.    // #2 is done in one line just to show another method.   
  38.    entryr.setEntryItems(entryItems);   
  39.    entryr.create();   
  40.    System.out.println("Entry created, id #"  
  41.      + entryr.getEntryID().toString());   
  42.   } catch (ARException e) {   
  43.    handleException(e, "Problem while creating entry: ");   
  44.   }   
  45.  }   
  46.   
  47.  cleanup();   
  48. }   
  49.   

II)Dorado操作Remedy流程引擎,包含核心典型代码。
       因为Remedy的流程处理是与业务相关的,因此属于后台部分,对于dorado来说不存在特殊处理,因此与前面的处理类似

III)Dorado整合Remedy后的性能表现:绝对响应时间以及和Remedy原有系统响应时间对比(后者数据可能目前没法获得)。
       一套系统的系能瓶颈主要集中在两个方面:即一个是中间Web Server的并发处理能力,另一个就是数据库访问能力,而dorado展现层开发框架的性能经历过了多个大小项目的考验,事实证明了性能上的可行性,所以如果性能出现问题,只能出现在后台Remedy Java API的执行效率上,这个需要得到BMC公司提供相关的性能指标来加以参考

IV)整合过程的工作量评估,以几个典型界面的改造为例得出的工作量,以及对比传统MIS系统对应界面的开发工作量。
          这里工作量的对比应该是相对于其他的改造方案的对比,与传统mis系统没有可比性.与ext2.0之类的纯客户端ajax解决方案来比,dorado不仅有开发工具支持,同时还对前后台通信进行了封装,整合的工作量我们会有明显的优势.
          目前对于改造的工作量来说还无法准确进行准确评估,不过针对联通的电子运维系统中一个典型的应用来说,粗略估计周期在2周-4周之间,这个取决于合作双方的人员参与情况,我们的工程师熟悉Remedy AR System系统相关技术的过程,对方提供的相关的Remedy相关的技术支持和业务支持情况,还有就是取决于系统的复杂程度以及最终的改造目标的明确情况

V)可维护性:代码调试性、代码阅读性、流程和界面的松耦合性以及需求变更的解决方案。
            因为是一个特殊的表现层改造项目,其特殊之处在于如果界面需求发生改变,需要同时维护两套代码:一套Remedy AR System中定义的Forms, Action Links界面元素,一套是Dorado的Java代码+配置文件,但这也是采用所有其他改造方案都无法避免的问题.所以我们只能通过重用将这个工作量降到最低

VI)附一个典型界面改造的开发步骤。
(1)根据Remedy AR System Forms定义JavaBean数据模型
(2)根据Remedy AR System Forms定义view.xml(如果需要的话module.xml)
(3)给view.xml添加DataModel实现类或dataset监听器实现类调用Remedy Java API实现与Remedy集成
(4)根据Remedy AR System Active Links的定义,转换成Dorado中相应控件的事件代码,完成客户端的操作处理
(4)生成jsp,调整布局得到最终的展现界面
(6)测试通过,模块改造完成

VII)下图是以Remedy 自带是sample中城市维护为例做的一个Remedy与Dorado整合的Demo效果

代码结构图

Remedy Web UI效果:

remedy2 

使用Dorado后的效果:

分享到:
评论
1 楼 luckyhero 2009-02-11  
您好,在下有问题跟您请教,如果方便请加QQ76335527详谈,多谢!

相关推荐

Global site tag (gtag.js) - Google Analytics