Jargon Software
Getting Started with Jargon Writer
Completing Your Application

Contents:

Completing Your Application
Generating Source Code For Host Procedures
Host Communications Parameters
Writing Stored Procedures in Oracle PL/SQL
Writing Java Servlet Host Procedures
Writing Active Server Pages in VBScript
Writing Host Functions with PHP Scripts
Writing Host Procedures in the Progress 4GL
Testing and Deploying Your Application

Completing Your Application
The previous sections have explained how to develop the client side of an application, which deals primarily with the user interface. Now we turn to the host side, where additional business logic will be written to create data extracts to download to the mobile device, and to process transactions uploaded from the device, such as new sales orders, warehouse inventory movement, etc.

All programs on the host are written in a language specific to the host environment. Examples include: VBScript for Microsoft ASP pages, the Progress 4GL for Progress Software environments, PL/SQL for Oracle environments, PHP scripts for Linux, Unix and Windows, and Java for J2EE environments. In fact, any language that supports HTTP request/response protocols (either directly or via some other middleware product) will work for the host side code.

For host language environments that do not provide HTTP support, you can still interact with the mobile client by using FTP to upload and download text files containing the required data in some format, such as CSV files. While this will work just fine, you do lose most real-time interactivity capabilities with this more batch-oriented approach.

When designing your application, you should consider and answer the following questions at the outset:

1. Will any of the processing be done in a state-aware mode, or will all processing be "stateless"? This is probably the most important issue that must be answered up front, as it has a major impact on the number of host processes that will be needed for a given transaction workload and on how the host and client sides will be designed. See the sections below on writing host procedures for more details on the issues involved with this decision.

2. How will security be handled? A common approach is to present the user with a login screen (User ID and password) when the client application starts, followed by a host request which validates the user against a database table. Once approved, a user's identity must be sent in some manner as parameters with each host request, particularly in a stateless model, since any available host process might receive a processing request from any client, unlike in traditional character terminal applications.

3. How will the application maintain "context" between client requests in a stateless model? Context information includes such items as the nature of the latest action that the client had previously completed, intermediate values, security settings, and many similar data values. See the "Stateless and Event-Driven Programming" document for more on this topic.

4. What parameters must be sent to the host for each host request? As mentioned above, in a stateless model there will usually be User ID/password or session ID parameters that are sent each time, plus other parameters appropriate for the particular task, such as sending a customer number to the host in order to display the customer's name and address on the client screen.

5. What processing will the host do for each host request? If the database will be updated, how will the transaction be structured? How will the client be notified, or how will its original screen contents be restored, if the transaction is unwound (if the host program executes an "undo")?

6. What the possible responses that the host may return to the client for each possible outcome of the processing? If the processing completes normally, what will be changed on the client? If errors occur, how will the client be notified?

7. What directory structure will be used for the host programs and include files?

8. What naming conventions will be used for host procedures and related files?

9. Are there any configuration changes needed to enable host requests to access these host programs? Often, web server and firewall configuration changes are needed to allow access, especially with recent releases of web servers and operating systems that have tighter security.


Generating Source Code For Host Procedures

Jargon Writer can automate some of the creation of the host programming for you by generating template code for one or more host procedures that handle the receiving and parsing of the parameters sent from the client to the host for each host request. When you have completed the definition of each host request in your client application, you are ready to generate the host source procedure files.

This feature generates "template" source code for host procedure(s) that are run by http requests from this app. Code generation is done by a separate app that is specified by the "SourceCodeGeneratorApp" preference value in the "writer.ini" file. All generated files are placed in the folder specified by the "4GLRootDir" preference.

Currently, Jargon Writer includes a SrcCodeGenP4GL.xml generator for developing apps that will communicate with host procedures written in the Progress 4GL. It generates one or more Progress ".p" source programs, based on the specs and parameters in http requests that were defined in the Script Editor for the currently active app.

Other generators can be written for other host language environments such as Microsoft ASP pages, Oracle PL/SQL procedures, PHP scripts, etc. by using the included generator as a model.

If you are interested in writing a source code generator for Oracle PL/SQL, PHP, Microsoft ASP, Java servlets, or for any other host environment, please contact Jargon Software (email support@jargonsoft.com)

For the automated code generation to work correctly, each host request must be defined within a separate function, starting with a call to "MakeURL", followed by zero or more "http.AddParam" statements for any host parameters, and ending with an "http.SendRequest" statement.

Here is a simple example of a script with one host request ("GetCust"):

   // GLOBAL VARIABLES
   var thisApp  = 'cust';
   var HostProg = 'examples/cust.p';
   var UseSSL   = false;

   // GENERIC FUNCTIONS, DEFINED ONCE
   function MakeURL(program, procedure) {
     var HostURL = preference.GetPreference('HostURL');
     var Script  = preference.GetPreference('Script');
     http.SetNotifyProc(thisApp, 'NotifyCmdsRecvd');
     http.SetURL(HostURL + '/' + Script + '/' + program);
     http.AddParam('ProcName', procedure);
   }
   function NotifyCmdsRecvd() {
     if (! http.GetSuccess()) {
       sys.WarningBox('Host returned an error status');
       return;
     }
     var rcvSize = http.GetResponseSize();
     if (rcvSize > 0) sys.ProcessInstructions(http.GetResponseData());
   }

   // APPLICATION-SPECIFIC FUNCTION TO SEND A SPECIFIC HOST REQUEST
   function GetCust(CustID) {
      UseSSL = (preference.GetPreference('UseSSL') == 'true');
      MakeURL(HostProg, 'GetCust');
      http.AddParam('tCustNum', CustID);
      http.SendRequest(UseSSL);
   }

The steps to follow are straightforward:

  1. In the Script Editor Window, review the parameters of each host request to make sure that you have correctly entered the names for the Program file and the Internal Procedure name as parameters of a "MakeURL(program,procedure)" statement, and that the MakeURL function has been defined. Also note that Unix/Linux hosts are case-sensitive, so double-check the case of the Program filename on those systems.

  2. Create all host directories referenced in any of the program, procedure or include filenames. These must be created both on the client (in Jargon Writer's working directory) and on the host (in the program or script working directory). If you are using shared network folders or other techniques to map a host directory under the client working directory, then there could be just one set of directories that are shared by both host and client, for the development environment at least.

  3. In Jargon Writer, open the primary app file for which you want to create host procedure source code.

  4. Now, generate the host program file(s) by selecting Run-->Generate Host Procedure from the menubar, or click the ".P" button in the toolbar. The Jargon Writer generator app will examine all functions in the client app that contain "MakeURL" and "http.SendRequest" statements, and will create all referenced programs and procedures and all necessary variables and logic to parse the http parameters and populate these variables, as well as referencing any include files in which you choose to put your host business logic.

  5. If the host directories are not mounted under the client working directory, you must now move the generated programs to the host system. This may be done by using a file transfer program (FTP) that runs on the client.
    • IMPORTANT: If you have a Windows client and a Unix/Linux host, be sure to specify "text" mode (not "binary" mode) in FTP, before transferring the file. Since a host program is a text file, each line is delimited by some special character(s). On Windows systems, this is a CR/LF character pair, but on Unix/Linux, it should only be a LF character. (LF means line feed which is decimal "10"; CR means carriage return which is decimal "13"). In binary mode, FTP will not strip out the CR characters when uploading a text file from Windows to Unix/Linux, and this may cause a variety of problems which you are better off not experiencing firsthand.

The format of automatically generated Progress ".p" programs is as follows:
  • Several include file references in the main procedure section
  • A separate "internal procedure" section for each procedure named in a "MakeURL" function call in the xml script
  • A set of variables and the include statements to populate them, within each internal procedure, for each host parameter defined in an "http.AddParam" statement in the script function that calls that procedure
Note:
  • The variable names will be the same as the parameter names specified in the client script
  • The data type for each variable may be specified as an optional third parameter of each "http.AddParam" statement. The choices are: date, decimal, integer, logical (boolean), or character (default is character).


Here is a simple example of a generated Progress 4GL program (with some added comments):


   /* demo/cust.p */
      Generated on Jun 10, 2005 at 9:48:31 AM CST.
      Do not modify this code!  Use Jargon Writer to re-generate.
   */
   {jsi/dispatch.i}
   {jsi/getprocs.i}

    /* top-level include file for temp-tables and other functions/procedures */
   {demo/cust.i}

   procedure getcust:
     def var tCustNum         as int  no-undo.
     {jsi/getint.i &fieldname='tCustNum' &targetvar=tCustNum}
     {jsi/output.i}
     {demo/cust/getcust.i}  /* Business Logic goes into this include file */
   end procedure.

   procedure setcust:
     def var tCustNum         as int  no-undo.
     def var tCustName        as char no-undo.
     def var tLastOrderDate   as date no-undo.
     def var ckOnCreditHold   as logi no-undo.
     def var tCreditLimit     as dec  no-undo.
     {jsi/getint.i  &fieldname='tCustNum'       &targetvar=tCustNum}
     {jsi/getchar.i &fieldname='tCustName'      &targetvar=tCustName}
     {jsi/getdate.i &fieldname='tLastOrderDate' &targetvar=tLastOrderDate}
     {jsi/getlog.i  &fieldname='ckOnCreditHold' &targetvar=ckOnCreditHold}
     {jsi/getdec.i  &fieldname='tCreditLimit'   &targetvar=tCtCreditLimit}
     {jsi/output.i}
     {demo/cust/setcust.i}  /* Business Logic goes into this include file */
   end procedure.

Host Communications Parameters
When a host request is executed on the client, it always sends one or two parameters automatically: the procedure/program name and possibly an "Internal Procedure" or subroutine name (required with the Progress 4GL, optional for other environments). These parameters are assigned by the http.SetURL method as part of the host request (the standard "MakeURL" function does this for you). These parameters tell the host web server or middleware which program should be run, and (optionally) which internal procedure should be run within the program.

For some tasks that may be all there is to it -- no other parameters are needed. Examples might be a host request which kicks off a host report program that has no options, or a batch update program that likewise needs no options. In these examples, the host processing logic is "hard-wired".

However, most host requests will require one or more data parameters in order to accomplish the desired processing logic. As discussed above, a common parameter is a User ID or session ID of some kind, which is used both for security purposes and to access context information that may have been saved (in the database or elsewhere) from a previous interaction.

For an inquiry ("get") task, the client might supply a customer number as a parameter, so that the host request can find that customer in a database table and send back the customer's name and address values to be displayed on the client screen.

For an update ("set") task, the client will send all data fields that the user may have filled in, so that the database can be updated with these values.  Many other scenarios are also possible.

Each parameter sent by the client can be a constant, or it can be a result of invoking some method on a client component object, such as getting the current value of a quantity textfield. All parameters will be used to populate a corresponding variable or input parameter in the host procedure.

The data type (character, integer, decimal, date, logical) of the input parameters or variables must match the corresponding data type of the client component or constant. Note that for the Progress 4GL, the "logical" data type is referred to as "boolean" in Jargon Writer.

All values of buttons, checkboxes and radio buttons are mapped to logical variables. Current selection values for comboboxes and listboxes are mapped to character variables.

Writing Stored Procedures in Oracle PL/SQL

Oracle PL/SQL stored procedures can be coded without using a generator. For an example, see the "Oracle/demo/SQL/empdemo.sql" demo procedure included in the Jargon Writer installation directory. This working example has been tested with Oracle's Application Server.

Oracle middleware passes http input parameters as input parameters to the PL/SQL procedure named in the host request. Here is a header for a procedure that displays employee information for an employee number sent as a parameter in a host request that names this procedure (DisplayEmp):

    PROCEDURE DisplayEmp(nEmpNo IN NUMBER) IS
    BEGIN
    (code body here)
    END DisplayEmp;

Here is how an error message can be sent back to the client, using one of the pre-coded "jsi" procedures included in the "jsi.sql" library that is provided with Jargon Writer:

    MSGBOX.Warning('No such employee number: ' || TO_CHAR(nEmpNo));

Although Jargon Software does not currently supply a source code generator for this host environment, developers are free to implement one, since the generator appname is specified by the "SourceCodeGeneratorApp" preference value in the "writer.ini" file.

Please see the "Host Procedures for Oracle PL/SQL" help document for a list of the "jsi" procedures that can be used in PL/SQL to send data and commands from the host to a client app.

Writing Java Servlet Host Procedures

Java servlets can be easily coded without using a generator. For a simple example, see the "Java/getCust.java" sample servlet included in the Jargon Writer installation directory. This working example has been tested with IBM's WebSphere middleware.

Here is how an http input parameter is accessed in a Java servlet:

    // Get the parameter values from the input request
    String custNum = request.getParameter("custnum");

Here is how an error message can be sent back to the client, using one of the pre-coded "jsi" classes included in the "jargonsoft.jsi" class package that is provided with Jargon Writer:

    out.println(msgbox.warning("No such customer number: " + custNum));

Although Jargon Software does not currently supply a source code generator for this host environment, developers are free to implement one, since the generator appname is specified by the "SourceCodeGeneratorApp" preference value in the "writer.ini" file.

Please see the "Host Methods for Java" help document for a list of the "jsi" methods that can be used in a Java servlet to send data and commands from the host to a client app.

Writing Active Server Pages in VBScript

ASP routines can be easily coded without using a generator. For a simple example, see the "asp/triple.asp" sample script included in the Jargon Writer installation directory. This example can be run from the Jargon web site using the "xml/demo32/triple.xml" app. It reads customer credit data from an Access database and can also change the credit limit.

Here is how an http input parameter is accessed in VBScript:

   Dim cnum
   cnum = Request("CustNum")

Here is how an error message can be sent back to the client, using one of the pre-coded "jsi" functions included in the "jsi.asp" library that is provided with Jargon Writer:

   Response.Write( jsiWarn("Customer number not found: " & cnum) )
   Response.End

Although Jargon Software does not currently supply a source code generator for this host environment, developers are free to implement one, since the generator appname is specified by the "SourceCodeGeneratorApp" preference value in the "writer.ini" file. However, as you can see from the examples, it is not really needed for this environment, because VBScript was designed to make it easy to read and send http data in response to a client http request.

Please see the "Host Functions for Microsoft ASP " help document for a list of the "jsi" functions that can be used in an ASP script to send data and commands from the host to a client app.

Writing Host Functions with PHP Scripts

PHP functions can be easily coded without using a generator. For a stub of a host sync procedure, see the "php/HostSync.php" sample script. For complete syntax examples of all jsi functions, see the "php/jsiTest.asp" sample script included in the Jargon Writer installation directory. This example can be run from a web browser (use View Source to see the output in a more readable format).

Here is a handy function that can be used to access http input parameters in PHP:

   // get input param from either GET or POST web server values
   function GetParam($pParamName) {
     $getVal  = $_GET[$pParamName];
     $postVal = $_POST[$pParamName];
     if ($getVal  > '') return $getVal;
     if ($postVal > '') return $postVal;
     return '';
   }
   // example
   $tRep = GetParam('tRep');

Here is how an error message can be sent back to the client, using one of the pre-coded "jsi" functions included in the "jsi.php" library that is provided with Jargon Writer:

   jsiWarn("Sales rep ID not found: " . $tRep);

Although Jargon Software does not currently supply a source code generator for this host environment, developers are free to implement one, since the generator appname is specified by the "SourceCodeGeneratorApp" preference value in the "writer.ini" file. However, as you can see from the examples, it is not really needed for this environment, because PHP was designed to make it easy to read and send http data in response to a client http request.

Please see the "Host Functions for PHP Scripts " help document for a list of the "jsi" functions that can be used in a PHP script to send data and commands from the host to a client app.

Writing Host Procedures in the Progress 4GL
Coding host-side business logic for a Progress 4GL application is done by creating each of the include files that were defined in the client host tasks, and writing the Progress 4GL statements that accomplish the desired processing. All logic should be placed in these include files. The automatically generated program should never be modified, as it may be regenerated in the future if new parameters are added or for other reasons. The Progress 4GL host procedures used with AppServer or WebSpeed use standard Progress 4GL syntax (Version 9 or later), with two exceptions:

1. No screen I/O statements are allowed, since the WebSpeed or AppServer agent does not have a direct connection to the client screen. This means that no "DISPLAY", "ASSIGN", "PROMPT-FOR", "SET" or "UPDATE" statements can be used in relation to screen frames, and no screen "frames" or other screen "widgets" can be used with the default input and output streams, nor can INPUT FROM TERMINAL or OUTPUT TO TERMINAL be used.

2. In "stateless" mode, the WebSpeed or AppServer agent starts a new copy of the program each time, so variable and temp-table contents are not retained between interactions with the client ("context" is not maintained). In fact, on a host system with two or more agents running, the agent which handles one client host request may not be the same agent that handles the next host request from that same client. This means that, if knowledge of previous client actions is needed, the host must have some other way to get this context information. Possible means of doing this include storing context information in a database table or a text file and associating it with a User ID or session ID that is sent by the client with each interaction, or sending all context information to the client and having the client send it back each time. Each approach has different benefits and drawbacks, which are beyond the scope of this document (see "Stateless and Event-Driven Programming" for a more detailed discussion of this topic).

When writing the contents of the include files, you can immediately access the parameters sent from the client by referencing the variables and temp-table records and fields defined in the automatically generated program. Use these values to perform whatever processing is required, such as finding a record in a database table, creating or updating a record, or calculating a total.

Then, use the "jsi" include files to create one or more commands to be sent back to the client. These commands may change the contents of a client component (such as displaying a customer name in a textfield) or change the state of a component (such as disabling a button so that it cannot be clicked). New components may also be created dynamically by host commands, with all of the same options for assigning component properties as are available when creating components in Jargon Writer. Other important general-purpose include files allow a host program to invoke any client method on a client object, and to invoke any existing client tasklist to perform whatever actions it specifies. For details of available "jsi" include files, see the Host Methods for Progress 4GL section.

Here is how an http input parameter is accessed in the Progress 4GL (this code is normally provided for you by the generator app in the ".p" program):

   def var tCustNum as int no-undo.
   {jsi/getint.i &fieldname='tCustNum' &targetvar=tCustNum}

Here is how an error message can be sent back to the client, using one of the pre-coded "jsi" include files included in the "jsi" 4GL directory that is provided with Jargon Writer:

   def var vMsg as char no-undo.
   vMsg = "Customer number not found: " + string(tCustNum).
   {jsi/msgbox/warning.i &component='frame0' &msg=vMsg }

Some important syntax rules to remember:

1. A literal character value used as an include parameter should be enclosed in single quotes.

Example:
    &b='true'.

This is needed because single quotes are passed through to the referenced include file, and many jsi include files contain nested include files that require quoted parameters to pass through multiple levels of include parameters. (Double quotes are not passed through and do not work correctly for this purpose).

2. If using a literal character value with embedded spaces as an include parameter, it should be enclosed in an outer pair of double quotes and an inner pair of single quotes.

Example:
    &msg="'Hi there'".

Do not put any spaces between the double and single quotes. Failure to follow these rules will result in some very misleading Progress compiler syntax errors.

3. All "jsi" include files are either single statements or contain enclosing "DO:  END" blocks that make them the equivalent of a single statement. This means that you do NOT need to enclose "jsi" statements with your own "DO:  END" blocks inside of "IF" statements or otherwise. For example, you can write code such as:

IF condition1 THEN {jsi/...}. ELSE {jsi/...}.


Testing and Deploying Your Application
When you have completed the coding of all include files, use a compiler provided by the language vendor, or the Jargon Software RDU utility (Progress only), to compile the host procedure to make sure there are no syntax errors.

Then, open the client application in Jargon Writer and run it from the Run menu or toolbar button. Test as many different scenarios as possible. If possible, get real end users to test your application. They will often try sequences of actions that were not envisioned when the application was designed, and may expose possible problems that other users could experience. Also, observing a "naive" user (one who did not participate in designing the application) may highlight areas where the user interface is confusing or misleading.

If the host request never finishes, the host process may have failed. To view any error messages generated by a host procedure, use a text editor on the host to view the contents of any available log files for the web server, middleware, and language runtime (this varies by type of host environment).

When your quality assurance testing is completed, the final step is to deploy the client and host programs that you have developed. For information on the various ways to deploy the client-side files, see the Jargon Software Installation Instructions. The host procedures are deployed like any other application. You can deploy source files, encrypted source files, or object files only, depending on your organization's policies and requirements and your host environment's capabilities in this regard.


<-- Previous Section      Up to Top      Return to Help Index