2008
年 12 月 11 日
CICS(Customer Information Control System),即客户信息控制系统,是为
IBM 和非 IBM 平台上一系列应用提供联机事务处理和事务管理的产品,其主要功能是为商业应用提供一个事务处理环境。该产品拥有近四十年的悠久历史,被广泛应用于银行金融业。但随着当前信息技术的迅猛发展,很多经典的事务处理应用面临着如何被扩展和重用,以求与其他平台应用相集成的问题。CICS
作为 IBM 的重要产品,借鉴了 SOA 的主要思想,采用 Web service 封装已有的应用,实现了
CICS 与其他平台应用的结合与互操作。本文通过一个实际的例子,将一个已有的 CICS 应用程序封装成
Web service 的请求者(requester)请求另一个 Web service,同时又作为服务提供者(provider)接受其它应用的访问。读者不仅能从本文详细了解到如何在
z/OS 上构建 CICS Web service 的详细步骤,同时能够把握 CICS Web service
如何与部署在其他平台上的 Web service 进行互操作,以及与 IBM WSRR(WebSphere
Service Registry and Repository) 的结合使用。
概述
主机 (Mainframe) 上的 CICS 服务由于其历史的悠久,存在着很多对于事务处理的经典应用。如何将这些应用重用,并与其他平台的服务进行交互是本文的主要内容。本文模拟了一个非常普遍的应用场景,通过实例介绍
CICS Web service 的封装和具体应用。该实例的总体框架如图 1 所示,主要包括三部分。
1. 实时汇率服务 (Exchange Rate Service, 下文简称为
RateService),是部署在 Windows 操作系统 Websphere Application
Server(WAS) 上的一个 Web service,提供汇率值的实时查询服务,由 Java 语言实现。为了使例子简单易懂,这里仅仅提供了人民币对美元的汇率和人民币对欧元的汇率。
2. 转账服务 (TransferService),一个存在于主机 z/OS
环境中的 CICS 事务处理应用程序,它是由 C 语言编写,用于银行帐户不同币种的转账处理。例如某银行客户张三,上月去美国透支了信用卡中
1000 美元用于消费,现在回到中国必须用人民币转账到自己的信用卡美元账户以偿还透支额度。转账过程中必须知道人民币对美元的汇率,因此需要封装成为
Web service 的客户端 (requester) 访问 RateService 提供的实时汇率服务。同时,为了使转账服务能够提供给异构平台上各种语言的客户端调用,还需要将其封装成
Web service 的提供者 (provider)。
3. 网上银行 (Online Trading Platform),模拟的网上交易平台。客户端调用转账服务
(TransferService) 完成客户用人民币偿还信用卡美元帐户等类似转账交易。作者在本文中给出了一个
Struts 框架实现的 Web 应用程序来模拟这一交易平台。
图 1. 实例总体框架
第一步:汇率服务的创建
1. 开发环境
开发平台:Windows 操作系统,IBM Rational Application
Developer 7.0.0( 内置 Websphere Application Server 6.1)
开发语言:Java
2.开发步骤
新建一个动态 web 项目。在 IBM RAD7 开发环境中,选择 "File->New->Project",
选择动态 web 项目,命名为 exchange,保留其它选项默认值。
编写要暴露成 Web service 的 Java bean。右键点击
Java Resources:src 目录,选择 "New->Class",填写包名
rate、类名 Rate。Java bean 源代码如清单 1 所示,提供了人民币对美元和人民币对欧元的汇率。
清单 1. Java Bean 源代码
|
package rate;
public class Rate {
double RMBtoDollar = 0.1426;
double RMBtoEuro = 0.09026;
String errorMsg = "Input is not correct";
public double getRate(String source, String target) {
if (source.equalsIgnoreCase("RMB")) {
if (target.equalsIgnoreCase("Dollar"))
return RMBtoDollar;
if (target.equalsIgnoreCase("Euro"))
return RMBtoEuro;
}
// any input error, return 0
return 0;
}
} |
将 Java Bean 封装成 Web service。右键点击项目名称
exchange, 选择 "New->Other->Web Services->Web
Service"。设置 Web service 的构建方式,选择 "Bottom Up
Java Bean Web Service"——自底向上(由 Java Bean 生成 WSDL
文件)的构建方式。同时指定 Rate 类作为该 Java Bean,如图 2 所示。点击 "Finish",一个
Web service 便构建成功。在 "...\exchange\WebContent\WEB-INF\wsdl"
目录下可以找到刚刚生成的 Rate.wsdl 文件。wsdl 文件描述了该服务的相关信息,该文件可从附件中下载查看。
图 2. 设置 Web service 构建方式
部署 Web service 到应用服务器。启动应用服务器(这里是 Websphere
Application Server 6.1),加载该动态项目的 EAR 包 exchangeEAR。
3.测试 Web service
利用内嵌在 Rational Application Developer
开发环境中的 Web service 客户端工具 (Web Services Explorer) 测试
RateService 是否工作正常。
首先在 "...\exchange\WebContent\WEB-INF\wsdl"
目录下找到 Rate.wsdl 文件,右键单击该文件选择 "Web Services->Test
with Web Services Explorer",打开客户端测试窗口。
在 "Web Services Explorer"
窗口左侧找到 Rate.wsdl 文件,选中该 Web Service 提供的操作(Operation)——"getRate",窗口右侧出现该服务的详细描述并提供输入界面并显示输出结果。在
source 项中输入 RMB,在 target 项中输入 DOLLAR,得到人民币对美元的汇率 0.1426。这说明
RateService 运行正常,如图 3 所示。
图 3. 使用 Web Services Explorer 测试 Web
service
4.发布 RateService 到 WSRR(WebSphere Service
Registry and Repository)。
最后需要将描述 RateService 的 wsdl 文件 (Rate.wsdl)
上传到 WSRR->WSDL 管理中心,由 WSRR 统一管理,方便用户查找该服务,如图 4 所示。CICS
在 3.2 版本之后于 2008 年上半年发布了支持 WSRR 的工具包,将在下文详细介绍。
图 4. WSRR 发布 RateService
第二步:转账服务的实现
1. 开发环境
开发平台:CICS 3.2 on z/OS, DB2 v8 on z/OS
开发语言:C 语言
2.CICS Web service 相关概念。CICS 对 Web
service 的支持主要通过以下几方面来实现:
CICS 支持 Web service 的相关资源,主要有 PIPELINE、URIMAP、WEBSERVICE、TCPIPSERVICE
等,这些资源能够定义 WebService 的处理过程。
Web Services Assistant 工具,最新的 CICS 3.2
工具包主要由两个程序组成:DFHWS2LS 和 DFHLS2WS。它们在 3.1 的版本上有所增强,提供了更丰富的支持,可支持的语言包括:COBOL、PL/I、C、C++。用户可以通过使用
Web Services Assistant 来快速方便地实现 WebService,也可以通过自己编程完全地控制
CICS 程序和 WebService 接口之间的数据交互。
- DFHWS2LS: 帮助用户把 WSDL 文件中的数据定义映射为 CICS 程序所使用编程语言的数据结构。
- DFHLS2WS: 帮助用户把高级语言编写的 CICS 程序所使用的数据结构转换成 WSDL 定义。
支持 WebService 的 CICS API,例如 INQUIRE
WEBSERVICE, INVOKE WEBSERVICE 等。
此外 CICS 在推出 3.2 版之后又发布了一个独立的工具包 CICS
SupportPac for WSRR,支持 CICS Web service 与 WSRR 的结合使用。这个工具包主要包含两个程序:DFHWS2SR
和 DFHSR2WS。
- DFHWS2SR: 帮助用户来把已有的 wsdl 文件从主机 USS 系统中发布到 WSRR。
- DFHSR2WS: 用来帮助用户把发布在 WSRR 上的 wsdl 文件下载到主机 USS 系统中。
3. 背景分析
转账服务 (TransferService, 下文中两者通用 ) 通常是部署在
CICS 上的一个应用程序,它负责完成各种货币之间的兑换和帐户的转账交易,这是 CICS 应用程序在银行业务中最常见的一种应用。在没有引入
Web service 以前,转账服务必须将有关汇率的处理包含在程序逻辑之内,增加了程序的耦合性。最好的情况也只能封装成
CICS 区域 (region) 上的不同应用程序,通过 CICS 提供的程序之间或区域之间通信的 API
来互相调用。这样一来汇率服务就很难与其他平台和语言编写的程序实现互操作。而 Web service 的引入有效的解决了上述问题,充分实现了服务的可重用性和互操作性。
转账服务的详细处理逻辑:转账服务首先作为 Web service 的服务端
(provider),等待客户端的参数输入。输入包括四个参数:用户名、转账金额、源账户、目标账户。例如:Zhanglin,
100, rmb, dollar 四个参数表示从 zhanglin 的人民币账户中转出 100 元人民币到他的美元账户。转账过程中,需要用到人民币与美元之间的汇率。此时,转账服务转变角色,作为
Web service 的客户端 (requester) 调用 RateService 提供的汇率服务。
4. 开发步骤
下面通过 Web service 封装转账服务的详细步骤,向读者展示 CICS
Web service 的应用,并结合实际应用阐述以上有关 CICS Web service 相关的理论和概念。
转账服务作为 RateService 的客户端 (requester),需要知道
RateService 相关描述,所以必须首先通过 DFHSR2WS 从 WSRR 上下载描述 RateService
的 Rate.wsdl 文件。
在主机上通过提交一个 JCL,指定相关参数,便可以调用 DFHSR2WS
程序,将 Rate.wsdl 文件下载到 USS 系统文件夹下。JCL 源码如清单 2 所示:
清单 2. 调用 DFHSR2WS 下载 Rate.wsdl 文件的
JCL 源代码
|
***************************** Top of Data ******************************
//DSR2WSRT JOB MSGCLASS=H,CLASS=A,NOTIFY=&SYSUID,REGION=0M
//*********************************************************************
//* *
//* DESC : retrieve the wsdl file from WSRR *
//* *
//*********************************************************************
//WSDLREAD JCLLIB ORDER=LIUGUAN.CA1N.JCL
//EXEC EXEC DFHSR2WS,
// JAVADIR='java142s/J1.4',
// WORKDIR='/u/liuguan/install',
// TMPDIR='/tmp',
// TMPFILE='SR2WS'
//INPUT.SYSUT1 DD *
HOSTPORT=http://cicsrts3.hursley.ibm.com:9080
LOCATION=/u/liuguan/userdemo/wsdl/
LOGFILE=/u/liuguan/userdemo/wsdl/wsdlrate.log
NAME=Rate.wsdl
*/
**************************** Bottom of Data ****************************
|
- Dataset "LIUGUAN.CA1N.JCL" 指定了执行 DFHSR2WS
程序所需要的相关资源
- HOSTPORT 指定 WSRR 部署的服务器和端口。
- LOCATION 指定 wsdl 文件存放在 USS 下的具体位置。
- LOGFILE 指定日志文件,记录程序执行成功或失败的相关信息。
- NAME 指明在 WSRR 上要下载的 wsdl 文件名。
上述参数是执行 DFHSR2WS 所必须的,其他参数及有关于 DFHSR2WS
更详细的介绍可以在工具包的帮助文档中查到。
Rate.wsdl 文件成功下载后,即可以通过 CICS 3.2 工具包中的
DFHWS2LS 程序,将 wsdl 文件中描述的输入输出转换成具体语言的数据结构,提供给转账服务程序使用。
调用 DFHWS2LS 仍然通过提交一个 JCL,成功执行后会有两个 member
产生,一个描述服务的输入,另一个描述输出。JCL 的源码如清单 3 所示:
清单 3. 调用 DFHWS2LS 实现 XML 到 data 转换的
JCL 源代码
|
***************************** Top of Data ******************************
//TWS2LS JOB 616,LGJ,MSGLEVEL=(1,1),REGION=0M,NOTIFY=&SYSUID
//*JUSTIN
//*THIS JCL CONVERT WSDL(GET FROM PROVIDER) TO LANGUAGE STRUCTURE
//* AND WSBIND FILE
//*THIS IS A SAMPLE OF WSCELL
//MYPROC JCLLIB ORDER='CTS320.CICS650.SDFHINST'
//JAVAPROG EXEC DFHWS2LS,PATHPREF='',USSDIR='cerbsf'
//STEPLIB DD DSN=CTS320.CICS650.SDFHINST,DISP=SHR
// DD DSN=CNTESTD.CICS.C.SRC,DISP=SHR
//INPUT.SYSUT1 DD *
LOGFILE=/u/liuguan/userdemo/ws2ls/rate.log
PDSLIB=//LIUGUAN.ACICS.WSAT.SOURCE
REQMEM=RATEO
RESPMEM=RATEI
LANG=C
STRUCTURE=(ratestq,ratestr)
WSBIND=/u/liuguan/userdemo/wsclient/wsbind/rateask.wsbind
WSDL=/u/liuguan/userdemo/wsdl/Rate.wsdl
/*
//
**************************** Bottom of Data **************************** |
- Dataset "CTS320.CICS650.SDFHINST" 指定了执行
DFHWS2LS 程序所需要的相关资源。
- PDSLIB 指定输入输出两个 member 产生的位置。
- REQMEM 指定转换输入的数据结构。
- RESPMEM 指定转换输出的数据结构。
- LANG 指定要转换为哪种语言的数据结构。
- WSBIND 指定转账服务在作为 Web service 客户端所需要的相关配置信息,它将会在
PIPELINE 安装时用到。通过 wsbind 文件,真正的语言结构 (Language Structure)
和 SOAP 包中 xml 对于数据结构的定义才能相互对应并转换。
- WSDL 则指定要生成 Language Structure 的 wsdl 文件。
JCL 执行成功后,会在 Dataset "LIUGUAN.ACICS.WSAT.SOURCE"
生成两个 member,RATEO01 和 RATEI01(末尾加上 01 是 DFHWS2LS 的命名规则)。
RATEO01 中存储的是 TransferService 作为 RateService
客户端请求 RateService 时发出的数据结构,源码如清单 4 所示(主机中因为编码的原因 ??(
代表 [,而 ??) 代表 ], 下同):
清单 4. RATEO01 源代码
|
struct ratestq01
{
struct
{
char source??(255??);
char target??(255??);
} getRate;
}; |
RATEI01 则存储的是经过 RateService 处理请求之后返回给
TransferService 的数据结构,源码如下:
清单 5. RATEI01 源代码
|
struct ratestr01
{
struct
{
char getRateReturn??(32??);
} getRateResponse;
}; |
在产生了上述的 wsbind 文件和相应的输入输出数据结构之后,便可以开始
TransferService 代码的编写。TransferService 作为 Web service
的服务端 (provider) 也必须定义输入和输出数据结构两个 member 文件,分别为 TRANSI
和 TRANSO。TRANSI 中的输入结构必须命名为 CMDINPUT,TRANSO 中的输出结构则必须命名为
OUTPUT。根据上文提到的逻辑,输入结构 (CMDINPUT) 中应该有四个值 : 用户名,转账金额,源账户和目标账户,如清单
6 所示。输出结构 (OUTPUT) 中定义账户转账之前和之后的金额两个值,如清单 7 所示。
清单 6. TRANSI 中 CMDINPUT 结构体的定义:
|
struct CMDINPUT
{
char user??(32??);
char sum??(255??);
char source??(255??);
char target??(255??);
} ; |
清单 7. TRANSO 中 OUTPUT 结构体的定义:
|
struct OUTPUT
{
char before??(255??);
char after??(255??);
} ; |
完成上述准备工作,焦点转移到 TransferService 程序的逻辑编写,该程序命名为
TRANSFER。TRANSFER 程序中几段核心的源码介绍如下。
清单 8. CICS DB2 应用接口的声明:
|
EXEC SQL BEGIN DECLARE SECTION;
char dbuser??(11??);
double money = 0;
double rmb_account = 0;
double target_account = 0;
EXEC SQL DECLARE LIUGUAN.USERDEMO TABLE(
USER_NAME CHAR (10) NOT NULL,
RMB_ACCOUNT DOUBLE,
DOLLAR_ACCOUNT DOUBLE,
POUND_ACCOUNT DOUBLE,
EURO_ACCOUNT DOUBLE,
JPY_ACCOUNT DOUBLE,
HKD_ACCOUNT DOUBLE,
TWD_ACCOUNT DOUBLE,
KRW_ACCOUNT DOUBLE
);
EXEC SQL END DECLARE SECTION;
|
清单 8 中,"EXEC SQL BEGIN DECLARE
SECTION" 和 "EXEC SQL END DECLARE SECTION"
之间声明了程序将会连接的数据库表和相关变量,这是 CICS 操作 DB2 的用法,必须在 main 函数前首先声明。从这个
DECLARE SECTION 中可以看到程序将会操作数据库名为 LIUGUAN 下的 USERDEMO
表。该表的结构如 SECTION 所示,已在主机 DB2 中建好。完成相关的声明,在函数内部才能使用 CICS
操作 DB2 的 API。
清单 9. CICS Web service API 的应用:
|
//* put data in the container and send the request to get rate value
EXEC CICS PUT CONTAINER(name_container)
CHANNEL(channel_name)
FLENGTH(sizeof(rateout.getRate))
FROM(rateout.getRate);
//* invoke the web service which provides rate value
EXEC CICS INVOKE WEBSERVICE(webservice)
CHANNEL(channel_name)
OPERATION(operation)
URI(uri)
RESP(respcode)
RESP2(resp2);
//* get the reponse from the container
EXEC CICS GET CONTAINER(name_container)
CHANNEL(channel_name)
INTO(&ratein)
FLENGTH(ratein_len);
ratein.getRateResponse.getRateReturn??(32??) = '\0';
//* transfer from char[] to double
double ratevl = atof(ratein.getRateResponse.getRateReturn);
double rmbvl = atof(ws_input->sum);
double destvl = rmbvl * ratevl;
|
在清单 9 中:
- "EXEC CICS PUT CONTAINER" API 将要发送的请求
(Request) 数据放入 Container 内存数据区。Container 是 CICS 为处理
Web service 定义的概念,它专用于数据结构的存储。
- "EXEC CICS INVOKE WEBSERVICE" API 调用 RateService,将
Container 中的请求数据发送给 RateService。
- RateService 处理完请求并返回 (response) 数据,返回数据仍然存储在先前请求数据所存储的
Container 中。"EXEC CICS GET CONTAINER" API
就是从该 Container 取出返回数据并存入 ratein 变量中。此时 ratein 的值就是相应的汇率值。经过一系列数据类型转换,最后
destvl 变量中存储的就是美元账户中需要新增的数额。
清单 10. CICS DB2 API 的应用:
|
EXEC SQL SELECT DOLLAR_ACCOUNT INTO :target_account
FROM LIUGUAN.USERDEMO
WHERE USER_NAME=:dbuser;
target_account = target_account + destvl;
EXEC SQL UPDATE LIUGUAN.USERDEMO SET
DOLLAR_ACCOUNT=:target_account
WHERE USER_NAME=:dbuser;
EXEC SQL UPDATE LIUGUAN.USERDEMO SET
RMB_ACCOUNT=:rmb_account
WHERE USER_NAME=:dbuser; |
在清单 10 中:
首先从 DB2 中查找到该用户的美元账户余额付给变量 target_account
存储起来;destvl 是计算好的转账金额,新的美元账户需要加上这部分金额;最后在 DB2 中更新该用户的美元和人民币账户。CICS
DB2 API 中的参数要求用冒号 ":" 加变量名来表示,如 :target_account。
CICS 会把这一系列操作作为事务处理,保证其 ACID 的事务特性,即原子性
(Atomic)、一致性 (Consistent)、隔离性 (Isolated)、永久性 (Durable)。TRANSFER
程序的源码在附件中提供了下载。
通过 JCL 调用 C 程序编译器编译 TRANSFER 程序。
在 JCL 中必须指明程序要绑定的 DB2 PLAN,它与之后定义的 CICS
DB2 ENTRY 资源中指定的 PLAN 相同。JCL 执行的最大返回值通常是 4,这说明有警告出现,但可以忽略,视为编译成功。至此,TransferService
相关的程序开发完成。接下来需要在 CICS 区域 (Region) 上定义 TransferService
所需要的所有资源。
5.CICS 上定义 Web service 相关资源 ? 定义 Pipeline:
因为 TransferService 同时充当了 Web service
的 provider 和 requester,所以需要定义两个 PIPELINE 资源。一个作为 requester
处理发送到 RateService 的 soap 包,一个作为 provider 处理客户端发送来的 SOAP
请求。
- CEDA DEF PIPELINE(PIPERATE) G(CNTEST) 定义作为 requester
时使用的 PIPELINE,名为 PIPERATE,置于 CNTEST 组 (GROUP) 下。需要配置三个选项:Configfile,
SHelf 和 Wsdir。Configfile 指明该 PIPELINE 的类别,是作为 requester
使用还是作为 provider 使用;SHelf 指定一个目录存放 PIPELINE 的描述文件;Wsdir
指定 wsbind 文件的位置,如图 5 所示。
图 5. 定义 PIPELINE(PIPERATE)
- CEDA DEF PIPELINE(PIPETRAN) G(CNTEST) 定义作为 provider
时使用的 PIPELINE,名为 PIPETRAN,仍然置于 CNTEST 组 (GROUP) 下。同样需要配置三个选项:Configfile,
SHelf 和 Wsdir。如图 6 所示。
图 6. 定义 PIPELINE(PIPETRAN)
定义 Tcpipservice:
CEDA DEF TCPIPS(TCPTRAN) G(CNTEST) 定义作为
provider 时必须提供的网络服务资源,需要配置两个选项:port 和 portocol。port
指明端口号,protocol 设定协议为 Http。
定义 DB2 Connection:
CEDA DEF DB2C(CONNDBV8) G(CNTEST),定义了名为 CONNDBV8 的 DB2
Connection 并置于组 CNTEST 下。这是任何一个 CICS 程序连接 DB2 数据库,无论是否用到
Web service,都必须指定的。
定义 DB2 Entry:
CEDA DEF DB2E(TEST) G(CNTEST),定义名为 TEST
的 DB2 Entry,同样置于组 CNTEST 下。这也是任何一个 CICS 程序连接 DB2 数据库必须定义的资源。
定义应用程序:
CEDA DEF PROG(TRANSFER) G(CNTEST) 将程序
TRANSFER 定义在 CICS 区域。
通过以上步骤,所有资源的定义完成,最后还需要安装它们。
6. 在 CICS 上安装所有资源:
因为以上定义的资源都置于 CNTEST 组的管理下,因此最简单的安装方式就是直接安装这个组。通过下面这个命令来完成:
CEDA INST GROUP(CNTEST)
至此,部署在 CICS 上的 TransferService 全部完成。
7. 生成 wsdl 文件:
TransferService 部署在 CICS 上,还需要将自己提供的服务以
wsdl 文件的形式发布到 WSRR 上。所以,首先需要利用 CICS 3.2 工具包中的 DFHLS2WS
程序根据 TRANSFER 程序规定的输入输出数据结构生成 wsdl 文件。用 JCL 调用 DFHLS2WS
的源码如清单 11 所示:
清单 11. 调用 DFHLS2WS 生成 wsdl 文件的 JCL
源代码:
|
***************************** Top of Data *************************
//LS2WS1 JOB (WINMVS,LIUGUAN),MSGCLASS=H,
// CLASS=A,NOTIFY=&SYSUID,REGION=0M
//*
//MYPROC JCLLIB ORDER='CTS320.CICS650.SDFHINST'
//LS2WS EXEC DFHLS2WS,
// PATHPREF='',TMPFILE='LIUGUAN',
// USSDIR='cerbsf'
//STEPLIB DD DSN=CTS320.CICS650.SDFHINST,DISP=SHR
// DD DSN=LIUGUAN.ACICS.WSAT.SOURCE,DISP=SHR
//INPUT.SYSUT1 DD *
LOGFILE=/u/liuguan/userdemo/wsserver/transfer.log
PDSLIB=//LIUGUAN.ACICS.WSAT.SOURCE
REQMEM=TRANSI
RESPMEM=TRANSO
LANG=C
PGMNAME=TRANSFER
STRUCTURE=(CMDINPUT,OUTPUT)
URI=transfer
PGMINT=COMMAREA
WSBIND=/u/liuguan/userdemo/wsserver/wsbind/transf.wsbind
WSDL=/u/liuguan/userdemo/wsdl/transfer.wsdl
/*
**************************** Bottom of Data ********************** |
PDSLIB 表示输入输出定义的 member 所在的 dataset。
REQMEM 表示输入结构定义的 member。RESPMEM 表示输出结构定义的
member。
LANG 指定编程语言的类型。
PGMNAME 指定提供 Web service 的程序。
URI 指定作为 service provider 端使用的链接标识。
PGMINT 是作为 service provider 端必须指定的参数,表示用什么资源来存储
SOAP 请求中的数据格式转换为编程语言的数据结构。有 COMMAREA 和 CHANNEL 两种方式。
WSBIND 和 WSDL 两个参数的意义同上文 DFHWS2LS。
JCL 执行成功之后,可在主机 USS 的 /u/liuguan/userdemo/wsdl
目录下产生 transfer.wsdl 文件。
8. 发布 TransferService 到 WSRR
最后利用 CICS SupportPac for WSRR 工具包中的
DFHWS2SR 将该文件发布到 WSRR 上,JCL 调用 DFHWS2SR 的源码如清单 12 所示。JCL
执行成功,可在浏览器 WSRR 控制台下看到 transfer.wsdl 文件。客户可以通过该文件获取
TransferService 的相关信息,并调用转账服务完成自己的业务逻辑。
清单 12. 调用 DFHWS2SR 发布 wsdl 文件到 WSRR
的 JCL 源代码:
|
***************************** Top of Data **********************
//DWS2SR01 JOB (MYSYS,AUSER),MSGCLASS=H,
// CLASS=A,NOTIFY=&SYSUID,REGION=0M
//WSDLPUB JCLLIB ORDER=LIUGUAN.CA1N.JCL
// EXEC DFHWS2SR,
// JAVADIR='java142s/J1.4',
// WORKDIR='/u/liuguan/install',
// TMPDIR='/tmp',
// TMPFILE='WS2SR'
//INPUT.SYSUT1 DD *
HOSTPORT=http://cicsrts3.hursley.ibm.com:9080
LOGFILE=/u/liuguan/wsrrtest/log/transfer.log
LOCATION=/u/liuguan/userdemo/wsdl/transfer.wsdl
NAME=TRANSFER
*/
**************************** Bottom of Data ******************** |
第三步:网上银行调用转账服务
1. 开发环境
开发平台:Windows 操作系统,IBM Rational Application
Developer 7.0.0( 内置 Websphere Application Server 6.1)
开发语言:Java
2.开发实例
最后给出一个简单的例子,用 Struts 框架实现客户登录网上银行并转账的
web 应用程序。当然,基于 Web service 跨平台、互操作性强的特点,用户可以使用其他任何平台、任何语言来实现网上银行,调用
CICS 提供的转账服务。网上银行有关页面显示和访问主机 DB2 数据库的代码不再赘述,和其他 web
应用程序一样。这里要给出的是在 Action 里完成业务逻辑时,如何调用 CICS 上部署的 TransferService.
首先从 WSRR 上下载 transfer.wsdl 文件,通过该文件在
RAD 集成环境中生成 Web service 客户端框架。生成的代码如图 7 所示:
图 7. TransferService 客户端框架代码结构
然后在 Action 中编写调用 TransferService 的代码如清单
13:
清单 13. 调用 TransferService:
|
// 创建客户端代理对象,通过该对象调用 TransferService
TRANSFERPortProxy sampleTRANSFERPortProxy = new TRANSFERPortProxy();
// 创建 request 对象,即 TransferService 的输入
Cmdinput cmdinput = new Cmdinput();
// 从页面获取用户对象
String user = (String) request.getSession().getAttribute("user");
tform.setUser(user);
// 将用户页面输入的信息封装进 request 对象
cmdinput.setUser(tform.getUser());
cmdinput.setSum(tform.getAmount());
cmdinput.setSource(tform.getSource());
cmdinput.setTarget(tform.getTarget());
// 创建 response 对象,即 TransferService 的输出
Output output = new Output();
// 通过客户端代理对象调用 TransferService 提供的服务操作 TransferOperation,将 request 对象作为参数传入
output = sampleTRANSFERPortProxy.TRANSFEROperation(cmdinput);
|
程序部署在 WAS6.1 上。成功启动服务器后,通过浏览器访问此 web
应用程序,可以看到模拟的网上银行页面,如图 8 所示,网上银行创建成功。
图 8. 网上银行登录页面
3.网上银行运行效果演示
输入用户名和密码,进入网上银行转账页面,该页面显示了用户当前各币种账户的余额。如图
9 所示:
图 9. 网上银行转账页面
在页面上选定源账户 (Source)、目标账户 (Target),输入转账金额
(Amount),并提交便可完成转账业务。转账信息如图 10 所示:
图 10. 网上银行转账结果显示
图 10 所示页面表示用户转账操作成功,也同时意味着网上银行成功调用 CICS
提供的 TransferService。至此,CICS 应用程序作为 Web service 的 requester
和 provider 都成功编写。
结束语
通过引入 SOA 架构的思想,将 CICS 上原本耦合性很强的转账服务拆分成汇率服务和转账服务。通过
Web service 实现了这些服务的封装及其互操作以及与其他任意平台任意语言的应用程序进行互操作,极大的提高了程序的扩展性与可重用性。本文通过模拟客户转账的经典应用,介绍了
CICS Web service 的相关概念和具体用法。相信通过本文,有一定主机和 Web service
经验的初级用户也可以自己开发出 CICS 上的 Web service 程序。 |