• The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
Menu
  • The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
  • Guru: Consuming A REST Web Service Using SQL And GET

    September 18, 2017 Mike Larsen

    The use of web services in the industry continues to grow, and sometimes it can be challenging to find information on how to work with them on IBM i. So, what is a web service? In a nutshell, web services allow systems to communicate via the web using file formats such as JSON and XML.

    This article demonstrates how to consume a REST web service using SQL. The example I’m working with uses the ‘GET’ verb to retrieve information from an Amazon Web Service (AWS). I created a simple REST Amazon Web Service that retrieves information about a pet from a pet store database. I pass a pet ID to the service and it returns the pet ID, pet type, and price of the pet. The expected result when consuming the pet store web service is:

    {
      "id": 1,
      "type": "dog",
      "price": 249.99
    }

    Since the web service returns a JSON table, I parse the results and write them to a DB2 table so I can view them. Let’s step through each section of code.

    This story contains code, which you can download here.

    I begin by populating a variable that holds the URL to the web service. The last position of the URL contains the pet ID (1) I’m inquiring about.

    // this would be a soft-coded parameter passed to the program
    
       WebServiceUrl = 'https://um3q1dvnv6.execute-api.us-east-1.amazonaws.com/' +
                       'test/pets/petstorewalkthrough/pets/1';
    

    Next, I clear the DB2 table that stores the results from the web service to make sure I only have the results from the latest invocation.

    // clear the output file before consuming the web service
    
    Exec sql
      Delete from pet_Get;
    

    Pretty easy so far, right? Here’s where it gets interesting. The following section of code does the majority of the work. I’ll show the entire routine first, before breaking it down piece by piece.

    Begsr ConsumeWs;
    
     Exec sql
       Declare CsrC01 Cursor For
    
         Select * from
           Json_Table(Systools.HttpGetClob(:WebServiceUrl, :WebServiceHeader),
           '$'
           Columns(ws_pet_id    BigInt       Path 'lax $.id',
                   ws_pet_type  VarChar(30)  Path 'lax $.type',
                   ws_pet_price decimal(5,2) Path 'lax $.price')
           ) As x;
    
       Exec Sql Close CsrC01;
       Exec Sql Open  CsrC01;
    
       DoU 1 = 0;
         Exec Sql
             Fetch Next From CsrC01 into :jsonData;
    
            If SqlCode < *Zeros or SqlCode = 100;
    
               If SqlCode < *Zeros;
                  Exec Sql
    
                    // perform error handling
    
                       Get Diagnostics Condition 1
                       :Text = MESSAGE_TEXT;
               EndIf;
    
               Exec Sql
                    Close CsrC01;
               Leave;
            EndIf;
    
            // insert the parsed JSON data into a db2 table
    
            Exec sql
             Insert Into Pet_Get
                         (pet_id, pet_type, pet_price, AddPgm, AddUser,        UpdatePgm,
                          UpdateUser)
                  Values (:jsonData.petId, :jsonData.petType, :jsonData.petPrice,
                          :pgm_stat.ProgramId, :pgm_stat.User,
                          :pgm_stat.ProgramId, :pgm_stat.User);
    
      Enddo;
    
     Endsr;
    

    I declare a cursor, then execute the SQL statement to consume the REST service using the HTTPGETCLOB function. The JSON_TABLE function parses the results returned from the service.

    Declare CsrC01 Cursor For
    
         Select * from
           Json_Table(Systools.HttpGetClob(:WebServiceUrl, :WebServiceHeader),
           '$'
           Columns(ws_pet_id    BigInt       Path 'lax $.id',
                   ws_pet_type  VarChar(30)  Path 'lax $.type',
                   ws_pet_price decimal(5,2) Path 'lax $.price')
           ) As x; 
    

    I pass two parameters to the HTTPGETCLOB function; the web service URL and a Header. In this example, there isn’t a need to pass Header data, so the Header parameter is blank. The URL was populated earlier and is stored in variable WebServiceUrl. HTTPGETCLOB is one of many user-defined functions (UDFs) available on the IBM i that allow us to consume REST web services via HTTP.

    The JSON_TABLE function allows us to decompose JSON JavaScript Object Notation) objects into a relational format. I define the columns and data types of the JSON object I expect to receive as well as a path to where information can be found inside the JSON object. In essence, I provide directions on how to find the data stored in the JSON object.

    Let’s take a look at the directions I give in this example. The ‘$’ tells the function to start with the current JSON object. Next, I define the fields and data types for the columns contained in the JSON object. Finally, I give the path to the data elements. In this case, I tell it to look for the actual column names as defined in the service. The period in the path expression (for example, ‘lax $.id’) directs it to look inside the column id. So, what is that ‘lax’ thing? The SQL/JSON path expression has a mode associated with it. The mode can either be lax or strict. When using ‘lax’ mode, certain error conditions are tolerated when the SQL/JSON path expression is evaluated. When using ‘strict’ mode, error conditions are not tolerated, resulting in a failure.

    The next section of code reads the results returned from the service.

    Exec Sql Close CsrC01;
    Exec Sql Open  CsrC01;
    
       DoU 1 = 0;
         Exec Sql
             Fetch Next From CsrC01 into :jsonData;
    
            If SqlCode < *Zeros or SqlCode = 100;
    
               If SqlCode < *Zeros;
                  Exec Sql
    
                    // perform error handling
    
                       Get Diagnostics Condition 1
                       :Text = MESSAGE_TEXT;
               EndIf;
    
               Exec Sql
                    Close CsrC01;
               Leave;
            EndIf;   
    

    I open the cursor, read through it, and fetch it into a data structure where I process the individual fields. Once I’ve read all the rows, the cursor is closed. The data structure is shown below:

    dcl-ds jsonData qualified;
           petId    zoned(2:0);
           petType  varchar(30);
           petPrice packed(5:2);
    end-ds;  
    

    The last piece of code inserts the data elements retrieved from the web service into a DB2 table.

    // insert the parsed JSON data into a db2 table
    
            Exec sql
             Insert Into Pet_Get
                         (pet_id, pet_type, pet_price, AddPgm, AddUser, UpdatePgm,
                          UpdateUser)
                  Values (:jsonData.petId, :jsonData.petType, :jsonData.petPrice,
                          :pgm_stat.ProgramId, :pgm_stat.User,
                          :pgm_stat.ProgramId, :pgm_stat.User);
    

    After running the program, I view the results stored in the DB2 table using ACS and see the expected results match what was returned.

    This article showed how to use SQL to consume a REST service using the UDF HTTPGETCLOB. As mentioned, there are many other UDFs that can be used as well. In a future article, I’ll show how to use the HTTPPOSTCLOB UDF to consume a REST service, while sending it both a Header and a Body.

    Share this:

    • Reddit
    • Facebook
    • LinkedIn
    • Twitter
    • Email

    Tags: Tags: 400guru, Amazon Web Service, AWS, JSON, REST, XML

    Sponsored by
    WorksRight Software

    Do you need area code information?
    Do you need ZIP Code information?
    Do you need ZIP+4 information?
    Do you need city name information?
    Do you need county information?
    Do you need a nearest dealer locator system?

    We can HELP! We have affordable AS/400 software and data to do all of the above. Whether you need a simple city name retrieval system or a sophisticated CASS postal coding system, we have it for you!

    The ZIP/CITY system is based on 5-digit ZIP Codes. You can retrieve city names, state names, county names, area codes, time zones, latitude, longitude, and more just by knowing the ZIP Code. We supply information on all the latest area code changes. A nearest dealer locator function is also included. ZIP/CITY includes software, data, monthly updates, and unlimited support. The cost is $495 per year.

    PER/ZIP4 is a sophisticated CASS certified postal coding system for assigning ZIP Codes, ZIP+4, carrier route, and delivery point codes. PER/ZIP4 also provides county names and FIPS codes. PER/ZIP4 can be used interactively, in batch, and with callable programs. PER/ZIP4 includes software, data, monthly updates, and unlimited support. The cost is $3,900 for the first year, and $1,950 for renewal.

    Just call us and we’ll arrange for 30 days FREE use of either ZIP/CITY or PER/ZIP4.

    WorksRight Software, Inc.
    Phone: 601-856-8337
    Fax: 601-856-9432
    Email: software@worksright.com
    Website: www.worksright.com

    Share this:

    • Reddit
    • Facebook
    • LinkedIn
    • Twitter
    • Email

    Three Lessons IBM i Shops Can Learn From The Equifax Hack More Database Tools Highlight Latest IBM i Access Client

    11 thoughts on “Guru: Consuming A REST Web Service Using SQL And GET”

    • Alan Shore says:
      September 18, 2017 at 10:27 am

      Hi Mike
      we are on V7r1
      I downloaded the 2 objects – Pet_get and PetWs_get
      Created the table
      But when I attempted to compile the SQLRPGLE program PetWs_get, it did not compile
      The error was with
      Json_Table(Systools.HttpGetClob(:WebServiceUrl, :WebServiceHeader),
      SQL0104 30 106 Position 18 Token ( was not valid. Valid tokens: FOR USE
      SKIP WAIT WITH FETCH LIMIT ORDER UNION EXCEPT OFFSET.

      Is there something I am missing?

      Alan Shore

      Reply
      • Mike says:
        September 21, 2017 at 9:02 am

        Hi Alan. I wrote the programs on an IBM i that is at V7R2. I believe the JSON_TABLE function is only available on 7.2+. Do you have access to a V7R2 IBM i?

        Reply
    • Jack says:
      September 18, 2017 at 2:07 pm

      Mike, Thanks for the article and the complete code. I created the DB and compiled the pgm but am receiving SQL0332 on the Fetch

      “Character conversion between CCSID 65535 and CCSID 1200 not valid.”

      Did you experience this issue at all in your testing?

      Reply
      • Mike says:
        September 21, 2017 at 8:58 am

        Hi Jack. Please try to issue this command on a command line before running the program.
        CHGJOB CCSID(37)

        Let me know if this works for you. Thanks, Mike

        Reply
    • Buck Paiva says:
      December 6, 2017 at 4:31 pm

      Mike. I have a far more complex JSON that I need to consume.Do you have an example of consuming a multi-dimension object? What would would the Json_Table function consider a “row” in this situation? Would it be possible/necessary to just grab the entire object and write to it the IFS and use another tool to parse?

      Reply
      • Buck Paiva says:
        December 6, 2017 at 4:48 pm

        You can delete this. I just checked the documentation. I think I can figure this out.

        Reply
    • Phil says:
      May 23, 2019 at 7:37 pm

      Hi I tried this but I believe the API is no longer valid I am getting message
      User-defined function error on member QSQPTABL.
      Java stored procedure or user-defined function SYSTOOLS.HTTPGETCLOB,
      specific name HTTPG00005 aborted with an exception
      “java.net.UnknownHostException:um3q1dvnv6.execute-api.us-east-1.amazonaw
      s.com”.

      Reply
      • Phil says:
        May 23, 2019 at 7:38 pm

        Additional message info is
        1 — The external program or service program returned SQLSTATE 38000. The
        text message returned from the program is:
        SYSTOOLS.HTTPGETCLOBHTTPG00005<java.net.UnknownHostException:um3q1dvnv6
        .execute-api.us-east-1.amazonaws.com .

        Reply
    • Reynaldo Dandreb Medilla says:
      October 18, 2019 at 7:48 am

      another good article Mike, thanks

      Reply
    • Dave Kirby says:
      March 27, 2020 at 10:32 am

      Hi Mike,
      A really useful article. Using this now but getting issues with security accessing the webservice. With SOAP webservice consume from our iSeries I am using the following and it works OK. Is it a different set up for REST or should the setup below also work before I make the ConsumeWS.
      Thanks.

      // Get Webservice stub.
      clear WsStub;
      WsStub.endpoint = ‘xxxxxxxxxxxxxxxxxx’;

      If (stub_create_PRSSoap(WsStub) = *ON);

      // Initialise the secure settings for the secure service.
      // Disable SSLv2, SSLv2, TLSv1
      NULLSTR = X’00’;
      axiscStubSetSecure(WsStub.handle:
      ‘/QIBM/USERDATA/ICSS/CERT/SERVER/DEFAULT.KDB’:
      NULLSTR: NULLSTR:
      ‘NONE’: ‘NONE’: ‘NONE’ : *NULL);

      // Set username and password
      axiscStubSetUsername(WsStub.handle: ‘xxxxxxxxx’);
      axiscStubSetPassword(wsStub.handle: ‘xxxxxxxxx’);
      endif;

      Reply
    • Keith says:
      August 26, 2021 at 2:31 pm

      Is there a way to change the timeout for ling running web service calls?

      Reply

    Leave a Reply Cancel reply

TFH Volume: 27 Issue: 59

This Issue Sponsored By

  • T.L. Ashford
  • ProData Computer Services
  • WorksRight Software
  • Linoma Software
  • Manta Technologies

Table of Contents

  • Crazy Idea # 542: Port IBM i To The Mainframe
  • More Database Tools Highlight Latest IBM i Access Client
  • Guru: Consuming A REST Web Service Using SQL And GET
  • Three Lessons IBM i Shops Can Learn From The Equifax Hack
  • The State Of Systems In The Second Quarter

Content archive

  • The Four Hundred
  • Four Hundred Stuff
  • Four Hundred Guru

Recent Posts

  • IBM Unveils Manzan, A New Open Source Event Monitor For IBM i
  • Say Goodbye To Downtime: Update Your Database Without Taking Your Business Offline
  • i-Rays Brings Observability To IBM i Performance Problems
  • Another Non-TR “Technology Refresh” Happens With IBM i TR6
  • IBM i PTF Guide, Volume 27, Number 18
  • Will The Turbulent Economy Downdraft IBM Systems Or Lift It?
  • How IBM Improved The Database With IBM i 7.6
  • Rocket Celebrates 35th Anniversary As Private Equity Owner Ponders Sale
  • 50 Acres And A Humanoid Robot With An AI Avatar
  • IBM i PTF Guide, Volume 27, Number 17

Subscribe

To get news from IT Jungle sent to your inbox every week, subscribe to our newsletter.

Pages

  • About Us
  • Contact
  • Contributors
  • Four Hundred Monitor
  • IBM i PTF Guide
  • Media Kit
  • Subscribe

Search

Copyright © 2025 IT Jungle