LESSON 6 · Advanced

Modern RPGLE: modules, service programs & runtime

Plain-English notes, safe code skeletons, IBM i commands, and a checkpoint you can use before opening the deeper question bank.

After this lesson

Learning notes

How the ILE pieces connect

Modern RPGLE usually means fully free source, procedures with clear prototypes, and ILE objects assembled for reuse. The important distinction is between the build-time path and the run-time path: a binding directory helps the binder find providers while an activation group owns the resources used after a program is called.

A simple order application might call an *PGM named ORDENTRY. ORDENTRY uses procedures from an *SRVPGM named ORDERAPI. ORDERAPI is made from one or more *MODULE objects. A *BNDDIR can list ORDERAPI so builders do not repeat every dependency on each create command. At run time, the program and service program activate in a chosen activation group.

  1. Write RPGLE source and define the procedure contract
  2. Compile each source unit into a *MODULE
  3. Package shared procedures in a *SRVPGM and publish deliberate exports
  4. Use a *BNDDIR at build time to resolve only the imports that are needed
  5. Create the runnable *PGM that calls the procedure
  6. At run time, an activation group initializes and owns the program resources

Build a small service, not a giant program

An ILE module is a compiled unit that can be bound into a program or service program. A program is a callable runnable object. A service program exposes reusable exported procedures and data through a binding contract. This separation lets a team change one implementation module and rebuild the affected object without copying the implementation into every caller.

Start an interface discussion with the procedure prototype, parameter types, error contract, and ownership of resources. The object names matter, but the contract is what protects callers. Keep a service program focused: validation, tax calculation, or customer lookup are clearer shared services than one catch-all application library.

Compile a module, then bind the caller

CRTRPGMOD MODULE(APPDATA/ORDERMOD) SRCFILE(APPDATA/QRPGLESRC) SRCMBR(ORDERMOD)
CRTRPGMOD MODULE(APPDATA/ORDENTRY) SRCFILE(APPDATA/QRPGLESRC) SRCMBR(ORDENTRY)
CRTPGM PGM(APPDATA/ORDENTRY) MODULE(APPDATA/ORDENTRY) BNDSRVPGM(APPDATA/ORDERAPI)

Use a binding directory to reduce build noise

A binding directory is an optional convenience for the binding step. It lists modules and service programs the binder may inspect when an import remains unresolved. It is not a run-time registry, a deployment tool, or a way to load code dynamically.

Keep a directory focused on a logical API set. A very large, global binding directory makes builds harder to reason about and can make binding slower. Prefer a small application directory such as APPBND with the service programs the application is designed to use.

Create and use an application binding directory

CRTBNDDIR BNDDIR(APPDATA/APPBND)
ADDBNDDIRE BNDDIR(APPDATA/APPBND) OBJ((APPDATA/ORDERAPI *SRVPGM))
CRTPGM PGM(APPDATA/ORDENTRY) MODULE(APPDATA/ORDENTRY) BNDDIR(APPDATA/APPBND)

Treat binding signatures as compatibility promises

A service program’s binder language describes exported procedures and a signature. When a caller binds to a signature, changing parameter order or type can break the contract. Add a new export for an intentional interface change and keep older exports while callers migrate. Avoid EXPORT(*ALL) for a stable API: it accidentally makes internal procedures part of the public contract.

A good answer distinguishes compile-time binding from run-time lookup and explains how the team detects an incompatible service program before production. Replacing a module alone does not refresh a program that has copied it during static binding; rebuild or update the bound consumer through a controlled release.

Binder language outline

STRPGMEXP PGMLVL(*CURRENT) SIGNATURE('ORDERAPI V2')
  EXPORT SYMBOL('postOrder')
  EXPORT SYMBOL('cancelOrder')
ENDPGMEXP
/* Keep prior signatures when compatibility is required. */

Activation groups define lifetime and cleanup

An activation group is the runtime scope for static storage, open files, SQL cursors, and resources used by ILE programs. *NEW, *CALLER, and named activation groups have different reuse and cleanup behavior. Choose deliberately: reuse can preserve state and reduce setup, while a fresh group can isolate state and simplify cleanup.

*CALLER is often suitable for a cooperating service that should share the caller's scope. A named group can keep a complete application alive across calls when its state and cleanup are managed deliberately. *NEW gives a separate fresh group. When an issue appears, ask which object opened the resource, which group owns it, and what happens on return or reclaim. Do not fix a leak by changing the group attribute without understanding the lifecycle.

Inspect compiled attributes

DSPPGM PGM(APPDATA/ORDENTRY)
DSPSRVPGM SRVPGM(APPDATA/ORDERAPI)
WRKOBJ OBJ(APPDATA/*ALL) OBJTYPE(*PGM)

Open the detailed question chapters

Practice checkpoint

Answer all five, then review the explanations. The interactive site stores your completed learning checkpoints in this browser.

  1. 1. Can CL CALL directly execute a standalone *MODULE?
    1. Yes, always
    2. Only if the source is free-form
    3. Only in QTEMP
    4. No
  2. 2. What is copied into a program during binding?
    1. Selected module code
    2. Every job in QBATCH
    3. All source members automatically
    4. The entire library list
  3. 3. What does a binding directory provide?
    1. Runtime message storage
    2. Candidates for resolving imports
    3. A list of active jobs
    4. A record-format buffer
  4. 4. How are service-program functions normally called?
    1. By CALL directly to *SRVPGM
    2. By RCVF
    3. Through exported procedure references
    4. By adding a job queue entry
  5. 5. Replacing a *MODULE alone updates all bound consumers:
    1. True immediately
    2. True after the next CHAIN
    3. True only for CL callers
    4. False
Show answer key and explanations

1. D — No Modules must be incorporated into a callable program or service program.

2. A — Selected module code Bind by copy incorporates selected modules into the resulting object.

3. B — Candidates for resolving imports It is used by the binder to find exports for unresolved imports.

4. C — Through exported procedure references Consumers bind to exported procedures rather than treating the service object as a normal program entry.

5. D — False Consumers contain copied code and need an appropriate update or rebuild.

IBM documentation for this path