Your
ticket to platform independence
WebSmart Java Servlet Edition (JSE) is an enhanced version of WebSmart that allows you to deploy your WebSmart program definitions using Java Servlet technology. Although it is shipped as part of every copy of WebSmart version 3.0 or higher, a separate security code is required in order to use the product. You can Install the latest version of WebSmart JSE for evaluation purposes, and obtain a security code from the BCD sales office at 630-986-0800.
You can also download the WebSmart JSE Runtime package from our website. This installs Java and the Tomcat servlet engine on any machine running a Windows operating system, and allows you to run WebSmart JSE demonstration applications on the local system. You can also create your own WebSmart JSE servlets and copy them to the Windows system for execution. This illustrates the platform independent nature of programs produced using the product, and frees you from the need to configure a Web server and servlet engine on the iSeries while evaluating the product.
This white paper outlines the differences between the original RPG CGI version of WebSmart and the Java Servlet edition, so if you are looking for general information concerning the product, please refer to the Unleash iSeries Data on the Web with ProGen WebSmart white paper.
Table of
Contents
WebSmart
JSE servlet deployment scenarios
The
WebSmart JSE Servlet Creation Process.
Changes
to the IDE to support WebSmart JSE
Class
reloading on the iSeries
Porting
WebSmart JSE Servlets to non-iSeries systems
Connecting
to a JDBC data source
Using
pgmf_lasterror and pgmf_lasterrtx
The concepts and functionality provided by WebSmart are almost identical regardless of which language you are deploying to. The product consists of an Integrated Development Environment (IDE) which executes on any PC using the Microsoft Windows Operating System. This system will be referred to as the “development client” for the remainder of this paper. WebSmart Original Edition (OE) can be used to generate CGI scripts for the IBM iSeries that provide access to DB2 data using a Web browser. These scripts are created using compiled RPG ILE source code which is generated from a WebSmart program definition. WebSmart JSE and WebSmart OE both require an association between the IDE and an IBM iSeries server, which will be referred to as the “development server” for the remainder of this paper. The development server is the machine on which the RPG and Java source code is compiled into executable objects.
The purpose of WebSmart JSE is to reproduce the functionality of existing RPG based WebSmart program definitions using the Java language, and to allow the creation of new definitions. This means that the existing iSeries dependent features of the product have been preserved. These include features such as access to data areas, the ability to call iSeries programs, record level access to DB2 data and the use of validation lists. For this reason the dependency between the iSeries and WebSmart JSE remains.
The most unique feature of Java technology is the portable nature of the executable Java byte code. Java objects will run on any hardware/OS platform that supports a Java virtual machine (VM). This means that WebSmart JSE servlets can be transferred to a variety of platforms. All that is required is the presence of a servlet engine on the non-iSeries system, and network access to an iSeries machine on which the WebSmart WAS is installed. This allows you to separate the Web serving and Servlet execution infrastructure from the iSeries, while still accessing iSeries data using existing program definitions. This has security and performance advantages over the CGI approach provided by WebSmart OE. For the remainder of this paper, the system on which a WebSmart JSE Servlet executes will be referred to as the “execution server”. The implementation of such an approach is discussed later in this paper.
The Java DataBase Connectivity (JDBC) standard allows a Java program to access a wide variety of data bases in a platform independent manner. JDBC defines a set of objects that enable a Java program to access a database using the SQL-92 syntax. Using JDBC, a Java program running on a PC could access an Oracle database running under the Solaris operating system on a Sun SPARC workstation. Another Java program running on an iSeries server could access a MySQL database running under the FreeBSD operating system on a PC. In each of these cases, the platform dependent code required to access the database is provided by a JDBC driver which is loaded when the program runs. WebSmart JSE Servlets have access to this functionality using the same SQL access functions provided by WebSmart OE. This frees your program definitions from reliance on DB2 as the single data source when using SQL access. The record level access functions are restricted to DB2 access on the iSeries. For the remainder of this paper, the system(s) on which the data resides will be referred to as the “database server(s)”.
The following table summarizes the different hardware/software components utilized in the creation and execution of a WebSmart JSE servlet:
|
Server |
Description |
|
Development Client |
The Microsoft Windows based system on which the WebSmart IDE executes. |
|
Development Server |
The system with which the WebSmart IDE interacts when creating WebSmart JSE Servlets. This is always an iSeries system on which the WebSmart WAS is installed. |
|
Execution Server |
The system on which the WebSmart JSE Servlet runs. |
|
Web Server |
The system that handles the HTTP requests used to invoke the WebSmart JSE Servlet. Depending on the platform and servlet engine used, this may be a different system from the Execution Server. |
|
Database Server |
A system from which data that can be accessed using SQL or the Record Level Access Functions. In the latter case this is always an iSeries system. It is possible to maintain SQL and RLA connections with two different systems at the same time. |
You may want to execute a Servlet using the IBM HTTP Server (Powered by Apache) and the Tomcat servlet engine on an iSeries machine, and access SQL data using an iSeries DB2 JDBC driver. In this case the Development Server, the Execution Server, the Web Server and the Database Server may all be the same machine. This is illustrated in figure 1:

Figure 1
In another situation you may want to execute your WebSmart JSE servlet on a PC, Unix machine or other execution server, but still access iSeries data using SQL or record level access as shown in figure 2:

Figure 2
Another permutation of work load distribution may involve using the iSeries as the Web Server, the Execution Server and for record level access, while using a separate machine for SQL data access as shown in figure 3:

Figure 3
These examples illustrate only three potential solutions, in reality your situation may require another approach that can be easily implemented.
Servlets are persistent objects that exist within an application server known as a Servlet engine. They handle requests that are issued from an external source. These requests can originate from another Java program, or as a result of a request from a Web Browser. WebSmart JSE Servlets are HTTP servlets, i.e., they service Web browser requests.
Previous versions of WebSmart produced only RPG CGI scripts, which are native iSeries executables. On the iSeries, a CGI script runs using a single thread of execution in a process under the QHTTPSVR subsystem. Using the classic CGI model the HTTP request is serviced using a single entry point, the program runs to completion and the output is returned to the Web browser. The process then terminates and all the data created by that process (the state information) is discarded. Under this single threaded model, all data within the program can be global without risking corruption by other threads. This is a good execution model for PML programs, as all data is global.
Java servlets run using a multi-threaded model in which all global data is shared between threads. This poses a problem when translating between a PML program and a Java servlet. In WebSmart JSE this problem is addressed by storing all global data in a table. Variables in this table can be accessed by name, and the table is stored in a ThreadLocal object. This allows a copy of the table associated with the current thread to be retrieved whenever the value of a PML variable needs to be read or updated. A knowledge of this approach is a great help in understanding the Java code generated from a PML program.
In order to improve performance, servlets perform time consuming operations as infrequently as possible, and preferably only once – at the time the servlet is invoked. Under the most basic Servlet execution model, the Servlet object is loaded into memory when it is first invoked. The Servlet engine allocates any storage the Servlet requires, and invokes its initialization method. The Java VM may also use a Just In Time (JIT) compiler to convert the Java byte code of the Servlet into native machine code, and may create a pool of threads to draw on when servicing requests. In addition to these servlet engine dependent tasks, a WebSmart JSE servlet may also perform the following tasks on startup: the establishment of JDBC connections, the creation of AS/400 Toolbox connections for DB2 record level access and the retrieval of DB2 file formats. This initial start up phase may be quite time consuming, but once the servlet is loaded in memory, subsequent requests will be handled much faster.
The source code for JSE Servlets is produced by merging the procedural components of the program definition, represented by the PML segment, with the presentation components, represented by the html segments, into a single Java source file. There is also a single compiled Java program with the extension .class for each WebSmart definition. There is a close correspondence between the structure of the Java source code and that of the PML, although they differ in their syntax. The servlet creation process has the following steps:
1. The formats of any files used by the definition are loaded into the repository at design time, using the Exodus middleware product, which ships with WebSmart. Currently this is only an option for DB2 files residing on the iSeries. You must define work fields that correspond with the fields of tables residing in other databases that will be accessed using SQL.
2. When the “generate” option is selected from the file menu, by clicking the toolbar button or by hitting F6, the generate/compile cycle is started.
3. The program definition is converted into Java source code on the PC, and the source code is transferred to the iSeries development server using FTP. The source code then resides in the iSeries’ IFS.
4. An FTP command is issued which invokes the QSHELL interpreter on the iSeries in order to compile the source code that was uploaded in step 3. The resulting class file is placed in the same IFS directory as the source code.
5. A program is run on the iSeries which returns any compilation error messages to the WebSmart IDE over the same FTP connection that is used to upload the Java source code. If there were no compilation errors the servlet is ready to run.
If you have an instance of the WebSphere application server running on your iSeries, and the IFS directory which contains the newly compiled servlet is in WebSphere’s classpath, you will now be able to run the servlet. This is not the case if you are running the Tomcat servlet engine as each servlet has to be configured as part of a Web Application before it can be run.
Note: If there is a firewall between the development client and the development server, the firewall must be configured to allow FTP traffic to pass between the two machines.
The servlet creation process, and the software and hardware components involved, is illustrated diagrammatically in Figure 4.

Figure 4
Some minor changes have been made to the interface of the IDE for situations where the RPG approach differs from the Java approach. All of these changes are contained in the Attributes dialog, which can be displayed by selecting any entry from the Attributes menu, and the options dialog, which can be displayed by selecting the Tools>Options menu option. We’ll deal with the changes to the Attributes dialog first. The Generation options tab now contains a drop down list from which the target platform/language for generation can be chosen, as shown in Figure 5:

Figure 5: The Generation options tab
The choices are “Java Servlets for WebSphere” and “iSeries ILE RPG Generator”. The value present in this drop down affects the set of fields that are displayed in the Program Attributes tab. When “iSeries ILE RPG Generator” is selected the fields displayed are as shown in figure 6:

Figure 6: The Program Attributes tab for the ILE RPG platform
When “Java Servlets for WebSphere” is selected the fields are as shown in figure 7:

Figure 7: The Program Attributes tab for the Java platform
Note: When you change the target platform, by selecting a different value from the dropdown in the Generation options tab, the contents of the Program Attributes tab will not be changed unless you first click on the OK button, and then reopen the dialog.
The differences between these two versions of the tab are mostly a result of the different file systems to which the source code and executable code are written. The RPG source and executable code are written to the QSYS file system, so the IDE needs to know which source file to use and which library the file resides in. The executable ILE object can be saved to a different library from that containing the source file, so the program library is prompted for as well.
These three fields are replaced with the single field “Path to Servlet” in figure 7. This field contains the fully qualified path to the IFS directory that will contain both the source code and the executable Java object. The names for the source and executable object files are derived from the program name, so using the example in figure 7 the source file would be called vldtst.java and the compiled program would be called vldtst.class. As the source and executable files are stored in the same IFS directory, there is no need to prompt for a second directory in which to place the executable file.
Note: Java is a case dependent language. This means that the names of all objects, including the Java servlet that you create, must be referenced using the correct case. While the full URL that you enter in the location field of your Web browser to run the Servlet depends on the location of the file in the execution server’s file system, and how the Web server and servlet engine are configured, the name of the servlet must always be referred to using the same case that you entered in the “Program name” field. An example URL to run the servlet named in figure 7 could be as follows:
http://127.0.0.1:8080/servlet/vldtst
If you entered VldTst instead of vldtst as the last portion of this URL, the servlet engine would not be able to find the definition for the servlet class, and an error would result. To make certain of the case to use in the URL you can check the contents of the Java source file, in this case vldtst.java, for the line that defines the class. This should be as follows:
public class vldtst extends WSUser
You’ll also note that the “Library list object” dropdown is missing from the “Program Attributes” tab in figure 7. This is because it is not possible to recreate the library list handling approach used in the RPG solution with the AS/400 Toolbox for Java. This issue is discussed in more detail in the “Library List Issues” section.
The remaining Interface changes are contained in the “Options” dialog. A Target Platform dropdown has been added to the “Environment” tab as shown in figure 8. This allows you to select the default platform to use when creating new program definitions:

Figure 8: The Environment Tab
The first time you run the WebSmart version 3 IDE, it will prompt you for the value of this field using the dialog shown in figure 9:

Figure 9: The platform selection dialog
Figure 10 shows the “Paths and Repository” tab. This has been renamed from the “Paths” tab in WebSmart version 2, and contains more changes than those relating specifically to WebSmart JSE. The single field to note in this context is the “Servlet Directory” field. This allows you to define the default value for the “Path to Servlet” field, in the “Program Attributes” tab, that will be used for new definitions.

Figure 10: The Paths and Repository tab
Some minor changes have been made to the PML syntax because of the introduction of new features, and incompatibilities between Java and the PML supported in WebSmart version 2.
PML now supports function calls within function calls. Consider the following example which generates a random number between 0 and 9, and assigns it to an alphanumeric variable:
crtfld(aRand, 1, “A”, 0, “Alphanumeric
random number”);
aRand = numtoalpha(genrand(9));
In order to achieve the same result using the RPG solution you would have to produce the following code:
crtfld(aRand, 1, “A”, 0, “Alphanumeric
random number”);
crtfld(nRand, 1, “N”, 0, “Numeric random
number”);
nRand
= genrand(9);
aRand = numtoalpha(nRand);
This technique avoids the creation of temporary variables, such as nRand above, in many situations. Another situation where this technique is useful involves the display of a numeric value in a Web page using the wrthtml() function. Using the definition of nRand above:
nRand
= genrand(9);
wrthtml(“The value of nRand is “, numtoalpha(nRand));
While these examples seem trivial, they can significantly reduce the amount of effort involved in producing a program definition, in situations where the technique is applicable. This approach can also aid in the readability of the PML code.
Note: While this functionality is available in WebSmart JSE, it is not transferable to the RPG solution. This means that if you use this approach you will be making your program definitions dependent on the Java platform.
The introduction of the function call within a function call syntax produced an ambiguity in the syntax of the runtask() function. In WebSmart version 2 the following line appears in the main() function of many of the templates:
runtask("DEFAULT", display());
This instructs the CGI script generated from the PML to execute the display() function when the value of the TASK parameter is “DEFAULT” or blank. The second argument has the same syntax as a function call, and the generator is unable to determine whether the value of the argument should contain the output of the display() function, or if the name of the function should be associated with the value of the first argument (which is the correct interpretation). For this reason WebSmart version 3 expects the following syntax:
runtask("DEFAULT", display);
the only difference being that the opening and closing parentheses no longer follow the function name. This is the syntax used by all of the templates that ship with WebSmart version 3. As all the program definitions created using WebSmart version 2 will contain the old syntax, the IDE that ships with version 3 automatically removes the parentheses from the second argument of runtask() when an old definition is loaded.
The PML provided in WebSmart version 2 allowed you to test for the equality of two values using the following two approaches:
if(value1 = value2)
and
if(value1 == value2)
assignment was accomplished using a single approach:
variable1 = value1;
In most programming languages a distinction is made between the operator used for assignment and the operator used to test for equality. RPG uses the single equals sign in both cases, and determines the function of the operator from the context in which it is used. The PML implementation in WebSmart version 2 allowed you to use either the RPG syntax, or the syntax used by C and Java to test for equality. In order to support the Java syntax, however, WebSmart version 3 requires a distinction between the assignment and equality operators. Assignment is always performed using a single equals sign, and tests for equality are always performed using a double equals sign.
When opening a program definition that was created using WebSmart version 2 in the version 3 IDE, any occurrences of a single equals sign that are used to test for equality are converted to a double equals sign.
Two new program fields have been introduced to aid in the production of platform independent PML code. These are:
1. pgmf_qpgmnam
2. pgmf_platform
These are described in the following paragraphs. All versions of WebSmart include a program field called pgmf_pgmnam which contains the name of the currently executing program. It is common to build hypertext links in an HTML segment that link to the currently executing program. This may also be done in the PML code. Two examples of this can be seen below, firstly the HTML then the PML:
1.
<a
href=”<field name=*pgmflds.pgmf_pgmnam>.pgm?TASK=display”>...
2.
url = append(pgmf_pgmnam,
“.pgm?TASK=display”);
redirect(url);
In the first example the <a> tag is followed by some link text, and then an </a> tag which are not shown. Clicking on the link text will run the program with the task “display”. In the second example the program is run by redirecting to the url that is built programmatically by appending the contents of the pgmf_pgmnam variable, the string “.pgm” and the query string.
The difficulty with these two code examples relates to the presence of the “.pgm” string. In each case, accessing the link works fine if the target program is an RPG CGI script running on an iSeries, but if it is a servlet the request will fail. This is because servlets are invoked, by default, using their program names with no extension, and the presence of the “.pgm” string at the end of the URL prevents the servlet engine from finding a matching class file.
A platform independent solution to this is to remove the hard coded “.pgm” strings from all locations in the HTML and PML code, and to substitute the variable pgmf_qpgmnam for pgmf_pgmnam. The latter contains a different value depending on the target platform selected in the “Generation options” tab for the program definition. For example, if the program name is “custmnt” and the target platform is set to “iSeries RPG ILE Generator”, the variable pgmf_qpgmnam will contain the string custmnt.pgm. If the target platform is “Java Servlets for WebSphere” the variable will contain custmnt. Making this change ensures that you can use the same program definition to generate either RPG or Java code.
Performing this step manually would be very time consuming, so the WebSmart version 3 IDE is capable of making the changes for you. There may be situations where you want to override this automatic translation process, so the IDE presents the dialog shown in figure 11 the first time you open a program definition that was created using WebSmart version 2:

Figure 11: The conversion options dialog
This solution is satisfactory if the program being referenced in the URL is the program that is currently executing. However, there may be times when you want to create links to other programs. In these cases you may not know whether the target program is a CGI script or a Servlet at design time, but you do know that it is using the same target platform as the program that is currently executing. This will be the case when you have a set of program definitions, and you want the entire set to run either on an iSeries as RPG CGI scripts, or as Servlets on an iSeries or other execution server.
In this case you would use the pgmf_platform variable to determine which execution platform is being used, and build all program names accordingly. For example, a customer maintenance system may consist of three program definitions: custlist, custupd and custdsp which list, update and display customers respectively. The main program is custlist, and the other two programs are called by selecting the links that are created by custlist. These links may be constructed either in HTML segments, or in PML functions. Placing the following code in the main() function of the custlist program, before any wrtseg() or runtask() calls, creates variables corresponding to the two called programs, and assigns values to them in a platform independent manner:
crtfld(custupd, 20, "A", 0,
"Customer update program name");
crtfld(custdsp, 20, "A", 0,
"Customer display program name");
if(pgmf_platform == "servlets")
{
custupd = "custupd";
custdsp = "custdsp";
}
else
{
if(pgmf_platform == "RPG400")
{
custupd = "custupd.pgm";
custdsp = "custdsp.pgm";
}
}
Notice that the pgmf_platform variable has the value “servlets” if the generated program is executing as a servlet, and “RPG400” if the program is executing as an RPG CGI script. After this code has executed, a link can be built to run the default task of the custupd program in an HTML segment as follows:
<a href=”<field
name=*WRKFLDS.custupd>?TASK=default”>...
A link can be constructed to redirect to the default task of the custdsp program in a PML function as follows:
url = append(custdsp,
“?TASK=default”);
Both of these links will access the called program using the correct syntax for the target platform. These examples illustrate one of many potential uses of the pgmf_platform variable. The same approach can be used to isolate any code that should only be executed on one of the available platforms.
The following section describes the structure of the Java libraries used by WebSmart JSE.
The WAS for WebSmart JSE takes the form of a class library consisting of two packages:
1. com.esdi.websmart
2. com.esdi.client
The websmart package contains code produced by ExcelSystems, the client package contains code produced, or modified, by you. These packages consist of a set of uncompressed .class files beneath the IFS directory /esdi/websmart/lib. The class locations follow the Java package naming convention of using a domain name with the order of its components reversed. The dots between the components of the package name correspond with the ‘/’ characters in the directory path that references the package, e.g., the websmart package that ships with the initial product release is contained in the directory /esdi/websmart/lib/com/esdi/websmart.
The websmart package is equivalent to the service program used by the ILE RPG version of WebSmart. It contains the following classes:
|
Class Name |
Description |
|
WebSmart |
Contains all WebSmart functions. Extends Java’s HttpServlet class to provide handling for HTTP requests. Each request invokes a separate thread that executes the code for the class. The WSUser class extends the WebSmart class, and all WebSmart JSE servlets extend the WSUser class. This gives WebSmart JSE servlets access to all methods in the WebSmart class, and allows users to write their own functions as methods in the WSUser class. |
|
WebSmartException |
Thrown whenever a WebSmart error occurs. |
|
WSConnectionPool |
Provides a JDBC connection pool to improve the performance of SQL Database access. |
|
WSConst |
Contains all constant definitions used by the package. |
|
WSDate |
The data type representing PML dates. |
|
WSDB2File |
Provides support for DB2 Record Level Access. |
|
WSDecimal |
The data type representing PML numeric variables. |
|
WSExitException |
Thrown whenever a WebSmart JSE servlet needs to exit immediately, e.g., by the execution of the “exit” keyword. |
|
WSFHandle |
Represents a PML file handle for stream file access. |
|
WSGlobal |
Contains the global PML variables and their values for each HTTP request. |
|
WSKlist |
A Key List implementation for DB2 Record Level Access. |
|
WSSmurf |
Represents the value of a smurf returned by getsmurf(). |
|
WSString |
The data type representing PML alpha fields. |
|
WSStruct |
The data type representing PML structures. |
|
WSTime |
The data type representing PML time variables. |
|
WSUtil |
Contains utility methods used by the package. |
|
WSVariable |
An Interface implemented by all WebSmart JSE data types. |
These classes are accessible to all JSE servlets running on the iSeries as long as the directory /esdi/websmart/lib is present in the classpath of the servlet engine.
After making changes to a class, either by recompiling an existing Java source file, or by installing a new version of an existing file, the file must be reloaded by the Servlet engine before the new code can be used. This is the case when an update has been applied to the WebSmart JSE class libraries, so after applying an update you must restart your servlet engine. A description of the issues behind this requirement is given in this section.
A Java VM will cache, in main memory, the classes that have been loaded as a result of a set of program invocations. This avoids the need to load a class each time it is accessed, which significantly improves performance. In a perfect world, the VM would only have to load each class once, and would continue to use that class until the process terminated. However, if the class file is modified it needs to be reloaded for the changes to be reflected. The process of choosing which classes, if any, to reload is not a trivial issue, but the alternative is unacceptable. Imagine a development environment in which you had to reboot your computer every time you made a change to your program. Without a reboot the computer would continue to use the old version of the program. This is the equivalent of stopping and restarting your servlet engine whenever you make a code change. On the iSeries the process of restarting WebSphere or Tomcat can easily take as long as rebooting a PC.
To avoid this behaviour, the class loader must compare the modified date and time of the class which resides in the memory cache with that of the class file on the storage device. This must be done each time the class is accessed, which in itself incurs a performance overhead. For this reason most servlet engines allow you to choose whether the modified date and time of the Servlet’s class file should be checked each time it is accessed.
WebSphere and Tomcat on the iSeries take two different approaches to this issue. WebSphere maintains two separate class paths: the reloadable classpath and the non-reloadable classpath. Any classes placed in IFS directories or Jar files in the reloadable classpath are checked for modifications on a regular basis, although this is not each time they are accessed. You may find that you have to press the reload button on your browser up to four times before changes to your WebSmart JSE servlet are reflected. Classes placed in the non-reloadable classpath are never checked for modifications, and changes will only be reflected when WebSphere is restarted. This is why we recommend you generate all of your WebSmart JSE servlets to the following directory:
/QIBM/ProdData/WebAsAdv/servlets
until they are released to production, as this directory is in WebSphere’s reloadable classpath.
Tomcat supports a “Reloadable” flag for each servlet, which indicates that the class file should be monitored for updates on a regular basis. Unfortunately this feature is described as “experimental” in the Tomcat documentation, and is not guaranteed to work. This means that you may have to restart the Tomcat worker each time you make a change to each of your servlets. This is invasive enough when you use Tomcat as a production Servlet engine, but makes it unsuitable as a development platform. If you do not have a WebSphere instance on your iSeries, we advise you to download the WebSmart JSE runtime package from our Web site. This contains a Tomcat installation for the Windows platform that can be used for development, as it does not suffer from the class reloading problem.
Due to the dependence of WebSmart JSE on the AS/400 Toolbox for Java, it is not possible to provide the same kind of library list support that is available in RPG. Files that are opened using the record level access functions do not use library lists at all, and the library in which each file resides is hard coded at design time. This is not the case for SQL access to DB2 data on the iSeries. The sqlconnect() function uses the library list identified in the call to the setlibl() function. Each WebSmart JSE program contains the following call to the setlibl() function by default:
setlibl("*FILES");
You can modify the library list name to a library list of your choice, and the change will be reflected in SQL access to DB2 data. You can find out how to create and modify library lists, using the EWRKLIBL command, by reading the “Creating and working with library list objects” section in Section 4 of the WebSmart Reference Guide.
The ILE RPG version of WebSmart creates programs that run as CGI jobs in the QHTTPSVR subsystem. From the Java perspective, the CGI approach is viewed as inefficient as it requires the initiation of a new process each time a CGI program is executed. The creation of processes is a resource intensive task compared with the multi-threaded approach taken by Java. On the iSeries, IBM has largely avoided the process creation bottleneck by maintaining a pool of active processes for each Web server instance in the QHTTPSVR subsystem. This allows a CGI request to be executed in a process that has already been created and initialized. The pool of processes will grow and contract depending on the number of requests the server receives. The expansion and contraction of the pool does involve a process creation and tear down overhead.
Despite these issues, the execution of Java Servlets on the iSeries does not provide a performance advantage over CGI execution, at least not when the system is receiving a small number of requests. Java’s multi-threaded approach may provide better performance when many requests are being received, but this can only be determined by evaluating the performance of an individual application under load, and comparing the two execution platforms. The Apache foundation offers a free performance monitoring tool called JMeter which can be downloaded from the following location:
http://jakarta.apache.org/jmeter/
Although this program is written in Java, it can be used to measure HTTP server performance regardless of the kind of content served. All it needs to know is the URL of the resource that is to be accessed, and how many threads of execution should be used to send requests to the server. You may find this tool to be a satisfactory performance monitoring solution when determining the relative performance of WebSmart JSE servlets versus RPG CGI scripts under various load conditions.
The two main advantages of WebSmart JSE are:
1. Portability
2. Accessibility to non-iSeries data
These two issues are dealt with in the following sections.
Although an iSeries server is required in order to compile WebSmart JSE programs, you can move the resulting executable files (the .class files) to any system that has a Web Application server which supports the servlet standard. Unfortunately, as we do not know which Web server/Web application server combination you will be using, we cannot provide configuration information for your chosen execution platform.
In order to execute the servlet you will also need to copy the class libraries and support files that it requires. The simplest way to accomplish this is by copying the IFS directory /esdi/websmart and all of its contents to the alternate system. This directory also contains all of the graphics, include files, style sheets and JavaScript source files used by the WebSmart templates and any programs that were created using those templates. Ensure that the directory “websmart” is placed under the directory “esdi” which is at the root level of the target system’s directory hierarchy. You will need to configure the classpath of your servlet engine to include the jar files contained in the directory /esdi/websmart/lib, or place these files in a special deployment directory, if your servlet engine supports this. The directory /esdi/websmart/lib should also be added to the classpath, as this provides access to the WSUser class, which is the superclass of all WebSmart JSE servlets.
Certain WebSmart functions require access to an iSeries server even when they are executing on a non-iSeries machine. These functions use the AS/400 Toolbox for Java, regardless of whether the servlet is running on the iSeries or not. The Toolbox classes are contained in the file jt400.jar which must be copied from the iSeries to the non-iSeries system. The location of this file on the iSeries varies depending on which version of OS/400 you are using. Under V4R5 it is located in the following directory:
/QIBM/ProdData/HTTP/Public/jt400/Lib
You can place the file in a location of your choice on the non-iSeries system, after which you must add it to the classpath of the servlet engine.
The functions that are dependent on access to an iSeries system include:
1. Transaction functions
2. Validation list functions
3. Smurf functions
4. Program Calls and some other server side functions
5. Record level access functions
When these functions are executing on the iSeries, the user profile used, when establishing a connection with the server using the Toolbox, is inherited from the process in which the servlet is running. As we cannot rely on consistent user profile handling across all Java execution environments, an alternate method has been supplied by which the system name, user id and password can be provided to the servlet. The file /esdi/websmart/conf/login.properties is a java properties file (analogous to a Windows ini file) which contains the following text:
default.system=<iSeries IP address or domain name>
default.userId=<user ID>
default.password=<password>
You can create this file in the directory indicated using any text editing tool, as properties files consist of plain ASCII text. Just substitute the correct values in place of the text between angle brackets shown above. As this file contains the password of an AS400 user profile, you should use the operating system’s access control features to protect it.
Finally, you must add a URL mapping from the following address:
http://<domain or IP><:port>/websmart/
to the directory /esdi/websmart. Please refer to your Web server’s documentation for information on how to accomplish this.
WebSmart JSE servlets can access AS/400 data in the normal manner using the record level access functions. They can also access data using the SQL functions, but while SQL access may appear to work in a similar manner using Java and ILE RPG, there are some major underlying differences.
RPG on the iSeries uses the SQL/400 syntax, while WebSmart JSE servlets use the Java DataBase Connectivity (JDBC) standard (which implements SQL-92). We have made every effort to ensure that in most cases the SQL/400 statements contained in existing WebSmart definitions will work in both RPG and Java, but sometimes functionality may have been used that is only available under SQL/400. In these cases the programs will have to be modified to work with JDBC.
The WebSmart JSE SQL functions emulate the use of SQL/400 cursors by mapping JDBC result sets to a cursor name, and then handling “fetch” requests on the result set using the embedded SQL/400 syntax. For example, the following statements:
selectStmt
= "SELECT CCO#, CCUST#, CCUSTN FROM CUSTMST";
sqlquery(selectStmt, "MC");
would execute the select statement, and associate the resulting JDBC result set with the cursor name “MC”. Data can then be retrieved from the result set using “FETCH NEXT” or “FETCH RELATIVE” statements that reference the cursor name, for example:
sqlexec("FETCH NEXT FROM MC INTO :CCO#, :CCUST#,
:CCUSTN");
The names of the variables that are to receive the data from the result set are presented using the SQL/400 host variable syntax, i.e., a comma delimited list of variable names, each preceded by a colon (“:”). The first argument to sqlquery() is passed as-is to the JDBC driver. The string argument to sqlexec() is processed to translate between embedded SQL/400 syntax, and JDBC syntax. The main goal of this translation is the assignment of values from a JDBC result set to the corresponding host variables (in the case of the FETCH statement), and the substitution of the host variable values for the variable names (in the case of the UPDATE statement). The WebSmart JSE sqlexec() function currently supports the FETCH, UPDATE, DELETE and CLOSE statements. The argument to sqlexec() is converted to lower case before processing.
When deploying WebSmart programs as ILE RPG CGI scripts, you have the option of using the local iSeries DB2 database or a remote iSeries DB2 database for SQL access. WebSmart JSE gives you the opportunity to connect to any database for which a corresponding JDBC driver is available. This includes such systems as Microsoft Access, Microsoft SQL Server, MySQL and Oracle. Before accessing any data from a remote system you must first make a connection to that system using either the sqlconnect() function or the jdbcconnect() function.
Using WebSmart JSE you can connect to a DB2 database on an iSeries server using the sqlconnect() function, which has the following prototype:
VOID sqlconnect(ALPHA
rdn, ALPHAFIELD user, ALPHAFIELD password);
In this case, the rdn variable is interpreted as the domain name or IP address of the remote system. In order to make a JDBC connection to another system, the Java servlet must have access to a JDBC driver. This is a set of Java classes which normally reside in a jar file that is in the classpath of the servlet engine. sqlconnect() allows you to connect to an iSeries machine using the Toolbox JDBC driver which is located in the file jt400.jar. To make this available to your non-iSeries server, locate the file jt400.jar under the /QIBM IFS directory on the iSeries, and copy it to a location on the target system that is in the classpath of the servlet engine. The location of this file varies depending on which version of OS/400 you are using. Under V4R5 it is located in the following two directories:
/QIBM/ProdData/HTTP/Public/jt400/Lib
/QIBM/ProdData/HTTPA/Admin/Pgm
It will only be present in the second directory if the Apache web server has been installed on the iSeries. When you connect to a system in this way, the class com.ibm.as400.access.AS400JDBCDriver will be loaded, and a pool containing four JDBC connections to the target system will be created. This connection pool vastly improves the performance of any JDBC access to a remote database, because the creation of a JDBC connection is the most time consuming part of the data access sequence. The four data base connections are kept open until the servlet terminates.
The jdbcconnect() function has the following prototype:
VOID jdbcconnect(ALPHA driver, ALPHA jdbcurl);
A call to this function is required when you are connecting to a non-iSeries database server. The sqlconnect() function is able to assume two things based on the fact that it is connecting to an iSeries machine using the Toolbox JDBC driver:
1. The class name of the JDBC driver
2. The format of the JDBC URL
A JDBC URL is analogous to a URL that you would use to access a web page using a web browser. It is generally the only piece of information that a JDBC driver needs in order to establish a connection. Each JDBC driver has a different class name, and may have a totally unique URL format. The following example illustrates how a connection can be established between a WebSmart JSE servlet, and an Oracle database:
url = "jdbc:oracle:thin:SYSTEM/manager@192.168.0.96:1521:JSESID";
sqlconnect("oracle.jdbc.driver.OracleDriver",
url);
The url syntax expected by the Oracle JDBC driver is unconventional. It has the following format:
<protocol>:<user>/<password>@<system>:<port>:<database identifier>
In order for the jdbcconnect() call to work, the oracle thin JDBC driver must be in the classpath of the servlet engine. Before you can install it you first have to obtain it. The driver may ship with the product, but if not, try going to the Web site belonging to the database vendor and searching for the term “JDBC”. You can also search the Internet using a similar search term, as sometimes third party software developers create JDBC drivers for other vendor’s products. Most JDBC drivers are available free of charge, or on a trial basis. Normally the JDBC driver is in a jar file that must be added to the classpath of the servlet engine to make it available to the jdbcconnect() function.
WebSmart JSE version 3 does not support the downloading of JDBC table formats into the repository. This means that you will have to define work fields that correspond to each field you will be referencing in each table. Each work field must have the correct data type and attributes when it is used to read values from the table and save values to the table using the SQL “select” or “update” statements, respectively. For example, the following declarations are required in order to support the SQL calls that follow:
crtfld(compnbr, 3,"N", 0,
"Company Number");
crtfld(custnbr, 6,"N", 0,
"Customer Number");
crtfld(custname, 30,"N", 0,
"Customer Name");
selectStmt
= "SELECT CCO#, CCUST#, CCUSTN FROM CUSTMST";
sqlquery(selectStmt, "MC");
sqlexec("FETCH NEXT FROM MC INTO :COMPNBR, :CUSTNBR,
:CUSTNAME");
This restriction will be addressed in a later release of the product.
These two program fields contain the number of the most recent program error that occurred, and a textual description of the error. The iSeries has an established method of error reporting which is incompatible with the Java exception handling approach. This means that the Java version of a WebSmart function is not aware of which error number will be returned from the corresponding ILE version of the function under all circumstances. If you have code which uses either of these variables and you need to generate a Java servlet version of the program, please review the behavior of the program.
So go
ahead and think smart, Think ProGen WebSmart !
To try
ProGen WebSmart call BCD or your authorized BCD reseller and
you will
soon see why this is the Smart choice for you.
Business Computer Design Int'l, Inc. - 630-986-0800 - www.BCDsoftware.com
ProGen
WebSmart and ProGen Plus are TM's of ESDI, all other TM's are TM's of their
respective owners. © 2000 BCDI