EXFMT and the web
Converting an RPG online application to a Java web application requires an inversion of control:
- In RPG, the interaction is controlled by the program, which calls the EXFMT instruction whenever it decides to interact with the screen.
- In a web-based application, the interaction is controlled by the web client (the browser), and the program reacts to requests from the client.
How should the program be converted in order to implement this inversion of control?
In technical terms, this is called a continuation-passing transformation. Namely, the program stops and returns as result a “continuation” object. Later, the program can be restarted from the same point with the same state by calling this continuation.
However, such a transformation changes the entire structure of the code, like pulling a sock inside out. This would lead to code that is not very intuitive to understand, and quite different than the legacy code.
Some programming languages offer continuations as first-class objects so that such complex transformations are not required. But what about Java?
Actually Java has a construct that mimics continuations, although you have heard of it only as a construct for parallel programming: Threads. You can stop a thread, and restart it later exactly from where it stopped.
Here is an example of a simple RPG online program:
FSCRFM CF E WORKSTN C MOVEL *BLANK FIRST C MOVEL *BLANK LAST C EXFMT SCRR1 C FIRST CAT LAST FULL C EXFMT SCRR2
It reads first name and last name from the first screen, and displays their concatenation on the second screen. The Neograms converter converts it to the following Java code:
public class Pgm { public void main() { scrfm.scrr1.first = " "; scrfm.scrr1.last = " "; scrfm.scrr1.exfmt(); scrfm.scrr2.full = scrfm.scrr1.first + scrfm.scrr1.last; scrfm.scrr2.exfmt(); } }
The magic works because the program and the web request are processed in separate threads. In our example, we use the stand-alone web server Spark and create a new thread to run the program:
// Launch the program in a separate thread Thread t = new Thread(() -> { new Pgm(screen).main(); }); t.start();
Your application server may not allow you to create threads, but it will always offer a way to run code in a thread pool managed by the server.
The actual inversion of control happens inside the Java code for exfmt() :
public void exfmt() { // Send the response to the previous GET or POST request String response = htmlResponse(); // Create HTML from fields file.responseChannel.put(response); // Then wait for a request and process it QueryParamsMap request = file.requestChannel.take(); processPost(request); // Set field values from request data // And return control to the caller }
requestChannel
and responseChannel
are two synchronous queues that let threads wait until both are ready to communicate.
Et voilà ! Your RPG program is turned into a live web application !
In a future article, we will see how to create nice web pages by automatically converting DSPF display attributes to CSS classes.