本文向您展示怎样使用 Rational Software Architect V7.5
的 UML-to-JPA 及 UML-to-XSD 转换工具,并结合 WebSphere Integration
Developer V6.1.2 的 SCA 开发环境,来进行模型驱动的服务开发。本文通过对一个具体案例的分析,介绍了从如何从
UML 模型生成 JPA 标注的 Java Bean 源代码;如何配置编译环境对 Java Bean 类文件实现
JPA 增强;如何从 UML 模型生成业务对象模型;如何在服务实现中将业务数据对象(SDO)转换成 Java
Bean 对象并用 JPA 对其进行持久化。本文主要面向 Java 开发和设计人员,假定读者对 JPA、SCA、Web
service 有基本的了解,您也可以参见参考资料以了解更多 JPA 和 SCA 相关的知识。
如何进行快速、高效的服务设计和开发一直是很多软件架构人员和开发人员所关注的问题。服务设计和开发流程可以包括以下内容:
- 架构师根据需求进行模型设计
- 数据库设计师根据模型进行数据库的设计及实现
- 服务开发人员根据模型进行业务对象、服务接口的设计和服务的实现
在进行服务的设计和开发的过程中,软件架构人员和开发人员往往会遇到以下问题:
- 在软件架构师根据需求设计完 UML 模型后,数据库设计师会根据 UML 模型进行数据库模型的设计。由于
UML 模型的结构不同于数据库表的结构,在两种模型之间进行转换的时候,往往要花费大量的时间和精力。
- 在软件架构师根据需求设计完 UML 模型后,服务设计人员会根据 UML 模型设计服务对象。由于
UML 模型的结构不同于业务对象的结构,两者之间相互的映射和转换是很大的工作量。
IBM 的软件家族对服务的设计和开发提供了丰富的软件资源的支持,其中 Rational Software
Architect(RSA)是 IBM Rational 产品线的一个重要产品,它提供用户基于业界建模标准
UML 的建模功能,并且支持将 UML 模型转化为其他数据对象的能力,其中包括将 UML 模型转化为 Java
Bean 以便进行数据库的构建及数据的持久化,和将 UML 模型转化为 XSD 以便进行服务对象的转化及服务的开发的功能,可以大大简化软件架构师和设计开发人员的模型设计和转换工作,提高生产效率。
本文将通过一个具体的案例分析和介绍如何使用 RSA 来实现一个端到端的基于模型驱动的服务开发过程,内容将包括以下三个部分:
- 架构师如何根据需求进行 UML 模型的设计
- 数据库设计师如何根据已有的 UML 模型通过 RSA V7.5 中的 JPA 的功能组件实现数据库的设计和创建
- 服务开发人员如何根据已有的 UML 模型通过 RSA V7.5 中的 UML 到 XSD 的转换的功能实现业务对象的设计和实现,并在
WebSphere Integration Developer 中进行服务的开发和测试
这里我们通过一个网上商城的案例介绍如何借助 RSA 实现模型驱动的服务开发。客户想开发一个网上商城,用于进行基于网络平台的商品交易。这个平台需要提供客户登录、订购产品、查询订购记录等功能。
根据客户的需求,可以将网上商城的模型设计成以下内容:一个客户(Customer)的对象,用于表示使用网上商城的客户;一个订单(Order)对象,用户描述用户订购产品的订单;一个产品(Product)对象,用于表示网上商城售卖的产品;一个产品价格(ProductPrice)对象,用于描述产品的价格。其中一个客户可以有多个订单,每个订单可以包含多个产品,每个产品根据打折粒度等因素会有不同的价格。图
1 显示了网上商城的 UML 模型图:
图 1. UML 模型
网上商城需要为客户提供以下服务:
- getAllProduct() 为客户列出所有可以购买的商品
- getCustomerByID(customerID) 根据客户的 ID 获取客户的信息
- getOrderByOID(orderID) 根据订单的 ID 获取订单的信息
- getProductByPID(productID) 根据商品的 ID 获取商品的信息
- getOrdersByCID(customerID) 根据客户的 ID 获取订单的信息
接下来我们将会进一步讲解如何根据模型通过 RSA 实现服务的开发。
首先我们需要根据需求创建 UML 模型。RSA 提供了 UML 模型的创建编辑功能,构建模型的步骤如下:
3.1. 创建 UML
项目
点击新建工程,创建 UML 工程,在工程名中输入”ExmapleDataModel”作为工程名,点击”Finish”完成
UML 工程的创建。
3.2 环境配置
在建模前,我们首先要在 RSA 中添加对 XSD 数据类型和 JPA 构造型的支持,从而能够进行 UML
模型到 XSD 和 JPA 的转变,进而实现业务对象的创建和数据库的建立。
3.2.1 添加
XSD 数据类型
本步骤在工程中添加 XSD 类型支持,以扩充 UML 建模取值类型。
在新建的项目下右键单击“Package”选择“UML Properties”。
点击“PackageImport”,添加 XSDDataTypes。
图 2. PackageImport 编辑界面
3.2.2 添加
JPA 构造型
本步骤在工程中添加 JPA 的支持,以提供将 UML 模型转化为 Java bean 的功能。
点击“ProfileApplication”, 点击“Insert new Profile Application”,“Select
Profile”对话框弹出,如图 6 所示:
图 3. PackageApplication 编辑界面
在“Select Profile”对话框的“Deployed Profile”中选择“JPA Transformation”,点击“OK”添加
JPA。
3.3 建模
在添加完对 XSD 和 JPA 的支持后,我们将在 RSA 中创建网上商城的 UML 模型。
首先根据客户的需求创建四个对象:Customer 表示客户,Order 表示客户的一条订购,Product
表示产品,ProductPrice 表示产品价格。每个客户可以有多条订购。每一条订购对应一个产品,一个产品可以被多次订购,即有多条订购记录。每一个产品有多个价格,例如针对不同客户有不同的打折力度。
然后进一步细化各个对象的定义:依次为 Customer, Order, Product, ProductPrice
添加属性,并为标识属性添加 JPA 的 <<Id>> 构造型。设置对象之间的关系,如创建
Customer 到 Order 的关联 order,设置关系为一对多。点击“Stereotypes”,点击“Apply
Stereotypes”添加“RelationshipOptions”,在 RelationshipOptions
Property 中设置 cascade 属性为 0-ALL,fetch 属性为 0-EAGER,optional
属性为 True。其他关系设置请参照附件代码。
图 4. Stereotypes 编辑界面
在 RSA 中创建完四个 UML 对象并添加了相关属性后,UML 模型的设计部分就完成了。接下来为创建数据库结构合
Java Bean 对象,将要借助 JPA 进行 UML 到 Java Bean 的转换。
在创建完 UML 模型后,需要将 UML 模型进一步转化,从而创建数据库来存储数据。在这里采用 RSA
的 JPA 工具来实现 UML 到 Java Bean 的转换,进而通过新生成的 Java Bean 实现数据库的自动创建,创建简化数据库操作,省去了大量的数据库的创建
sql 的工作,加速服务开发的进度。这部分内容介绍如何在 RSA 中借助 JPA 进行 UML 到 Java
Bean 的转换,从而实现 Java Bean 对象和网上商城数据库的创建,转换的步骤如下:
4.1 创建转换配置
为了进行 UML 到 JPA 的转换,需要首先定义转换文件。点击“Modeling”下的“Transformation”中的“New
Configuration”,弹出“New Transformation Configuration”对话框。
图 5. 创建转换文件编辑界面
在“Name”中添加“UML2JPA”,“Configuration file destination”中选择“/ExampleDataModel”,在“Transformation”中选择“Java
Transformation”中的“UML to JPA”。点击“Next”。
图 6. 转换文件编辑界面
在弹出的对话框中点击“Create Target Container”,创建 JPA 工程。
在“New JPA Project”对话框中添加工程名称“ExamplePersistence”,点击“Finish”。
在“New Transformation Configuration”对话框中选择“ExampleDataModel”作为“Selected
source”,选择“ExamplePersistence”作为“Selected target”,点击“Finish”。
编辑新生成的 UML2JPA.tc 文件。
在“Source and Target”选项中选择“model”作为“Selected source”。
图 7. 选择 source 和 target
设置“Properties”中的属性,如图所示:
图 8. 属性编辑界面
图 9. Collections 编辑界面
设置“Collections”中的属性,如图所示:
Figure xxx. Requires a heading
上述步骤创建的转换配置能将带 JPA 构造型的 UML 模型转换成带 JPA 标注的 Java Bean
源代码。
4.2 配置编译环境
将 UML 转换成带 JPA 标注的 Java Bean 源代码之后,还需要对编译环境进行配置,利用
JPA 提供的工具对编译后的 Java Bean 类文件进行 JPA 增强,只有带 JPA 增强的 Java
Bean 类才能被 JPA 操作。
4.2.1 添加
build.xml
在 ExamplePersistence 工程下添加 build.xml 文件,“perpertiesFile”用于指定
persistence.xml 文件的地址,“pathelement”用于指定 class 文件的地址。
清单 1. build.xml
<?xml version="1.0" encoding="GB2312" ?>
<project default="enhance">
<target name="enhance">
<taskdef name="openjpac" classname="org.apache.openjpa.ant.PCEnhancerTask"/>
<openjpac>
<config propertiesFile="${basedir}/src/META-INF/persistence.xml"/>
<classpath>
<pathelement location="${basedir}/src"/>
</classpath>
</openjpac>
</target>
</project> |
右键点击“ExamplePersistence”工程,选择“Java Build Path”中的“Source”,设置“Default
output folder”为“ExamplePersistence/src”。
4.2.2 添加
JPABuilder
右键点击“ExamplePersistence”工程,在“Builders”选项中点击“New”,创建“JPABuilder”。
在“Main”中的“Name”中添加“JPABuilder”作为名称,选择“ExamplePersistence”下的“build.xml”作为“Buildfile”,选择“ExamplePersistence”作为“Based
Directory”。
图 10. Builder Main 编辑界面
在 Classpath 中添加“com.ibm.ws.jpa.thinclient_7.0.0.jar”。
4.2.3 更新
persistence.xml
更新 ExamplePersistence 工程中的 src/META-INF 下的“persistence.xml”文件。
在“persistence-unit”中的“class”中添加要持久化的类的名称。在“properties”中添加数据库的连接信息,如“DriverClassName”,“Url”,“Username”,“Password”等。
清单 2. persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0"
xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="ExamplePersistence">
<class>com.ibm.example.model.Customer</class>
<class>com.ibm.example.model.Order</class>
<class>com.ibm.example.model.Product</class>
<class>com.ibm.example.model.ProductPrice</class>
<properties>
<property name="openjpa.ConnectionProperties"
value="DriverClassName=com.ibm.db2.jcc.DB2Driver,
Url=jdbc:db2://localhost:50000/EM,
Username=db2admin,Password=db2admin"/>
<property name="openjpa.ConnectionDriverName"
value="org.apache.commons.dbcp.BasicDataSource"/>
<property name="openjpa.jdbc.Schema"
value="EXAMPLE" />
<property name="openjpa.jdbc.SynchronizeMappings"
value="buildSchema" />
</properties>
</persistence-unit>
</persistence> |
4.3 进行 UML
到 JPA 的转换
运行 UML2JPA.tc 文件,点击“Run”按钮,进行 UML 到 JPA 的转换。
图 11. UML 到 JPA 的转换
在 ExamplePersistence 的 src 文件夹下会生成转化的 Java 代码,Customer.java,Order.java,Product.java,ProductPrice.java。
图 12. UML 到 JPA 的转换结果
4.4 导出 Java
Package
右键点击项目 ExamplePersistence,选择 Export,选择 Java->Jar
File 选项,点击下一步,选中 ExamplePersistence->src->com.ibm.example.model,添加生成
jar 文件的目录和文件名 d:/com.ibm.example.model.jar,点击完成。这样用于进行服务开发的
Java Bean 对象就生成完毕,我们将把 RSA 生成的 jar 包文件添加到 WID 的服务开发项目中,作为服务对象。
在创建 UML 模型后,需要为服务的开发创建业务对象。RSA 提供了将 UML 转化为服务业务对象的转换工具,即
UML 到 XSD 的转换,这样省去了很多创建服务业务对象的人工工作,加速了服务的开发进程。在这一步中将介绍如何使用
RSA 的转化功能,将 UML 模型转化为 WID 的服务开发项目中所使用的服务的业务对象,步骤如下:
5.1 创建转换配置
点击 Modeling->Transform->New Configuration,添加“UML2XSD”作为属性名,选择
Service Oriented Architecture Transformations 下的 UML
to XSD,点击 Finish.
图 13. 创建 UML 到 XSD 的转换
配置 UML2XSD.tc 文件,选择 Source and Target 选项,选择 model 作为
Selected source, schema 作为 Selected target。
图 14. UML 到 XSD 的转换编辑界面
在 Output Options 中配置 Namespace, 设置为http://example.ibm.com/model/
图 15. 配置 Target namespace
5.2 生成 XSD
文件
点击 Main 选项,点击 Run 按钮,进行 UML 到 XSD 的转换,生成相应的 xsd 文档。
图 16. UML 到 XSD 转换
新生成的业务对象保存在 Example 工程下的 schema 目录里。
图 17. UML 到 XSD 转换的转换结果
在 RSA 中新生成的 model.xsd 文件,包含了服务开发所需要的业务对象的内容,稍后我们将把这个文件复制到
WID 的服务开发项目中提供所需的业务对象。
通过使用 RSA,我们根据客户的需求设计了 UML 模型,并且通过 RSA 的 JPA 的转化工具,实现了
UML 模型到 Java Bean 的转换,为服务的实现提供的模型,为快速创建数据库打下了基础,通过 RSA
的 UML 到 XSD 的转换工具,创建了服务的业务对象,为实现服务提供了所需的业务对象。在此基础上,我们将进一步实现网上商城的服务功能,包括根据已生成的
Java Bean 对象快速创建数据库,结合已生成的服务的业务对象设计服务的接口和实现服务,步骤如下:
6.1 将模型持久化到数据库
首先要将模型持久化到数据库中。这里我们将通过在 RSA 中调用 UML 模型转化为 Java Bean
过程中产生的代码实现数据的创建。
在 ExamplePersistence 工程下新建包“com.ibm.example.persistence”,创建类“DatahaseCreator.java”,在类中加入以下内容:
清单 3. DatahaseCreator.java
public static void main(String[] args) {
Product prod = new Product();
prod.setProductID("Product0");
EntityManagerFactory factory = Persistence
.createEntityManagerFactory("ExamplePersistence");
EntityManager manager = factory.createEntityManager();
manager.getTransaction().begin();
manager.persist(prod);
manager.remove(prod);
manager.getTransaction().commit();
} |
运行以上代码,通过创建删除产品,在数据库中添加表结构,并为数据库添加示例,数据库示例如附件中 ExampleData
所示。
清单 4. 在数据库中添加表结构
INSERT INTO EXAMPLE.CUSTOMER (CUSTOMERID, ADDRESS, CELLPHONE, NAME)
VALUES ('C2009-VIP01', ' 北京 ', '13011001100', ' 李明 ');
INSERT INTO EXAMPLE.PRODUCT (PRODUCTID, DESCRIPTION, NAME)
VALUES ('PRODUCT1', ' 雨露牌加湿器 ', ' 雨露牌加湿器 ');
INSERT INTO EXAMPLE.PRODUCT (PRODUCTID, DESCRIPTION, NAME)
VALUES ('PRODUCT2', ' 阳光牌早餐吧 ', ' 阳光牌早餐吧 ');
INSERT INTO EXAMPLE.PRODUCT (PRODUCTID, DESCRIPTION, NAME)
VALUES ('PRODUCT3', ' 民族舞教学光盘 ', ' 民族舞教学光盘 ');
INSERT INTO EXAMPLE.PRODUCT (PRODUCTID, DESCRIPTION, NAME)
VALUES ('PRODUCT4', '360 度神奇拖把 ', '360 度神奇拖把 ');
INSERT INTO EXAMPLE.PRODUCTPRICE (PRICEID, CURRENCY, DESCRIPTION, NAME, PRICE)
VALUES ('PRICE1', 'RMB', ' 雨露牌加湿器 228 元 ', ' 雨露牌加湿器 228 元 ', 228.00);
INSERT INTO EXAMPLE.PRODUCTPRICE (PRICEID, CURRENCY, DESCRIPTION, NAME, PRICE)
VALUES ('PRICE2', 'RMB', ' 阳光牌早餐吧 348 元 ', ' 阳光牌早餐吧 348 元 ', 348.00);
INSERT INTO EXAMPLE.PRODUCTPRICE (PRICEID, CURRENCY, DESCRIPTION, NAME, PRICE)
VALUES ('PRICE3', 'RMB', ' 民族舞教学光盘 18 元 ', ' 民族舞教学光盘 18 元 ', 18.00);
INSERT INTO EXAMPLE.PRODUCTPRICE (PRICEID, CURRENCY, DESCRIPTION, NAME, PRICE)
VALUES ('PRICE4', 'RMB', '360 度神奇拖把 399 元 ', '360 度神奇拖把 399 元 ', 399.00);
INSERT INTO EXAMPLE.ORDER (ORDERID, DESCRIPTION, NAME, ORDERDATE, STATUS,
PRODUCT_PRODUCTID)
VALUES ('ORDER4', ' 雨露牌加湿器 ', ' 雨露牌加湿器 ',1254119935352, ' 已下单 ', 'PRODUCT1');
INSERT INTO EXAMPLE.ORDER (ORDERID, DESCRIPTION, NAME, ORDERDATE, STATUS,
PRODUCT_PRODUCTID)
VALUES ('ORDER3', ' 阳光牌早餐吧 ', ' 阳光牌早餐吧 ',1254013035359, ' 已发货 ', 'PRODUCT2');
INSERT INTO EXAMPLE.ORDER (ORDERID, DESCRIPTION, NAME, ORDERDATE, STATUS,
PRODUCT_PRODUCTID)
VALUES ('ORDER2', ' 民族舞教学光盘 ', ' 民族舞教学光盘 ',1250119930359, ' 交易结束 ', 'PRODUCT3');
INSERT INTO EXAMPLE.ORDER (ORDERID, DESCRIPTION, NAME, ORDERDATE, STATUS,
PRODUCT_PRODUCTID)
VALUES ('ORDER1', '360 度神奇拖把 ', '360 度神奇拖把 ',1244119955952, ' 交易结束 ', 'PRODUCT4'); |
6.2 创建 Library
工程
然后我们将在 WID 中创建一个 Library 工程,用于存储通过 RSA 实现 UML 模型到 XSD
转化生成的服务的业务对象。在 WID 中点击 New->Project->Library 创建
Library 工程,输入 ExampleLib 作为工程名,将生成的 model.xsd 复制到 Library
工程下,即可看到业务对象:
图 18. Customer 业务对象
图 19. Order 业务对象
图 20. Product 业务对象
在 Library 工程下创建接口 IExample,用于定义服务的接口,其中包括 :getAllProduct(
查询所有可订购的产品 ),getCustomerByCID( 根据客户 ID 查询客户信息 ),getOrderByOID(
根据订单 ID 查询订单的信息 ),getProdutByPID(根据产品 ID 查询产品信息),getOrdersByCID(
根据客户 ID 查询该客户的所有订单 )。
图 21. IExample 接口及方法
6.3 创建 Module
工程
在创建完数据库和服务的业务对象及接口后,我们将进行服务的实现,步骤如下:
在 WID 中点击 New->Project->Module 创建 Module 工程,输入
ExampleModule 作为工程名,在 Assembly Diagram 创建 ExampleComponent,并且添加相应的实现。
图 22. ExanpleComponent
ExampleComponent 实现示例代码如下:
清单 5. ExampleComponent 实现示例代码
public DataObject getOrdersByCID(String customerID) {
DataObject result = createOrderListBO();
List scope = new ArrayList();
scope.add("com.ibm.example.model.Order");
scope.add("com.ibm.example.model.Customer");
try {
manager = factory.createEntityManager();
Query query = manager
.createQuery("select o from Order o, Customer c where c.customerID
= :param1 and o member of c.order");
query.setParameter(1, customerID);
Iterator iter = query.getResultList().iterator();
while (iter.hasNext()) {
Order order = (Order) iter.next();
DataObject item = (DataObject) SDOTransformer.getInstance()
.convertPOJOToSDO(order, scope);
result.getList("orders").add(item);
}
} catch (Exception e) {
e.printStackTrace();
throw new ServiceRuntimeException(e);
} finally {
manager.close();
return result;
}
} |
创建 Java Bean 和 SDO 之间相互转换的代码,创建 SDOTransformer.java,创建
convertPOJOToSDO 方法,实现内容如下:
清单 6. SDOTransformer.java
public Object convertPOJOToSDO(Object object, Collection scope,
Collection exclusion) throws Exception {
…
if ( defaultValues.containsKey(subClass) ||
subClass.getName().equals("java.lang.Object")) {
try {
Class instanceClass =
sdo.getType().getProperty(subName).
getType().getInstanceClass();
if ( ! instanceClass.equals(subClass) ) {
subValue = createJavaObject(instanceClass,
subValue.toString());
}
sdo.set(subName, subValue);
} catch ( Exception e ) {
e.printStackTrace();
}
} else if(subClass.getName().equals("java.util.List") ) {
Iterator iter = ((List)subValue).iterator();
while ( iter.hasNext() ) {
Object pojo = iter.next();
if ( exclusion!=null
&& exclusion.contains(className + ">" + pojo.getClass().getName()))
break;
Object propValue =
convertPOJOToSDO(pojo, scope, exclusion);
if ( propValue != null ) {
sdo.getList(subName).add(propValue);
}
}
} else {
Object propValue =
convertPOJOToSDO(subValue, scope, exclusion);
if ( propValue != null ) {
sdo.set(subName, propValue);
}
}
}
return sdo;
} |
将 ExamplePersistence 工程下通过 UML->JPA 转换生成的代码打成的 jar
包,添加至 ExampleModule 工程 Java Build Path 下:
图 23. 添加 jar 包
将 ExamplePersistence 工程下的 persistence.xml 复制到 ExampleModule
工程的 META-INF 目录下。
在完成以上步骤后,我们就完成了服务的实现工作,接下来我们将会将服务打包部署到 WPS 上,进行服务的测试工作。
将应用程序导出的 ear 包 ExampleModuleApp.ear 和 ExampleUIApp.ear
部署到 WPS 上,测试服务,在浏览器中输入http://localhost:9080/ExampleUI/pages/orders.jsp,输入
C2009-VIP01 作为客户编号,点击查看订单按钮,即可查看查询结果:
图 24. 查询界面
图 25. 查询结果
本文将通过一个案例的分析和介绍,使用 IBM Rational Application Developer
7.5 的 UML,JPA 和 WID6.1.2 工具,讲解了如何根据需求构建 UML 模型,并通过 UML
到 JPA 的转换实现持久化数据,简化开发人员的数据库操作,以及通过 UML 到 XSD 的转换,生成业务对象,进而进行服务开发,完成基于模型驱动的服务开发。
学习
获得产品和技术
讨论 |