Your RPG programs handle the business logic your organization depends on - the validation, the calculations, the workflows that have been running correctly for years. Nobody wants to rewrite that logic. But right now, the only way to reach it is a 5250 green screen, and the web application your agency is building doesn't speak 5250. Neither does the dashboard your trading partner needs, or the mobile app your field staff have been asking about.
Exposing Your Business Logic
You can bolt an API onto the IBM i itself - IBM's Integrated Web Services has done it for years, and middleware products do the same over the network. Either way, every API call becomes another job on the machine that runs your nightly batch, your order entry, your month-end close. A new web application means new traffic, and it lands on a system you size carefully and license by the core.
The alternative is to move that workload off the machine. Triton RPG compiles your RPG programs - source unchanged, still maintained by your team - to run on ordinary servers: Linux, a container, a cloud VM. The API traffic lands there instead.
A thin Java HTTP layer handles the routing, and the compiled programs connect back to your Db2 for i through JDBC. This allows for perfect interoperability with all of your existing RPG programs.
Here is what that looks like, using IBM's Company System - a department-and-employee CRUD application written in SQLRPGLE with DDS display files. A program not too dissimilar from those running countless businesses today.
From Green Screen to JSON
The Company System's department listing is a display-file program called DEPTS. On the IBM i, it renders a 5250 screen with a subfile full of department records. After compilation with Triton RPG, the same program runs on the JVM - and the Triton host API intercepts its screen output instead of sending it to a terminal.
Here's the Java method that calls it:
public List<Dto.Department> listDepartments() {
ListCapture cap = new ListCapture();
host.run(new DEPTS(), cap);
List<Dto.Department> out = new ArrayList<>();
for (RpgRecord r : cap.rows()) {
out.add(new Dto.Department(
r.getString("XID").trim(),
r.getString("XNAME").trim()));
}
return out;
}
ListCapture tells the host to run the DEPTS program, read whatever it writes to its subfile, and hand back the records. The RPG fills its subfile with department data exactly as it always has. It just never reaches a terminal.
The HTTP route that exposes this is one line:
app.get("/departments", ctx -> ctx.json(svc.listDepartments()));
Request comes in. The compiled RPG program runs. Subfile records come back. A DTO maps the RPG field names - XID, XNAME - to clean JSON keys. Response goes out. The RPG source is identical to what ran on the IBM i.
RPG Procedures as Java Methods
Not all RPG lives behind a display file. If your code has nomain service modules - programs built as reusable procedure libraries with exported functions - those exports become ordinary Java method calls after compilation.
The Company System's empdet module exports getDeptDetail and getEmployeeDetail as callable procedures. After Triton compiles it, the Java service calls them directly:
try (Connection c = ds.getConnection()) {
EMPDET e = new EMPDET();
e.setActivationGroup(new RpgActivationGroup());
e._initSql(c);
var r = e.getDeptDetail(new RpgString(deptNo, 3));
if (!r.found) return Optional.empty();
return Optional.of(new Dto.DepartmentDetail(
deptNo.trim(),
r.deptname,
r.location,
r.totalsalaries.toBigDecimal()));
}
No screen interaction. No host API. The compiled RPG module gets a database connection, the procedure runs, and it hands back a result object whose fields - found, deptname, totalsalaries - are named for the RPG procedure's own return parameters. The DTO layer maps them to clean JSON on the way out.
This is the path for well-structured RPG: service programs, nomain modules, exported procedures. After compilation, they're a Java library.
An AS/400 REST API in 310 Lines of Java
The entire Java adapter - HTTP server, service layer, data transfer objects - is 310 lines across three files:
- App.java - HTTP routes and error mapping: 96 lines
- CompanyService.java - calls the compiled RPG: 172 lines
- Dto.java - maps RPG field names to JSON: 42 lines
That is the only new code. The business rules, the validation logic, the data access patterns, the calculations - all of it stays in the RPG, where it has been tested and running for years. The Java layer is plumbing: it maps URL paths to RPG program calls, and maps RPG field names to JSON keys. If the plumbing is the most interesting part of your system, something went wrong somewhere else.
And 310 lines is small enough to audit. An afternoon of reading tells you exactly what the API does.
Everything Else Keeps Running
The compiled RPG in the container connects back to your Db2 for i through JDBC and the jt400 driver - same database, same tables, same data. The RPG programs you haven't moved yet still run on the IBM i. The ones behind the API run on the JVM. They share the database.
The IBM i keeps serving database queries - work it was already doing - while the program execution behind the API happens off the machine. The workload that's new and hard to predict runs on servers you can add to; the workload the machine has always handled stays put.
This is not a big-bang migration. You pick the programs that need an API, compile them with Triton RPG, put them behind HTTP, and everything else stays where it is. The API programs and the green-screen programs coexist because they're reading and writing the same Db2.
Need your RPG programs behind a REST API?
Start a Conversation