Exposing RPGLE as Webservices - Build the Backend on IBM i

This lesson focuses on the IBM i side: creating Physical Files (PFs) for data storage and structures, then building a robust RPGLE program for CRUD basics. By the end, you'll have a callable module ready to power API endpoints. No prior web service experience required, just solid RPGLE fundamentals.

Why Use RPGLE for Web Services?

IBM i handles high-volume transactions well, such as in banking or inventory. Expose that with RESTful APIs. Keep data logic in RPGLE for rules, validation, and I/O. Use JavaScript for HTTP. You gain these.

  • Centralized Logic one program serves multiple frontends (web, mobile, etc.).
  • The RPGLE program serves web and mobile frontends written in normal style as your existing IBM i Applications.
  • Native DB2 access runs faster than middleware database access.
  • IBM i auth and auditing add security leverages IBM i's built-in auth and auditing..

Enough burble... we now what we want to do "learn how to create a simple webservice using iTOOLKIT and RPGLE" so let's dive in let's build the database foundation and an RPGLE program to read and serve that as a webservice. Then we will cover the JS wrapper and go through some testing with a free tool like SOAPUI or Postman.

Step 1: Set Up Test Data with Physical Files

Define our database first, we will create a very simple physical file for food ingredients - this is how you guess I am feeling hungry!

First let's create a sample library (aka schema) for this example:

CRTLIB LIB(FOODLIB)
  TYPE(*TEST)
  TEXT('Sample Library for WEBSERVICE Lesson')
  CRTAUT(*USE)
Exposing RPGLE as Webservices - Build the Backend on IBM i 1

Here’s a classic DDS layout for FOODFILE, because this webservice will track basic ingredient info:

A R FOODREC
A   INGID     10S 0 TEXT('Ingredient ID')
A   INGNAME   30A   TEXT('Ingredient Name')
A   CATEGORY  20A   TEXT('Ingredient Category')
A   MEASURE   10A   TEXT('Measurement Unit')
A   QUANTITY   7S 2 TEXT('Quantity Available')
A   EXPDATE    L    TEXT('Expiration Date')
A   ORGANIC   1A    TEXT('Organic? Y/N')
A K INGID

Let's assume each of these fields (aka Columns) means this:

INGID: Primary key, numeric ID.
INGNAME: Ingredient name (e.g., "Tomato").
CATEGORY: Type (e.g., "Vegetable", "Spice").
MEASURE : Measurement unit (e.g., "grams", "ml").
QUANTITY: Decimal quantity.
EXPDATE: Expiration date.
ORGANIC: Flag for organic status.

Create this DDS in an IBM i Source File, or from your VSCode development environment. Once created you need to populate it with some sample data. You can use DFU to manually enter the data.

Alternately - let's give old fashioned DDS the boot and do this simply, quickly and easily with SQL:

SQL DDL Equivalent

If you're modernizing with SQL, here’s the equivalent CREATE TABLE statement:

CREATE TABLE FOODLIB.FOODFILE (
INGID DECIMAL(10,0) NOT NULL PRIMARY KEY,
INGNAME VARCHAR(30) NOT NULL,
CATEGORY VARCHAR(20),
MEASURE VARCHAR(10),
QUANTITY DECIMAL(7,2),
EXPDATE DATE,
ORGANIC CHAR(1) CHECK (ORGANIC IN ('Y', 'N'))
);
Exposing RPGLE as Webservices - Build the Backend on IBM i 2
Exposing RPGLE as Webservices - Build the Backend on IBM i 3

SQL Enhancements:

VARCHAR allows flexible text storage.
CHECK constraint ensures valid organic flag.
DATE type for expiration is more precise than L in DDS.

Bonus: Sample Insert

Now lets throw in some sample data for using in our code examples

INSERT INTO FOODLIB.FOODFILE (INGID, INGNAME, CATEGORY, MEASURE , QUANTITY, EXPDATE, ORGANIC) VALUES
(1001, 'Tomato', 'Vegetable', 'grams', 250.00, '2025-11-01', 'Y'),
(1002, 'Basil', 'Herb', 'grams', 50.00, '2026-06-15', 'Y'),
(1003, 'Olive Oil', 'Pantry', 'ml', 500.00, '2027-03-01', 'N'),
(1004, 'Parmesan', 'Dairy', 'grams', 200.00, '2025-12-10', 'N'),
(1005, 'Black Pepper','Spice', 'grams', 30.00, '2028-01-01', 'N');

We now have a sample file, ready to be served up to the internet, or any external system.

But first, let's consider some important security considerations.

{"email":"Email address invalid","url":"Website address invalid","required":"Required field missing"}
>