RPG-XML Suite Web Service Program: DVA
Invoked by calling http://<i5 IP>:8181/myrxs/dva
//*******************************************************************************************
// @Author: Aaron Bartell
// @Created: 2005-08-23
// @Desc: This RPG-XML Suite web service is used by third parties to gain insight to what
// you have for items inventoried. Multiple item inventory requests can be made in
// a single web service call. Store each detail item in array gDtl as it is parsed,
// then turn around and compose the response XML by reading through the gDtl array and
// look for matches in PF INVITM (dow loop).
// Use the Web Service Test client (PC app) to call.
// @Notes:
//*******************************************************************************************
H dftactgrp(*no) bnddir('RXSBND')
FINVITM if a e k disk prefix('II.')
D II e ds qualified extname(INVITM)
/copy rxs,RXSCp
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
D errRsp pr
// Location of data after being parsed out of xml
D gDVA ds qualified inz
D msgTyp 2a
D sndrId 20a
D reqLocId 20a
D trnId 20a
D reqDt d
D reqTm t
D tmCd 2a
D gDtl ds qualified inz dim(500)
D prdQlf 2a
D prd 45a
D qty 9S 0
D uom 2a
D gDtlCnt s 10i 0
D gError ds likeds(RXS_Error) inz
D gXml s 65535a varying
D gSndHdr s n
D gBaseEnv s 70a varying
D i s 10i 0
/free
monitor;
clear gError;
// Prefill the base XML envelope for ease of element reference
gBaseEnv = '/DirectVendorAccess/Details/Detail';
gSndHdr = *on;
gDtlCnt = 0;
gXml = RXS_readStdIn();
exsr parse;
if gError.code <> *blanks;
RXS_stdOutError('error': gError: *on);
return;
endif;
exsr compose;
on-error;
RXS_stdOutError('error': RXS_catchError(): *on);
endmon;
*inlr = *on;
//--------------------------------------------------------------------------------------------
// @Author: Aaron Bartell
// @Created: 2007-06-13
// @Desc: Setup event handlers and invoke the parser.
//--------------------------------------------------------------------------------------------
begsr parse;
monitor;
// Add event handler notifications for the begin <Detail> tag so we
// can appropriately increment a counter to prepare the next row in
// the gDtl array.
RXS_addHandler(gBaseEnv + '>': %paddr(allHandler));
// Tell the parser we want to be notified of all element content
// events.
RXS_allElemContentHandler(%paddr(allHandler));
// Invoke the parser (see local sub proc allHanlder below)
RXS_parse(gXml: RXS_VAR: %paddr(errHandler));
on-error;
gError = RXS_catchError();
endmon;
endsr;
//--------------------------------------------------------------------------------------------
// @Author: Aaron Bartell
// @Created: 2007-06-13
// @Desc: Initialize the RPG-XML Suite Template Engine and write out the beginning root tags
// and HTTP headers.
//--------------------------------------------------------------------------------------------
begsr compose;
// Initialize the template engine
RXS_initTplEng(RXS_STDOUT: *omit: *omit: *omit: *omit: *off);
RXS_loadTpl('directvendoraccess.tpl');
RXS_wrtSection('HTTP_HEAD');
// Compose XML header elements and values.
RXS_updVar('MessageType': gDVA.msgTyp);
RXS_updVar('SenderID': gDVA.sndrId);
RXS_updVar('RequestorLocationID': gDVA.reqLocId);
RXS_updVar('TransactionID': gDVA.trnId);
RXS_updVar('ResponseDate': %char(%date()));
RXS_updVar('ResponseTime': %char(%time()));
RXS_updVar('TimeCode': gDVA.tmCd);
RXS_updVar('IDCode': '');
RXS_updVar('HeaderErrorCode': '');
RXS_updVar('HeaderErrorDesc': '');
RXS_wrtSection('DirectVendorAccess_beg');
// Go through each detail item and read through INVITM for each.
for i = 1 to gDtlCnt;
RXS_updVar('ProductQualifier': gDtl(i).prdQlf);
RXS_updVar('Product': gDtl(i).prd);
RXS_updVar('QuantityRequested': %char(gDtl(i).qty));
RXS_updVar('UnitOfMeasure': gDtl(i).uom);
RXS_updVar('DetailErrorCode': '');
RXS_updVar('DetailErrorDesc': '');
RXS_wrtSection('Detail_beg');
RXS_wrtSection('ResponseDetails_beg');
setll gDtl(i).prd INVITM;
reade gDtl(i).prd INVITM;
dow not %eof(INVITM);
RXS_updVar('LocationID': II.LOCID);
RXS_updVar('ProductQualifier': II.PRDQLF);
RXS_updVar('Product': II.PRD2);
RXS_updVar('UnitOfMeasure': II.UOM);
RXS_updVar('DateAvailable': %char(II.DTAVL));
RXS_updVar('AvailableCutOffTime': %char(II.AVLCOT));
RXS_updVar('CityName': II.CTYNAM);
RXS_updVar('StateCode': II.STTCD);
RXS_updVar('CountryCode': II.CTRYCD);
RXS_updVar('PostalCode': II.PSTCD);
RXS_updVar('AvailableQty': %char(II.AVLQTY));
RXS_updVar('PriceType': II.PRCTYP);
RXS_updVar('Price': %char(II.PRC));
RXS_updVar('MeasurementQualifier': II.MSMNTQLF);
RXS_updVar('MeasurementValue': %char(II.MSMNTVAL));
RXS_wrtSection('ResponseDetail');
reade gDtl(i).prd INVITM;
enddo;
RXS_wrtSection('ResponseDetails_end');
RXS_wrtSection('Detail_end');
endfor;
RXS_updVar('CntOfItmsRtrnd': %char(gDtlCnt));
RXS_updVar('CntOfItmsRtrndByLoc': '');
RXS_wrtSection('DirectVendorAccess_end': *on);
endsr;
/end-free
//--------------------------------------------------------------------------------------------
// @Author: Aaron Bartell
// @Created: 2007-06-13
// @Desc: This local sub procedure will be called for each element content event and <Detail>
// begin and end tag that occurs during the parsing of the PostAdr document. Based on the event this sub
// procedure is being notified of it will place the value in the appropriate global
// variable.
// @Notes: There are four events that your program can be notified of through the allHandler
// sub procedure and they are passed in the pEvntType parm. An event is triggered
// as the parser reads the document top down, left to right (same way you read the
// newspaper). Note that you will only be notified of events you specified before the
// call to RXS_parse by using API's RXS_allElemBegHandler, RXS_allElemContentHandler,
// RXS_allElemEndHandler, and RXS_allAttrHandler.
//
// The four events and their values (note that these can all be overidden by
// changing the RXSCFG file or by doing a temporary override on the RXS_parse command)
//
// Element Begin = '>' -- Placed at end of string (i.e. '/elem>')
// Element Content = '/' -- Placed at end of string (i.e. '/elem/')
// Element End = '/>' -- Placed at end of string (i.e. '/elem/>')
// Attribute = '@' -- Placed between the elem and attr (i.e. '/elem@attr')
//
// The most common events you will use are Element Content and Attribute simply
// because these are the two that provide business data via the pData parm on the
// allHandler procedure interface. Events Element Begin and Element End are very
// helpful when you have repeating XML data. You can then use the Begin and End
// events to do a CLEAR and WRITE to a PF record respectively. Remember that
// in-between the Element Begin and Element End events you will be notified of all the
// element content, which means that after the CLEAR (i.e. Element Begin event) you
// can place data into the PF record until you reach the Element End event at which
// time you can do a WRITE of that record because it has now been populated with data.
//--------------------------------------------------------------------------------------------
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)
/free
select;
when pXPath = '/DirectVendorAccess/MessageType/';
gDVA.msgTyp = pData;
when pXPath = '/DirectVendorAccess/SenderID/';
gDVA.sndrId = pData;
when pXPath = '/DirectVendorAccess/RequestorLocationID/';
gDVA.reqLocId = pData;
when pXPath = '/DirectVendorAccess/TransactionID/';
gDVA.trnId = pData;
when pXPath = '/DirectVendorAccess/RequestDate/';
gDVA.reqDt = %date(pData);
when pXPath = '/DirectVendorAccess/RequestTime/';
gDVA.reqTm = %time(pData);
when pXPath = '/DirectVendorAccess/TimeCode/';
gDVA.tmCd = pData;
when pXPath = gBaseEnv +'>';
gDtlCnt = gDtlCnt + 1;
when pXPath = gBaseEnv +'/ProductQualifier/';
gDtl(gDtlCnt).prdQlf = pData;
when pXPath = gBaseEnv +'/Product/';
gDtl(gDtlCnt).prd = pData;
when pXPath = gBaseEnv +'/QuantityRequested/';
gDtl(gDtlCnt).qty = RXS_charToNbr(pData: 0);
when pXPath = gBaseEnv +'/UnitOfMeasure/';
gDtl(gDtlCnt).uom = pData;
endsl;
/end-free
P e
//--------------------------------------------------------------------------------------------
// @Author: Aaron Bartell
// @Created: 2007-06-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 = 'DVA.1';
gError.severity = 100;
gError.pgm = 'DVA.errHandler';
gError.text =
'Line:' + %char(pCurLine) +
' Column:' + %char(pCurCol) +
' ' + pErrStr;
/end-free
P E
File: INVITM
*-------------------------------------------------------------------------
* @Name - INVITM
* @Author - Aaron Bartell
* @Desc - Holds inventory item information that can be used to determine
* product that is available for purchase.
*-------------------------------------------------------------------------
A UNIQUE
A R INVITMR TEXT('Item Price')
A PRD1 45A COLHDG('Product1')
A LOCID 20A COLHDG('Location Id')
A PRDQLF 2A COLHDG('ProductQualifier')
A PRD2 20A COLHDG('Product2')
A UOM 2A COLHDG('UOM')
A DTAVL L COLHDG('Date Avail')
A AVLCOT T COLHDG('Avail Cut Off Time')
A CTYNAM 20A COLHDG('City Name')
A STTCD 20A COLHDG('State Code')
A CTRYCD 20A COLHDG('Country Code')
A PSTCD 20A COLHDG('Postal Code')
A AVLQTY 10S 0 COLHDG('Avail Qty')
A PRCTYP 20A COLHDG('Price Type')
A PRC 7P 2 COLHDG('Price')
A MSMNTQLF 20A COLHDG('Measurement Qualfr')
A MSMNTVAL 9S 3 COLHDG('Measurement Value')
A K PRD1
RPG-XML Suite Template Engine file used to compose response XML. Found in /www/myrxs/templates/directvendoraccess.tpl
/$HTTP_HEAD
Content-type: text/xml
/$DirectVendorAccess_beg
<DirectVendorAccess xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<MessageType>/%MessageType%/</MessageType>
<SenderID>/%SenderID%/</SenderID>
<RequestorLocationID>/%RequestorLocationID%/</RequestorLocationID>
<TransactionID>/%TransactionID%/</TransactionID>
<ResponseDate>/%ResponseDate%/</ResponseDate>
<ResponseTime>/%ResponseTime%/</ResponseTime>
<TimeCode>/%TimeCode%/</TimeCode>
<IDCode>/%IDCode%/</IDCode>
<HeaderErrorCode>/%HeaderErrorCode%/</HeaderErrorCode>
<HeaderErrorDesc>/%HeaderErrorDesc%/</HeaderErrorDesc>
<Details>
/$Detail_beg
<Detail>
<ProductQualifier>/%ProductQualifier%/</ProductQualifier>
<Product>/%Product%/</Product>
<QuantityRequested>/%QuantityRequested%/</QuantityRequested>
<UnitOfMeasure>/%UnitOfMeasure%/</UnitOfMeasure>
<DetailErrorCode>/%DetailErrorCode%/</DetailErrorCode>
<DetailErrorDesc>/%DetailErrorDesc%/</DetailErrorDesc>
/$ResponseDetails_beg
<ResponseDetails>
/$ResponseDetail
<ResponseDetail>
<LocationID>/%LocationID%/</LocationID>
<ProductQualifier>/%ProductQualifier%/</ProductQualifier>
<Product>/%Product%/</Product>
<UnitOfMeasure>/%UnitOfMeasure%/</UnitOfMeasure>
<DateAvailable>/%DateAvailable%/</DateAvailable>
<AvailableCutOffTime>/%AvailableCutOffTime%/</AvailableCutOffTime>
<CityName>/%CityName%/</CityName>
<StateCode>/%StateCode%/</StateCode>
<CountryCode>/%CountryCode%/</CountryCode>
<PostalCode>/%PostalCode%/</PostalCode>
<AvailableQty>/%AvailableQty%/</AvailableQty>
<PriceType>/%PriceType%/</PriceType>
<Price>/%Price%/</Price>
<MeasurementQualifier>/%MeasurementQualifier%/</MeasurementQualifier>
<MeasurementValue>/%MeasurementValue%/</MeasurementValue>
</ResponseDetail>
/$ResponseDetails_end
</ResponseDetails>
/$Detail_end
</Detail>
/$DirectVendorAccess_end
</Details>
<CntOfItmsRtrnd>/%CntOfItmsRtrnd%/</CntOfItmsRtrnd>
<CntOfItmsRtrndByLoc>/%CntOfItmsRtrndByLoc%/</CntOfItmsRtrndByLoc>
</DirectVendorAccess>
Sample request document to use with the Web Service Tester:
<DirectVendorAccess
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<MessageType>IQ</MessageType>
<SenderID>077316412</SenderID>
<RequestorLocationID>0314</RequestorLocationID>
<TransactionID>2004062209522214</TransactionID>
<RequestDate>2004-06-22</RequestDate>
<RequestTime>095222</RequestTime>
<TimeCode>V</TimeCode>
<Details>
<Detail>
<ProductQualifier>UP</ProductQualifier>
<Product>662289344802</Product>
<QuantityRequested>1</QuantityRequested>
<UnitOfMeasure>EA</UnitOfMeasure>
</Detail>
<Detail>
<ProductQualifier>VP</ProductQualifier>
<Product>700180</Product>
<QuantityRequested>2</QuantityRequested>
<UnitOfMeasure>EA</UnitOfMeasure>
</Detail>
<Detail>
<ProductQualifier>UP</ProductQualifier>
<Product>662289319688</Product>
<QuantityRequested>3</QuantityRequested>
<UnitOfMeasure>EA</UnitOfMeasure>
</Detail>
<Detail>
<ProductQualifier>UP</ProductQualifier>
<Product>123456789010</Product>
<QuantityRequested>4</QuantityRequested>
<UnitOfMeasure>EA</UnitOfMeasure>
</Detail>
<Detail>
<ProductQualifier>VP</ProductQualifier>
<Product>1078336</Product>
<QuantityRequested>5</QuantityRequested>
<UnitOfMeasure>EA</UnitOfMeasure>
</Detail>
<Detail>
<ProductQualifier>UP</ProductQualifier>
<Product>662289263271</Product>
<QuantityRequested>6</QuantityRequested>
<UnitOfMeasure>EA</UnitOfMeasure>
</Detail>
<Detail>
<ProductQualifier>VP</ProductQualifier>
<Product>700176</Product>
<QuantityRequested>7</QuantityRequested>
<UnitOfMeasure>EA</UnitOfMeasure>
</Detail>
<Detail>
<ProductQualifier>UP</ProductQualifier>
<Product>662289263272</Product>
<QuantityRequested>8</QuantityRequested>
<UnitOfMeasure>EA</UnitOfMeasure>
</Detail>
<Detail>
<ProductQualifier>VP</ProductQualifier>
<Product>700174</Product>
<QuantityRequested>9</QuantityRequested>
<UnitOfMeasure>EA</UnitOfMeasure>
</Detail>
</Details>
</DirectVendorAccess>
