# Calling the OAGIS SalesOrder Web Service This proof of concept was developed to demonstrate RPG-XML Suite's ability to process and respond with OAGIS specified documents. In this program, we work exclusively with SalesOrder documents, and work with ProcessSalesOrder and RespondSalesOrder. Due to the verbose nature of the OAGIS specification, this proof of concept has the following limits: - Accepts a maximum of 5 SalesOrderLine elements. - Implements a very limited subset of the specifications - Has hardcoded data and does not use DB2 tables. ## Source Code ```rpgle //?*************************************************************************************** //?@Author: Adam Taylor //?@Desc: Read incoming ProcessSalesOrder XML via STDIN, create a RespondSalesOrder //? in an XML file, and return it to the requestor via STDOUT. //?@Notes: This example only accounts for up to 5 items being present in a // ProcessSalesOrder, and is a limited subset of both XML documents as compared // to their full form per OAGIs. //?*************************************************************************************** H dftactgrp(*no) bnddir('RXSBND') /copy rxs,RXSCp ?RXS_* procedures & definitions D gError ds likeds(RXS_Error) inz D salesOrder ds qualified inz D sndLogicalId 10a D sndCmpntId 12a D sndRefId 5a D sndConfirmURI 40a Varying D sndConfirmCd 15a D sndAuthId 12a D rcvLogicalId 10a D rcvId 10a D crtDateTime d D BODID 3a Varying D saleOrderType 1a D saleHdrDesc 50a Varying D noteAuthor 4a Varying D noteDateTime d D noteStatus 1a D note 50a Varying D totAmtCurType 6a D totAmt 8 2 D salesOrderLine ds qualified inz dim(5) D lineNumber 5 0 D description 50a Varying D originCountry 50a Varying D serialNumber 20a D gLineCnt s 10i 0 Inz(0) D counter s 10i 0 Inz(0) D gReqFile s like(RXS_FilePath) D gRspFile S like(RXS_FilePath) 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 /free monitor; gReqFile = RXS_cmpTransFile('_': '.xml': 'cargill_req'); gRspFile = RXS_cmpTransFile('_': '.xml': 'cargill_rsp'); RXS_readToFile(gReqFile); exsr parse; exsr compose; exsr respond; on-error; RXS_stdOutError('error': RXS_catchError(): *on); endmon; *inlr = *On; //?-------------------------------------------------------------------------------------- //?@Author: Adam Taylor //?@Desc: Prime parsing engine //?-------------------------------------------------------------------------------------- begsr parse; monitor; // Ignore all namespaces. RXS_ignElemNamSpc(); RXS_allElemContentHandler(%paddr(allHandler)); RXS_allAttrHandler(%paddr(allHandler)); RXS_parse(gReqFile : RXS_STMF : %paddr(errHandler)); on-error; gError = RXS_catchError(); endmon; endsr; //?-------------------------------------------------------------------------------------- //?@Author: Adam Taylor //?@Desc: Build RespondSalesOrder XML file using Template Engine //?-------------------------------------------------------------------------------------- begsr compose; monitor; // Composing our XML RespondSalesOrder and storing it in a STMF RXS_initTplEng(RXS_STMF: gRspFile: *omit: *omit: *omit: *off); RXS_loadTpl('RespondSalesOrder.tpl'); RXS_updVar('LogicalID' : salesOrder.sndLogicalId); RXS_updVar('ComponentID' : salesOrder.sndCmpntId); RXS_updVar('ReferenceID' : salesOrder.sndRefId); RXS_updVar('languageID' : 'en-US'); RXS_updVar('ConfirmationCode' : salesOrder.sndConfirmCd); RXS_updVar('AuthorizationID' : salesOrder.sndAuthId); RXS_updVar('BODID' : salesOrder.BODID); RXS_updVar('CreationDateTime' : %Char(salesOrder.crtDateTime)); RXS_updVar('currencyID' : salesOrder.totAmtCurType); RXS_updVar('TotalAmount' : %Char(salesOrder.totAmt)); RXS_updVar('SaleHeaderDescription' : salesOrder.saleHdrDesc); RXS_updVar('author' : salesOrder.noteAuthor); RXS_updVar('entryDateTime' : %Char(salesOrder.noteDateTime)); RXS_updVar('status' : salesOrder.noteStatus); RXS_updVar('Note' : salesOrder.note); RXS_updVar('Code' : 'INI'); RXS_updVar('EffectiveDateTime' : %Char(%Date())); RXS_updVar('ChangeDateTime' : %Char(%Date() - %Days(3))); RXS_updVar('FromStateCode' : 'ORD'); RXS_updVar('ReasonCode' : 'CDE'); RXS_updVar('ToStateCode' : 'PRC'); RXS_updVar('actionCode' : 'Always'); RXS_updVar('ResponseExpression' : 'Successful'); RXS_wrtSection('RespondSalesOrder_beg'); // Print out however many order lines we parsed. for counter = 1 To 5; if salesOrderLine(counter).lineNumber > 0; RXS_updVar('LineNumber' : %Char(salesOrderLine(counter).lineNumber)); RXS_updVar('CountryOfOriginCode' : salesOrderLine(counter).originCountry); RXS_updVar('Description' : salesOrderLine(counter).description); RXS_updVar('SerialNumber' : salesOrderLine(counter).serialNumber); RXS_wrtSection('SalesOrderLine'); endif; endfor; // Finalize XML file, flush buffer to XML file RXS_wrtSection('RespondSalesOrder_end' : *On); on-error; gError = RXS_catchError(); endmon; endsr; //?-------------------------------------------------------------------------------------- //?@Author: Adam Taylor //?@Desc: Return RespondSalesOrder via STDOUT //?-------------------------------------------------------------------------------------- begsr respond; monitor; RXS_writeXmlHdr(); RXS_outFromFile(gRspFile); on-error; gError = RXS_catchError(); endmon; endsr; /end-free //--------------------------------------------------------------------------------------- // @Author: // @Created: // @Desc: //---------------------------------------------------------------------------------------- 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 chgMe s like(RXS_XmlData) D baseEnv s 70a varying /free // For the sake of this example, we're loading the repeating // SalesOrderLine elements into an array, limited at 5 elements. // In normal use, you would most likely want to load these into a // DB2 table. baseEnv = '/Envelope/Body/ProcessSalesOrder'; select; when pXPath = baseEnv +'/ApplicationArea/Sender/LogicalID/'; salesOrder.sndLogicalId = pData; when pXPath = baseEnv +'/ApplicationArea/Sender/ComponentID/'; salesOrder.sndCmpntId = pData; when pXPath = baseEnv +'/ApplicationArea/Sender/ReferenceID/'; salesOrder.sndRefId = pData; when pXPath = baseEnv +'/ApplicationArea/Sender/ConfirmationCode'+ '@listURI'; salesOrder.sndConfirmURI = pData; when pXPath = baseEnv +'/ApplicationArea/Sender/ConfirmationCode/'; salesOrder.sndConfirmCd = pData; when pXPath = baseEnv +'/ApplicationArea/Sender/AuthorizationID/'; salesOrder.sndAuthId = pData; when pXPath = baseEnv +'/ApplicationArea/Receiver/LogicalID/'; salesOrder.rcvLogicalId = pData; when pXPath = baseEnv +'/ApplicationArea/Receiver/ID/'; salesOrder.rcvId = pData; when pXPath = baseEnv +'/ApplicationArea/CreationDateTime/'; salesOrder.crtDateTime = %DATE(pData : *ISO); when pXPath = baseEnv +'/ApplicationArea/BODID/'; salesOrder.BODID = pData; when pXPath = baseEnv +'/DataArea/SalesOrder/SalesOrderHeader'+ '/Description/'; salesOrder.saleHdrDesc = pData; when pXPath = baseEnv +'/DataArea/SalesOrder/SalesOrderHeader/Note'+ '@author'; salesOrder.noteAuthor = pData; when pXPath = baseEnv +'/DataArea/SalesOrder/SalesOrderHeader/Note'+ '@entryDateTime'; salesOrder.noteDateTime = %DATE(pData : *ISO); when pXPath = baseEnv +'/DataArea/SalesOrder/SalesOrderHeader/Note/'; salesOrder.note = pData; when pXPath = baseEnv +'/DataArea/SalesOrder/SalesOrderHeader'+ '/TotalAmount@currencyID'; salesOrder.totAmtCurType = pData; when pXPath = baseEnv +'/DataArea/SalesOrder/SalesOrderHeader'+ '/TotalAmount/'; salesOrder.totAmt = %DEC(pData : 8 : 2); // Process up to 5 incoming line items. when pXPath = baseEnv +'/DataArea/SalesOrder/SalesOrderLine/LineNumber/'; gLineCnt += 1; salesOrderLine(gLineCnt).lineNumber = %Dec(pData : 5 : 0); when pXPath = baseEnv +'/DataArea/SalesOrder/SalesOrderLine/Item'+ '/Description/'; salesOrderLine(gLineCnt).description = pData; when pXPath = baseEnv +'/DataArea/SalesOrder/SalesOrderLine/Item'+ '/CountryOfOriginCode/'; salesOrderLine(gLineCnt).originCountry = pData; when pXPath = baseEnv +'/DataArea/SalesOrder/SalesOrderLine/Item'+ '/SerialNumber/'; salesOrderLine(gLineCnt).serialNumber = pData; endsl; /end-free P e P errHandler B D errHandler PI D pCurLine 10i 0 value D pCurCol 10i 0 value D pErrStr 1024a value varying /free gError.code = 'SALE001'; gError.severity = 100; gError.pgm = 'SALE001.errHandler'; gError.text = 'Line:' + %char(pCurLine) + ' Col:' + %char(pCurCol) + ' ' + pErrStr; /end-free P E ``` ## Template File ```xml .:LogicalID:. .:ComponentID:. .:ReferenceID:. .:ConfirmationCode:. .:AuthorizationID:. .:CreationDateTime:. .:BODID:. .:LogicalID:. .:ComponentID:. .:ReferenceID:. .:ConfirmationCode:. .:AuthorizationID:. .:CreationDateTime:. .:BODID:. .:ResponseExpression:. .:Code:. .:EffectiveDateTime:. .:ReasonCode:. .:FromStateCode:. .:ToStateCode:. .:ChangeDateTime:. .:SaleHeaderDescription:. .:Note:. .:TotalAmount:. ::SalesOrderLine .:LineNumber:. .:Description:. .:CountryOfOriginCode:. .:SerialNumber:. ::RespondSalesOrder_end ``` ## Sample XML Request ```xml 1159963824 64720-22-358 16683 Always 489665871337 4283699511 1594826735 2010-07-13 485 Example order description would go here. Some notes would go here. 12300.99 100 Item description here. Canada 153-8894-778-9636-45 200 2nd Item description here. Spain 956-4421-263-5684-23 300 3rd Item description here. Belgium 223-8695-748-9644-78 400 A Fourth Item description here. Peru 845-9595-748-3625-24 ```