一个典型的开发周期涉及到分析和捕获业务目标的业务分析(Business Analysis)
模型的创建,然后将其转换为一个软件体系结构模型。IBM ®Rational® Software
Architect 中的 Business Process-to-Service Model SOA 转换特性有助于您创建这一模型。本文提供了一个入门示例,向您详细演示如何创建一个自定义的过程分解(process
decomposition),用于将您的业务处理过程转换为一个服务模型。本文所面向的是那些对如何创建转换扩展比较熟悉的读者。
IBM Rational Software Architect 中的 Business Process-to-Service
Model 转换特性包括主体转换和三个默认的扩展。
主体转换创建一个统一建模语言控件(Unified Modeling Language Component)来描述服务提供者(Service
Provider)。转换还通过端口对组件进行组装,每一个表现界面或者是被服务所提供,或者是被服务所需要。最终,一个
CollaborationUse 元素被创建出来,它将体系结构模型中的服务所表现的组件同业务分析模型(Business
Analysis Model)中的协作(Collaboration)链接起来。组件上的每一个端口都将被绑定到适当的角色。CollaborationUse
元素,同端口和角色绑定一起,表现为一个协议验证段。该合同确认允许跟踪到业务分析(Business Analysis),确认组件按照业务分析模型中所指定的处理过程得以实现。
图 1. 转换工具的主要输出包括:端口、协议验证段、CollaborationUse
元素以及角色绑定。
主体转换并不提供它所生成的组件的任何内部分解。其原因就在于这些细节依靠执行和配置域的决定和约束。
创建内部分解的任务落到了主体转换的扩展肩上。每一个扩展都创建其自己的业务处理过程的分解,并且描述它的内部工作。尽管很少有这样的扩展被提供,但是您能够通过创建和注册自定义的扩展来创建不同的服务分解,从而满足这些特定的需要。
在这个例子中,假设您已经为新的服务创建了一个业务分析(Business Analysis)模型,并且将遗产服务综合到解决方案之中。这一模型描述了通过共同工作来创建一个
Medical Marketplace 一族服务。这个 Medical Marketplace 呈现出各种各样的医疗服务。提供服务的每一个客户请求都将被处理,并且一个适当的服务将被选中来提供给客户端。当服务被执行时,付款将被收集,并且客户反馈将被提交到市场数据库(请参见图
2 所示)。
图 2. Medical Marketplace 的 Business
Analysis Model 的业务处理过程。
我们来关注以下付款收集(Payment Collector)服务,它负责在医疗服务被提供之后开列账单以及收集付款。它要求某些种类的簿记保存有关交易的记录。它将日志(Logger)服务用于这些目的。这些服务的目的是有效利用现已存在的
Java™ 代码。
假设现有遗传下来的账单(Billing)和日志(Logging)服务。账单(Billing)服务表现了一个被称作
Billing 的 Java 接口。这里有一个通过 com.acme.billing.MedicalBilling
Java 类的具体执行。MedicalBilling
使用由另一个遗产库所定义的日志(Logging)服务:com.acme.logging (请参见图
3 所示)。
图 3. Java 遗产库包含了 Billing 和 Logging
服务的 Java 执行。
完整的 SOA 解决方案被配置在服务组件定义语言(Services Component Definition
Language,SCDL)中。自定义扩展的目的是生产一个被连接到基于 Java 的遗产库的 SCDL
模块。
- 创建一个 Eclipse 插件程序项目。
- 创建一个转换类(请参见列表 1 中的例子)。
列表 1. 创建一个转换类的代码。
package com.ibm.xtools.transform.cfm.example.transform;
import com.ibm.xtools.transform.cfm.example.rules.MyPopulateComponentRule;
import com.ibm.xtools.transform.core.Transform;
public class MyTransform
extends Transform {
//id of the transformation
public static final String TRANSFORM_ID =
"com.ibm.xtools.transform.cfm.example.transform.MyTransformId";
public MyTransform() {
super(TRANSFORM_ID); // instantiate transformation using id
add(new MyPopulateComponentRule());//program transformation with this rule
}
} |
注释:
当创建一个扩展号的时候,请尽量做到唯一性。这一点是非常重要的,这是因为当转换配置指明一个处理过程应当使用一个扩展号被转换的时候,具有那个扩展号的扩展将被选中,并且被用于转换该处理过程。
- 将功能性编入
MyPopulateComponentRule
的代码。列表 2 中的代码强调了这一规则的关键功能。
列表 2. 用于 MyPopulateComponentRule
的代码。
public class MyPopulateComponentRule extends ModelRule {
/*
* canAccept method asserts wither or not the extension is applicable
*/
public boolean canAccept(ITransformContext context) {
// the rule will be invoked if the current node on the source side is
// an instance of UML Collaboration and the node on the target side
// is instance of UML Component
return context.getSource() instanceof Collaboration
& context.getTarget() instanceof Component;
}
/*
* createTarget method will perform additional (to main) transformation of the
Collaboration(service) in the source
* model to the elements in the target model
*/
protected Object createTarget(ITransformContext context) throws Exception {
Component collaborationComponent = (Component) context.getTarget();
Component java_adapter = createJavaConverter(collaborationComponent);
assert (java_adapter != null);
Property attribute = collaborationComponent.createOwnedAttribute(
"java_adapter", java_adapter);
for (Iterator e = collaborationComponent.getOwnedPorts().iterator(); e.hasNext();) {
Port port = (Port) e.next();
// there will only one port that provides interface to the outside.
if (!port.getProvideds().isEmpty()) {
Port in_port = java_adapter.createOwnedPort("in_" + port.getName(), null);
Interface anInterface = (Interface) port.getProvideds().get(0);
addProvidedInterface(anInterface, in_port);
createConnector(collaborationComponent, port, in_port, null, attribute,
ConnectorKind.DELEGATION_LITERAL);
} else if (!port.getRequireds().isEmpty()) {
Interface anInterface = (Interface) port.getRequireds().get(0);
Type type = createUsage(java_adapter, anInterface);
Port out_port = java_adapter.createOwnedPort("out_" + port.getName(), type);
createConnector(collaborationComponent, out_port, port, attribute, null,
ConnectorKind.DELEGATION_LITERAL);
}
}
return collaborationComponent;
}
/*
* auxiliary method – creates java adapter component for the role,
which represents Collaboration (service) itself
*/
private Component createJavaAdapter(Component collaborationComponent) {
for (Iterator e = collaborationComponent.getOwnedPorts().iterator(); ehasNext();) {
Port port = (Port) e.next();
if (!port.getProvideds().isEmpty()) {
return (Component) collaborationComponent..createPackagedElement(port.getName() +
"Adapter",UMLPackage.Literals.COMPONENT);
}
}
return null;
}
…
}
Create the extension condition class:
/**
* com.ibm.xtools.transform.cfm.example.condition.MyExtensionCondition
*/
public class MyExtensionCondition
extends TransformCondition {
public MyExtensionCondition() {
super();
}
protected boolean isContextSatisfied(ITransformContext context) {
return (context.getSource() instanceof Collaboration)
& CommonConfigUtil.getExtensionIdFor(
(Collaboration) context.getSource(), context).equals(
MyTransform.TRANSFORM_ID);
}
} |
该条件将在运行时被使用,来断定一个业务处理过程是否使用您自定义的转换被配置、被转换。
- 将您的扩展注册到一个 XML 插件程序文件中。列表 3 显示了一个声明自定义扩展的例子。
列表 3. 一个声明自定义扩展的 XML 插件程序文件的代码示例。
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.2"?>
<plugin>
<extension
point="com.ibm.xtools.transform.core.transformationExtensions">
<TransformationExtension
author="you"
description="my custom extension"
document="optional"
enabled="true"
id="com.ibm.xtools.transform.cfm.example.transform.MyTransformId"
name="My custom extension"
targetTransformation="com.ibm.xtools.transform.cfm.wbm.transforms.MainTransform"
version="1.0.0">
<TransformDefinition
acceptCondition="com.ibm.xtools.transform.cfm.example.condition.MyExtensionCondition"
class="com.ibm.xtools.transform.cfm.example.transform.MyTransform"
id="com.ibm.xtools.transform.cfm.example.transform.MyTransformId"/>
<ExtendTransform
targetTransform="com.ibm.xtools.transform.cfm.wbm.transforms.OwnedBehaviorTransform">
<AddTransform id="com.ibm.xtools.transform.cfm.example.transform.MyTransformId"/>
</ExtendTransform>
</TransformationExtension>
</extension>
</plugin> |
这一例子自定义扩展的目标是 Business Process-to-Service Model 主体转换:
com.ibm.xtools.transform.cfm.wbm.transforms.MainTransform
它也指定了那些扩展条件需要被用来决定扩展的能力:
com.ibm.xtools.transform.cfm.example.condition.MyExtensionCondition
最后,它指定了转换的分支,哪一个转换将通过这个扩展被扩展:
com.ibm.xtools.transform.cfm.wbm.transforms.OwnedBehaviorTransform
配置自定义的扩展
- 配置转换。
- 在您完成前述各个步骤之后,将您的插件程序导出到您的插件程序目录下,并且重新启动 Rational
Software Architect。
您的自定义扩展将可以用于从 Configuration UI (用户接口)中进行选择,如图 4 中所示。
图 4. 配置一个带有自定义扩展的转换。
- 配置一种处理过程,用来使用自定义的扩展。
- 保存配置,并且运行转换。
- 处理输出、继续建模、授权到遗留代码(请参见图 5 所示)。
图 5. 被转换的付款收集器(Payment Collector),使用自定义的扩展分解。
为了自定义的扩展而被创建的分解如图 5 中所示。现在,可以继续下一步的操作。
授权调用 Java
库的服务
Java 适配器的作用是授权到 Java 库的调用。以建模:
- 通过键入
BillingComponent
为付款收集器(Payment Collector)创建第二个属性(部分),并且添加两个端口:
- 向 myRoleAdapter 添加第一个端口,设置被需要的接口为:
com.acme.billing.Billing
- 向 Billing 组件 添加第二个端口,设置其类型为:
com.acme.billing.MedicalBilling
(请参见图 6 所示)。
- 连接两个端口。
图 6. 将扩展适配到遗留代码。
注释:
账单(Billing)服务需要另外一种被称作日志(Logger)的服务。如果 Logger 服务的执行同
Billing 一样可用的话,那么您就能够以同样的方式建模 Logger 和 Billing。否则的话,它就被作为
myRoleAdapter 组件的一部分功能被建模。
这一模型现在能够被 SOA 转换来使用,创建配置产品。SOA Transformation 将把 Payment
Collector 组件转换到一个 IBM®WebSphere® Integration
Developer 业务集成模型项目中。用于 Java 适配器和 Medical Billing 的部分将被修改到那个模块内部的一个
Service Component Architecture (SCA)组件中。为 MedicalBilling
而创建的 SCA 将把组件实现参考内容指向 Java 遗留库。
正如您从本文中所学到的,Business Process-to-Service Model 转换特性支持在
WebSphere Business Modeler 中的业务分析建模和 UML 中的设计建模之间搭建的桥梁。具有特定配置域和执行域需求的业务,能够适应这一转换来满足它们的需要。由转换所创建的产品能够在
Rational Software Architect 中被进一步的建模。它还能够通过使用由 Rational
Software Architect 所提供的 SOA 转换工具被转换到一个 WebSphere Integration
Developer 项目中。
您能够在本系列文章的下一部分(第 3 部分:UML 到 SOA)中找到更多关于 SOA 转换的信息。那篇文章详细解释了如何使用包含在
Rational Architect Version 7.0.0.2 及其以后版本中的 UML-to-SOA
转换工具从软件服务的 UML 模型转换到特定域的 SOA 实现。这一工具将把用于特定软件执行和运行时间的不同转换扩展汇集到一起。
学习
获得产品和技术
讨论
|