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


//?***************************************************************************************
//?@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

::RespondSalesOrder_beg
<RespondSalesOrder xmlns="http://www.openapplications.org/oagis/9" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xsi:schemaLocation="http://www.openapplications.org/oagis/9 ../../Developer/BODs/RespondSalesOrder.xsd" 
      languageCode="en-US" 
      versionID="9_4" 
      releaseID="9_4" 
      systemEnvironmentCode="Production">
   <ApplicationArea>
      <Sender>
         <LogicalID>.:LogicalID:.</LogicalID>
         <ComponentID>.:ComponentID:.</ComponentID>
         <ReferenceID>.:ReferenceID:.</ReferenceID>
         <ConfirmationCode languageID=".:languageID:.">.:ConfirmationCode:.</ConfirmationCode>
         <AuthorizationID>.:AuthorizationID:.</AuthorizationID>
      </Sender>
      <CreationDateTime>.:CreationDateTime:.</CreationDateTime>
      <BODID>.:BODID:.</BODID>
   </ApplicationArea>
   <DataArea>
      <Respond>
         <OriginalApplicationArea>
            <Sender>
               <LogicalID>.:LogicalID:.</LogicalID>
               <ComponentID>.:ComponentID:.</ComponentID>
               <ReferenceID>.:ReferenceID:.</ReferenceID>
               <ConfirmationCode languageID=".:languageID:.">.:ConfirmationCode:.</ConfirmationCode>
               <AuthorizationID>.:AuthorizationID:.</AuthorizationID>
            </Sender>
            <CreationDateTime>.:CreationDateTime:.</CreationDateTime>
            <BODID>.:BODID:.</BODID>
         </OriginalApplicationArea>
         <ResponseCriteria>
            <ResponseExpression actionCode=".:actionCode:.">.:ResponseExpression:.</ResponseExpression>
            <ChangeStatus>
               <Code languageID=".:languageID:.">.:Code:.</Code>
               <EffectiveDateTime>.:EffectiveDateTime:.</EffectiveDateTime>
               <ReasonCode languageID=".:languageID:.">.:ReasonCode:.</ReasonCode>
               <StateChange>
                  <FromStateCode languageID=".:languageID:.">.:FromStateCode:.</FromStateCode>
                  <ToStateCode languageID=".:languageID:.">.:ToStateCode:.</ToStateCode>
                  <ChangeDateTime>.:ChangeDateTime:.</ChangeDateTime>
               </StateChange>
            </ChangeStatus>
         </ResponseCriteria>
      </Respond>
      <SalesOrder>
         <SalesOrderHeader>
            <Description languageID=".:languageID:.">.:SaleHeaderDescription:.</Description>
            <Note languageID=".:languageID:." author=".:author:." entryDateTime=".:entryDateTime:." status=".:status:.">.:Note:.</Note>
            <TotalAmount currencyID=".:currencyID:.">.:TotalAmount:.</TotalAmount>
         </SalesOrderHeader>
::SalesOrderLine
         <SalesOrderLine>
            <LineNumber>.:LineNumber:.</LineNumber>
            <Item>
               <Description languageID=".:languageID:.">.:Description:.</Description>
               <CountryOfOriginCode languageID=".:languageID:.">.:CountryOfOriginCode:.</CountryOfOriginCode>
               <SerialNumber>.:SerialNumber:.</SerialNumber>
            </Item>
         </SalesOrderLine>
::RespondSalesOrder_end  
      </SalesOrder>
   </DataArea>
</RespondSalesOrder>
</source>

Sample XML Request

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://www.openapplications.org/oagis/9">
<soapenv:Header/>
<soapenv:Body>
   <ns:ProcessSalesOrder systemEnvironmentCode="Production" languageCode="en-US">
      <ns:ApplicationArea>
         <ns:Sender>
            <ns:LogicalID>1159963824</ns:LogicalID>
            <ns:ComponentID>64720-22-358</ns:ComponentID>
            <ns:ReferenceID>16683</ns:ReferenceID>
            <ns:ConfirmationCode listURI="http://www.example.org">Always</ns:ConfirmationCode>
            <ns:AuthorizationID>489665871337</ns:AuthorizationID>
         </ns:Sender>
         <ns:Receiver>
            <ns:LogicalID>4283699511</ns:LogicalID>
            <ns:ID>1594826735</ns:ID>
         </ns:Receiver>
         <ns:CreationDateTime>2010-07-13</ns:CreationDateTime>
         <ns:BODID>485</ns:BODID>
      </ns:ApplicationArea>
      <ns:DataArea>      
         <ns:SalesOrder type="N">
            <ns:SalesOrderHeader>
               <ns:Description languageID="en-US">Example order description would go here.</ns:Description>
               <ns:Note languageID="en-US" author="986" entryDateTime="2010-07-13" status="9">Some notes would go here.</ns:Note>            
               <ns:TotalAmount currencyID="en-US">12300.99</ns:TotalAmount>                       
            </ns:SalesOrderHeader>
            <ns:SalesOrderLine>
               <ns:LineNumber>100</ns:LineNumber>
               <ns:Item>
                  <ns:Description languageID="en-US">Item description here.</ns:Description>
                  <ns:CountryOfOriginCode languageID="en-US">Canada</ns:CountryOfOriginCode>                
                  <ns:SerialNumber>153-8894-778-9636-45</ns:SerialNumber>
               </ns:Item>
            </ns:SalesOrderLine>
            <ns:SalesOrderLine>
               <ns:LineNumber>200</ns:LineNumber>
               <ns:Item>
                  <ns:Description languageID="en-US">2nd Item description here.</ns:Description>
                  <ns:CountryOfOriginCode languageID="en-US">Spain</ns:CountryOfOriginCode>                
                  <ns:SerialNumber>956-4421-263-5684-23</ns:SerialNumber>
               </ns:Item>
            </ns:SalesOrderLine>
            <ns:SalesOrderLine>
               <ns:LineNumber>300</ns:LineNumber>
               <ns:Item>
                  <ns:Description languageID="en-US">3rd Item description here.</ns:Description>
                  <ns:CountryOfOriginCode languageID="en-US">Belgium</ns:CountryOfOriginCode>                
                  <ns:SerialNumber>223-8695-748-9644-78</ns:SerialNumber>
               </ns:Item>
            </ns:SalesOrderLine>
            <ns:SalesOrderLine>
               <ns:LineNumber>400</ns:LineNumber>
               <ns:Item>
                  <ns:Description languageID="en-US">A Fourth Item description here.</ns:Description>
                  <ns:CountryOfOriginCode languageID="en-US">Peru</ns:CountryOfOriginCode>                
                  <ns:SerialNumber>845-9595-748-3625-24</ns:SerialNumber>
               </ns:Item>
            </ns:SalesOrderLine>
         </ns:SalesOrder>
      </ns:DataArea>
   </ns:ProcessSalesOrder>
</soapenv:Body>
</soapenv:Envelope>