几年来,RPG程序员已经能够使用wsdl2ws.sh工具发出的C存根调用Web服务。 但是,在RPG应用程序中使用C存根的过程很麻烦。 程序员需要执行以下步骤:
将C结构映射到RPG结构。 添加用于服务接口功能和操作的RPG原型。
根据WSDL文件的复杂性,第一步可能是一场噩梦。
并说您完成了上述步骤,您仍然必须处理指针并担心内存泄漏!
RPG程序员很高兴。 IBM增强了wsdl2ws.sh工具,以便用户能够生成RPG存根。 本文提供了一个简单的示例,说明如何使用wsdl2ws.sh工具生成的RPG存根代码创建用ILE RPG编写的Web服务客户端应用程序。
先决条件
软件
表1列出了IBM i操作系统的每个受支持版本所需要的PTF。
表1.软件先决条件
我6.1
我5.4
IBM i发布 PTFs
我7.1 SI43607 SI43608 SI43609
假设条件
由于该示例依赖于ConvertTemp服务,因此您可能要按照学习Web服务服务器中所述创建一个Web服务服务器 (创建Web服务服务器时,不需要部署Web服务,我们将使用示例Web创建服务器时自动部署的服务)。 否则,运行该应用程序将导致错误。
注意 :ILE的Web服务客户端的安装目录是/QIBM/ProdData/OS/WebServices/V1/client 。 在本文中,安装目录显示为<install_dir> 。
创建使用RPG存根代码的RPG应用程序
要开发Web服务客户端应用程序,应遵循以下步骤:
使用wsdl2ws.sh命令生成客户机Web服务存根。 生成客户端应用程序。 运行客户端应用程序。
以下各节将讨论每个步骤。 为了便于说明,我们将使用产品随附的示例代码在目录<install_dir>/samples/ConvertTemp 。 表2中列出了我们将使用的文件,这些文件包含在“ 下载”部分的样本下载中。
表2.示例中使用的文件
文件 描述
ConvertTemp.wsdl WSDL文件。 ConvertTempClientWSDL2RPG.RPGLE 用RPG编写的客户端实现代码。
清单1中显示的WSDL文件用于温度转换服务,该服务将温度从华氏温度转换为摄氏温度。 定义了两个操作:
转换温度 converttemp_XML
converttemp操作以摄氏度为converttemp_XML返回温度,而converttemp_XML操作以XML文档形式返回结果。 请注意,清单1提供了此服务的WSDL的局部视图,仅显示了converttemp操作中涉及的部分,这是我们将在RPG应用程序中使用的操作。
清单1. WSDL定义
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions xmlns:wsdl=http://schemas.xmlsoap.org/wsdl/
xmlns:ns1="http://org.apache.axis2/xsd"
xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:ns0="http://converttemp.wsbeans.iseries/xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
targetNamespace="http://converttemp.wsbeans.iseries">
<wsdl:types>
<xs:schema xmlns:ns="http://converttemp.wsbeans.iseries/xsd"
attributeFormDefault="qualified" elementFormDefault="qualified"
targetNamespace="http://converttemp.wsbeans.iseries/xsd">
...
<xs:complexType name="CONVERTTEMPInput">
<xs:sequence>
<xs:element minOccurs="0" name="_TEMPIN" nillable="true" type="xs:string"/>
</xs:sequence>
<xs:complexType>
...
<xs:element name="converttemp">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="param0" nillable="true"
type="ns:CONVERTTEMPInput"/>
</xs:sequence>
<xs:complexType>
</xs:element>
<xs:element name="converttempResponse">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="return" nillable="true"
type="ns:CONVERTTEMPResult"/>
</xs:sequence>
<xs:complexType>
</xs:element>
<xs:complexType name="CONVERTTEMPResult">
<xs:sequence>
<xs:element minOccurs="0" name="_TEMPOUT" nillable="true"
type="xs:string"/>
</xs:sequence>
<xs:complexType>
</xs:schema>
</wsdl:types>
...
<wsdl:message name="converttempRequest">
<wsdl:part name="parameters" element="ns0:converttemp"/>
</wsdl:message>
<wsdl:message name="converttempResponse">
<wsdl:part name="parameters" element="ns0:converttempResponse"/>
</wsdl:message>
<wsdl:portType name="ConvertTempPortType">
<wsdl:operation name="converttemp_XML">
<wsdl:input message="axis2:converttemp_XMLRequest"
wsaw:Action="urn:converttemp_XML"/>
<wsdl:output message="axis2:converttemp_XMLResponse"
wsaw:Action="urn:converttemp_XMLResponse"/>
</wsdl:operation>
<wsdl:operation name="converttemp">
<wsdl:input message="axis2:converttempRequest" wsaw:Action="urn:converttemp"/>
<wsdl:output message="axis2:converttempResponse"
wsaw:Action="urn:converttempResponse"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="ConvertTempSOAP11Binding" type="axis2:ConvertTempPortType">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
<wsdl:operation name="converttemp_XML">
<soap:operation soapAction="urn:converttemp_XML" style="document"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="converttemp">
<soap:operation soapAction="urn:converttemp" style="document"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="ConvertTemp">
<wsdl:port name="ConvertTempSOAP11port_http"
binding="axis2:ConvertTempSOAP11Binding">
<soap:address location="http://localhost:10022/web/services/ConvertTemp"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
步骤1.创建客户端存根代码
在创建Web服务客户端应用程序之前,必须首先使用wsdl2ws.sh工具生成RPG客户端存根。 wsdl2ws.sh工具使用传递给它的WSDL文件以及WSDL文件中引用的任何相关XSD文件来创建客户机存根。
要从WSDL源文件生成客户机存根,请完成以下步骤。
创建一个名为CVTTEMP的库,通过从CL命令行发出CL命令CRTLIB来存储程序对象,如下所示: CRTLIB CVTTEMP 通过从CL命令行发出QSH CL命令来启动Qshell会话。 运行wsdl2ws.sh工具来生成客户机RPG存根代码,如以下示例所示: <install_dir>/bin/wsdl2ws.sh -o/convtemp/RPG -lrpg -s/qsys.lib/cvttemp.lib/wsrpg.srvpgm<install_dir>/samples/ConvertTemp/ConvertTemp.wsdl
如果检查该命令,则会看到我们正在向wsdl2ws.sh工具指示应生成RPG存根代码并将其存储在目录/convtemp/RPG ,并且指示服务程序/qsys.lib/cvttemp.lib/wsrpg.srvpgm ,应使用生成的存根代码创建。
清单2显示了wsdl2ws.sh工具生成的文件:
清单2.生成的存根文件
ConvertTempPortType_util.rpgle
ConvertTempPortType_util.rpgleinc
ConvertTempPortType_xsdtypes.rpgleinc
ConvertTempPortType.c
ConvertTempPortType.cl
ConvertTempPortType.h
ConvertTempPortType.rpgle
ConvertTempPortType.rpgleinc
CONVERTTEMPInput.c
CONVERTTEMPInput.h
CONVERTTEMPResult.c
CONVERTTEMPResult.h
请注意,除了生成RPG存根代码外,还生成了C存根代码,因为RPG存根代码是建立在C存根代码之上的。 出于所有实际目的,可以忽略C存根代码。
这是每个生成的RPG文件的描述:
ConvertTempPortType_util.rpgle – RPG实用程序例程。 ConvertTempPortType_util.rpgleinc –包括RPG实用程序例程。 ConvertTempPortType_xsdtypes.rpgleinc –包括标准数据类型。 ConvertTempPortType.rpgle – RPG Web服务实现代码。 ConvertTempPortType.rpgleinc – RPG Web服务包括。
从RPG程序员的角度来看,您需要查看的唯一文件是
ConvertTempPortType.rpgleinc和ConvertTempPortType_xsdtypes.rpgleinc文件。 除了Web服务操作之外, ConvertTempPortType.rpgleinc文件还定义了RPG函数以创建和销毁Web服务接口对象。 文件中还定义了Web服务操作所需的任何类型。 ConvertTempPortType_xsdtypes.rpgleinc文件定义所有原始类型和各种常量。
清单3显示了ConvertTempPortType.rpgleinc文件。
清单3. ConvertTempPortType.rpgleinc文件
* ********************************************************************
* ********************************************************************
* D A T A T Y P E S
* ********************************************************************
* ********************************************************************
D CONVERTTEMPInput_t...
D DS qualified based(Template)
D isNil_CONVERTTEMPInput_t...
D 1n
D TEMPIN likeds(xsd_string)
D CONVERTTEMPResult_t...
D DS qualified based(Template)
D isNil_CONVERTTEMPResult_t...
D 1n
D TEMPOUT likeds(xsd_string)
* ********************************************************************
* ********************************************************************
* P R O T O T Y P E S
* ********************************************************************
* ********************************************************************
* ********************************************************************
* WEB SERVICE CLIENT STUB PROTOTYPES
* ********************************************************************
* **************************************************************
* RPG Call : stub_create_ConvertTempPortType
* **************************************************************
D stub_create_ConvertTempPortType...
D PR 1N extproc('stub_create_ConvertTempPo+
D rtType@')
D this likeds(This_t)
* **************************************************************
* RPG Call : stub_destroy_ConvertTempPortType
* **************************************************************
D stub_destroy_ConvertTempPortType...
D PR 1N extproc('stub_destroy_ConvertTempP+
D ortType@')
D this likeds(This_t)
* ********************************************************************
* WEB SERVICE OPERATION PROTOTYPES
* ********************************************************************
* **************************************************************
* RPG call : stub_op_converttemp_XML
* **************************************************************
D stub_op_converttemp_XML...
D PR 1N extproc('converttemp_XML@')
D this likeds(This_t)
D Value0 likeds(CONVERTTEMPInput_t)
D out likeds(xsd_string)
* **************************************************************
* RPG call : stub_op_converttemp
* **************************************************************
D stub_op_converttemp...
D PR 1N extproc('converttemp@')
D this likeds(This_t)
D Value0 likeds(CONVERTTEMPInput_t)
D out likeds(CONVERTTEMPResult_t)
在检查清单3时,请注意以下几点:
ConvertTemp.wsdl仅具有一项称为ConvertTemp服务。 该服务只有一种端口类型,称为ConvertTempPortType 。 ConvertTempPortType端口类型具有两个操作,分别称为converttemp和converttemp_XML 。 相应的RPG存根操作(在生成的ConvertTempPortType.rpgleinc包含文件中定义)是stub_op_converttemp()和stub_op_converttemp_XML() 。 该Web服务称为ConvertTempPortType 。 因此,要获取Web服务的实例,您可以调用stub_create_ConvertTempPortType ()函数。 然后,在调用Web服务操作时应使用该函数返回的句柄。 要销毁该Web服务实例,可以调用stub_destroy_ConvertTempPortType ()函数。 (这两个函数都在生成的ConvertTempPortType.rpgleinc包含文件中定义。)
最后,还会生成文件ConvertTempPortType.cl 。 该文件是一个CL源文件,其中包含重新创建包含存根代码的服务程序所需的CL命令。 您可以将此源文件复制到源物理文件并创建一个CL程序。
步骤2.构建客户端应用程序
生成客户端存根之后,可以使用存根创建Web服务客户端应用程序。
清单4显示了使用已创建的RPG存根来调用converttemp Web服务操作的RPG客户端应用程序。
清单4.使用生成的RPG存根的RPG应用程序
h DFTNAME(CVTTEMP)
*
/copy ConvertTempPortType.rpgleinc
d OutputText s 50
d WsStub ds likeds(This_t)
d Input ds likeds(CONVERTTEMPInput_t)
d Result ds likeds(CONVERTTEMPResult_t)
*--------------------------------------------------------------------
* Program entry point. The input parameter is a character field
* representing the temperature in Fahrenheit.
*--------------------------------------------------------------------
C *ENTRY PLIST
C PARM TEMPIN 32
*--------------------------------------------------------------------
* Web service logic. The code will attempt to invoke a Web
* service in order to convert temperature in Fahrenheit to Celsius
* and then display the results.
*--------------------------------------------------------------------
/free
// Get a Web service stub. The host and port for the endpoint may need
// to be changed to match host and port of Web service. Or you can pass
// blanks and endpoint in the WSDL file will be used.
clear WsStub;
WsStub.endpoint = 'http://localhost:10000/web/services/ConvertTemp';
clear input;
Input.TEMPIN.value = %trim(TEMPIN);
if (stub_create_ConvertTempPortType(WsStub) = *ON);
// Invoke the ConvertTemp Web service operation.
if (stub_op_ConvertTemp(WsStub:Input:Result) = *ON);
OutputText = Input.TEMPIN.value + ' Fahrenheit is '
+ Result.TEMPOUT.value + ' Celsius.';
else;
OutputText = WsStub.excString;
endif;
// Display results.
dsply OutputText;
// Destroy Web service stubs.
stub_destroy_ConvertTempPortType(WsStub);
endif;
*INLR=*ON;
/end-free
要构建客户端应用程序,请完成以下步骤。
将当前工作目录更改为RPG存根代码的位置。 从CL命令行发出以下命令: cd '/convtemp/RPG' 通过从CL命令行发出以下命令,将使用产品示例目录生成的存根代码的示例RPG代码复制到当前工作目录: COPY OBJ('<install_dir>/samples/ConvertTemp/ConvertTempClientWSDL2RPG.RPGLE') TODIR('/convtemp/RPG') 如果已创建Web服务服务器,则在上一步中复制的文件中更改端点的服务器名称和端口号,以匹配服务器和服务器中安装的ConvertTemp Web服务的端口。 文件中的端点是: 'http://localhost:10000/web/services/ConvertTemp' 通过从CL命令行使用以下命令来构建客户端应用程序: CRTRPGMOD MODULE(CVTTEMP/CNVRTTEMP) SRCSTMF('/convtemp/RPG/ConvertTempClientWSDL2RPG.rpgle') CRTPGM PGM(CVTTEMP/CNVRTTEMP) MODULE(CVTTEMP/CNVRTTEMP) BNDSRVPGM(QSYSDIR/QAXIS10CC CVTTEMP/WSRPG)
步骤3.运行客户端应用程序
完成编码和构建Web服务客户端应用程序后,运行并测试客户端应用程序。 通过从CL命令行发出以下命令来运行客户端应用程序(在此示例中,我们要找出摄氏5度是多少摄氏度):
CALL CVTTEMP/CNVRTTEMP '5'
检查客户端应用程序是否显示上面使用的华氏值的摄氏度表示。 下面的图1中的示例屏幕快照显示了从命令行运行的客户端应用程序(请注意,要查看结果,您需要按“ F10 =包括详细消息”功能键):
图1.调用客户端应用程序
摘要
从RPG程序员不得不弄清楚如何使用C Web服务存根开始,生成RPG Web服务存根的能力是一个巨大的飞跃。 那你还在等什么?
资料下载
ConvertTemp.wsdl
ConvertTempClientWSDL2RPG.RPGLE
翻译自: https://www.ibm.com/developerworks/ibmi/library/i-amrawsdl2rpg/index.html
相关资源:JAVA上百实例源码以及开源项目