[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

WSDL2RPG Trouble parsing multiple data maps from webservice



I've been using the Thomas Raddatz WSDL2RPG tool, but I'm seeing some occurrences of failures.  Getting the error "-1: Length of varying length variable is out of range."  If I recall correctly, this error may have originated in one of the WSDL2R94 procedures.  After a lot of digging around, I find that on these occurrences, there appears to be a couple of different data maps being returned by the webservice.  The production program is handling the simple type, where I receive back items defined as:


     D impl_getRGDeviceDetailsReturnMvd_t...
     D                 DS                  template
     D                                     qualified
     D  item                               likeds(apachesoap_RpgArrayOfItem_t)

     D apachesoap_RpgArrayOfItem_t...
     D                 DS                  template
     D                                     qualified
     D  x                            10I 0
     D  mapItem                            likeds(apachesoap_mapItem_t)
     D                                     dim(DIM_A1)  // DIM_A1 = 512

     D apachesoap_mapItem_t...
     D                 DS                  template
     D                                     qualified
     D  key                         256A   varying
     D  value                       256A   varying

This works well until I encounter a nested array, where the "Value" is actually a map of a number of key/value pairs.

So I messed with it until I got a test program to accommodate those.  (I used patterns from another program Thomas helped me set up last August.)  I also had to do a lot of trial/error to get the array dimensions right so it would compile and run without error.  It now runs without error (at least for my very limited test inputs), and I can get the key/value pairs of the inner nested values, using the following definitions in my test stubs:  

     D apachesoap_RpgArrayOfItem_t...
     D                 DS                  template
     D                                     qualified
     D  x                            10I 0
     D  mapItem                            likeds(apachesoap_mapItem_t)
     D                                     dim(DIM_A1)  // DIM_A1 = 400 for this test stub

     D apachesoap_mapItem_t...
     D                 DS                  template
     D                                     qualified
     D  key                          64A   varying
     D  value                              likeds(apachesoap_AnyMap_t)

     D apachesoap_AnyMap_t...
     D                 DS                  template
     D                                     qualified
     D  item                               likeds(apachesoap_RpgArrayOfItem1_t)

     D apachesoap_RpgArrayOfItem1_t...
     D                 DS                  template
     D                                     qualified
     D  x                            10I 0
     D  anyMapItem                         likeds(apachesoap_anyMapItem_t)
     D                                     dim(DIM_A2)  // DIM_A2 = 64 for this test stub

     D apachesoap_anyMapItem_t...
     D                 DS                  template
     D                                     qualified
     D  key                          64A   varying
     D  value                        64A   varying

All is cool except that the returned data is a mix of the nested types and the simple types.  I have not found a way to resolve the simple value, which my test stubs don't appear to resolve.  I get the "simple" key, but the value is expected to also be a nested set of key/value pairs, which for some pairs it is, but others it is not.  

I know what the result set should be from a "northbound Interface" that should be using the same web service, and I see the different types of data maps there.  I just can't seem to replicate those results with my programs.

Attached is the original wsdl from the web service (Provision.wsdl) and a modified version that provides for the nested key/value pairs (Provision4.wsdl).  The method I'm working with here is getRGDeviceDetails.  I've attached my test caller as well (ws5test05.txt).

If you think you can help me through this, let me know what other pieces you might need.

Many thanks,
  Michael



<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="urn:Provision" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"; xmlns:apachesoap="http://xml.apache.org/xml-soap"; xmlns:impl="urn:Provision" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"; xmlns:xsd="http://www.w3.org/2001/XMLSchema"; xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"; xmlns:intf="urn:Provision">
<!--WSDL created by Apache Axis version: 1.4
Built on Apr 22, 2006 (06:55:48 PDT)-->
 <wsdl:types>
  <schema xmlns="http://www.w3.org/2001/XMLSchema"; targetNamespace="http://xml.apache.org/xml-soap";>
   <import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
   <complexType name="mapItem">
    <sequence>
     <element name="key" nillable="true" type="xsd:anyType"/>
     <element name="value" nillable="true" type="xsd:anyType"/>
    </sequence>
   </complexType>
   <complexType name="Map">
    <sequence>
     <element name="item" minOccurs="0" maxOccurs="unbounded" type="apachesoap:mapItem"/>
    </sequence>
   </complexType>
  </schema>
 </wsdl:types>

   <wsdl:message name="deprovisionPortRequest">

      <wsdl:part name="in0" type="apachesoap:Map"/>

   </wsdl:message>

   <wsdl:message name="sendDeviceCommandResponse">

      <wsdl:part name="sendDeviceCommandReturn" type="soapenc:string"/>

   </wsdl:message>

   <wsdl:message name="backupDeviceConfigRequest">

      <wsdl:part name="in0" type="apachesoap:Map"/>

   </wsdl:message>

   <wsdl:message name="modifyPortResponse">

      <wsdl:part name="modifyPortReturn" type="soapenc:string"/>

   </wsdl:message>

   <wsdl:message name="getRGDeviceDetailsResponse">

      <wsdl:part name="getRGDeviceDetailsReturn" type="apachesoap:Map"/>

   </wsdl:message>

   <wsdl:message name="getDeviceInterfacesRequest">

      <wsdl:part name="in0" type="soapenc:string"/>

      <wsdl:part name="in1" type="soapenc:string"/>

   </wsdl:message>

   <wsdl:message name="provisionPortResponse">

      <wsdl:part name="provisionPortReturn" type="soapenc:string"/>

   </wsdl:message>

   <wsdl:message name="modifyRGRequest">

      <wsdl:part name="in0" type="apachesoap:Map"/>

      <wsdl:part name="in1" type="apachesoap:Map"/>

   </wsdl:message>

   <wsdl:message name="deprovisionPortResponse">

      <wsdl:part name="deprovisionPortReturn" type="soapenc:string"/>

   </wsdl:message>

   <wsdl:message name="getDeviceVlansRequest">

      <wsdl:part name="in0" type="soapenc:string"/>

      <wsdl:part name="in1" type="soapenc:string"/>

   </wsdl:message>

   <wsdl:message name="getRGDeviceDetailsRequest">

      <wsdl:part name="in0" type="apachesoap:Map"/>

      <wsdl:part name="in1" type="soapenc:string"/>

   </wsdl:message>

   <wsdl:message name="getDeviceVlansResponse">

      <wsdl:part name="getDeviceVlansReturn" type="apachesoap:Map"/>

   </wsdl:message>

   <wsdl:message name="sendDeviceCommandRequest">

      <wsdl:part name="in0" type="apachesoap:Map"/>

   </wsdl:message>

   <wsdl:message name="modifyPortRequest">

      <wsdl:part name="in0" type="apachesoap:Map"/>

   </wsdl:message>

   <wsdl:message name="provisionPortRequest">

      <wsdl:part name="in0" type="apachesoap:Map"/>

   </wsdl:message>

   <wsdl:message name="backupDeviceConfigResponse">

      <wsdl:part name="backupDeviceConfigReturn" type="soapenc:string"/>

   </wsdl:message>

   <wsdl:message name="getDeviceInterfacesResponse">

      <wsdl:part name="getDeviceInterfacesReturn" type="apachesoap:Map"/>

   </wsdl:message>

   <wsdl:message name="modifyRGResponse">

      <wsdl:part name="modifyRGReturn" type="soapenc:string"/>

   </wsdl:message>

   <wsdl:portType name="ProvisionInterface">

      <wsdl:operation name="getDeviceInterfaces" parameterOrder="in0 in1">

         <wsdl:input name="getDeviceInterfacesRequest" message="impl:getDeviceInterfacesRequest"/>

         <wsdl:output name="getDeviceInterfacesResponse" message="impl:getDeviceInterfacesResponse"/>

      </wsdl:operation>

      <wsdl:operation name="getDeviceVlans" parameterOrder="in0 in1">

         <wsdl:input name="getDeviceVlansRequest" message="impl:getDeviceVlansRequest"/>

         <wsdl:output name="getDeviceVlansResponse" message="impl:getDeviceVlansResponse"/>

      </wsdl:operation>

      <wsdl:operation name="getRGDeviceDetails" parameterOrder="in0 in1">

         <wsdl:input name="getRGDeviceDetailsRequest" message="impl:getRGDeviceDetailsRequest"/>

         <wsdl:output name="getRGDeviceDetailsResponse" message="impl:getRGDeviceDetailsResponse"/>

      </wsdl:operation>

      <wsdl:operation name="provisionPort" parameterOrder="in0">

         <wsdl:input name="provisionPortRequest" message="impl:provisionPortRequest"/>

         <wsdl:output name="provisionPortResponse" message="impl:provisionPortResponse"/>

      </wsdl:operation>

      <wsdl:operation name="deprovisionPort" parameterOrder="in0">

         <wsdl:input name="deprovisionPortRequest" message="impl:deprovisionPortRequest"/>

         <wsdl:output name="deprovisionPortResponse" message="impl:deprovisionPortResponse"/>

      </wsdl:operation>

      <wsdl:operation name="modifyPort" parameterOrder="in0">

         <wsdl:input name="modifyPortRequest" message="impl:modifyPortRequest"/>

         <wsdl:output name="modifyPortResponse" message="impl:modifyPortResponse"/>

      </wsdl:operation>

      <wsdl:operation name="modifyRG" parameterOrder="in0 in1">

         <wsdl:input name="modifyRGRequest" message="impl:modifyRGRequest"/>

         <wsdl:output name="modifyRGResponse" message="impl:modifyRGResponse"/>

      </wsdl:operation>

      <wsdl:operation name="backupDeviceConfig" parameterOrder="in0">

         <wsdl:input name="backupDeviceConfigRequest" message="impl:backupDeviceConfigRequest"/>

         <wsdl:output name="backupDeviceConfigResponse" message="impl:backupDeviceConfigResponse"/>

      </wsdl:operation>

      <wsdl:operation name="sendDeviceCommand" parameterOrder="in0">

         <wsdl:input name="sendDeviceCommandRequest" message="impl:sendDeviceCommandRequest"/>

         <wsdl:output name="sendDeviceCommandResponse" message="impl:sendDeviceCommandResponse"/>

      </wsdl:operation>

   </wsdl:portType>

   <wsdl:binding name="ProvisionSoapBinding" type="impl:ProvisionInterface">

      <wsdlsoap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>

      <wsdl:operation name="getDeviceInterfaces">

         <wsdlsoap:operation soapAction=""/>

         <wsdl:input name="getDeviceInterfacesRequest">

            <wsdlsoap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"; namespace="urn:Provision"/>

         </wsdl:input>

         <wsdl:output name="getDeviceInterfacesResponse">

            <wsdlsoap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"; namespace="urn:Provision"/>

         </wsdl:output>

      </wsdl:operation>

      <wsdl:operation name="getDeviceVlans">

         <wsdlsoap:operation soapAction=""/>

         <wsdl:input name="getDeviceVlansRequest">

            <wsdlsoap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"; namespace="urn:Provision"/>

         </wsdl:input>

         <wsdl:output name="getDeviceVlansResponse">

            <wsdlsoap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"; namespace="urn:Provision"/>

         </wsdl:output>

      </wsdl:operation>

      <wsdl:operation name="getRGDeviceDetails">

         <wsdlsoap:operation soapAction=""/>

         <wsdl:input name="getRGDeviceDetailsRequest">

            <wsdlsoap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"; namespace="urn:Provision"/>

         </wsdl:input>

         <wsdl:output name="getRGDeviceDetailsResponse">

            <wsdlsoap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"; namespace="urn:Provision"/>

         </wsdl:output>

      </wsdl:operation>

      <wsdl:operation name="provisionPort">

         <wsdlsoap:operation soapAction=""/>

         <wsdl:input name="provisionPortRequest">

            <wsdlsoap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"; namespace="urn:Provision"/>

         </wsdl:input>

         <wsdl:output name="provisionPortResponse">

            <wsdlsoap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"; namespace="urn:Provision"/>

         </wsdl:output>

      </wsdl:operation>

      <wsdl:operation name="deprovisionPort">

         <wsdlsoap:operation soapAction=""/>

         <wsdl:input name="deprovisionPortRequest">

            <wsdlsoap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"; namespace="urn:Provision"/>

         </wsdl:input>

         <wsdl:output name="deprovisionPortResponse">

            <wsdlsoap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"; namespace="urn:Provision"/>

         </wsdl:output>

      </wsdl:operation>

      <wsdl:operation name="modifyPort">

         <wsdlsoap:operation soapAction=""/>

         <wsdl:input name="modifyPortRequest">

            <wsdlsoap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"; namespace="urn:Provision"/>

         </wsdl:input>

         <wsdl:output name="modifyPortResponse">

            <wsdlsoap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"; namespace="urn:Provision"/>

         </wsdl:output>

      </wsdl:operation>

      <wsdl:operation name="modifyRG">

         <wsdlsoap:operation soapAction=""/>

         <wsdl:input name="modifyRGRequest">

            <wsdlsoap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"; namespace="urn:Provision"/>

         </wsdl:input>

         <wsdl:output name="modifyRGResponse">

            <wsdlsoap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"; namespace="urn:Provision"/>

         </wsdl:output>

      </wsdl:operation>

      <wsdl:operation name="backupDeviceConfig">

         <wsdlsoap:operation soapAction=""/>

         <wsdl:input name="backupDeviceConfigRequest">

            <wsdlsoap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"; namespace="urn:Provision"/>

         </wsdl:input>

         <wsdl:output name="backupDeviceConfigResponse">

            <wsdlsoap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"; namespace="urn:Provision"/>

         </wsdl:output>

      </wsdl:operation>

      <wsdl:operation name="sendDeviceCommand">

         <wsdlsoap:operation soapAction=""/>

         <wsdl:input name="sendDeviceCommandRequest">

            <wsdlsoap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"; namespace="urn:Provision"/>

         </wsdl:input>

         <wsdl:output name="sendDeviceCommandResponse">

            <wsdlsoap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"; namespace="urn:Provision"/>

         </wsdl:output>

      </wsdl:operation>

   </wsdl:binding>

   <wsdl:service name="ProvisionService">

      <wsdl:port name="Provision" binding="impl:ProvisionSoapBinding">

         <wsdlsoap:address location="http://192.168.41.252:9090/axis/services/Provision"/>

      </wsdl:port>

   </wsdl:service>

</wsdl:definitions>

Attachment: Provision4.wsdl
Description: Provision4.wsdl

      * =====================================================================
      *  Generated by WSDL2RPG 1.15beta7 / 25.01.2012
      *  Built on Feb 14, 2013 (12:48:38)
      *  Built for V7R1M0
      *  Based on WS_PGM v1.15
      * =====================================================================
      *CRTPGM PGM(gsttstlib/ws5test05)
      *  MODULE(gsttstlib/ws5test05)
      *  BNDSRVPGM(gsttstlib/ws5prvsn)
      *DETAIL(*BASIC)
      *ACTGRP(*NEW)
      *TEXT('Web service test caller - getRGDevDtls')
      * =====================================================================
      *
     H DEBUG
     H OPTION(*SRCSTMT : *NODEBUGIO)
     H EXTBININT(*YES)
      *
      *  Include generated web service stub module to
      *  define the prototype of the web service procedure
      *  and the required type definitions (aka reference fields).
      /DEFINE PROTOTYPE_WS5PRVSN05
 CPY  /COPY MKOESTER/WS_STUBSRC,WS5PRVSN05
      /UNDEFINE PROTOTYPE_WS5PRVSN05
      *
      *  Program entry point
     D WS5TEST05...
     D                 PR
      *
      *  Sends a message to the command line.
     D sndMsg...
     D                 PR                  extproc('sndMsg')
     D  i_text                      128A   value  varying
      *
      * =====================================================================
      *  Program entry point
      * =====================================================================
     D WS5TEST05...
     D                 PI
      *
      *  Web service error message text
     D errText         S                   like(wsdl_errText_t ) inz
      *
      *  Request message
      *  These fields needs to be filled with reasonable values
      *  right before calling the web service.
     D in0             DS                  likeds(apachesoap_AnyMap_t)
     D                                     inz
     D in1             S                   like(impl_in1_t)
     D                                     inz
      *
      *  Response message
      *  This structure contains the result values returned by
      *  the web service.
     D getRGDeviceDetailsRpc...
     D                 DS                  likeds(impl_getRGDeviceDetailsRpc_t)
     D                                     inz
      *
      *  Text of messages sent to the command line
     D text            S            128A   varying inz
     D paircount1      s              5u 0 inz
     D paircount2      s              5u 0 inz
     D set#            s              5u 0 inz
     D set2            s              5u 0 inz
     D DisplayThis     S             52A   varying inz
     D PairKey         S             64a   varying inz
     D PairValue       S             64a   varying inz
     D outerKey        S             64a   varying inz
     D outerValue      S             64a   varying inz
     D Fullstring      S            150a

2/25 d NotNested       dS                  qualified
     d key                           64a   varying
     d value                         64a   varying
      * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      /free

         // Enable/disable http api debug log
         // (Enable the http api debug log in case of problems with the web service)
test   Provision_Port_setHttpDebug(
test               *ON: '/tmp/httpapi_debug.txt');   // Default path of http api

         // Specify a proxy server if your network requires it.
         // Provision_Port_setHttpProxy(
         //    'your.proxy.server': 8080);

         // Set the paramater values of the request message
         // of the web service.
         //    assign values here
         // Set number of array items:
         in0.item.x = 1;
         // Set array item values:
         in0.item.anyMapItem(in0.item.x).key = 'upstreamDevicePort';
         in0.item.anyMapItem(in0.item.x).value = '192.168.31.42_4.5';
         in1 = '';

         // Now let's call the web service.
         getRGDeviceDetailsRpc =
            Provision_getRGDeviceDetails(
                in0:
                in1:
                errText);

       // If the Web service finished successfully ...
 B01   if (not Provision_Port_isError());
          // ... get response data from response data structure


          paircount1 = getRGDeviceDetailsRpc
                      .getRGDeviceDetailsReturn
                       .item
                        .x;

          DSPLY ('item x is ' + %editc(paircount1 : '3') + '.');

          if paircount1 > 0;
             for set# = 1 to paircount1;
             paircount2 = getRGDeviceDetailsRpc
                           .getRGDeviceDetailsReturn
                            .item
                             .mapItem(set#)
                              .value
                               .item
                                .x;

                if paircount2 > 0;
          DSPLY ('inner pairs: ' + %trim(%editc(paircount2 : '3')) + '.');
                   for set2 = 1 to paircount2;
                      PairKey = getRGDeviceDetailsRpc
                           .getRGDeviceDetailsReturn
                            .item
                             .mapItem(set#)
                              .value
                               .item
                                .anyMapItem(set2)
                                 .key;

                      PairValue = getRGDeviceDetailsRpc
                           .getRGDeviceDetailsReturn
                            .item
                             .mapItem(set#)
                              .value
                               .item
                                .anyMapItem(set2)
                                 .value;

                      Fullstring = %trim(%editc(set# : '3'))
                                           + '/'
                                           + %trim(%editc(set2 : '3'))
                                           + ': '
                                           + PairKey
                                           + ' => '
                                           + PairValue;

                      displayThis = %subst(Fullstring : 1 : 52);

          DSPLY (displayThis);
                   endfor;

                else;
2/25               // Can we can get a view of the "simple" key/value pair
2/25               // by splitting them out in a data structure?
2/25               NotNested = getRGDeviceDetailsRpc
2/25                          .getRGDeviceDetailsReturn
2/25                           .item
2/25                            .mapItem(set#);

2/25               outerKey = NotNested.Key;
2/25               outerValue = NotNested.Value;

       //            outerKey = getRGDeviceDetailsRpc
       //                       .getRGDeviceDetailsReturn
       //                        .item
       //                         .mapItem(set#)
       //                          .key;
       //            outerValue= getRGDeviceDetailsRpc
       //                       .getRGDeviceDetailsReturn
       //                        .item
       //                         .mapItem(set#)
       //                          .value
2/25   //                          .item
2/25   //                           .anyMapItem(1)
2/25   //                           .value;

                   if outerKey <> *blanks
                    or outerValue <> *blanks;
                      Fullstring = %trim(%editc(set# : '3'))
                                   + ': '
                                   + outerKey
                                   + ' => '
                                   + outerValue;
                      displayThis = %subst(Fullstring : 1 : 52);
          DSPLY (displayThis);
                   endif;
                endif;
             endfor;
          endif;
           //  exec sql
           //  insert into RGDevDetls
           //         (Order#, Phone#, PairKey, Pairvalue)
           //  values (:Order#, :Phone#, :PairKey, :Pairvalue)
           //    with nc;

 X01   else;
          // ... else show error messages ordered by priority:
          // 1. HTTP error information
          text = %char(
                      Provision_HttpError_getCode()
                      ) + ': ' +
                   Provision_HttpError_getText()
                   ;
          sndMsg(text);
          // 2. SOAP error information
 B02      if (Provision_SoapError_getCode()
                  <> '');
             text = Provision_SoapError_getCode()
                      + ': ' +
                      Provision_SoapError_getText()
                      ;
               sndMsg(text);
 E02        endif;
            // 3. XML parser error information
 B02        if (Provision_XmlError_getCode()
                  <> 0);
               text = %char(Provision_XmlError_getCode())
                      + ': ' +
                      Provision_XmlError_getText()
                      ;
               sndMsg(text);
 E02        endif;
 E01     endif;

         *inlr = *on;

      /end-free
      *
      * =====================================================================
      *  *** private ***
      *  Sends a message to the command line.
      * =====================================================================
     P sndMsg...
     P                 B
      *
     D sndMsg...
     D                 PI
     D  i_text                      128A   value  varying
      *
      *  Local fields
     D msgKey          S              4A   inz
      *
      *  Qualified message file name
     D qMsgF           DS                  qualified inz
     D  name                         10A
     D  lib                          10A
      *
      *  API error code
     D errCode         DS                  qualified inz
     D  bytPrv                       10I 0
     D  bytAvl                       10I 0
     D  excID                         7A
     D  reserved                      1A
     D  excDta                      256A
      *
      *  Send Program Message (QMHSNDPM) API
     D QMHSNDPM        PR                         extpgm('QMHSNDPM')
     D   i_msgID                      7A   const
     D   i_qMsgF                     20A   const
     D   i_msgData                32767A   const  options(*varsize )
     D   i_length                    10I 0 const
     D   i_msgType                   10A   const
     D   i_callStkE               32767A   const  options(*varsize )
     D   i_callStkC                  10I 0 const
     D   o_msgKey                     4A
     D   io_ErrCode               32767A          options(*varsize )
      * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      /free
         clear qMsgF;
         qMsgF.name = 'QCPFMSG';
         qMsgF.lib  = '*LIBL';
         clear errCode;
         errCode.bytPrv = %size(errCode);
         QMHSNDPM('CPF9897': qMsgF: i_text: %len(i_text): '*INFO'
                  : '*CTLBDY': 1: msgKey: errCode);
         return;
      /end-free
      *
     P sndMsg...
     P                 E
      * 
-----------------------------------------------------------------------
This is the FTPAPI mailing list.  To unsubscribe, please go to:
http://www.scottklement.com/mailman/listinfo/ftpapi
-----------------------------------------------------------------------