Using RPG As Your ASP Language, Part 1
April 28, 2004 Howard F. Arner, Jr., and Holley Davis
I have a weird rule about evaluating new software that has served me well throughout my career. If I can’t make the software do something useful or interesting in the first hour, it sucks. And I deduct points if I actually have to read the manual. As many of you know, I am not an RPG programmer. When I program on the iSeries, I use the C compiler. For programming client applications that talk to the iSeries, I use Visual Basic or Prolog, or I program in C.
I know enough RPG to be very dangerous, like a toddler with matches. My partner, Holley Davis, is an exceptional RPG and Java programmer–some would say he’s the real brains in our organization. However, Holley does not do Visual Basic or Visual C++.
Last Wednesday, Holley and I sat down to figure out how hard it would be for an average RPG programmer to begin to develop an ASP-and-Web-based application using ASNA Visual RPG for Visual Studio .NET (AVR for .NET). Not only did we have it doing interesting things in the first five minutes, we also wrote a fully functional Web application in under 90 minutes that interacts with the iSeries and can display stored procedure results. In this two-part series, I will recount our experience with the product and point out some of the pitfalls you might encounter if you decide to use the product.
WHAT IS AN ASP APPLICATION?
Let me digress a moment to explain what an ASP application is. An ASP application allows you to write HTML, along with server-side script, in a programming language. When a browser requests an ASP page, the server reads the HTML and ASP code, executes the code part, and then returns the processed results to the requestor, in HTML. ASP is a neat technology, because you can embed your programming script right into the HTML files, but when users see the page, they do not see the code; they see the results. Most shops using ASP technology code their ASP scripts in Visual Basic or JScript. With the advent of Visual Studio .NET, many shops now code ASP pages in C#. Some Java shops code ASP applications and call them JSP, or JavaServer Pages. This is the same idea: script embedded in Web pages that executes on the server for rendering results to the client. The neat thing about using AVR for .NET is that you can now use RPG as your ASP language. In fact, in the .NET environment ASP programs are no longer scripted; they actually compile to machine-executable code, which offers vast performance improvements over traditional ASP scripted applications.
PREPARATION AND PROJECT SELECTION
I installed the AVR product on a development machine that already contained Microsoft Visual Studio .NET and was configured with iSeries Navigator V5R2. This machine was also set up to act as a Web server (running Windows XP Professional). When Holley arrived, we began to discuss what we wanted to develop in order to test the product.
We decided to produce an application that would allow a user to investigate iSeries-dependent files via a Web browser. The user interface would let the user type in library and file names in a Web form. When the user clicked the “go” button, the form would then communicate with the iSeries to call a stored procedure and return the list of dependent files for the identified file (the procedure does this by calling an API on the iSeries, creating an array of dependent files, and returning the array as an SQL result set). The application would then process the list of returned files to produce an HTML table, listing the file, library, description, and attribute. If the user clicked on any of the returned file names, the Web page would again communicate with the iSeries to retrieve and display the fields in that file (by calling another stored procedure in RPG that calls an API to determine the fields in a file, creates an array of the fields, and returns the array as an SQL result set).
In building a Web application, we were able to evaluate a number of things, like how easy is it to develop a Web application using AVR for .NET, how hard will it be for RPG programmers to “get” doing Web applications with AVR for .NET, how well the Web application and AVR for .NET perform, and how hard is it to integrate with the iSeries using AVR for .NET.
On the iSeries side of our application, we decided to use stored procedures to return results primarily because we already had them written for other, production programs. In this way, we were modeling the “real world” of Web development, in that you are usually calling some process or program to display results in a browser, rather than creating a new program or process. This approach allowed us to evaluate the code reuse abilities of AVR for .NET.
Another decision we made was not to use ASNA DataGate, AVR’s native database access mechanism, for our communication with this iSeries. We chose not to use it because we wanted to evaluate the product based just on the RPG language and its ability to use Microsoft services, like OLEDB and ODBC. We did not want to cloud the evaluation with issues like cost, performance, and use of the DataGate product. Judging by ASNA’s Web site, DataGate might help you write iSeries applications in AVR for .NET or save you time by allowing better record level access, but I wanted to stick with standards like SQL and stored procedures and use IBM’s proven ODBC driver.
With the project design inked out, we began our evaluation of the product. The first step was to select the type of project that we were creating. When you start AVR for .NET, you can select many types of projects, like Web services applications, Windows applications, class libraries, console applications, Windows controls, or ASP .NET Web applications. We choose to create an ASP .NET Web application, and called it WebDBi. Once we supplied the name of the application, AVR for .NET set up the development environment for creating the Web application.
At this point, Holley and I were staring at a blank Web page and wondering what to do next. The first order of business was to create an interface for the user to type in library and file names. So Holley selected the toolbox in Visual Studio and drew two text boxes on the Web form. He then placed a push button on the form and quickly asked, “How do I change the name of the button?” This was quite easy, as pressing F4 when you have an object selected causes a properties window to appear. Via the properties window, you can set various settings, like the text to display in a button, the name of the button, button colors, and more. Figure 1 shows the AVR for .NET development environment, where we edited the Web page and viewed the properties of the “go” button.
Figure 1: The Visual Studio editor makes it easy to set and view object properties
At my prompting, Holley changed the ID properties for the two textbox controls to “lib” and “file,” so that they would be easier to remember than “textbox1” and “textbox2.” I then had Holley place a label control on the Web page that we could use to display debug text during the execution of the program.
Now it seemed like we were ready to go, but what about interaction with the iSeries? To communicate with the iSeries, we needed an ODBC connection. First, I went to the ODBC control panel applet, in the Windows control panel, and set up a system data source, called MYAS400. Why a system data source? Well, if you set up an ODBC data source as a user data source, it is only seen by the user account it was created under. A system data source can be seen by any Windows user account. When ASP Web applications are running on a Windows server, they are running under various system accounts. So, in order to see the ODBC data source, it must be configured as a system data source, not as a user data source. Once the ODBC connection was defined, the question was, how to let our ASP page communicate with the ODBC connection? This was accomplished by dropping an ODBC connection control from the toolbox onto the Web page and setting the connection controls properties to use the ODBC data source we just created. Setting the data source was easy, as once you drop the control on the page, you simply select the control with the mouse, press F4 to view its properties, and click the “connection string” property. A small drop-down icon appears and, when selected, gives you the ability to configure a new connection. By following the screen prompts, we quickly configured the ODBC connection object to communicate with our iSeries.
Now we figured it was time to write some code, so we double-clicked the “go” button on our Web page and were transferred to the code editor. ASP .NET Web pages implement something called “code behind.” Code behind works by maintaining two distinct code files: one for your HTML and presentation code and one for your server-side code. Your HTML file is named page_name.aspx, and the code-behind file is named page_name.aspx.vr. The “vr” extension lets the editing environment know that the page language is Visual RPG. Double-clicking the “go” button let Visual Studio know that we wanted to edit the code associated with the button, so Visual Studio opened the code-behind file for the Web page and positioned us at the Button1_Click event code (Figure 2).
Figure 2: Double-clicking an object in the design window opens the code editor window. Note that a subroutine was automatically added to capture the button click event
Remember, Windows and Web coding are primarily event-driven architectures. You present a page to a user, then the user fills in a form and presses a button. Pressing the button fires a click event in the browser. We wanted to trap the event and cause some code to execute on the server, which is why we needed to trap the Button1_Click event. In the case of our Web application, we want to check that the library and file name boxes were not blank, and if they were not, we wanted to call a subroutine that would get our file data and place it on the Web page. The subroutine shown in Figure 2 does just that.
THE GETFILEDATA SUBROUTINE
Once the button was clicked and the text box contents were verified, we called the subroutine getFileData, which would connect to the iSeries, execute our stored procedure, and return the result set. However, before we continued and wrote the code to display the results of the procedure call, we decided to confirm that the procedure was executing and that the results were returned. To do this, we created code to call the procedure and then set the label control on the client Web page to display how many fields were in the result set returned by the call to the stored procedure. Here is the code that calls the procedure:
begsr getFileData odbcConnection1.Open() dclfld r Type(System.Data.Odbc.OdbcDataReader) dclfld Cmd1 Type(System.Data.Odbc.OdbcCommand) Cmd1 = *new system.Data.Odbc.OdbcCommand() Cmd1.CommandText = "call sqlbook.dspdbrp(?,?)" Cmd1.CommandType = System.Data.CommandType.StoredProcedure Cmd1.Connection = *this.odbcConnection1 Cmd1.Parameters.Add(*new System.Data.Odbc.OdbcParameter("Parameter1", System.Data.Odbc.OdbcType.Char, 10)) Cmd1.Parameters.Add(*new System.Data.Odbc.OdbcParameter("Parameter2", System.Data.Odbc.OdbcType.Char, 10)) cmd1.Parameters(1).value = File.Text cmd1.Parameters(0).value = lib.Text r = cmd1.ExecuteReader() label2.Text= r.FieldCount *This.databind() odbcconnection1.Close() endsr
This subroutine first opens a connection with the iSeries by calling the “open” method of the odbcConnection object we placed on the form earlier. Then the subroutine uses DCLFLD to declare an ODBC DataReader object, which will be used to retrieve the results of our stored procedure call. A data reader can present the results of a stored procedure or SQL statement as a forward only, read only collection of records. Next, we again used DCLFLD to create an ODBC Command object that we would use to call the stored procedure on the iSeries. The next lines initialize the command object and set its properties so that we could call the stored procedure. Once all of the properties were set, we would issue a call to the ExecuteReader method of the command object, which would cause the stored procedure to be executed on the iSeries and the results to be returned to the data reader object. Then we set the text property of the label2 control to the FieldCount property of the DataReader object, in order to tell the user how many fields are in the result set. The next line calls the DataBind method, which causes all bound controls to display their data, and then we close the connection and end the subroutine.
At this point, Holley and I wanted to try out our code, so we pressed F5 in the Visual Studio environment. F5 causes the program to be compiled and, if there are no errors in the environment, it will start a Web browser pointed at the Web page. At first, we had a few errors in our code, and this is where AVR for .NET really shined. By clicking the error in the output window of AVR for .NET, the file containing the offending code was opened and our cursor was placed right at the offending point in the code. This is wicked cool. Once we cleaned up the errors, we were able to run the Web application and test the calling of the procedure, which worked flawlessly.
So far, we have explained how to attach code to browser events and how ASNA’s Visual RPG for Visual Studio .NET development environment lets you program visually. Holley and I were extremely impressed with the language and features of the environment, not to mention how easy it was to use. In the next article in this series, Holley and I will explain how we created interactive grids that displayed the results of our stored procedures, and how we programmed the grids to respond to user events. We’ll also share our opinions of the ASNA product and how easy it will be for RPG developers to use.
Howard F. Arner, Jr., is the author of iSeries and AS/400 SQL at Work and is a consultant at Client Server Development in Jacksonville, Florida. Holley Davis is president of Davis Software and works as a consultant in Jacksonville. Howard and Holley pool their time to create tools for the iSeries, like the Atomic Time Manager 400, SQLThing Enterprise Edition, and Programmer in a Box. You can find out more at www.sqlthing.com or www.fad400.com. E-mail: email@example.com or firstname.lastname@example.org