IBM®
跳转到主要内容
    中国 [选择]    使用条款
 
 
Select a scope:Search for:    
    首页    产品    服务与解决方案     支持与下载    个性化服务    
跳转到主要内容

developerWorks 中国  >  Rational  >

基于RSA开发SOA Pattern

developerWorks
文档选项

未显示需要 JavaScript 的文档选项


级别: 初级

王强 田晨, 中国软件开发实验室 SOA设计中心高级软件工程师, IBM

2005 年 8 月 01 日

本文介绍了基于RSA模式的相关概念,并以一个简单的例子说明如何开发及调试模式插件。

1 摘要

Pattern 即模式是SOA资产的重要组成部分。创造和使用模式促进了软件再应用。一个模式一旦被设计出来,就可以被反复的使用。模式的可重用性潜在地降低了制造成本。RSA中的模式这种特殊的资产遵循RAS(Reusable Asset Specifications)所制定的标准, 通过遵循这些统一的规范,可以更加便利利用地使用模式。本文介绍了基于RSA模式的相关概念,并以一个简单的例子说明如何开发及调试模式插件。





回页首


2 引言

SOA体系架构具有提高企业IT资产利用率、提高系统适应性等特征,能够根据用户的业务需求和变动快速做出调整,保证服务上市时间;同时也强调通过建立一定的标准,实现研发成果可重复利用性,来降低成本。SOA很重要的方面就是资产重用,可重用的软件组件、设计、代码是软件开发企业最重要的资产。资产重用一直以来都是软件开发追求的重要目标之一。资产重用可以缩短软件开放周期,提高软件质量。Rational Software Architect (RSA)提供了通过支持模型和代码模板开发模式插件来达到软件重用目的机制,可以实现各个层次的软件重用。可重用的软件组件、设计、代码是软件开发企业最重要的资产。

本文是将向大家介绍如何在RSA 中创建自己的模式,并利用RSA的代码模板和模式的结合更加促进软件的重用。





回页首


3 相关概念介绍

  • SOA:面向服务的体系结构(service-oriented architecture,SOA)是一个组件模型,它将应用程序的不同功能单元(称为服务)通过这些服务之间定义良好的接口和契约联系起来。接口是采用中立的方式进行定义的,它应该独立于实现服务的硬件平台、操作系统和编程语言。这使得构建在各种这样的系统中的服务可以以一种统一和通用的方式进行交互。
  • Pattern : Pattern是解决某类特定问题的一般性方法。IBM Rational pattern实现从一个初始UML2.0 Model 到另一个应用该模式的UML2 Model, 也可以称之为Model to Model Transformation. 模式设计的关键之处就在于找出可重复的结构和过程,并将它们转化到可重用的模式之中。模式的设计者可以应用RAD中的框架完成一个最简单的到非常复杂的模式设计。
  • Asset:资产是SOA中的重要元素,RAS(Reusable Asset Specifications)标准提供了系列的工具来方便管理和共享Pattern Assets,提供分类、搜索、组织和文档功能。模式通过分发和重用来实现他的最大价值。Pattern 是一种独特类型的RAS资产。
  • MDD(Model Driven Development):模型驱动开发技术的主要思想是在模型这一更高的抽象层次来构造软件系统,从而使架构设计师和软件开发人员专注于"业务逻辑"而不是编程细节,代码可以通过手工或自动的方法从模型中自动生成。Pattern在RAD中的应用过程就是模型驱动开发的过程,它实现的是Model 到 Model转化。




回页首


4 开发流程

一般模式插件的开发主要分为以下几步:

1. 以RSA提供的项目模板为基础,建立Project。

2. 建立Pattern,并设定相关参数,包括Pattern名字,参数,基本描述,所属的组等等。

3. 扩展点编程,扩展点主要分为三部分:

  • 针对各个参数内部类的expand()方法,这个方法根据使用pattern时的bind动作和终于上来了unbind动作又被重载为两个方法。
  • 在参数设置时,有可能设定参数之间的依赖关系,那么在参数内部,又会生成一个内部类,并生成的方法update(), update也会有多个重载,扩展相应的update()方法,就可以对相关联的参数发生变化是进行处理。
  • 隐性扩展点,在Project显示给出的扩展框架之外,还有一些隐性的扩展点完成更多的功能,下面分别介绍:
    • protected IStatus validToAddArgument(PatternParameterValue.Proposed proposed)
    • public IStatus validToCreateArguments(AbstractPatternInstance instance, IPatternMetatype metatype)
    • ……
    这些隐性扩展主要完成对应用在Pattern参数上的元素进行更进一步的验证,以保证绑定的参数能够符合要求,这些验证包括类型、Stereotype等各类,从而配合基本扩展点完成一些复杂的工作。

4.调试,发布Pattern 插件。





回页首


5 范例

范例是一个Simple Cache Pattern, 这个Pattern为一般的服务访问提供缓冲功能,降低系统开销,提高响应速度。应用该Pattern后将在Model内生成一个类,该类实现或继承目标对象(接口或类),将从服务提供者中获得的数据缓存,并用它们作为客户端请求的响应。这个Pattern定义了Service, getEntry, CacheSize 和Timeout四个参数,这四个参数分别表示在应用这个Pattern时的必要设置。Service制定要应用pattern的对象(是Interface或者是Class),getEntry表示要应用缓存的方法,CacheSize表示需要Cache空间的大小,Timeout用来表示Cache失效时间。

步骤一:应用RSA提供的Pattern工程模板创建项目

1. 选择菜单File -> New ->Project->Plug-in Development -> Plug-in project,弹出如下窗口,在Project name 中为项目命名为com.ibm.pattern.cache,其他保持缺省设置即可



2. 点击Next按钮,弹出如下窗口,保持缺省设置:



3. 点击Next按钮,进入如下窗口,这个窗口可以选择根据已有的Plug-in模板来建立工程,选中<Create a plug-in using one of template>,然后选择Plug-in with patterns。



4. 点击Finish,生成了一个新的Project,如下图所示:



步骤二:创建Pattern

1. 选择Window'show view'Modeling'Pattern Authoring, 打开Pattern authoring视图.



2. 新建Pattern,在Pattern Authoring视图中,选择我们刚刚建立的Project, 在上面击右键弹出菜单,选择New Pattern。弹出如下窗口,命名为Cache Pattern, 则对应Class Name为CachePattern,选择Pattern Type为Collaboration,并为该Pattern创建一个组,称之为Tutorial Pattern.



3. 创建Pattern参数,在上图的Parameters栏中,点击Add…按钮,弹出下图的对话框。分别定义前面的四个参数,下图为Service参数的建立,由于该参数绑定的类型可能为Interface或是Class,指定其类型为Classifier。下面第二图为getEntry参数建立Parameter Dependency,指定其Supplier parameter为Service。这种设定为两个参数建立了依赖关系,如果没有绑定Service,则不能绑定getEntry,因为getEntry所绑定的operation实现是Service参数的元素。





4. 完成Pattern 参数定义后,转到Detail Tab,可以定义一些Pattern的描述信息。Keywords为Pattern在RAS中进行搜索是提供方便。



5. 单击OK,在Pattern Authoring视图下,生成的结构如下



在Package Explorer下生成的结构如下:



步骤三:扩展点编程

在生成的代码框架中我们可以看到,在CachePattern中添加了四个内部类,这四个类分别对应我们所添加的四个模式参数,我们展开其中一个内部类可以看到内部类由PARAMETER_ID,构造函数和两个基本扩展方法所构成,如上图红圈所标注,对于GetEntry内部类对应getEntry参数,由于在参数构建时设定了依赖关系,所以在getEntry内部类中又产生一个内部类GetEntry_ServiceDependency,在其内部产生了若干个update()扩展方法。下面说明在该例中如何扩展这些扩展方法。

1. 两个基本扩展点:

  • public boolean expand(PatternParameterValue value) 在参数被绑定时触发,完成绑定参数的动作,同时可以观察到该方法返回值为boolean类型,但是不要以为返回false该动作不会发生,即无论扩展后该方法返回何值,bind事件都会被触发。若想改变这种状况,则必须进行验证,验证方法后面会提到。下面代码为在Service内部类扩展该方法的代码:

    		public boolean expand(PatternParameterValue value) {
    	Object obj = value.getValue();
    	if( obj instanceof Classifier ) {
    		Classifier classifier = (Classifier) obj;
    		// instance -- instance of the pattern in the model which 
    		gives values specified for this pattern.
    		com.ibm.xtools.patterns.framework.AbstractPatternInstance patternInstance =
    		value.getOwningInstance();
    		CachePatternImplementation impl;
    		impl = (CachePatternImplementation) instanceToImplMap.get(patternInstance);
    		if (impl == null) {
    			impl = new CachePatternImplementation (patternInstance);
    			instanceToImplMap.put(patternInstance, impl);
    		}
    		impl.expandService(classifier);
    		}
    			return true;
    		}
    		

    该段代码完成在绑定Service参数时,根据绑定的类生成相应的UML2 元素,其中主要的实现在CachePatternImplementation类中完成,以减少项目主类中的代码数量。

  • public boolean expand(PatternParameterValue.Removed value) 该方法在解除参数绑定时所触发,只要解除动作发生了,那么该方法将被执行。下面代码仍为在Service内部类扩展该方法的代码:比如,我们以在该例中的Service的expand方法编程,我们在该例子中为该Pattern的Service方法添加代码如下:

    		public boolean expand(PatternParameterValue.Removed value) {
    	Object obj = value.getValue();
    	if( obj instanceof Classifier ) {
    		Classifier classifier = (Classifier) obj;
    		// instance -- instance of the pattern in the model which gives 
    		values specified for this pattern.
    		com.ibm.xtools.patterns.framework.AbstractPatternInstance patternInstance =
    		value.getOwningInstance();
    		CachePatternImplementation impl;
    		impl = (CachePatternImplementation) instanceToImplMap.get(patternInstance);
    		if (impl == null) {
    			impl = new CachePatternImplementation (patternInstance);
    			instanceToImplMap.put(patternInstance, impl);
    		}
    		impl.removeService(classifier);
    		}
    			return true;
    		}
    		

2. 依赖关系扩展点:

生成的依赖关系扩展点有如下三个

  • public boolean update(PatternParameterValue value, PatternParameterValue dependencyValue)
  • public boolean update(PatternParameterValue.Maintained value, PatternParameterValue.Removed dependencyValue)
  • public boolean update(PatternParameterValue.Removed value, PatternParameterValue.Maintained dependencyValue)

我们在此例中只有getEntry参数建立了依赖关系,而至扩展了第二个方法,因为第二个方法是在getEntry所依赖的Service方法删除时调用,而getEntry所绑定的参数的提供这恰为Service的参数,所以在Service参数解除绑定时,对应的getEntry也应该解除绑定,代码如下所示:


public boolean update(PatternParameterValue.Maintained value, 
PatternParameterValue.Removed dependencyValue){
	Object obj = value.getValue();
	if( obj instanceof Operation) {
		Operation oper = (Operation) obj;
		// instance -- instance of the pattern in the model which gives values 
		specified for this pattern.
		com.ibm.xtools.patterns.framework.AbstractPatternInstance patternInstance =
		value.getOwningInstance();
		CachePatternImplementation impl;
		impl = (CachePatternImplementation) instanceToImplMap.get(patternInstance);
		if (impl == null) {
			impl = new CachePatternImplementation (patternInstance);
			instanceToImplMap.put(patternInstance, impl);
		}
		impl.unbindOperation(oper);
		}
			return true;
		}

这段代码利用CachePatternImplementation类中的方法解除了getEntry方法的参数绑定。

3. 验证扩展点:

在此例中我们注意到Service的参数应当为Interface或是Class,而我们在指定类型时只能将其指定为Classifier,而Classifer作为UML2种的一个类型,包含许多子类型,比如Component、UseCase等等,而将这些类型作为Service的参数是不允许的,所以我们必须使用验证扩展点来保证这一点。在此例中我们扩展的方法及代码如下所示是:


protected  IStatus validToAddArgument(PatternParameterValue.Proposed proposed){
	// Use to judge whether the parameter can be bound.
	IStatus status = super.validToAddArgument(proposed);			
	if (status.isOK()){
		Object obj = proposed.getValue();	
           if ((obj instanceof Class)||( obj instanceof Interface)) ;
           else return Status.CANCEL_STATUS;			
	}
	return status;
}

至此,基本Pattern Authoring 的工作就算完成了,下面进行调试。

步骤四:调试

调试是必须运行一个runtime_workbench,这里我们建议选择eclipse的JVM,并设置参数为-Xj9,这样可以支持"hotcode-replacement"方便我们减少我们在调试过程中启动runtime_workbench的次数。调试界面如下图所示:



1. 在Runtime_workbench中切换到Model perspective,并打开Pattern Explorer视图,如上图所示。

2. 可以看到我们刚刚创建的Cache Pattern已经在Tutorial Pattern组中,将其拖至建好的空的Model中,建立测试用的接口或类,绑定适当的参数,就可以借助RSA提供的强大功能进行调试了。

调试完成,也就完成了这个简单而又实用的Cache Pattern的开发工作。





回页首


6 结语

通过本文的介绍,我们可以看到,模式是一种抽象的软件解决方案,用来解决一个在特定场景中的连续的或反复出现的问题。开发设计过程中大量地使用模式有很多的优点,我们可以利用已有的模式来解决一些软件问题,从而节省了设计人员的时间。模式的用户并不需要知道如何去设计一个具体的模式,但是用户需要有好的模式文档,好的模式文档能帮助模式的用户定位、选择和应用不同的模式。用户需要了解这个模式是用来解决什么问题的,这个问题是如何被解决的以及应用这个模式的结果。模式的作者能够创造多种类型的与模式打包在一起的模式文档,在模式应用过程中,用户可以使用这些文档。

模式的可重用性还能够节省大量的设计开发时间。 可重用的特性增加了软件的可靠性和编码设计的连续性。一个模式可以在一个项目中、一个公司内部以至不同公司间共享。模式的局限性由模式的设计以及模式开发者的设计意图所决定。而RSA中的模式都由标准的Eclipse插件构成,我们可以通过将包含模式的插件打包成可重用的资产(Reusable Asset Specifications)并且在RAS资产库中注册和管理它们来实现最大程度的模式可重用性。通过由模式开发者提供的模式的关键字和描述的匹配,潜在的模式用户可以从RAS资产库里搜索和选择所需的模式。模式这种特殊的资产遵循RAS(Reusable Asset Specifications)所制定的标准, 通过遵循这些统一的规范,模式用户和模式开发者之间可以非常便利地交换模式。





回页首


7 参考文献

  1. RSA帮助文档
  2. RSA: http://www.ibm.com/developerworks/rational/products/rsa/
  3. MDA: http://www.omg.org/mda
  4. UML: http://www.omg.org/technology/uml/index.htm


关于作者

IBM中国软件开发实验室SOA设计中心 是IBM全球四个SOA设计中心中最大的一个,成立一年多来,已经取得了可喜的成果。我们在全球范围内实施了多个 SOA 应用项目,为多个行业的客户提供了 SOA 解决方案。我们正在实施的 SOA 项目涵盖了很多的重要行业,包括零售业、航运业、电力、银行、保险等等。通过这些不断增长的成功案例,我们不仅深入地推广了 SOA 的理念,树立了 SOA 成功实施的范例,也为我们的队伍积累了经验,培养了人才。与此同时,我们还是 IBM 开发 SOA 的软件平台 -- SOA Integration Framework -- 的主力军。该产品基于模型驱动的思想,旨在最大化地重用软件资产,它为 SOA 项目的实施提供了一整套源自成功实践的方法论,设计范式和工具集。它的出现将极大地方便 SOA 系统架构师、设计人员、开发人员快速地开发 SOA 应用项目。
参与本系列撰写的主要技术人员包括:
毛新生 IBM 中国软件开发实验室 资深经理, SOA计中心中国区 首席架构师
何蕾 IBM 中国软件开发实验室 SOA设计中心 高级软件工程师
孙瑛霖 IBM 中国软件开发实验室 SOA设计中心 软件工程师
田晨 IBM 中国软件开发实验室 SOA设计中心 软件工程师
王强 IBM 中国软件开发实验室 SOA设计中心 软件工程师




对本文的评价

太差! (1)
需提高 (2)
一般;尚可 (3)
好文章 (4)
真棒!(5)

建议?




回页首


IBM 公司保留在 developerWorks 网站上发表的内容的著作权。未经IBM公司或原始作者的书面明确许可,请勿转载。如果您希望转载,请通过 提交转载请求表单 联系我们的编辑团队。
    关于 IBM 隐私条约 联系 IBM 使用条款