Program: CALCPRC – This program sits in library MYRXS and waits to be executed by Apache.
//*******************************************************************************************
// @Author: Aaron Bartell
// @Created: 2007-04-13
// @Desc:
// @Notes:
// Inbound XML
//<?xml version="1.0" encoding="utf-8"?>
//<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
// <soap:Body>
// <calcPriceRequest>
// <item id="HDR4423" />
// <customer id="123" />
// </calcPriceRequest>
// </soap:Body>
//</soap:Envelope>
//*******************************************************************************************
H dftactgrp(*no) bnddir('RXSBND')
/copy rxs,RXSCp
D calcPrc pr 15p 2
D pCstId 10a value
D pItmId 10a value
D allHandler pr
D pType value like(RXS_Type)
D pXPath value like(RXS_XPath)
D pData value like(RXS_XmlData)
D pDataLen value like(RXS_Length)
D errHandler pr
D pCurLine 10i 0 value
D pCurCol 10i 0 value
D pErrStr 1024a value varying
// Location of data after being parsed out of xml
D gCalcPrcReq ds qualified inz
D custId 10a
D itemId 10a
D gError ds likeds(RXS_Error) inz
D gXml s 65535a varying
D gPrc s 15p 2
/free
monitor;
clear gError;
reset gCalcPrcReq;
//
// Read in XML from standard input (i.e. Apache)
//
gXml = RXS_readStdIn();
//
// Parse XML
//
RXS_allAttrHandler(%paddr(allHandler));
RXS_parse(gXml: RXS_VAR: %paddr(errHandler));
if gError.code <> *blanks;
RXS_stdOutError('error': gError: *on);
return;
endif;
//
// Call business logic to get price
//
gPrc = calcPrc(gCalcPrcReq.custId: gCalcPrcReq.itemId);
//
// Compose xml response
//
RXS_initTplEng(RXS_STDOUT: *omit: *omit: *omit: *omit: *off);
RXS_loadTpl('calcprc.tpl');
RXS_updVar('amount': %char(gPrc));
RXS_wrtSection('calcPriceResponse': *on);
on-error;
RXS_stdOutError('error': RXS_catchError(): *on);
endmon;
*inlr = *on;
/end-free
//--------------------------------------------------------------------------------------------
// @Author: Aaron Bartell
// @Created: 2007-04-13
// @Desc: Normally this would be in a separate RPG service program but was included here for
// sake of simplicity.
//--------------------------------------------------------------------------------------------
P calcPrc B
D calcPrc PI 15p 2
D pCstId 10a value
D pItmId 10a value
/free
if pCstId = '111';
return 111.45;
else;
return 222.45;
endif;
/end-free
P E
//--------------------------------------------------------------------------------------------
// @Author: Aaron Bartell
// @Created: 2007-04-13
// @Desc: This local sub procedure will be called for each attribute event that occurs during
// the parsing of the SOAP document. Based on the event this sub procedure is being
// notified of it will place the value in the appropriate global variable.
//--------------------------------------------------------------------------------------------
P allHandler b
D allHandler pi
D pType value like(RXS_Type)
D pXPath value like(RXS_XPath)
D pData value like(RXS_XmlData)
D pDataLen value like(RXS_Length)
D baseEnv s like(RXS_XPath)
/free
baseEnv = '/soap:Envelope/soap:Body/calcPriceRequest';
select;
when pXPath = baseEnv + '/customer@id';
gCalcPrcReq.custId = pData;
when pXPath = baseEnv + '/item@id';
gCalcPrcReq.itemId = pData;
endsl;
/end-free
P e
//--------------------------------------------------------------------------------------------
// @Author: Aaron Bartell
// @Created: 2007-04-13
// @Desc: If an error occurs this local sub procedure will be called by the parser.
//--------------------------------------------------------------------------------------------
P errHandler B
D errHandler PI
D pCurLine 10i 0 value
D pCurCol 10i 0 value
D pErrStr 1024a value varying
/free
gError.code = 'RXS3.1';
gError.severity = 100;
gError.pgm = 'RXS3.errHandler';
gError.text =
'Line:' + %char(pCurLine) +
' Column:' + %char(pCurCol) +
' ' + pErrStr;
/end-free
P E
File: /www/myrxs/templates/calcprc.tpl
/$calcPriceResponse
Content-type: text/xml
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns1:calcPriceResponse xmlns:ns1="http://ABCCompany.com/OrderServices/">
<price amount="/%amount%/" />
</ns1:calcPriceResponse>
</soap:Body>
</soap:Envelope>
File: /www/myrxs/htdocs/orderservices.wsdl (by placing this document in htdocs it is available via HTTP on your System i5, meaning a .NET programmer could easily use this WSDL to consume your RPG-XML Suite web service)
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions xmlns:hh="http://ABCCompany.com/OrderServices/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="OrderServices" targetNamespace="http://ABCCompany.com/OrderServices/">
<wsdl:types>
<xsd:schema targetNamespace="http://ABCCompany.com/OrderServices/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="calcPriceResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="price">
<xsd:complexType>
<xsd:attribute name="amount" type="xsd:double" use="required"></xsd:attribute>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="calcPriceRequest">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="item">
<xsd:complexType>
<xsd:attribute name="id" type="xsd:string" use="required"></xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:element name="customer">
<xsd:complexType>
<xsd:attribute name="id" type="xsd:string" use="required"></xsd:attribute>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</wsdl:types>
<wsdl:message name="calcPriceResponse">
<wsdl:part element="hh:calcPriceResponse" name="calcPriceResponse"/>
</wsdl:message>
<wsdl:message name="calcPriceRequest">
<wsdl:part element="hh:calcPriceRequest" name="calcPriceRequest"/>
</wsdl:message>
<wsdl:portType name="OrderServices">
<wsdl:operation name="calcPrice">
<wsdl:input message="hh:calcPriceRequest"/>
<wsdl:output message="hh:calcPriceResponse"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="OrderServicesSOAP" type="hh:OrderServices">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="calcPrice">
<soap:operation soapAction="http://ABCCompany.com/OrderServices/NewOperation"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="OrderServices">
<wsdl:port binding="hh:OrderServicesSOAP" name="OrderServicesSOAP">
<soap:address location="http://192.168.0.11:8181/myrxs/calcprc"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
C#.NET program consuming web service CALCPRC. Use this code AFTER you have added the above WSDL as a Web Reference in your Visual Studio environment.
using System;
using System.Collections.Generic;
using com.abccompany;
namespace abccompany
{
class MainClass
{
public static void Main(string[] args)
{
// Create customer
calcPriceRequestCustomer cpReqCust = new calcPriceRequestCustomer();
cpReqCust.id = "111";
// Create item
calcPriceRequestItem cpReqItem = new calcPriceRequestItem();
cpReqItem.id = "HAE332";
// Create price request and fill it with the customer and item objects.
calcPriceRequest cpReq = new calcPriceRequest();
cpReq.customer = cpReqCust;
cpReq.item = cpReqItem;
// Execute the web service on the iSeries
OrderServices os = new OrderServices();
calcPriceResponse cpRsp = os.calcPrice(cpReq);
calcPriceResponsePrice cpRspPrc = cpRsp.price;
Console.WriteLine("price:" + cpRspPrc.amount);
Console.Read();
}
}
}