RPG Beans from VB Apps
June 3, 2009 Hey Mike
Recently we implemented the use of RPG beans on the iSeries. Some of us like it, some of us hate it. I think it’s great because I have some exposure to C# and Java.
We also benchmarked it for performance and didn’t find any problems in the iSeries side. We are planning on instantiating the RPG beans from VB apps. Do you know if there are any performance issues from instantiating the RPG beans from a VB application?
Do you know if someone has done any research related to this topic?
You pose two very good questions:
Before I throw out some answers, let’s get a little background for our readers.
When referring to an “RPG bean,” Frank is referring to encapsulating database logic within an RPG service program. (Don’t confuse this “bean” with the RPG “call bean,” which allows Java to call an RPG program.) This type of programming approach is primarily borrowed from the object-oriented world where an object is created to represent a database object, usually a table.
Once a database object or bean is available, application programs no longer need to query or update the database directly, but rather they call methods (subprocedures in RPG lingo) of the object to do things like get and set field values (commonly known as “getters” and “setters”) and perform CRUD (create, read, update, and delete) operations. The benefit of this approach is that complex validations and relationships, can be written in a powerful and re-usable high-level language routine, rather than attempting to code all the rules at the database level with constraints, referential integrity, etc.
If all application programs make use of an object or bean instead of coding directly against the database itself then:
Of course it doesn’t take a brain surgeon to figure out that it is more difficult to write a bean service program to encapsulate a database table than to write some SQL or native I/O to get the job done. Yes, it takes lots of time and discipline to take the bean approach. However, the long term ease of maintenance and consistent interface are supposed to merit the extra up-front work.
As it turns out, Joel Cochran has already written a few nice articles for IT Jungle on this very topic:
Joel also has a site called RPGBeans.com that provides many resources on encapsulation and even offers a free utility to generate a service program bean from a database table. This kind of code generation tool takes much of the grunt work out of encapsulating a database table with RPG.
Now for the bad news. When using an RPG service program in a client/server environment, (the language doesn’t really matter whether VB, C# or Java) there is no direct way to create (i.e., instantiate) an RPG service program and call its subprocedures. There are indirect methods including creating any of the following kind of wrappers around your RPG subprocedures: SQL functions and stored procedures, Java Call Beans, and Web Services.
In VB 6, one of the easiest ways to talk to an RPG program or service program is via SQL using the ActiveX Data Objects (ADO) library and the IBM ODBC driver or OLE DB providers. This means you need to first define an SQL wrapper for your bean’s public subprocedures using the CREATE PROCEDURE or CREATE FUNCTION statements. If you have a bean object with many getters and setters, for example, then you’ll have many SQL wrappers to define. Further, each time a service program method is accessed, it requires the client program to make a round trip to the server, which carries a performance penalty. While you noted that there is not a discernable penalty for using this method for server based operations, this may not be the case in a client/server environment because there is now network traffic and database server jobs being thrown into the equation.
So to answer your first question, yes there can be a performance penalty for using an RPG service program bean from a client/server application. Of course if there are a small number of users and a small number of subprocedure calls then it may not be a big deal–it largely depends on the situation.
Another aspect of using a bean approach involves the concept of maintaining “state.” Traditional interactive RPG programs are examples of programs that maintain state. Maintaining state simply means that the program can generally rely on its resources being continuously available (think of open data paths, display files, etc.), and being able to depend on enforcing the user interface logic to lead a user down a certain series of steps to accomplish a task. In other words, a traditional interactive RPG program generally doesn’t have to worry about losing or disconnecting from its resources whether database, data area, etc., and it doesn’t have to worry about the user doing things outside of its control.
In contrast, many modern applications like Internet/intranet apps are designed to be “stateless” (or at least semi-stateless). If hundreds of users are using their Web browser to review finance transactions on a company intranet, developers don’t necessarily want to leave hundreds of database connections open in anticipation of the next query because we never know how long it will be before the user makes his next move. In general, these applications open a database connection, do their thing, and immediately disconnect. Also, since the browser client is disconnected from the server (unlike the interactive green screen where everything is interdependent), the server has no control over what the user is doing on his browser.
A stateless application often performs its operations with no assumptions about what the user may have already done (i.e., a browser based app can’t necessarily force the user to follow certain steps.) While many complex Web applications do have to maintain some form of state (tracking a user’s shopping cart requires a unique shopping cart key, for example, to identify the user’s items), they generally connect to the database or other resource, perform a task, and then immediately disconnect again until the next operation. In summary, stateless programming is very important in Web development because you never know when your user will drop, surf somewhere else for an hour, or hit the browser’s back button when they’re not supposed to!
In the client/server world, a client/server app could be designed to maintain state or to be stateless, depending on the situation. To maintain state, the database connection could be left open for a long period of time under the assumption that the user will do something in a relatively short order. Like a 5250 app, a VB client can have firm control over what the user will do and how the user will do it.
One thing is for sure, when using an RPG bean from a client/server app, you’ll want to open a database connection (with correct library list, etc.), call all the necessary subprocedures consecutively to accomplish your task, and then optionally close the database connection.
If there are a large number of subprocedure calls to your bean, then one good way to improve performance is to create a “wrapper” subprocedure with all the parameters required to perform a specific function. For example, consider an INSERT row subprocedure wrapper. This wrapper will call all relevant field setters and then attempt to perform the INSERT. These wrappers will allow your client/server application to remain “stateless” and improve performance by only requiring one call (with many parameters). In contrast, calling subprocedures individually requires some degree of state maintenance because each successive call may depend on the prior call completing successfully. (I.e., you can’t call an insert subprocedure before you call the requisite setters.)
Also, if you’re concerned about the cost of the database engine creating an instance of a large service program, then consider leaving the database connection open. As long as the connection is open and the activation group remains active, your service program will maintain state between calls to the various subprocedures. If you don’t have that luxury of leaving the connection open due to a large number of users, then you may end up paying a performance penalty (depending on the number of users and frequency of calls to the service program).
While we’re on the topic of beans, one other option is to look for (or write yourself) is a code generator that will generate a VB class module with its own getters and setters to represent a database table. This will give you a VB bean that represents a DB2 database table that you can instantiate natively within VB. In any development environment you’ll always get the best performance if you create an object with the environment’s native language(s). VB doesn’t work with an RPG program very well, but it can instantiate a VB class of its own and call the class functions and subroutines with little overhead.
The drawback of this method is that the RPG bean logic will have to be duplicated in the VB bean code. The more validation rules you can push to the database level (such as constraints, and, if your database philosophy allows, triggers), the less logic you will need in RPG/VB. Either way, this VB bean approach can simplify coding and help performance on the VB side.
Finally, to answer your second question, I don’t know of any research off the top of my head (although I haven’t looked.) It is intuitive that doing an INSERT SQL statement directly into a DB2 table from VB is quicker that making multiple calls to encapsulated setter methods, or even a single call to an RPG program containing parameters for each field, which in turn calls the setters internally. However, developers have often moved away from the traditional INSERT for security and other reasons outlined in this tip. In the client/server world, a large number of server calls to RPG logic can hinder performance unless additional wrappers are implemented to allow a large number of operations to be completed in a single step.
Hope that helps!
Michael Sansoterra is a programmer/analyst for i3 Business Solutions, an IT services firm based in Grand Rapids, Michigan. Send your questions or comments for Mike to Ted Holt via the IT Jungle Contact page.