Program: RXSAJAX
      //*******************************************************************************************
      // @Author: Aaron Bartell
      // @Created: 2007-08-28
      // @Desc:
      // @Compile: CRTBNDRPG PGM(MYRXS/RPGAJAX) SRCFILE(MYRXS/QSOURCE) SRCMBR(RPGAJAX)
      //*******************************************************************************************
     H dftactgrp(*no) bnddir('RXSBND': 'SINBND')

      /copy rxs,RXSCp
      /copy sin,CustCp

     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

     D gAction         s             25a   varying

     D CM            e ds                  qualified extname(CUSTMST)
     D gError          ds                  likeds(RXS_Error) inz
     D gXml            s          65535a   varying
     D gCustErr        s                   like(Cust_Error)
     D gCustNbr        s                   like(CM.CUSTNBR)
      /free

       monitor;
         clear gError;
         clear gAction;

         // MYLIB was added here to show how to use a PF that is not
         // in your default MYRXS library.
         if RXS_libLEExists('MYLIB') <= 0;
           RXS_addLibLE('MYLIB');
         endif;

         gXml = RXS_readStdIn();

         RXS_allElemContentHandler(%paddr(allHandler));
         RXS_addHandler('/ENV@ACTION': %paddr(allHandler));
         RXS_parse(gXml: RXS_VAR: %paddr(errHandler));

         if gError.code <> *blanks;
           RXS_stdOutError('error': gError: *on);
           *inlr = *on;
           return;
         endif;

         exsr compose;

       on-error;
         RXS_stdOutError('error': RXS_catchError(): *on);
       endmon;

       *inlr = *on;



       //--------------------------------------------------------------------------------------------
       // @Author: Aaron Bartell
       // @Created: 2005-08-03
       // @Desc: Using the template engine compose the response and send it to standard out (i.e.
       //        RXS_STDOUT).
       //--------------------------------------------------------------------------------------------
       begsr compose;

       // Compose xml
       RXS_initTplEng(RXS_STDOUT: *omit: *omit: *omit: *omit: *off);
       RXS_loadTpl('rxs_ajax.tpl': '::': '': '.:': ':.');
       RXS_wrtSection('HTTP_HEAD');

       RXS_wrtSection('env_beg');
       select;
       when gAction = 'CUST_NEXTNBR';
         Cust_nextNbr(gCustErr: gCustNbr);
         RXS_updVar('ERROR': gCustErr);
         RXS_wrtSection('ERROR');
         RXS_updVar('CUSTNBR': %char(gCustNbr));
         RXS_wrtSection('CUSTNBR');
       when gAction = 'CUST_SAVE';
         Cust_save(gCustErr: CM);
       when gAction = 'CUST_GETREC';
         Cust_getRec(gCustErr: CM: gCustNbr);
         RXS_updVar('CUSTNBR': %char(CM.CUSTNBR));
         RXS_updVar('FNAM': CM.FNAM);
         RXS_updVar('LNAM': CM.LNAM);
         RXS_updVar('CMPNY': CM.CMPNY);
         RXS_updVar('ADR1': CM.ADR1);
         RXS_updVar('ADR2': CM.ADR2);
         RXS_updVar('CTY': CM.CTY);
         RXS_updVar('STT': CM.STT);
         RXS_updVar('ZIPCD': CM.ZIPCD);
         RXS_updVar('PHN': CM.PHN);
         RXS_wrtSection('CUSTMST');
       other;
         RXS_updVar('ERROR': 'No action specified');
       endsl;

       RXS_updVar('ERROR': gCustErr);
       RXS_wrtSection('ERROR');

       RXS_wrtSection('env_end': *on);

       endsr;

      /end-free
      //--------------------------------------------------------------------------------------------
      // @Author: Aaron Bartell
      // @Created: 2005-08-03
      // @Desc: This local sub procedure will be called for each element content and attribute event
      //        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.
      //--------------------------------------------------------------------------------------------
     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 = '/ENV@ACTION';
         gAction = pData;

       when pXPath = '/ENV/CUSTMST/CUSTNBR/';
         CM.CUSTNBR = RXS_charToNbr(pData: 0);
       when pXPath = '/ENV/CUSTMST/FNAM/';
         CM.FNAM = pData;
       when pXPath = '/ENV/CUSTMST/LNAM/';
         CM.LNAM = pData;
       when pXPath = '/ENV/CUSTMST/CMPNY/';
         CM.CMPNY = pData;
       when pXPath = '/ENV/CUSTMST/ADR1/';
         CM.ADR1 = pData;
       when pXPath = '/ENV/CUSTMST/ADR2/';
         CM.ADR2 = pData;
       when pXPath = '/ENV/CUSTMST/CTY/';
         CM.CTY = pData;
       when pXPath = '/ENV/CUSTMST/STT/';
         CM.STT = pData;
       when pXPath = '/ENV/CUSTMST/ZIPCD/';
         CM.ZIPCD = pData;
       when pXPath = '/ENV/CUSTMST/PHN/';
         CM.PHN = pData;
       when pXPath = '/ENV/CUSTNBR/';
         gCustNbr = RXS_charToNbr(pData: 0);

       endsl;

      /end-free
     P                 e


      //--------------------------------------------------------------------------------------------
      // @Author: Aaron Bartell
      // @Created: 2005-08-03
      // @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 = 'RXSAJAX.1';
       gError.severity = 100;
       gError.pgm = 'RXSAJAX.errHandler';
       gError.text =
         'Line:' + %char(pCurLine) +
         ' Column:' + %char(pCurCol) +
         ' ' + pErrStr;

      /end-free
     P                 E 
 


Program: CUSTFN
      //------------------------------------------------------------------------
      // @Author: Aaron Bartell
      // @Created: 2007-08-28
      // @Desc: Modular customer RPG service program.
      // @Compile: CRTRPGMOD
      //             MODULE(MYLIB/CUSTFN) SRCFILE(MYLIB/SIN) SRCMBR(CUSTFN)
      //
      //           CRTSRVPGM
      //             SRVPGM(MYLIB/CUSTSV)
      //             MODULE(MYLIB/CUSTFN) SRCFILE(MYLIB/SIN)
      //------------------------------------------------------------------------
     h nomain

     fCUSTMST   uf a e           k disk    prefix('CM.')
     d CM            e ds                  qualified extname(CUSTMST)

      /copy sin,CustCP


      //------------------------------------------------------------------------
      // @Author: Aaron Bartell
      // @Created: 2007-08-28
      // @Desc: Get the next available customer number.
      //------------------------------------------------------------------------
     p Cust_nextNbr    b                   export
     d Cust_nextNbr    pi
     d  pError                             like(Cust_Error)
     d  pNbr                               like(CM.CUSTNBR)
      /free

         clear pError;
         setgt *hival CUSTMST;
         readp CUSTMST;
         pNbr = CM.CUSTNBR + 1;
         clear CUSTMSTR;
         CM.CUSTNBR = pNbr;
         write CUSTMSTR;
         pError = 'Customer ' + %char(pNbr) + ' reserved for insertion.';

      /end-free
     p                 e


      //------------------------------------------------------------------------
      // @Author: Aaron Bartell
      // @Created: 2007-08-28
      // @Desc: Retrieve a customer record.
      //------------------------------------------------------------------------
     p Cust_getRec     b                   export
     d Cust_getRec     pi
     d  pError                             like(Cust_Error)
     d  pCustRec                           likeds(CM)
     d  pCustNbr                           like(CM.CUSTNBR)
      /free

         clear pError;
         clear pCustRec;
         chain(n) pCustNbr CUSTMST;
         if not %found;
           pError = 'Customer ' + %char(pCustNbr) + ' Not Found';
         else;
           pCustRec = CM;
           pError = 'Customer ' + %char(pCustNbr) + ' Found';
         endif;

      /end-free
     p                 e


      //------------------------------------------------------------------------
      // @Author: Aaron Bartell
      // @Created: 2007-08-28
      // @Desc: Save a customer record
      //------------------------------------------------------------------------
     p Cust_save       b                   export
     d Cust_save       pi
     d  pError                             like(Cust_Error)
     d  pCustRec                           likeds(CM)
      /free

       monitor;
         clear pError;
         if ( pCustRec.CustNbr = 0
           or pCustRec.FNam = *blanks
           or pCustRec.LNam = *blanks
           or pCustRec.Cmpny = *blanks
           or pCustRec.Adr1 = *blanks
           or pCustRec.Cty = *blanks
           or pCustRec.Stt = *blanks
           or pCustRec.ZipCd = *zeros
           or pCustRec.Phn = *blanks );
            pError = 'Not all fields were set!';
           return;
         endif;

         chain pCustRec.CustNbr CUSTMST;
         CM = pCustRec;
         if %found(CUSTMST);
           update CUSTMSTR;
           pError = 'Customer updated.';
         else;
           write CUSTMSTR;
           pError = 'New customer record written.';
         endif;
       on-error;
         pError = 'Error occurred during save of customer!';
       endmon;

      /end-free
     p                 e

 


Copy book: CUSTCP

     D Cust_nextNbr    pr
     D  pError                             like(Cust_Error)
     D  pNbr                               like(CM.CUSTNBR)

     D Cust_getRec     pr
     D  pError                             like(Cust_Error)
     D  pCustRec                           likeds(CM)
     D  pCustNbr                           like(CM.CUSTNBR)

     D Cust_save       pr
     D  pError                             like(Cust_Error)
     D  pCustRec                           likeds(CM)


     D Cust_Error      s             50A 


Binder Language: CUSTSV
  strpgmexp
    export symbol(Cust_nextNbr)
    export symbol(Cust_getRec)
    export symbol(Cust_save)
  endpgmexp 


Physical File: CUSTMST
      **************************************************************************
      *  File: CUSTMST
      *  Use: Store customer information.
      **************************************************************************
     A                                      UNIQUE
     A          R CUSTMSTR
     A            CUSTNBR        5P 0       COLHDG('Cust Nbr')
     A            FNAM          15A         COLHDG('First Name')
     A            LNAM          15A         COLHDG('Last Name')
     A            CMPNY         20A         COLHDG('Company')
     A            ADR1          20A         COLHDG('Address 1')
     A            ADR2          20A         COLHDG('Address 2')
     A            CTY           15A         COLHDG('City')
     A            STT            2A         COLHDG('State')
     A            ZIPCD          5A         COLHDG('Zip Code')
     A            PHN           18A         COLHDG('Phone')

     A          K CUSTNBR 


IFS File: /www/myrxs/templates/rxs_ajax.tpl
::HTTP_HEAD
Content-type: text/xml

::env_beg
<ENV>

::CUSTMST
<CUSTMST>
  <CUSTNBR>.:CUSTNBR:.</CUSTNBR>
  <FNAM>.:FNAM:.</FNAM>
  <LNAM>.:LNAM:.</LNAM>
  <CMPNY>.:CMPNY:.</CMPNY>
  <ADR1>.:ADR1:.</ADR1>
  <ADR2>.:ADR2:.</ADR2>
  <CTY>.:CTY:.</CTY>
  <STT>.:STT:.</STT>
  <ZIPCD>.:ZIPCD:.</ZIPCD>
  <PHN>.:PHN:.</PHN>
</CUSTMST>

::CUSTNBR
<CUSTNBR>.:CUSTNBR:.</CUSTNBR>

::ERROR
<ERROR>.:ERROR:.</ERROR>

::env_end
</ENV>