I often work with IBM i shops on modernization projects. Figuring out how to leverage existing RPG infrastructure is usually critical. It was no accident, then, that the first EGL program I wrote called an RPG program. The mechanism in EGL for calling IBM i programs is better than anything I've encountered in Java and elsewhere. To give you an idea of the power of EGL, I walk you through an EGL call to an RPG program. If you want more information, take advantage of the additional resources listed in Find Out More, below.
EGL is short for Enterprise Generation Language. You write EGL code, and the tooling generates executable code in either Java or Cobol. I tend to think that Java generation is what most of the IBM i audience will use. Because EGL abstracts the target language, it matters little except that Java support is great on the IBM i and not all IBM i shops purchase or install a Cobol compiler.
When I talk about EGL's tooling, I am referring to IBM Rational Developer for System i for SOA Construction (RDi SOA) or Rational Business Developer (RBD). RDi SOA and RBD are Eclipse-based Integrated Development Environments. Today, these are the only tools you can use to write EGL programs.
I've spent a number of years writing Java code for all sorts of applications batch, desktop, web, handheld device, and so on. I've always had an IBM i platform in the mix, with only a few exceptions. Although using Java to leverage data and existing legacy code is possible, it is not usually easy. My biggest complaint is its lack of a primitive data type for working with decimal data. Without a clean way to work with decimal data, parameter passing becomes complicated and business data manipulation in Java is messier than it should be. EGL takes away this pain by providing primitive types for all the data types that a business programmer uses.
In Java, I would cringe at the prospect of calling an RPG program with parameters consisting of nested structures and structures containing arrays (or arrays of structures). As I say, it's hard enough to find compatible data types. EGL understands complex data structures just as RPG does and just as a business language should.
Before you can call an RPG program, your EGL project requires a bit of configuration. It's not much, just an entry in a build descriptor file so that EGL knows something about your program.
Take a look at Figure 1 [2] to see the complete build descriptor for a project I've called SimpleBatch. I added the following linkage attribute to the BuildDescriptor tag to the default build descriptor:
linkage="externalPrograms"
And a <LinkageOptions> node with the same name as the linkage attributes:
<LinkageOptions name="externalPrograms"> </LinkageOptions>
Within the <LinkageOptions> node, I added a <callLink> node containing the <remoteCall> definition of the RPG program that I call in my EGL code:
<callLink >
<remoteCall pgmName="MyRPGPgm"
conversionTable="CSOE037"
library="*LIBL"
location="my_i_server"
luwControl="SERVER"
remoteBind="GENERATION"
remoteComType="JAVA400"
remotePgmType="STATELESS"/>
</callLink>
You can have multiple <remoteCall> definitions within a single <callLink> node. Although I have broken down the remote call definition into multiple lines in my example, it is normally one line in your build descriptor. EGL is all about generation options, but to call an RPG program, you rarely need to change anything but the program name from one program definition to the next. (Figure 2 [3] describes the remote call attributes, and "Remote Program Type Options" on page 32 describes the remotePgmType attribute in detail.)
There is a graphical editor in RDi SOA/RBD for your build descriptor if you prefer to use a visual editor over a text editor. Because many options that appear in the graphical editor don't apply to calling RPG programs on IBM i, I find it less confusing to edit the build descriptor with a text editor.
With the build descriptor description of the program complete, you invoke an RPG program from an EGL program. First, establish credentials for the program call like this:
SysLib.setRemoteUser("DDARNELL", "MYPWD");
(See "Program Call Credentials," below, for a short note on how to avoid hard-coding credentials on calls to the setRemoteUser function.) Next, issue the program call, including parameters on the call as required:
call "MyRPGPgm" (parm1, parm2, parm3);
As long as compatible data types are used by the calling EGL program and the called RPG program, there is nothing difficult about the interaction between the two languages. Figure 3 [4] shows data types commonly used in both EGL and RPG programs.
For an illustration of EGL's capacity to handle complex parameters, look at Figure 4 [5]. The program is designed to return a nested structure to its caller. The single program parameter is defined by the root structure definition. Root is a structure that contains a name and an array of 50 branch structures. Each instance of the branch structure has a number, a name, and an array of 25 item structures. Each instance of the item structure has a number and a name. You can use the overall implementation to model something such as a menu tree with the root menu containing up to 50 submenus (branches) and with each submenu containing up to 25 menu items. In this implementation, you simply loop to fill all the elements.
You can see the EGL side in Figure 5 [6]. At the bottom of the program is a structure definition that exactly matches the RPG program's parameter. In the main() function of the EGL program, this structure is used on a call to the RPG program, and then the contents of the structure are dumped into the console. I would argue that it is actually easier to call an RPG program from EGL than to call an RPG program from another RPG program! Simply issue the call and pass the appropriate parameters. Figure 6 [7] shows a sampling of the console output.
In addition to using EGL for basic program calls, you can also use it to execute procedures in service programs. But this is a topic for another time, as is the data queue support in EGL a feature that might be even slicker than the program call support!
EGL is a business language capable of all the stuff we do today in RPG with equal productivity. Plus, EGL offers tons of other things that we either can't do in RPG today or can do only with great effort. EGL has a wide range of capabilities:
You can even write green-screen applications in EGL via the Text User Interface. Specific connectors and functions for IBM i, WebSphere MQ, J2EE security, and LDAP make it easier to leverage these elements of infrastructure.
In "System i Dev Experts Talk RDi, RDi SOA [8]" (May 2008, article ID 21246 at SystemiNetwork.com), Jon Paris said "EGL looks like a good product for extending RPG applications, but the only substitute for RPG is RPG." If you are interested in extending RPG applications, you should certainly consider EGL. Meanwhile, as you saw in this article, you can easily leverage RPG code from EGL, so you don't have to start from square one as you modernize and create applications outside of RPG's normal scope. I think of this as extending EGL.
Whether EGL can replace RPG is irrelevant because we all know that RPG isn't going anywhere anytime soon. In the end, you have to decide for yourself whether you need to replace RPG or just extend it. For most of my clients, replacement isn't an option, but EGL lets them extend what they have and create new applications in areas where EGL excels and RPG does not while still easily leveraging some existing RPG infrastructure. In the real world, I don't think it gets better than that.
Dan Darnell is the author of the book Java and the AS/400 Second Edition (29th Street Press), and an independent consultant in Little Rock, Arkansas. Dan wishes to thank Rusty Gadberry at Arkansas Data Services for his vision and support.
EGL Café [9] (for all things EGL, including forums, blogs, videos, and other resources)
EGL Documentation [10]
IBM Rational Business Developer Trial Version [11]
You can externalize the credentials by prompting for them or by storing them in a properties file or resource bundle and retrieving them at runtime. EGL provides a mechanism for easily encrypting and decrypting strings should you desire to store the password in a properties file. If you create a properties file called csouidpwd.properties in the JavaSource folder of your project, that file will automatically establish credentials for your program call (no call to setRemoteUser is required). Create two entries in your csouidpwd.properties file:
CSOUID=userID CSOPWD=password
D.D.
When making calls to RPG programs, you have three options to consider for the remotePgmType attribute of a remote call definition.
The STATEFUL option applies to EGL web applications, where a connection is made to your IBM i server and stored in the web session. Repeated calls to a program are over the same connection. Each web session gets a unique connection, making it possible to do things such as calling an RPG program to return a list of items to a web application one page at a time, with the RPG program keeping a file or result set open between calls.
Specify the STATELESS option when making calls to RPG programs from EGL batch applications or EGL web applications that do not require maintaining a state in the called program.
The STATEFUL and STATELESS options apply only to the IBM i, and both use the IBM Toolbox for Java connection pool support (the remoteComType attribute must be JAVA400 to use these options). Any commit or rollback operations must be handled in your RPG code rather than in your EGL program logic.
The third option for making a remote program call is EXTERNALLYDEFINED. With this option, your program is called via some EGL middleware that you put on your IBM i server. The middleware lets you do things in EGL to handle commit and rollback functions instead of accommodating these actions in your native code.
For this mechanism to work, you need to restore the QEGL library to your IBM i server. This library is distributed with RDi SOA/RBD as a save file within a PC file named QEGL.ZIP. After you unzip the file, you can copy its contents to a save file on your IBM i server and restore the QEGL library. In addition to the runtime middleware, the QEGL library contains source code for a CL program that you have to create in your application's library. The source member for the CL program is called QVGNRNCL and is in the source file QVGNSAMP. Simply compiling QVGNRNCL in your application's library is enough to get you going. However, to understand the options available to you with a program call of the EXTERNALLYDEFINED type, you should reference the manual EGL Server Guide for iSeries through the RDi SOA/RBD product help.
The benefits of the EXTERNALLYDEFINED program call option (handling commitment control actions from your EGL code) can be worth the added complexity of the setup required, but unless you really need this degree of EGL control over commitment control, I recommend you stick with the simpler STATELESS or STATEFUL calls.
D.D.
Links:
[1] http://systeminetwork.com/author/dan-darnell
[2] http://systeminetwork.com/files/62294-Fig1.html
[3] http://systeminetwork.com/files/62294-Fig2.gif
[4] http://systeminetwork.com/files/62294-Fig3.gif
[5] http://systeminetwork.com/files/62294-Fig4.html
[6] http://systeminetwork.com/files/62294-Fig5.html
[7] http://systeminetwork.com/files/62294-Fig6.html
[8] http://systeminetwork.com/article/system-i-dev-experts-talk-rdi-rdi-soa
[9] http://www-949.ibm.com/software/rational/cafe/index.jspa
[10] http://www-949.ibm.com/software/rational/cafe/community/egl/documentation
[11] http://www-949.ibm.com/software/rational/cafe/docs/DOC-1384