UML软件工程组织

基于Rational Software Architect实现SIBus模型到Jacl脚本的转换

 

作者:王 雪 来源:IBM

 

本文内容包括:

Rational Software Architect (RSA) 是IBM Rational软件家族中的用于建模和开发的软件产品,本文结合WebSphere Application Server 6.0中实现的ESB组件SIBus,深入分析了如何利用RSA的模型转换功能实现从SIBus模型到Jacl运行脚本的转换的方法。

1 RSA的模型转换框架

IBM Rational Software Architect(RSA)是IBM Rational新一代的建模和开发工具,它构建在开放的、可扩展的Eclipse3.0平台之上,集成了UML2.0和MDA技术,实现了多种行业的最新标准,提供了灵活的插件扩展机制。众所周知,UML2.0和MDA技术的应用,可以有效地解决传统软件开发过程中的生产效率问题、系统移植问题、互操作问题以及文档和系统后期的维护问题。而实现MDA的关键则是通过建立转换(Transformation)机制,实现模型到模型、模型到代码的转换。

为了支持模型驱动开发过程中各种模型之间的转换,RSA提供了一个功能强大、易于扩展的模型转换框架(Model Transformation Framework),该框架是一个基于规则的执行引擎,基于该框架,模型转换的开发者只需定义一系列转换规则即可,模型转换框架会负责加载执行规则,并提供统一的模型转换配置管理。该框架基于Eclipse 3.0和Eclipse Model Framework(EMF)、UML2、Graphical Editing Framework(GEF)和插件开发环境(PDE),支持标准设计(比如统一建模语言,UML )的模型构建,提供了从UML到Java、UML到C++、UML到EJB的模型转化,为模型驱动软件开发(MDA)提供了强大的工具支持。

本文就是基于RSA提供的模型转换功能,从实现角度说明如何从ESB模型转化为可部署、可执行的Jacl脚本。接下来让我们来看看什么是Jacl语言以及如何在WebSphere中通过脚本管理编制程序(wsadmin)调用Jacl脚本文件的。

2 WebSphere与Jacl语言

2.1 Jacl语言

Jacl(Java Command Language)是Tcl(Tool Command Language)脚本语言为适应Java环境的一个版本实现。Tcl是由Sun(by John Ousterhout)开发的一个非常优秀的编程语言。作为一种嵌入式脚本语言,Tcl的设计初衷是为了支持快速地开发在x 窗口系统下运行的应用程序。然而,Tcl的灵活性、易用性使得它被引入到几乎所有的操作系统中。Jacl 作为Tcl的Java实现,完全支持JAVA,其内核解释器完全用Java语言编写,可以运行在任何Java虚拟机上,可以完全访问Java API。Jacl使得Tcl可以作为Java 应用的脚本语言,帮助用户更快速、更容易地生成用户图形界面的Java程序。

Jacl通过引用一个Java Package的组件提供Java和Tcl的接口,使得Tcl脚本具有如下能力:

  • 创建Java类的实例;
  • 调用Java对象和类的方法(包括静态和非静态方法)
  • 访问公共域和Java对象;
  • 确定一个对象的所属类及其在整个Java类树中的位置;
  • 从类的路径加载类;
  • 从字节流定义新类;

另外,Jacl还支持Tcl脚本访问JavaBeans的方法、属性和事件的能力。它允许Tcl脚本创建JavaBeans,调用JavaBeans的方法,获取和设置JavaBeans的属性。此外,它还提供了Bean事件异常处理的支持。这些Bean事件被暴露给Tcl,可以在Tcl中通过绑定Tcl代码到事件上处理事件异常。

对于Tcl编程者,Jacl提供了一个独立于平台的Tcl的实现。这意味着在Java运行的地方,Tcl都可以运行。另外一个好处是,Jacl具有丰富的Java API的支持。关于Jacl的语法,详见http://tclJava.sourceforge.net/docs/website/index.html

2.2 WebSphere管理脚本编制(wsadmin)

脚本编制是非图形的备用方法,可以使用它来配置和管理应用程序及应用程序服务环境。WebSphere 管理(wsadmin)脚本编制程序是功能强大的、非图形的命令解释器环境,它允许用户用脚本语言运行管理操作。用户可以使用 wsadmin 工具执行那些可以用管理控制台执行的相同任务。wsadmin 工具支持整个范围的产品管理。下面列出了所有可以使用脚本编制完成的主题和任务:

  • 部署应用程序。提供部署和卸载应用程序的指示信息。例如,独立的 JAR 文件和 WAR 文件、管理控制台、EAR文件、文件传输应用程序等等。
  • 管理已部署的应用程序。包含部署应用程序后执行的任务。例如,启动和停止应用程序、检查状态、修改侦听器地址端口、查询应用程序状态、配置共享库等等。
  • 配置服务器。提供配置服务器的指示信息,如创建服务器、修改和重新启动服务器、配置 Java 虚拟机、禁用组件、禁用服务等等。
  • 配置到 Web 服务器的连接。包括各类主题,如重新生成插件、创建新的虚拟主机模板、修改虚拟主机等等。
  • 管理服务器。包括用于管理服务器的任务。例如,停止节点、启动和停止服务器、查询服务器状态、启动侦听器端口等等。
  • 配置安全性。包括安全任务,例如,启用和禁用全局安全性、启用和禁用 Java 2 安全性等等。
  • 配置数据访问。包括各类主题,如配置 Java 数据库连接(JDBC)提供者、定义数据源、配置连接池等等。
  • 配置消息传递。包括有关消息传递的主题,如 Java 消息服务(JMS)连接、JMS 提供者、WebSphere 队列连接工厂、MQ 主题等等。
  • 配置邮件、URL 和资源环境条目。包括各类主题,如邮件提供者、邮件会话、协议、资源环境提供者、可引用对象、URL 提供者、URL 等等。
  • 故障诊断。提供有关如何使用脚本编制进行故障诊断的信息。例如,跟踪、线程转储、概要文件等等。

图1描述了 wsadmin 脚本编制解决方案中涉及的主要组件。

图1.WebSphere Application Server 脚本编制解决方案
图1.WebSphere Application Server 脚本编制解决方案
 

脚本使用这些对象与运行在 WebSphere Application Server 进程中的 MBean 通信。MBean 是表示 Java 管理扩展(JMX)资源的 Java 对象。JMX 是附加于 Java 2 Platform Standard Edition(J2SE)的可选软件包。JMX 是提供简单和标准方法来管理 Java 对象的一种技术。

wsadmin 工具通过一组管理对象来进行配置和管理,每个管理对象都有可用来执行管理任务的命令,这些管理对象包括AdminConfig、AdminControl、AdminApp、AdminTask 和 Help。

在WebSphere Application Server中,系统的管理功能可以分为两个类别:WebSphere Application Server 的安装和配置,管理WebSphere Application Server 安装过程中正在运行的对象。下面我们举例说明这两个类别的不同。例如,对于WebSphere应用程序服务器,存在持久驻留在永久性存储器库中的服务器配置。用户可以创建、查询、更改或删除此配置,而无需启动应用程序服务器进程。而对于通过Java 管理扩展(JMX)MBean 正在运行的应用程序服务器的实例信息,则必须通过正在运行的对象上获取。因为该实例保留了可查询和更改的属性以及可调用的操作,这些对正在运行的应用程序服务器所采用的运行操作将不会影响服务器的持久配置。

下表对wsadmin管理对象进行了对比说明。

表1. wsadmin管理对象功能对照表
表1. wsadmin管理对象功能对照表

以上我们对WebSphere脚本编制管理程序进行了简要的介绍,下面重点介绍一下Jacl语言对wsadmin各管理对象的支持。

wsadmin 工具目前支持两种脚本语言:Jacl 和 Jython。Jacl 是缺省指定的语言。 当使用脚本编制执行任务时,首先使用Jacl编写脚本程序,在Jacl程序中,用户可以调用wsadmin的各种管理对象对应用服务器进行管理和配置,包括对运行时对象的管理。然后调用脚本编制进程的命令wsadmin以启动脚本编制客户机,如下所示, 使用 -f 选项运行 wsadmin 工具,并将您要运行的命令放入文件中。关于在Jacl中使用wsadmin管理对象的方法,本文将在第4节中举例说明。

wsadmin -f example.jacl

3 服务集成总线建模(SIBUS)

当前,企业服务总线(ESB)是讨论最为热烈的领域,它作为搭建SOA系统解决方案的基础设施,提供了连接企业内部及跨企业间新的和现有软件应用程序的功能,在实施SOA过程中起到了举足轻重的作用。

IBM WebSphere Application Server V6 中提出的Service Integration Bus(SIBus)组件包括了许多构建ESB必要的功能特性,其中三个重要的组件:总线(Bus),目标(Destination),调解(Mediation)组成了SIBUS的消息传递引擎。总线(Bus)是主要的消息传输机制,消息的发送者和接收者通过总线进行消息交换。每个总线包含了若干目标(Destination),每个目标是发送到总线中的消息的逻辑Target,消息的发送者将消息发送到总线目标,消息的消费者则通过访问总线目标获取消息,这就实现了消息用户的松耦合。另外,消息在被接收者接收之前,可以在总线中由一个目标路由到另一个目标,或者改变消息的格式。调解(Mediation)实现了这种机制,它是一种绑定在目标上的组件,在消息到达这个目标时处理该消息。

图2说明了总线中目标和调解的概念关系。

图2. 总线中目标和调解的概念关系
图2. 总线中目标和调解的概念关系
 

基于以上对WebSphere Application Server V6和SIBUS的介绍,我们已经基本了解到,SIBUS是ESB概念在WebSphere Application Server V6中的一种实现,它的提出可以更明确地支持服务集成和服务整合。在面向MDA的开发过程中,模型转化功能可以将与平台无关的模型(Platform Independent Model, PIM)转化为与平台相关的模型(Platform Specific Model, PSM),再将PSM转化为具体的实现代码或者部件,其中部件包括各种文档、部署和构建脚本、测试部件,模式应用等等。为了简化用户开发ESB应用的复杂性,这里引入MDA的设计理念,从PIM的层面刻画ESB,从PSM的层面刻画SIBUS, 在这个实现过程当中,我们就需要将SIBUS模型转化为可以直接部署执行的脚本,方便用户以非图形化的部署管理手段实现自动部署和安装SIBUS相关资源的功能。Jacl作为一种独立于平台的强大的脚本编程语言被纳入到WebSphere Application Server中,通过wsadmin脚本编制客户机来解释和执行。

接下来,我们将详细讨论如何利用RSA的模型转换功能实现WebSphere Application Server SIBUS到Jacl的转换。

4 SIBUS模型到Jacl脚本的转换开发

在这部分的叙述中,我们以一个典型的应用作为例子,说明如何将SIBUS模型转化为Jacl部署脚本。图3中,SIBus1拥有两个成员服务器:Application Server 1和Application Server 2,消息从producer发送到Destination1,经过Mediation1的处理,转发到Destination2,在Mediation2中根据消息的内容,将消息转发到两个接收者(Consumer1和Consumer2)中的一个。

图3.SIBus实例
图3.SIBus实例

4.1 创建插件工程

通过新建工程向导创建一个插件工程。该插件工程使用"带转换的插件模板"。利用该模板可以自动生成集成RSA模型转换框架的代码结构,包括转换提供程序(TransformationProvider)、转换(Transformation)。如果需要的话,可以同时定义转换规则(Rule)。图4--图6显示了创建该插件工程过程中的重要步骤。

图4.使用带转换的插件模板
图4.使用带转换的插件模板

图5.创建转换程序
图5.创建转换程序

图6.创建转换
图6.创建转换

4.2 扩展UML模型

UML的元素,例如类、接口、合作、组件、注释、关系等,在对普通问题进行建模时基本上是可以满足要求的。但是,针对特定的领域问题,有时候就需要扩展UML的元素模型来支持这种领域的特殊性。通常,我们使用UML Profile的stereotype来扩展当前UML模型的词汇(关于UML Profile 和 stereotype 及其相关概念,请参考本文参考资料)。这里,针对SIBus建模问题,我们分别定义了Bus, Destination, Mediation, attach 等stereotype,并且对它们定义了一组标记值和不同的图标,使得它们具有不同的视觉效果,如图7所示。

图7.SIBus Profile
图7.SIBus Profile

4.3 创建JET模板

EMF工程(eclipse模型框架)包含了两个非常强大的代码生成的工具:Java 发射器模板JET(Java Emitter Templates)和JMerge(Java Merge)。其中JET是一个用来在Eclipse Modeling Framework (EMF)中生成代码的开源工具。使用JET可以使用类似JSP一样的语法(事实上是JSP语法的子集),轻松地编写模板来表示用户希望生成的代码形式。JET是一个通用模板引擎,可以生成SQL,XML,Java代码以及其它类型的文件。JET引擎位于org.eclipse.emf.codegen中,包含在EMF运行插件中。

在该模型转换的实现中,我们使用JET作为Jacl脚本的模板,并应用了wsadmin的管理对象AdminTask 和AdminConfig。下面详细介绍如何在该plug-in项目中,创建JET模板。

1) 在RSA的包浏览器中选择该项目,在项目根目录下,右键选择New -> Folder, 添加一个templates的目录。

2) 在项目src文件夹下,添加"jetsrc"文件夹,用来保存jet模板生成的Java类。

3) 在RSA的包浏览器中选择该项目,右键选择新建 ->其他 -> Java 发射器模板->将项目转化为JET项目。点击完毕,这将为项目增加JET Nature,而且一个JET Builder 也被将入这个工程,这样每一个模板中的以jet为后缀结束的文件会自动被编译称为一个Java 类。

4) 修改JET设置。在RSA的包浏览器中选择该项目,右键选择属性 -> JET 设置,设置模板容器 为temlpaltes,源容器为src。你可以设定多个容器,用空格分开。

5) 创建JET模板文件。这里,我们根据SIBUS配置和部署的需要,创建了若干JET 模板。每个模板分别对应一段Jacl脚本片断,这些模板既可以单独使用,也可以组合使用。清单1和清单2分别展示了创建Bus和创建Destination的JET模板。

清单 1. 创建Bus的JET模板
 
<%@ jet package="sibusToJaclTransform.jacl.jetsrc" 
       	imports="java.util.Map"  class="CreateBus" skeleton="JET.skeleton" %>
# This JACL file create a bus
<%
    final Map parameterMap = (Map) argument;
	if (parameterMap == null) {
		 return stringBuffer.toString(); 
    }
	// extract incoming map parameters
	final String busName = (String)parameterMap.get("busName")	
%>
set busName "<%=busName%>"
#---------Creating a bus----------------#
$AdminTask createSIBus "-bus $busName"
$AdminConfig save

清单 2. 创建Destination的JET模板

<%@ jet package="sibusToJaclTransform.jacl.jetsrc" 
imports="java.util.Map" class="CreateMsgDestination"        skeleton="JET.skeleton" %>
<%
    final Map parameterMap = (Map) argument;
	if (parameterMap == null) {
		 return stringBuffer.toString(); 
    }
	// extract incoming map parameters
	final String msgDestName = (String)parameterMap.get("msgDestName");
	final String msgDestType=(String)parameterMap.get("msgDestType");
final String busName = (String)parameterMap.get("busName");
final String nodeName = (String)parameterMap.get("nodeName");
final String serverName = (String)parameterMap.get("serverName");
%>
$AdminTask createSIBDestination "-bus <%=busName%> -name
<%=msgDestName%> -type <%=msgDestType%> -node <%= nodeName%>
-server <%= serverName%>"
$AdminConfig save

6) 在创建了所有JET模板后,在保存这些JET模板的时候,JET builder会把所有的模板转变为相应的Java类,保存在文件夹jetsrc中。这些Java类是就是模板转换后的文件,每个类都有一个generate的方法。我们可以通过实例化这些类后,调用generate方法,用来返回相应的脚本片断。

4.4 定义转换规则(TransformationRule)

JET模板将Jacl脚本代码化,便于在后面的代码实现过程中调用。要实现SIBUS模型到Jacl脚本的转换,我们还需要定义若干转换规则。实际上,转换逻辑的实现正是封装在这些转换规则中,负责将源模型转化为目标模型或者部件的。转换规则的实现类实现了模型转换框架中提供的com.ibm.xtools.transform.core.AbstractRule接口。

这里,我们可以将所有的转换逻辑写在一条转换规则中,但是,为了代码编写的模块性和规范性,我们定义了若干转换规则,每条规则实现了逻辑上相对独立的一部分转换功能,若干条规则组合在一起实现整个转换功能。本例中,我们定义了七条转换规则:创建总线规则(CreateBusRule), 添加总线成员规则(AddBusMemberToBusRule), 创建目标规则(CreateDestinationRule),创建调解规则( CreateMediationRule),创建JMS连接工厂规则(CreateJMSConnectionFactoryRule), 创建JMS激活规范规则(CreateJMSActivationSpecificationRule),创建JMS队列规则(CreateJMSQueueRule)。每条转换规则都利用当前转换上下文(ITransformContext)中的源(Source),获取其相关属性,调用JET模板生成的Java类的generate方法,生成相应的Jacl脚本片断。清单3列出了CreateBusRule的部分源代码(其他规则源代码,请参阅附件Sibus2JaclTranRules.zip)。

清单 3. CreateBusRule部分源代码
 
protected Object createTarget(ITransformContext context) throws Exception {
		Object src = context.getSource();
		NamedElement busEle = (NamedElement)src;
		String busName = new String();
		busName = busEle.getName();		   
	    StringBuffer jaclContent = new StringBuffer();
		Map map = new HashMap();
		map.clear();
		map.put("busName",busName);
		jaclContent.append(new CreateBus().generate(map));
	    return new String(jaclContent.toString());    		
	}

在定义了所有的转换规则之后,根据转换的先后顺序,将以上规则添加到转换(Transform)中,在本例中,我们定义了一个扩展至UMLTransform的转换SIBusToJaclMainTransform,并在该转换的initialize()方法中,按照部署和配置顺序添加了以上规则,清单4列出了initialize()方法的部分源代码。

清单 4. initialize()方法的部分源代码
 
  private void initialize() {
		add(new CreateBusRule(CreateBusRule.ID, "CreateBusRule"));
		add(new AddBusMemberToBusRule(AddBusMemberToBusRule.ID,
		"AddBusMemberToBusRule"));
		add(new CreateDestinationRule
		(CreateDestinationRule.ID, "CreateDestinationRule"));
		add(new CreateJMSActivationSpecificationRule
		(CreateJMSActivationSpecificationRule.ID,
		"CreateJMSActivationSpecificationRule"));
		add(new CreateJMSConnectionFactoryRule
		(CreateJMSConnectionFactoryRule.ID, 
		"CreateJMSConnectionFactoryRule"));		
		add(new CreateJMSQueueRule(CreateJMSQueueRule.ID, "CreateJMSQueueRule"));
		add(new CreateMediationRule(CreateMediationRule.ID,
		"CreateMediationRule"));
	}
   	

4.5 运行测试

以上我们详细介绍了如何利用RSA的模型转换功能实现SIBus模型到Jacl脚本的转换功能。下面我们来进行创建总线实例的运行测试。

首先,启动RSA的运行环境,加载该转换插件。创建一个UML模型,在模型中创建Bus类和BusMember类:



 

右键点击其中一个Element,选择转换,之后会生成createBus.Jacl,如下所示:

清单 5. createBus.Jacl
 
#
# This JACL file create a bus
#
#==========Bus related properties==============
set busName "SIBus1"
#---------Creating a bus----------------#
puts "Creating a bus:$busName is as follows: "
$AdminTask createSIBus "-bus $busName"	
$AdminConfig save	

下面,我们需要在WebSphere Application Server运行createBus.Jacl脚本文件。在部署测试之前,首先要准备WebSphere Application Server的环境,这包括安装SDO Repository,Resource Adaptor,HTTP Channel以及和SIBus相关的应用。

1) 在Command窗口,进入WebSphere Application Server的bin 目录。

2) 输入如下命令,以-f 作为参数,指定要执行的Jacl文件。

wsadmin.bat" -f .\createBus.Jacl

3) 启动WebSphere Application Server 管理控制台,在服务集成栏中,点击"总线",从右侧的总线窗口中,可以看到一个名为"SIBus1"的总线被创建。


结束语

ESB作为搭建SOA系统解决方案的基础设施,是开发SOA应用的一个非常重要的部分,WebSphere Application Server 6.0中自带的ESB组件SIBus就是ESB理念的一种实现,在很大程度上就可以满足用户的要求。将MDA的开发方法应用到SIBus组件的开发过程中,利用RSA提供的模型转换框架,实现将SIBus模型转化为可以在WebSphere Application Server中部署和运行的Jacl脚本, 可以大大简化用户开发、部署和配置的繁冗和难度。

参考资料

 


版权所有:UML软件工程组织