skipjack server application development guide

150
Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html 1 of 150 5/11/2007 10:14 AM Skipjack Server Application Development Guide 5 October 2002 Skipjack Server is a general-purpose application server that is designed to flexibly support process control applications. Skipjack is based on the public-domain Tomcat Java Application Server developed under the Apache project. Tomcat provides all of the basic HTTP and Servlet processing, including connection and thread management, while Skipjack provides application level services for executing transactions that support one or more applications. This document provides an overview of the Skipjack Server from an Application Developer's perspective, discussing how to define transactions that can be used to support a wide range of application processing tasks. This document assumes that the reader has already installed the Skipjack Server according to the instructions provided in the Installation Guide and is familiar with the operational issues discussed in the Administration Guide . Table of Contents Model-View-Controller Approach 1. Hello World Example 2. Action Processing 3. Database Processing 4. Transaction Response 5. Shell Script Processing 6. Debug Management 7. Error Checking 8. Transaction Security 9. Client Application Support Java Client Package a. Perl Client Package b. C++ Client Package c. 10. Event Listening 11.

Upload: makoto-miharu

Post on 24-Apr-2015

112 views

Category:

Documents


1 download

DESCRIPTION

Skipjack Server Application Development Guidehttp://205.177.219.178/doc/appDevGuide/printable.html5 October 2002Skipjack ServerApplication Development GuideSkipjack Server is a general-purpose application server that is designed to flexibly support process control applications. Skipjack is based on the public-domain Tomcat Java Application Server developed under the Apache project. Tomcat provides all of the basic HTTP and Servlet processing, including connection and thread management,

TRANSCRIPT

Page 1: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

1 of 150 5/11/2007 10:14 AM

Skipjack Server

Application Development Guide

5 October 2002

Skipjack Server is a general-purpose application server that is designed to flexibly support process control applications. Skipjack is based on thepublic-domain TomcatJava Application Server developed under the Apache project. Tomcat provides all of the basic HTTP and Servlet processing, including connectionand thread management, while Skipjack provides application level services for executing transactions that support one or more applications.

This document provides an overview of the Skipjack Server from an Application Developer's perspective, discussing how to define transactionsthat can be used to support a wide range of application processing tasks.

This document assumes that the reader has already installed the Skipjack Server according to the instructionsprovided in the Installation Guide and is familiar with the operational issues discussed in the Administration Guide.

Table of Contents

Model-View-Controller Approach1.Hello World Example2.Action Processing3.Database Processing4.Transaction Response5.Shell Script Processing6.Debug Management7.Error Checking8.Transaction Security9.Client Application Support

Java Client Packagea.Perl Client Packageb.C++ Client Packagec.

10.

Event Listening11.

Page 2: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

2 of 150 5/11/2007 10:14 AM

Process Manager12.Session Management13.Data Importing14.HTML Form Macros15.

Page 3: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

3 of 150 5/11/2007 10:14 AM

Skipjack Server

Application Development Guide

Section 1: Model-View-Controller Approach

5 October 2002

The Model-View-Controller (MVC) Approach is a widely-used method for organizing distributed applications that are more easily modified andmaintained than previous distributed computing paradigms. In simplest terms, the MVC approach works as follows:

One or more data models are created using whatever structure is best suited for the task at hand. Typically, a relational database serves as theprimary model, although various models can (and often do) exist in an application at the same time.

One or more control tasks are created that can access and manipulate the data models, adhering to the operating rules established by theapplication requirements. Typically, control tasks are defined by a collection of database server stored procedures, Web-server CGI scripts,Java servlet classes, Enterprise Java Beans, or custom applications, to name just a few.

One or more user views are created to allow various types of users to execute the control tasks, providing whatever inputs are required andreceiving whatever output is generated. Typically, user-interface views are created using Web-based technology, such as HTML pages, usingthe HTTP protocol to manage the view-to-controller interaction. Increasingly, programmatic views, such as XML objects, exchanged usingthe SOAP protocol, are used to access distributed applications.

In theory, MVC-based distributed applications can be built with pure components; where each component performs solely in the Model, View orController areas. Generally, this is good design goal, since it simplifies application maintainence and increases flexibility, but reality often requiresthat some application components straddle two of the areas.

In the Skipjack Server, the following capabilities are provided in each of the MVC areas:

ModelThe MySQL relational database server is deployed as an integral part of the Skipjack Server, serving as the primary data model. All internalSkipjack Server administration functions use tables in the skipjack database for non-volatile storage. Any database server that supports theJava Data Base Connection (JDBC) standard can be used as a data model, with the server automatically managing all database connections.Furthermore, multiple database servers can be accessed at the same time by any Skipjack Server application.

In addition to the relational database, the Skipjack Server supports the use of Memory Tables for application tasks that require fast access todata that is initially loaded from a non-volatile storage location, such as a database table or data file.

View

Page 4: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

4 of 150 5/11/2007 10:14 AM

The Skipjack Server uses the HTTP protocol for all view-to-controller interactions, thereby allowing it to support the widest range ofapplications. As such, the server can accept inputs and generate outputs based on an arbitrary MIME data type. For example, the server canaccept inputs using the standard URL-encoded data type and can generate text/html, text/plain, or image/gif formatted outputs, to name just a few.

To support such a wide range of output formats, the Skipjack Server uses the Velocity Template Engine as the primary mechanism forformatting output files used to support a user interface view. Velocity supports a small number of easily-learned directives that facilitateformatting tasks, such as generating a tabular display of data or customizing the display for a given user. Since Velocity has a nominal set oflogical expressions (such as the if statement) and allows access to Java object methods defined by the application, it could be used for bothview and controller purposes. But, in practice, it is more effective to use Velocity solely as a view component whenever possible.

In addition to Velocity, the Skipjack Server can use the output of any of transaction response item, operating system executable or customapplication code as the output of a transaction. Such an approach is used, for example, to generate a chart image file based on the output of adatabase query.

To facilitate custom application views, Skipjack Client Libraries exist for C++, Java and Perl applications, allowing them to easily interactwith one or more Skipjack Servers. The Skipjack Client Library supports an object-based interface to the Skipjack Server, providing a set ofmethod calls that shield the client application developer from all networking and formatting issues. See Client Application Support for moredetails about the available client libraries.

ControllerAll controller tasks are performed in the Skipjack Server using a collection of transactions that are specified in Transaction Definition Files, which are formatted text files. Transactions typically consist of a collection of input validation, data model processing and outputgeneration steps that result in the desired output file. Skipjack Server transactions are very flexible, require no programming skills, and canbe easily modified as an application evolves.

Although the Skipjack Server is based on the HTTP protocol, that does not limit it to supporting only browser-based views. In fact, theHTTP protocol is increasingly used to support server-to-server interactions, so-called Web Services. In a Web Services approach, one serversends a request to another server and receives a response. Skipjack Server transactions can be invoked using the HTTP protocol, supplyinginput parameters as either URL-encoded data (typical for browser-based views) or as XML-encoded objects (typical for Web Services views.)

Page 5: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

5 of 150 5/11/2007 10:14 AM

Skipjack Server

Application Development Guide

Section 2: Hello World Example

5 October 2002

Enough theory for now ... let's look at some code. The infamous Hello World application is a good way to see the different capabilities provided bythe Skipjack Server. In this section, we demonstrate a number of Skipjack Server features by building a Hello World application in various ways.All of the examples discussed in this section can be found in the following locations:

Web URL http://$SKIPJACK_URL/tutorial/helloWorld/

File Path $SKIPJACK_HOME/app/WEB-INF/transaction/tutorial/helloWorld/

where $SKIPJACK_URL is the URL for the Skipjack Server ('localhost:8080' for default installations) and $SKIPJACK_HOME is the root location of the Skipjack Server runtime directory ('/tools/skipjack' for default installations).

Simple Transaction And Template

The simplest Hello World application consists of the following transaction definition file (ex1.tdf):

//// ex1.tdf//include "skipjack-common.tdf"

item main extends NOP { templateName = "ex1.vm";}

and a corresponding template file (ex1.vm):

#### ex1.vm##Hello World

The transaction definition file begins with three comment lines that specify the name of the file, followed by the include directive, that causes theitem definitions specified in the skipjack-common.tdf file to be included in this transaction. (We'll discuss the common items in detail later.)

Page 6: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

6 of 150 5/11/2007 10:14 AM

Specifically, the NOP item definition (defined in skipjack-common.tdf) is used as the basis for the main item definition for this transaction. (Transactionitem definitions can extend other item definitions, thereby inheriting all attribute definitions ... more on that later.)

All transactions must define the main action item, which is the starting point for all transaction processing. In this example, since the main action item extends the NOP action, No OPeration is actually performed. After the main has been fully processed, the templateName attribute is used todetermine the Velocity template file that will be used to generate the output for the transaction, which in this case is the ex1.vm template file. At thatpoint, Velocity is used to merge the contents of the template file with the current context (as it is called by Velocity), and the resulting file is usedas the transaction response.

In this example, the ex1.vm

template file consists of three initial comment lines (stripped out automatically by Velocity) and a single output line consisting of the words Hello World.

When executed from a browser using the following url:

http://$SKIPJACK_URL/tutorial/helloWorld/ex1.tdf

the following output will be seen:

Hello World

It is important to note that even though this example is very simple, it demonstrates a pure Model-View-Controller application layout. In this case,the items defined in ex1.tdf represent the Controller, the formatting defined in ex1.vm represents the View, and no Model is needed.

Velocity Variable Substitution

We can extend the simple Hello World application to display any greeting by using the variable substitution features provided by Velocity. Inparticular, we can modify the template file as follows (ex2.vm):

#### ex2.vm##<body bgcolor=white><h1 align=center>Hello $input.who</h1>

which allows us to change the specific object/person to be greeted while retaining a uniform HTML format (e.g. white background, centered text,etc.)

Page 7: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

7 of 150 5/11/2007 10:14 AM

In order to make use of this template, we need to supply a proper value for the $input.who context variable, when Velocity is called. That is, thetransaction definition needs to specify a value for $input.who during its processing phase, before calling the Velocity template engine during theresponse generation phase.

The simplest way to specify a value for $input.who is to define it explicity in the transaction definition file as follows (ex2.tdf):

//// ex2.tdf//include "skipjack-common.tdf"

item input { who = "World";}

item main extends NOP { templateName = "ex2.vm";}

where the input item definition has been added, with the who attribute being assigned a value of "World".

In fact, any item attribute defined in the transaction file can be accessed by the Velocity template using the syntax $item.attr where item is the item name and attr

is the attribute name. For example, the following transaction definition file and corresponding template file allows the background color and fonttype to be specified in the transaction file instead of being hardcoded in the template file:

//// ex3.tdf//include "skipjack-common.tdf"

item input { who = "Fred";}

item myPage { bgColor = "yellow"; font = "h2";}

item main extends NOP { templateName = "ex3.vm";}

#### ex3.vm##<body bgcolor=$myPage.bgColor><$myPage.font align=center>Hello $input.who</$myPage.font>

Page 8: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

8 of 150 5/11/2007 10:14 AM

There is nothing magic about the item names input, myPage, or even main with regards to Velocity variable substitution: any item attribute defined inthe transaction definition file can be referenced in the Velocity template file used to generate the response for that transaction.

The main item must always before defined for transaction processing purposes, even though it may not bereferenced for Velocity processing purposes.)

By judiciously using variables in Velocity templates that are defined in the transaction definition file, an application author can develop templatesthat can be used by a wider range of transactions. This directly supports the MVC approach, keeping the view (e.g., template format) separate fromthe underlying data model (e.g., item definitions).

If you mis-type a variable name in a Velocity template or the corresponding attribute is not defined in thetransaction definition file, then Velocity will not replace the variable at all and the variable notation will appearin the output file.

Finally, it is important to note that Velocity provides a set of directives that allow variables to be defined and manipulated in the template file itself,including macro definition and expansion. A full explanation of such features will not be addressed here, although we will show some morecomplex Velocity examples where appropriate. Visit the Velocity Home Page (http://jakarta.apache.org/velocity) for complete documentation on allVelocity capabilities. When reading those documents with regard to Skipjack Server, simply remember that all of the items and attributes defined ina transaction definition file serve as the context in which the Velocity template is processed.

Attribute Expressions

Attribute values can be defined in a transaction definition file using simple assignment statements, as seen in the previous examples, or morecomplex Java-like expressions. For example, the following item definition:

item myPage { greeting = "Hello"; who = "World"; message = greeting + " " + who;}

results in a value of "Hello World" for the myPage.message attribute. In this case, the '+' operator is used to concatenate the values of the greeting and who attributes, with a space in between.

No leading '$' notation is used to denote an attribute name in an attribute expression, as is required in a Velocitytemplate.)

Page 9: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

9 of 150 5/11/2007 10:14 AM

If you need to access an attribute from another item, then simply prepend the attribute name with the name of the item, as in the following example:

item input { who = "World";}

item myPage { greeting = "Hello"; message = greeting + " " + input.who;}

which references the who attribute from the input item while determining the value of the myPage.message attribute.

The following operators (derived from C, Java, Perl, SQL, etc) are supported for attribute expressions:

Operator Meaning

+, -, *, / Arithmetic

=, +=, -=, *=, /= Assignment

<, >, <=, >=, !=, == Comparison

=~, !~ Regular Expression Match

?: Conditional

!, - Unary Negation

&&, || Boolean Comparison

in, contains Membership

func(x,y,z) Function Call

object->method(x,y,z) Object Method Call

; End of Expression

In addition to these operators, a list of values can be specified by surrounding them with the '[' and ']' symbols and separating each list value by acomma. For example, the following attribute expression defines a list of colors:

colorMap = ["red", "white", "blue"];

The various conditional operators, including the Comparison, Boolean Comparison, Regular Expression, and Membership operators, can be used in

Page 10: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

10 of 150 5/11/2007 10:14 AM

conjunction with the ternary conditional operator '?:' to selectively assign a value to any attribute. For example, the following item definition:

item myPage { bgColor = (input.who == "Fred") ? "yellow" : "red";}

defines the background color based on the current value of the input.who attribute. See TDF Operators for a complete description of all attributeexpression operators and examples that make use of them.

Attribute expressions can invoke a function with a variable set of input values and make use of the value returned in subsequent expressionevaluation. For example, the following item definition:

item myPage { colorMap = ["red", "white", "blue"]; bgColor = element (colorMap, 1);}

extracts the second value "white" (zero-based indexing) from the colorMap attribute and assigns it to the bgColor attribute. See TDF Functions for acomplete description of all currently supported functions and instructions for creating and installing new functions as needed.

In some cases it is necessary to use the extensive power of Java objects and the Java runtime library to effectively determine the value of anattribute expression. Accordingly, attribute expressions can invoke arbitrary object and class methods, much like a function call. For example, thefollowing item definition:

item myPage { colorMap = ["red", "white", "blue"]; colorIndex = integer(3 * class("java.lang.M ath")->random()); bgColor = element(colorMap, colorIndex);}

will result in the background color being selected randomly from the colorMap list of colors, as can be seen by executing the ex4.tdf transaction. In thiscase, the class() function is used to access the "java.lang.Math" class and the -> operator is used to invoke the random() static class method to generate a random decimal number between 0 and 1. Then, the integer() function is used to convert the decimal number to an integer, so that it can be used bythe element() function to extract the desired color from the colorMap list. See TDF Method Calls for a discussion of object and class method invocationin attribute expressions.

Input Parameters

It most cases it is beneficial to replace hard-coded variables in a Velocity template, with references to item attributes in the transaction definition

Page 11: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

11 of 150 5/11/2007 10:14 AM

file. Similarly, it is usually beneficial to replace or overwrite hard-coded item attribute values with values that are provided by either the user orclient application. That is, we want to allow the user or client to specify the input parameters for the transaction.

Since Skipjack uses the HTTP protocol to invoke transactions, it is very easy for users to enter input parameters from a browser, simply byappending each parameter to the transaction URL as follows:

http://$SKIPJACK_URL/tutorial/helloWorld/ex4.tdf?wh o=Sally

which specifies the value "Sally" for the who input parameter. When the ex4.tdf transaction is executed by the Skipjack Server, it will automaticallystore any HTTP input parameter as a String attribute value in the input item, overwriting any similarly named attribute value that was defined in theTDF file itself.

In this example, since the ex4.tdf transaction was defined as follows:

//// ex4.tdf//include "skipjack-common.tdf"

item input { who = "World";}

item myPage { colorMap = ["red", "white", "blue"]; colorIndex = integer(3 * class("java.lang.M ath")->random()); bgColor = element(colorMap, colorIndex); font = "h2";}

item main extends NOP { templateName = "ex3.vm";}

then the value "World" will be overwritten by the value "Sally" when the transaction is executed. In this way, transaction authors can specifyhard-coded default values for all input parameters, allowing users or client applications to selectively overwrite any or all of them.

All input parameter encoding must adhere to the standard HTTP encoding scheme in order to be properlyprocessed when executing transactions from a browser or client application.

In general, since the input

item is used to automatically store all input parameters for a transaction, it shouldn't be used to store other internal attributes that may be needed toperform certain actions.

Any appropriate HTML form can also be used to submit input parameters to a transaction. The Skipjack Server supports both the GET and POST

Page 12: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

12 of 150 5/11/2007 10:14 AM

methods commonly used when submitting an HTML form from a browser.

Input Validation

Any time a user or client application is allowed to submit input parameters, it is generally prudent to perform some type of syntax and/or semanticvalidation on those inputs. To that end, the inputSchema item can be defined for a transaction that specifies the name, type and mode of each inputparameter supported by that transaction. For example, consider the following transaction definition (ex5.tdf):

//// ex5.tdf//include "skipjack-common.tdf"

schema inputSchema extends BaseSchema { attrs = [ ["who", "string", "default", "World"], ["fontSize", "integer", "default", 2], ["bgColor", colorMap, "default", "white"] ];

colorMap = ["red", "white", "blue"];}

item myPage { bgColor = input.bgColor; font = "h" + input.fontSize;}

item main extends NOP { templateName = "ex3.vm";}

By default, if no parameters are given, then this transaction produces a result similar to the previous examples, printing "Hello World" on a whitebackground. However, this transaction also allows the user or client application to define the who, fontSize and bgColor input parameters to control the type of output that is generated. All aspects concerning the supported input parameters are defined in the inputSchema item, which we will nowexplain in detail.

Schema Attribute Definitions

It is important to note that the inputSchema item is defined as a schema item, not a generic item. This tells the Skipjack Server to process the attrs

attribute, which should be defined as a list of lists, where each list entry defines an input parameter for the transaction. Other attributes may also bedefined in the inputSchema to make parameter definitions easier to understand (such as the colorMap attribute which will be explained shortly). Eachentry in the attrs list should be formatted as follows:

["name", "type", "nonempty | default | optional", " default value"]

Page 13: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

13 of 150 5/11/2007 10:14 AM

where "name" is the parameter name and "type" is the parameter type. (See Schema Class for a list of all parameter types supported.) The thirdelement indicates if the parameter must be specified (ie. "nonempty") or is optional. If "default" is specified, then the "default value" will be usedautomatically if the user or client application doesn't specify a value for that parameter. If "optional" is specified, then no value is specifiedautomatically. (The "optional" setting is used primarily for documentation purposes as will be discussed later.)

In the example above, the first input parameter is defined with the name "who" and a type of "string". That is, the who input parameter can consist ofan arbitrary string for which no syntax checking will be performed. Since the who parameter is marked as a "default" parameter, it will be assignedthe value of "World" if it is not otherwise defined by the user or client application.

The fontSize

input parameter is defined as an "integer" value, which means that a syntax check will be performed automatically before the transaction isexecuted and that the value will be converted to a Java Long object after successful validation.

Finally, the bgColor input parameter type is a reference to the colorMap attribute, which itself is defined as a list of values. Any time that a list ofvalues is specified as the input parameter type (either as an embedded list in the parameter definition tuple or a reference to a list value attribute),then the input parameter value must be contained in that list to be valid.

Based on the inputSchema definition, all of the following transaction URLs are valid:

ex5.tdfex5.tdf?who=Sallyex5.tdf?bgColor=redex5.tdf?who=Sally&bgColor=blue&fontSize=1ex5.tdf?ignore=this

and all of the following URLs will result in an error message being generated:

ex5.tdf?bgColor=greenex5.tdf?fontSize=not-a-number

Attribute Storage Format

A Storage Format Expression can be specified for each attribute defined in the attrs table, which can be used to convert a validated attribute inputvalue before storing it in the input item. This can be used to perform routine conversion, such as trimming white space from around a String value orensuring that a value falls within a given range, just to name a few examples.

Storage format expressions are specified by defining the fooFormat schema attribute, where foo is the name of the attribute being converted. Thestorage format expression may reference the _srcItem schema attribute to access the item currently being validated. The storage format expressionmay also reference any other schema or item attributes as needed to perform its task. That is, any valid TDF expression can be specified as theformat expression.

Page 14: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

14 of 150 5/11/2007 10:14 AM

For example, the following format expression could be used to ensure that the fontSize parameter is not greater than 32:

fontSizeFormat = _srcItem.fontSize < 32 ? _srcItem.fontSize : 32;

Non-Validated Input Attributes

Input parameters that are not defined by the inputSchema are simply ignored for validation purposes. This allows transaction authors to perform morecomplex parameter validation for some parameters, while using the easily specified inputSchema for other parameters.

Input/Output Separation

Note how the myPage item attributes have been re-defined in terms of the input item attributes so that they can be referenced by the same Velocitytemplate as before. In general, it is prudent to create separate items like myPage that are used to specify formatting or data values referenced within aVelocity template file, even if they need to trivially reference values from other items, like the input.bgColor reference. By defining a separate item,the transaction author is clearly differentiating between the transaction input parameters and the attribute values required by the template beingused. Essentially, the myPage

item defines the "inputs" specifically used by the template. This allows templates to be easily used across a number of transactions simply bydefining the myPage

item (or any name of your choosing) in each such transaction, specifying the attribute value mappings appropriate for that transaction. For example,some transactions may pass the values through from the input item, like the example above, while others hard-code myPage values or extract them from the database. (Later, we will discuss how the TDF "include" and "overrides" directives can be used to create a single item that is shared acrossall such transactions, requiring only individual attributes to be overwritten.)

Default Input Form

Given that the inputSchema

item defines all of the input parameters supported by a given transaction, it is possible to generate input forms for any transaction. In fact, theSkipjack Server includes a feature that automatically generates an input form for any transaction for which an inputSchema is defined. The input formdisplays a field for input parameters, indicates which inputs are required and displays the default value for an input field if specified. For inputparameters defined by enumerated lists, the input form displays a set of radio buttons or a choice list (depending on the number of items in the list).

A default transaction input form can be generated by replacing the normal .tdf transaction suffix by the .form suffix. For example, the following URL:

http://$SKIPJACK_URL/tutorial/helloWorld/ex5.form

Page 15: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

15 of 150 5/11/2007 10:14 AM

which will result in the following form being displayed:

The default form displays the transaction name, the input fields, and a set of buttons to submit, reset or cancel the transaction. The default form isbased on a collection of Velocity macros that are deployed as part of the standard Skipjack components and there are a number of attributes that canbe specified to alter the appearance of the form and individual fields. See HTML Form Macros for more details.

Clearly, the default input form is no substitute for a well-designed HTML-based user interface, where form fields and buttons are properly placed toreduce screen clutter and make it easier for the user to enter critical information. Nonetheless, when developing and/or trouble-shootingtransactions and applications, the default form provides a very convenient mechanism for executing any transaction.

Page 16: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

16 of 150 5/11/2007 10:14 AM

Skipjack Server

Application Development Guide

Section 3: Action Processing

5 October 2002

The Hello World examples demonstrate how input parameters, item attributes and Velocity templates can be combined into a simple transaction.Notably, however, none of the Hello World examples actually performed any actions (they all extended the NOP action), nor did they make use ofany data store. In this section, we discuss how transactions can be defined using a collection of action items, each of which performs one of thesteps required by the transaction, such as retrieving data from a database or memory table.

The primary mechanism for performing tasks within a transaction is to extend one or more action items and then execute them as part of the main

action item. Action classes (e.g., the Java code used to implement an action item) are relatively easy to implement and can be installed in theSkipjack Server simply by placing the Java class file in the appropriate directory. See TDF Actions for a complete list of actions that are available,including descriptions of the attributes that are supported for each action item.

Action items exist to perform a wide range of functions, serving as the interface between the transaction definition file and custom Java code. Thisseparation means that transaction authors do not need to have any Java programming experience to effectively develop a wide range oftransactions. If a person can read and understand the description for a given action item, then they can easily make use of such action items in theirtransaction definitions.

The most common way to use an action item is to extend the item defined in the skipjack-common.tdf, thereby assigning it a new name in the currenttransaction file. Then, appropriate action item attribute values can be defined in the extended item for the task at hand. For example, the CopyAction is very simple action that copies all of the attributes defined in the source item defined by the _srcItem attribute to the destination item defined by the_destItem attribute. So, if you wanted to copy all input parameters to the output item, the following item definition would suffice:

include "skipjack-common.tdf"

item copyInputToOutput extends CopyAction { _srcItem = "input"; _destItem = "output";}

Note, we need to include the skipjack-common.tdf file before extending the CopyAction item, because it is defined in that file.

After defining the copyInputToOutput action, we only need to "execute" it as part of the main action. In the Hello World examples, the main item extended the NOP action, which doesn't do anything. Therefore, if we want to execute the copyInputToOutput action, we need to extend a differentaction. Generally, the main item extends the BaseAction as in the following definition:

Page 17: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

17 of 150 5/11/2007 10:14 AM

item main extends BaseAction { actions = ["copyInputToOutput"];

templateName = "output.vm";}

The BaseAction executes all of the action items listed by the actions attribute, which in this case is only the copyInputToOutput action. Actions areexecuted sequentially by the BaseAction until all actions are done or an exception is thrown. If all actions complete successfully, then themain.templateName

attribute is used to determine which Velocity template to use to generate the transaction response. In this case, we can assume that the "output.vm"template references the output item attributes to format an appropriate response. (Otherwise, why else did we copy them there?)

In simplest terms, actions embody the essential Unix concept of using pipelines of small, flexible, building blocks to perform complex functions.Over time, evolution yields a powerful set of actions that can handle most application needs with little additional programming. Transactiondefinition files simply define what actions are required and what inputs to provide to them, while the actions actually perform the work.

As in many tutorials, we have a "chicken-and-egg" problem in that we need to discuss action processing beforewe can describe the actual actions themselves. So, for the remaining examples in the section, all of the actionsreferenced are "abstract actions" (ie. they don't really exist.) In subsequent sections, we will discuss the realactions provided by Skipjack for various processing tasks.

Undo Actions

If an error occurs while processing any of the action items referenced by the actions attribute, then all subsequent actions defined in that list will beautomatically ignored. In such cases, if the undoActions attribute references one or more actions, then each of those actions will be processedsequentially. Undo actions can be used to restore partially completed changes, execute custom error processing, record custom debug informationor perform any task that is required to compensate or handle the original action error.

For example, the following action item attempts to insert records into two different tables:

item insertRecords extends BaseAction { actions = ["insertOne", "insertTwo"];

undoActions = ["deleteOne", "deleteTwo"];}

If either insert action fails, then the undo action is called to remove both records. If one of the undo actions fail, then the remaining undo actions areignored and the original exception is used to generate the transaction status and error message.

Page 18: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

18 of 150 5/11/2007 10:14 AM

The actions referenced by the "undoActions" attribute don't necessarily have to "undo" anything, they can beused, for example, to simply log a problem or inform an operator about something that needs to be examined.

Prior to executing any undo actions, the tx.errorMsg, tx.errorClass and tx.errorAction attributes will be assigned values that can be used by any of the undoactions to determine what failed in the action list. The tx.errorMsg and tx.errorClass attributes will contain the message and class name of the Javaexception that was generated by the action that failed, while the tx.errorAction attribute will reference the Java Item object for the action that failed.

For example, the following undo action generates a message based on the name of the action that failed and the error message generated by thataction:

item genMessage extends BaseAction { msg = "Action " + tx.errorAction->getName() + " Failed With The Message '" + tx.errorMsg + "'";}

In addition to the transaction attributes described above, undo actions may also be able to use the tx.status attribute to determine the appropriateprocessing to be performed. The tx.status attribute is defined by most, but not all, actions when they throw an exception.

Done Actions

Regardless of the success or failure of the actions referenced by both the actions and undoActions attributes, one or more actions can be specified bythe doneActions

attribue that are executed after the other actions. Generally, such actions are used to release resources or record processing information despitefailures. Done actions can be used with or without undo actions, depending on the current task to be performed.

For example, the following action locks a table before inserting two records and then unlocks the table:

item insertRecords extends BaseAction { actions = ["lockTable", "insertOne", "i nsertTwo"];

undoActions = ["deleteOne", "deleteTwo"];

doneActions = ["unlockTable"];}

The table lock is released by an action specified in the doneActions attribute to ensure that the table is unlocked regardless of the outcome of theinsert and/or delete actions.

Page 19: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

19 of 150 5/11/2007 10:14 AM

As with the actions and undoActions attributes, all of the actions listed by the doneActions attribute are processed sequentially. If an error is generated byone of the doneActions then all remaining actions will be ignored. If no error was previously generated by one of the actions defined by the actions

attribute, then the error generated by the action in the doneActions list will be used as the error result for the overall action, causing the transaction tobe aborted in normal operation.

Developers familiar with the Java "try-catch-finally" language construct may note the similarity between thatconstruct and the actions, undoActions and doneActions attributes. Although the specific semantics are slightlydifferent, the overall concepts are the same.

Action Locks

In any multi-threaded server such as Skipjack, certain types of concurrent processing tasks may result in inconsistent behaviors, depending on theorder in which they are performed or other types of race conditions. In order to help eliminate such problems, Skipjack allows transaction authorsto allocate one or more resource locks to any action. Once allocated, a resource lock prevents all other actions from accessing the same lock until itis released by the original action. Resource locks are allocated simply by listing the name of each lock required and are automatically released whenthe action has been completed. Resource locks remain allocated for all sub-actions performed by a given action.

The following attributes can be defined for any action to specify which resource locks are needed and how to handle any locking errors:

Attribute Description

_locks Optional list of resource lock names that must be acquired before action processing begins. This can be used to prevent otheractions or transactions from interfering with the processing of the current action. Lock acquisition is attempted after anybackground thread is created (see Background Actions below for details), but before any preCondition check that may be specified(see Action Pre-Conditions below for details). All resource locks acquired by the current action will be automatically releasedafter all action processing is complete, including any exception processing.

_lockTimeout Optional timeout (in milliseconds) to be used when attempting to acquire one or more resource locks as specified by the _locks

attribute. If any of the locks cannot be acquired in the specified time period, then an exception will be thrown and the action willbe aborted, releasing any locks that were actually acquired. If a zero or negative value is defined, then no timeout will occur.The default value is 60 seconds.

_lockTimeoutMsg Optional error message to be used if the _lockTimeout expires. Prior to accessing this attribute, the values of the _lockTimeoutLock,_lockTimeoutThread and _lockTimeoutAction attributes will be assigned the name of the lock that caused the timeout, as well as thename of the thread and action that currently holds that lock. These attributes can be used to generate a custom timeout messageand/or to check for deadlock conditions.

_lockTimeoutStatus Optional error status to be used if the _lockTimeout expires.

Page 20: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

20 of 150 5/11/2007 10:14 AM

For example, the following action definition requires the Device12 and ChangeStatus resource locks to be allocated before the configDevice and resetDevice actions are executed. If either of the locks cannot be allocated within 10 seconds, then a custom error message is generated.

item doWork extends BaseAction { _locks = ["Device12", "ChangeStatu s"]; _lockTimeout = 10000; _lockTimeoutMsg = "Unable To Get Lock " + _ lockTimeoutLock + " Because It Is Currently Owned By " + _lockTimeoutAction;

actions = ["configDevice", "resetDe vice"];}

Action Errors

In normal operation, if any action generates an error then all subsequent action processing is aborted and an unsuccessful transaction response isgenerated. This is done to prevent non-deterministic side-effects from subsequent actions that may depend on the outcome of the failed action andto make it easier for transaction authors to trouble-shoot transaction failures.

In some situations, however, it may be necessary or desirable to ignore any error generated by a given action. For example, an action may attempt toupdate a record that may or may not exist. In such cases, a transaction author may override the normal error processing behavior for that action bysetting the _ignoreError attribute to true. When set to true, any error generated by that action will be ignored and transaction processing will continuewith the next action to be processed.

When the error is ignored, the current values of the tx.status and tx.errorMsg attributes will be copied into the tx.ignoredStatus and tx.ignoredErrorMsg

attributes, respectively, for subsequent use by the transaction. Then, the tx.status and tx.errorMsg attributes will be reset to the values that were set justprior to the action being processed. If the _ignoreError attribute is used for an action that is inside of a loop, the transaction author is responsible forclearing the tx.ignoredStatus and tx.ignoredErrorMsg attributes as needed.

The _ignoreError attribute does not affect the way that errors are handled while processing the actions, undoActions, and doneActions lists, only the way the overall action error is handled by the transaction. If a transaction authorwants to ensure that a list of actions are performed regardless of errors generated by any of those actions, thenthe _ignoreError attribute should be set to true in each of those actions, not in the action that defined the list ofactions.

For example, the following action defines the same behavior as in the previous example, but uses the _ignoreError attribute to continue transactionprocessing regardless of any error generated by this action:

item insertRecords extends BaseAction {

Page 21: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

21 of 150 5/11/2007 10:14 AM

_ignoreError = true;

actions = ["lockTable", "insertOne", " insertTwo"];

undoActions = ["deleteOne", "deleteTwo"];

doneActions = ["unlockTable"];}

Alternatively, the following action attempts to delete two records, ignoring errors generated by either action:

item deleteRecords extends BaseAction { actions = ["lockTable", "deleteOne", "d eleteTwo", "unlockTable"];}

item deleteOne extends MyDeleteAction { _ignoreError = true; ....}

item deleteTwo extends MyDeleteAction { _ignoreError = true; ....}

In this example, the _ignoreError attributes of the underlying delete actions are set to true, causing any errors generated by those actions to be ignored.Consequently, the actions performed by the higher level deleteRecords action can be specified solely within the actions list, since the delete actions cannot cause the list processing to be aborted.

Action Pre-Conditions

There are times when an action should be executed only if a certain pre-condition is true. All Skipjack actions support this feature through the useof the preCondition boolean attribute. Specifically, if the preCondition expression evaluates to "true", then the action will be executed. Otherwise, theaction will not be executed and the transaction will continue processing the next action, if any exists.

For example, suppose in the previous example that we want to delete the second record only if the input parameter RecordCount is greater than one.That could be specified using the following preCondition expression:

item deleteRecords extends BaseAction { actions = ["lockTable", "deleteOne", " deleteTwo", "unlockTable"];}

item deleteTwo extends MyDeleteAction { preCondition = integer(input.RecordCount) > 1; ....}

Page 22: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

22 of 150 5/11/2007 10:14 AM

Alternatively, if the records should only be deleted if the RecordCount is greater than zero, then we could add a preCondition expression to the top-level action as follows:

item deleteRecords extends BaseAction { preCondition = integer(input.RecordCount) > 0; actions = ["lockTable", "deleteOne", " deleteTwo", "unlockTable"];}

item deleteTwo extends MyDeleteAction { preCondition = integer(input.RecordCount) > 1; ....}

In this case, the deleteRecords.preCondition expression determines if any of the sub-actions should be performed, while the deleteTwo.preCondition

expression determines if the deleteTwo sub-action should be executed.

Action Argument Lists

All of the examples discussed so far have shown action lists that consist of one or more action names. For each action specified, the action item isprocessed using the current value of all attributes defined in that action. This generally leads to well-structured and well-understood transactiondefinition files, since each action item is relatively self-contained.

However, there are situations where the requirement to define all action attributes in the action item itself becomes onerous. For example, considerthe following transaction that needs to log three different debug messages while the transaction is being processed:

item logMsg extends LogAction { Severity = "INFO"; LogFile = "navius.skipjack.errorlog"; Message = "Unknown";}

item logMsg1 extends logMsg { Message = "Transaction Started";}

item logMsg2 extends logMsg { Message = "Transaction Still Running";}

item logMsg3 extends logMsg { Message = "Transaction Completed";}

item main extends BaseAction { actions = [ "logMsg1", ..., "logMsg2",

Page 23: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

23 of 150 5/11/2007 10:14 AM

..., "logMsg3" ];}

In this case, an action item must be created for each message, with the Message attribute being overwritten in each case. Although item inheritancemakes this a relatively straight-forward process, it still requires the author to invent unique names for each item and it otherwise clutters up thetransaction definition file.

To alleviate such problems and to allow action items to be easily re-used, actions can be invoked using an action argument list, An actionargument list consists of a Vector of values, where the first value is interpreted as the action name, followed by one or more (attribute, value) pairs.For each pair of values specified, the action item attribute will be temporarily overwritten with the value given for the duration of the actionexecution. After the action processing has been completed, the overwritten attribute values will be restored. Essentially, this allows actions to beexecuted as "subroutines" or "methods" with certain values supplied as "input" parameters.

For example, the previous example could be re-written as follows using action arguments:

item logMsg extends LogAction { Severity = "INFO"; LogFile = "navius.skipjack.errorlog"; Message = "Unknown";}

item main extends BaseAction { actions = [ ("logMsg", "Message", "Transaction Started") , ..., ("logMsg", "Message", "Transaction Still Running") , ..., ("logMsg", "Message", "Transaction Completed") ];}

In this case, the logMsg action itself is invoked three times, overwriting the Message attribute of that action item every time.

Any Vector value specified in an action list will be interpreted as an action argument list, using the first elementas the action name and all subsequent pairs of elements as the (attribute, value) pairs.

Any number of attribute value pairs can be specified when executing an action, provided that the attributes already exist in the action item. Forexample, the Severity attribue may be overwritten for the second message using the following definition:

item logMsg extends LogAction { Severity = "INFO"; LogFile = "navius.skipjack.errorlog"; Message = "Unknown";

Page 24: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

24 of 150 5/11/2007 10:14 AM

}

item main extends BaseAction { actions = [ ("logMsg", "Message", "Transactio n Started"), ..., ("logMsg", "Severity", "DEBUG", "Message", "Transaction Sti ll Running") , ..., ("logMsg", "Message", "Transactio n Completed") ];}

Since all of the logMsg

attributes are automatically restored after being invoked by each action argument list, the third message will still be assigned a Severity level of "INFO", which is the value defined for that attribute in the logMsg action item.

Action items that have their _readonly attribute set to "true" cannot by invoked using an action argument list.Furthermore, all of the attribute names specified in the action argument list must already exist in the action itemand an attribute value must be specified for each attribute name given (ie. the argument list must have an oddnumber of entries). If any of these conditions fails, an appropriate error will be generated.

Background Actions

In most transactions, all of the actions defined in the main.actions are sequentially executed to completion before the transaction response isgenerated. However, there are times when it is desirable to execute one or more actions in independent threads, thereby allowing them to beprocessed concurrently while the rest of the transaction is being processed or well after the transaction has generated its response. The SkipjackServer supports such a processing style through the use of background actions, which can be configured using the following collection of attributesthat are supported for all actions:

Attribute Description

_bgAction Optional boolean value that indicates if the action should be processed asa background thread. If true, a background thread is created, the action isprocessed by that thread and the transaction continues processing allsubsequent actions.

The Process ID for the background thread is stored as the value of the_bgProcessID attribute of the destination item for this action, which can be

Page 25: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

25 of 150 5/11/2007 10:14 AM

used to manage the process using the ProcessAction action.

_bgErrorLog By default, any exception thrown by a background action will be printedto the navius.skipjack.errorlog. If this attribute is defined, it specifies the nameof the log file to be used.

_bgAutoStatus By default, the status of the background process will be automaticallyupdated as it proceeds. If this attribute is set to false, then no statusupdates will be performed. In either case, transactions can use ProcessAction

to update the process status as needed, given the _bgProcessID attribute value.

_bgProcessName Optional string value that will be assigned as the name of the backgroundthread in the process table. If this attribute is not defined, the actionidentifier will be used.

_bgTrigger Specifies how action processing should be triggered, including types'REPEAT' or 'ALARM'.

If 'REPEAT' is specified, the action will be processed one or more timesdepending on the _bgRepeatCount attribute, with an optional delay betweeneach processing cycle, as specified by the _bgRepeatDelay attribute.

If 'ALARM' is specified, the action will be processed for eachchronological alarm specified by the _bgAlarm* attributes.

The default value is 'REPEAT'.

_bgRepeatCount Specifies the number of times that the action should be executed when_bgTrigger is 'REPEAT', with a default value of 1. If a negative or zerovalue is specified, then the action will be repeated until the backgroundaction process is stopped via the Process Manager.

Prior to each execution of the action, the _bgCount attribute of the action'sdestination item will be set to the current iteration count (if thedestination item is writable). The iteration count starts with 1 andautomatically rolls over after Integer.MAX_VALUE is reached.

_bgRepeatDelay Specifies an optional sleep time (in seconds) between repeated actionexecutions. If the value is less than or equal to zero, no delay will beinserted between action executions. The default value is 2.

Page 26: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

26 of 150 5/11/2007 10:14 AM

_bgAlarmDays An optional Vector of integers from 1 to 31 that designates each day ofthe month that an action should be executed when 'ALARM' is specifiedfor the _bgTrigger attribute. If this attribute is not defined or the Vector isempty, then the action will be executed every day of the month.

This attribute should not be specified if the _bgAlarmWeekdays attribute is specified.

_bgAlarmWeekdays An optional Vector of integers from 1 to 7 (1=Sunday, 2=Monday, ...)that designates each day of the week that an action should be executedwhen 'ALARM' is specified for the _bgTrigger attribute. If this attribute isnot defined or the Vector is empty, then the action will be executed everyday of the week.

This attribute should not be specified if the _bgAlarmDays attribute is specified.

_bgAlarmHours An optional Vector of integers from 0 to 23 that designates each hour ofthe day that an action should be executed when 'ALARM' is specified forthe _bgTrigger attribute. If this attribute is not defined or the Vector isempty, then the action will be executed every hour of the day.

_bgAlarmMinutes An optional Vector of integers from 0 to 59 that designates each minuteof the hour that an action should be executed when 'ALARM' is specifiedfor the _bgTrigger attribute. If this attribute is not defined or the Vector isempty, then the action will be executed every minute of the hour.

One-Time Actions

By default, if the _bgAction attribute is set to 'true', then the current action will be processed once as a background action. As soon as the backgroundaction is launched, the transaction will continue processing any subsequent actions and/or will generate the transaction response. Such an approachis commonly used for actions that may require a significant amount of time to complete and the transaction author does not want the client to waituntil it is done. Any type of action can be executed as a background action. For example, the following action item definitions results in abackground action that simply appends a message to the error log (using the LogAction):

item myBackgroundAction extends BaseAction { _bgAction = true; actions = ["logMsg"];}

item logMsg extends LogAction {

Page 27: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

27 of 150 5/11/2007 10:14 AM

Severity = "INFO"; LogFile = "navius.skipjack.errorlog"; Message = "Background Processing Performe d";}

After myBackgroundAction has been processed, the background will be terminated.

Repetitive Actions

Background actions can be repeated 2 or more times, by specifying the _bgRepeatCount attribute, or indefinitely by setting that attribute to zero or anegative value. A delay (in seconds) between each action execution can be specified using the _bgRepeatDelay attribute. For example, the followingmodification to the previous example results in myBackgroundAction being executed a total of 20 times, with a 5 second delay in between eachexecution:

item myBackgroundAction extends BaseAction { _bgAction = true; _bgRepeatCount = 20; _bgRepeatDelay = 5; actions = ["logMsg"];}

item logMsg extends LogAction { Severity = "INFO"; LogFile = "navius.skipjack.errorlog"; Message = "Background Processing Performe d";}

Such an approach might be used for delivering information to an external system, attempting delivery only a certain number of times beforeeventually giving up, as in the following example:

item myDeliveryAction extends BaseAction { _bgAction = true; _bgRepeatCount = 3; _bgRepeatDelay = 60;

doneFlag = false; preCondition = !doneFlag; actions = ["doDelivery", "setDoneFla g"];}

item doDelivery extends DeliveryAction { _formatType = "FILE"; fileInputFile = "/tmp/myData.txt";

_transportType = "FTP"; ftpOutputHost = "somewhere.com"; ftpOutputUsername = "somebody"; ftpOutputPassword = "easy to guess"; ftpOutputFile = "remoteFile.txt";}

Page 28: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

28 of 150 5/11/2007 10:14 AM

item setDoneFlag extends ComputeAction { _destItem = "myDeliveryAction"; doneFlag = true;}

Notice how the preCondition attribute of the myDeliveryAction action is used to abort subsequent action processing after the setDoneFlag action has beenexecuted, which can only happen if the doDelivery is successfully executed.

In this example, even if the doDelivery is successful the first time, the myDeliveryAction will be repeated two moretimes over the next two minutes. However, it won't actually do any processing because the preCondition will be false.

Periodic Actions

Background actions can be performed on a periodic basis (e.g., hourly, daily, weekly, etc.) by setting the _bgTrigger attribute to 'ALARM' and byspecifying one or more alarm times using the _bgAlarm* attributes. The action will be performed once for every time specified and will be repeatedindefinitely until the action is stopped by the Process Manager (see below for details). For example, the following background item definitioncauses the logMsg action from the previous example to be executed every quarter hour:

item myPeriodicAction extends BaseAction { _bgAction = true; _bgTrigger = "ALARM"; _bgAlarmMinutes = [00, 15, 30, 45]; actions = ["logMsg"];}

If such action processing is only desired during normal business hours (9am-5pm), then the _bgAlarmHours attribute can be specified as in thefollowing example:

item myPeriodicAction extends BaseAction { _bgAction = true; _bgTrigger = "ALARM"; _bgAlarmHours = [9, 10, 11, 12, 13, 14, 1 5, 16]; _bgAlarmMinutes = [00, 15, 30, 45]; actions = ["logMsg"];}

In this case, the action will be executed 32 times per day, 4 times each hour, from 9:00am to 4:45pm. Since the _bgAlarmDays and the _bgAlarmWeekdays

attributes were not specified, the action will be executed every day of the month.

Managing Background Actions

Page 29: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

29 of 150 5/11/2007 10:14 AM

Background actions are processed by server threads that are dynamically created as needed. If the background action terminates normally, suchthreads will also terminate normally, releasing any server resources that have been used by the transaction from which the action was launched.However, since repetitive and periodic background actions may never terminate, it may be necessary to monitor their progress and/or terminatethem manually.

In general, it is best to design periodic or repetitive background actions to print information to an appropriatelog for trouble-shooting purposes, but that is not a requirement.

All background action threads are automatically registered in the Skipjack Server's Process Table when they are created and un-registered whenthey are terminated. The Process Table can be viewed using the Skipjack console to monitor the status of a background action and/or to terminatethe process manually. (An error message will be appended to the error log associated with any background action that is terminated manually.) SeeProcess Manager for more information about the Process Manager and the Process Table.

Page 30: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

30 of 150 5/11/2007 10:14 AM

Skipjack Server

Application Development Guide

Section 4: Database Processing

5 October 2002

In this section we discuss a set of transaction examples that retrieve data from a database server based on a set of input parameters and generatedifferent types of results using Velocity templates. All of the examples discussed in this section can be found in the following locations:

Web URL http://$SKIPJACK_URL/tutorial/dbQuery/

File Path $SKIPJACK_HOME/app/WEB-INF/transaction/tutorial/dbQuery/

where $SKIPJACK_URL is the URL for the Skipjack Server ('localhost:8080' for default installations) and $SKIPJACK_HOME is the root location of the Skipjack Server runtime directory ('/tools/skipjack' for default installations).

In general, database processing is performed using the standard set of action items defined in skipjack-common.tdf, which includes the following:

SQLTableActionSQLRecordActionSQLColActionSQLMapActionSQLUpdateActionSQLAction

The SQLTableAction

is the primary action used to retrieve information from the database. The SQL expression itself is defined in a SQL template file which is processedthrough Velocity before being sent to the database server. This allows the SQL script to reference item attributes defined in the transactiondefinition file, thereby increasing the flexibility of such scripts. The resulting table generated by the query is stored as a collection of attributes inthe action item itself or in any item designated by the _destItem attribute.

The other SQL actions have similar capabilities, but generally store the results in different ways to accomodate subsequent transaction processingneeds.

Static Database Query

Page 31: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

31 of 150 5/11/2007 10:14 AM

Consider the following database transaction (ex1.tdf):

//// ex1.tdf//include "skipjack-common.tdf"

item getDBList extends SQLTableAction { sqlFile = "getDBList.sql";}

item main extends BaseAction { actions = ["getDBList"]; templateName = "ex1.vm";}

that retrieves the current list of databases defined on the database server. The actual SQL expression is defined in the "getDBList.sql" as follows:

#### getDBList.sql##show databases

which is processed as a Velocity template file (even though this specific script doesn't really use any Velocity features). After the getDBList action is executed, the following attributes will be automatically defined:

getDBList.sqlExpr = SQL expression sent to databas e servergetDBList.table = query resultsgetDBList.rowCount = number of rows in tablegetDBList.rows = Vector of TableRow objects in tablegetDBList.cols = Vector of TableCol objects in tablegetDBList.xxxCol = TableCol object for column xxx

which can then be referenced by the response template as follows (ex1.vm):

#### ex1.vm##<body bgcolor="white"><h2>Database List</h2><pre>#foreach ($row in $getDBList.rows)$row.getValue(0)#end</pre>

to yield the following results:

Page 32: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

32 of 150 5/11/2007 10:14 AM

Database Listauthoritymysqlplssecurityskipjacktest

The template file used in this example demonstrates how the #foreach() directive can be used in Velocity to easily iterate over a Vector of data.(Actually, any enumerable Java object can be iterated over using the #foreach() directive.) Velocity assigns each TableRow object defined in that list tothe $row variable, which is then used to access the getValue() method defined by the TableRow object.

The ability to execute any public method allows Velocity templates to handle a wide variety of formatting problems, as well as make decisionsabout the content that should be displayed. Clearly, such power can be quickly abused, turning Velocity templates into mind-boggling, hard-to-read,coding nightmares if you are not careful. But, when used in moderation, it can make complex formatting tasks much simpler. The primary drawbackof such an approach is the need to understand which Java methods are available, requiring access to the Java documentation for key objects. Forthat reason, a complete set of Java documentation for all objects used by Skipjack and the underlying toolkit can be found at:

http://$SKIPJACK_URL/apidoc/

including the table-related objects defined in the navius.toolkit.table package.

When executing Java methods from Velocity templates, it is important to remember that any exceptiongenerated by such methods are "consumed" by Velocity without notification. In such cases, the correspondingvariable substituion is aborted, resulting in the variable expression itself being passed to the output stream. SeeDebug Management for Skipjack mechanisms that can be used to trouble-shoot such problems.

Parameterized Database Query

We can extend the previous example to allow the user or client application to supply input parameters that determine the specific query that isexecuted. For example, the following transaction definition (ex2.tdf):

//// ex2.tdf//include "skipjack-common.tdf"

schema inputSchema extends BaseSchema {

Page 33: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

33 of 150 5/11/2007 10:14 AM

attrs = [ ["dbName", dbList, "default", "mysq l"] ];

dbList = ["mysql", "skipjack", "test"];}

item getTableList extends SQLTableAction { sqlFile = "getTableList.sql";}

item main extends BaseAction { actions = ["getTableList"]; templateName = "ex2.vm";}

allows the user to specify a database name and then it retrieves the list of all tables in that database using the following SQL script (getTableList.sql):

#### getTableList.sql##use $input.dbName;show tables;

In this case, the input.dbName attribute is used to dynamically construct the desired SQL expression. In subsequent examples, we'll see how the#foreach() directive can be used to easily generate a series of SQL insert statements.

We can exercise this transaction using the default input form:

http://$SKIPJACK_URL/tutorial/dbQuery/ex2.form

which will show the list of database tables, as well as the actual SQL expression used based on the following template file (ex2.vm):

//// ex2.tdf//include "skipjack-common.tdf"

schema inputSchema extends BaseSchema { attrs = [ ["dbName", dbList, "default", "mysq l"] ];

dbList = ["mysql", "skipjack", "test"];}

item getTableList extends SQLTableAction { sqlFile = "getTableList.sql";}

item main extends BaseAction {

Page 34: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

34 of 150 5/11/2007 10:14 AM

actions = ["getTableList"]; templateName = "ex2.vm";}

In this template, we used a more complicated variable reference:

$getTableList.table.getCol(0).getName()

to access the getCol() method of the Table object, and then the getName() method of the resulting TableCol object to get the name of the column.

Multiple SQL Statements

The getTableList.sql

script demonstrates how multiple SQL statements can be executed within a single script file by using ';' to separate them. Any delimiter string (1 ormore characters) can be used by defining it on the first line of the script file using the following syntax:

DELIM=mydelim

For each statement defined, the statement will be executed by the database server and the results will be processed by the Skipjack server.

If multiple query results are returned by a multi-statement SQL script, then only the last table result returned by the database server will be stored as the result of the SQL action. If all of the table results are needed, thenseparate SQL actions should be executed, one for each result.

Table Formatting

As we've seen, it is relatively easy to create a transaction that accepts a number of different input parameters, executes a dynamic SQL expressionand returns the results. Once such a transaction exists, it can be used by GUI and non-GUI applications alike to perform that function. For GUIapplications, however, more sophisticated output formatting is usually needed, and that is where Velocity begins to shine.

Consider the following transaction definition file (ex3.tdf):

//// ex3.tdf//include "skipjack-common.tdf"

Page 35: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

35 of 150 5/11/2007 10:14 AM

schema inputSchema extends BaseSchema { attrs = [ ["dbName", dbList, "default", "mysq l"], ["tblName", "string", "nonempty"] ];

dbList = ["mysql", "skipjack", "test"];}

item getTableSchema extends SQLTableAction { sqlFile = "getTableSchema.sql";}

item main extends BaseAction { actions = ["getTableSchema"]; templateName = "ex3.vm";}

and SQL script that retrieves a database table schema:

#### getTableSchema.sql##describe ${input.dbName}.${input.tblName}

Such a database query returns a table with multiple rows and columns that we would like to format using a standard HTML table tag. The followingVelocity template file performs such a formatting task:

#### ex3.vm##<body bgcolor="white"><center><h2>Table Schema For '${input.dbName}.${input.tblNa me}'</h2>

<table><tr bgcolor=#efefef>#foreach ($col in $getTableSchema.cols) <th>$col.getLabel()</th>#end</tr>

#foreach ($row in $getTableSchema.rows)<tr>#foreach ($col in $getTableSchema.cols) #if($row.getValue($col.getName())) <td>$row.getValue($col.getName())</td> #else <td>NULL</td> #end#end</tr>#end</table></center>

Page 36: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

36 of 150 5/11/2007 10:14 AM

Clearly, this template is more complicated than we've seen before, but is still constructed from only a couple of directives. Specifically, the #foreach()

directive is used to loop over all column labels to create the table column headers. Then, nested #foreach() directives are used to loop over each row and each column therein, to display each of the table cells. Finally, the #if() directive is used to determine when a NULL value exists in a table cell,replacing it by the string "NULL". (If Velocity generates a NULL value while performing a variable substitution, then it assumes that the variable isnot defined and does not replace it in the output stream. The #if() directive can be used to detect such a situation and generate an appropriate outputstring.)

HTML Table Macro

Since typical database applications generate a large number of tabular results, Skipjack Server includes a set of Velocity macros that can easilygenerate standard HTML table displays. Clearly, such macros can't solve all problems for all applications, but they can be used as starting point orrapid-prototype to get the ball rolling.

The #listShow() macro formats any Table object based on a set of formatting attributes defined in the transaction definition file. For example, considerthe following tblFormat item that could be added to the previous example (ex4.tdf):

item tblFormat { table = getTableSchema.table; rowColorMap = ["lightblue", "bisque"];}

which references the table retrieved by the getTableSchema action item and defines a color map for the rows that are displayed in the table. Bydefining that item in the transaction definition file, we can replace the previous template file by the following template file (ex4.vm):

#### ex4.vm##<body bgcolor="white"><center><h2>Table Schema For '${input.dbName}.${input.tblNa me}'</h2>

#listShow($tblFormat)

</center>

which uses the #listShow() macro to display the table. The #listShow() macro is defined in the following files:

$SKIPJACK_HOME/app/macros/list-macros-01.vm$SKIPJACK_HOME/app/macros/html-macros-01.vm

which is a self-documenting file. The documentation for all the macros defined in that file can be viewed using the following URL:

Page 37: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

37 of 150 5/11/2007 10:14 AM

http://$SKIPJACK_URL/MACROS/list-macros-01.vmhttp://$SKIPJACK_URL/MACROS/html-macros-01.vm

which also has the side-effect of reloading the macro definitions, if you need to make modifications to the macros without rebooting the server. Anumber of macros defined in those files are useful for generating common HTML displays, such as a shaded box surrounding other text, titles,section headers or error messages. There is also a macro for generating an HTML-based barchart for a table with numeric columns, using itemattributes defined in the transaction definition file, much like the #listShow() macro.

Database Record Retrieval

Since it is often necessary to retrieve a single row of data from the database, the SQLRecordAction is provided to extract one row of data and store eachcolumn/cell of that row in an item attribute named for that column. In that way, a transaction can easily reference individual values in subsequentactions.

For example, consider the following database table:

UserName Password-------- --------Fred asdasd8aSally 45&efXzwJim AAj8dygz

and the following transaction excerpt that uses the getUserRecord action to retrieve the data record associated with a given user:

item getUserRecord extends SQLRecordAction { sqlFile = "getUserRecord.sql"; UserName = "Fred"; _destItem = "userRecord";}

Since the _destItem

attribute is defined, the resulting values will be stored in the "userRecord" item. If no such item exists when the action is executed, it will be createdautomatically. After the getUserRecord action is executed, the following item attributes might hold the values retrieved from the database for user"Fred":

userRecord.UserName = "Fred"userRecord.Password = "asdasd8a"

Such information could then be used by another action, such as the following:

Page 38: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

38 of 150 5/11/2007 10:14 AM

item getUserAccount extends SQLRecordAction { sqlFile = "getUserAccount.sql"; UserName = userRecord.UserName; Password = userRecord.Password; _destItem = "userRecord";}

that might retrieve corresponding information from another table, using the UserName and Password values returned by the previous action as inputparameters for the getUserAccount.sql script. Note again how the _destItem attribute is used to store the results of the second SQL query in the same itemas before, resulting in the following attributes being defined:

userRecord.UserNameuserRecord.PassworduserRecord.SalaryuserRecord.BonususerRecord.ExpenseLimit

Clearly, the results of the SQLRecordAction, like any other item, can be used by an output template to format the detailed information for a given user.

Database Column Retrieval

It is often desirable to retrieve a column of data and iterate over it for subsequent processing or pass the entire column of data to the template file.For example, the database query may select a column of data based on a given input, which is then used to populate an HTML choice list as part ofan input form. In such cases, the SQLColAction can be used to retrieve a table of data and then to store one column as a Vector of data assigned to agiven item attribute.

For example, the following transaction excerpt:

item getUserList extends SQLColAction { sqlFile = "getUserList.sql"; _destItem = "userList";}

would retrieve all of the user names and store them as a list of values assigned to the userList.UserName attribute:

userList.UserName = ["Fred", "Sally", "Jim"];

which could then be referenced in a Velocity template as follows:

<select size=5>#foreach ($user in $userList.UserName)

Page 39: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

39 of 150 5/11/2007 10:14 AM

<option>$user#end</select>

to generate an HTML selection list.

Database Update/Insert

All of the examples so far have focused on retrieving data from the database, but the SQLTableAction can also be used to execute one or more SQLupdate, delete and insert statements in a SQL script. In such cases, the resulting rowCount will reflect the number of updates performed, not thenumber of rows in the table, which will be empty.

There are also situations when a record needs to be added to a database table or updated if it already exists. To easily support such operations, theSQLUpdateAction

action can be used to specify separate update and insert SQL scripts, defined as the "updateSql" and "insertSql" attributes (instead of the "sqlFile"attribute used for other SQL actions). The SQLUpdateAction first attempts to execute the "updateSql" script. If that succeeds and more than one row isupdated, then no further processing is done. If the "updateSql" fails to update any rows in the table, then the "insertSql" script is executed. In eithercase, if an exception is generated, the action is aborted.

For example, the following action:

item updatePassword extends SQLUpdateAction { updateSql = "password-update.sql"; insertSql = "password-insert.sql"; UserName = "Fred"; Password = "changethis";}

//// password-update.sql//update UserTableset Password = '$updatePassword.Password'where UserName = '$updatePassword.UserName'

//// password-insert.sql//insert UserTablevalues ( '$updatePassword.UserName', '$updatePassword.Password')

Page 40: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

40 of 150 5/11/2007 10:14 AM

attempts to update the password for 'Fred' using the password-update.sql. If no such record exists, the password-insert.sql script is executed to create theuser record and set the password.

Database Connection Re-Use

For each of the SQL actions described above, the Skipjack Server automatically creates (or re-uses) a connection to the database server when theaction begins and releases that connection when the action is done. Consequently, if a transaction executes a series of SQL actions, there is apossiblity that each action is performed using a different connection. Since some database servers base their locking and/or transactional serviceson a per-connection basis, it is possible that the use of multiple connections by a given Skipjack transaction may result in unusual behavior of thecorresponding database transaction.

To facilitate the processing of multiple actions using the same database connection, the SQLAction can be used to execute a list of actions. Forexample, the following excerpt would perform the same actions as in the previous example:

item getUser extends SQLAction { actions = ["getUserRecord", "getUserAccou nt"];}

item getUserRecord extends SQLRecordAction { sqlFile = "getUserRecord.sql"; UserName = "Fred"; _destItem = "userRecord";}

item getUserAccount extends SQLRecordAction { sqlFile = "getUserAccount.sql"; UserName = userRecord.UserName; Password = userRecord.Password; _destItem = "userRecord";}

When the getUser

action is executed, it will acquire a single database connection that is then shared by all of the actions executed by that action. When the getUser

action is done, the database connection will be released. In databases such as MySQL, this approach can be used to lock one or more tables, andthen to release the locks after all actions have been performed.

SQL Script Variables

In all of the SQL processing examples, we've shown how the SQL script file can reference arbitrary transaction item attributes in order todynamically generate SQL expressions. In general, it is beneficial to write such references in a way that allows the SQL script file to be used by thewidest range of transaction definition files, thereby isolating database commands as much as possible.

Page 41: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

41 of 150 5/11/2007 10:14 AM

To support such an approach, the $curAction Velocity variable can be used to reference the action item that caused this template to be processed. Forexample, consider the following SQL template file (getUser.sql):

select *from myUserswhere UserName = '$curAction.UserName'

and the following action item definitions:

item getFred extends SQLRecordAction { sqlFile = "getUser.sql"; UserName = "Fred"; _destItem = "userRecord";}

item getSally extends SQLRecordAction { sqlFile = "getUser.sql"; UserName = "Sally"; _destItem = "userRecord";}

Both action items reference the same SQL script file, while defining different UserName attributes. When the getFred action is executed, the $curAction

variable in the SQL script file will reference the getFred item and the value of $curAction.UserName will be "Fred". On the other hand, when the getSally

action is executed, the $curAction variable will reference the getSally item and the value of $curAction.UserName will be "Sally".

By using the $curAction variable in SQL script files as much as possible, and by defining all required SQL inputattributes in the same action item, the mapping between SQL action items and SQL script files is greatlysimplified and there is a greater chance that scripts (as well as SQL action items) can be re-used by othertransactions.

When generating SQL expressions, it is important to remember the string quote conventions used by SQL and to use the proper quote symbols foreach data value. To facilitate such processing, the #sqlString() macro can be used to properly quote a string value. For example, the previous examplescript file is best written as follows:

select *from myUserswhere UserName = #sqlString($curAction.UserName)

to ensure that the $curAction.UserName value is properly quoted.

The #sqlString() macro is designed to support the string quoting conventions used by MySQL and other ANSISQL database servers. Different servers may require different quote conventions.

Page 42: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

42 of 150 5/11/2007 10:14 AM

Column Labels

Since database column names are often cryptic and may appear in a wide-range of displays, the SQL actions are designed to automaticallydetermine column labels that are more appropriate for user displays. We've already seen an example of this when using the getLabel() method from the TableCol object as the column label in an HTML table.

By default, the column label is defined to be the same as the table column when a table is retrieved from the database. If, however, the guiLabel item exists and an attribute is defined in that item with the same name as a column label, then the corresponding value will be used as the column labelwhen the table is retrieved. For example, if the following items are defined:

item guiLabel { UserName = "User Name"; Street = "Street Address"; CityState = "City, State";}

item getData extends SQLTableAction { sqlFile = "getUserData.sql";}

then the labels defined in the guiLabel item will be assigned to each of the corresponding columns in the table returned by the getData action item.

In most cases, it is beneficial to define a single guiLabel item containing all of the labels used for a given application and then to include that item inall transactions. In fact, the skipjack-labels.tdf already defines the labels used by the internal Skipjack transactions and that file is automaticallyincluded whenever the skipjack-common.tdf file is included. Consequently, if you want to add or modify labels to the guiLabel you need only overwritethe default guiLabel item as follows:

include "skipjack-common.tdf"

item guiLabel overrides guiLabel { _readonly = true; UserName = "User Name"; Street = "Street Address"; CityState = "City, State";}

Note, the "overrides" directive is used instead of the common "extends" directive because both items have the same name and the overridesdirective tells the compiler that you really want to re-use the name. You can also use the "replaces" directive, which effectively erases all attributesdefined by the original guiLabel item, using only the attributes defined in this item definition.

You should also note the use of the "_readonly" attribute, which tells the server that the guiLabel item defined here will not be updated duringtransaction processing. This information allows the server to optimize the internal processing of items, decreasing the overall time needed toinitialize a transaction. See Performance Tuning for more details.

Page 43: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

43 of 150 5/11/2007 10:14 AM

SQL Exception Handling

Life would be peachy if database statements never failed, but that is not the case. In fact, a wide range of exceptions can be generated depending onthe specific database server being used. In order to gracefully handle such exceptions, all SQL actions support the optional definition of thesqlErrorMap attribute, as follows:

sqlErrorMap = [ (".*Duplicate entry.*", "301 Invalid Entry" , "Entry Already Exists"), (".*", "500 Database Error", "Internal Data base Failure") ];

The sqlErrorMap

defines a list of tuples, where each entry specifies how a matching set of exceptions should be handled. When a database exception is generated, theresulting error message is compared against the GNU regular expressions defined as the first element of each tuple. If the message matches one ofthe expressions (processed from top to bottom) then the second element in that tuple is assigned to the tx.status attribute and the third element in the tuple is assigned to the tx.errorMsg attribute. At that point, the action is aborted, which causes the transaction to be aborted and the tx.status and tx.errorMsg are sent back to the user or client application as part of the failed transaction's response.

In general, it is not necessary to specify the sqlErrorMap for most SQL actions, since the database error message is probably sufficient to explain thesource of the problem. However, in some cases, it is desirable to hide the details from the user, supplying a more application-specific error message.(See Error Response for more details.)

Page 44: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

44 of 150 5/11/2007 10:14 AM

Skipjack Server

Application Development Guide

Section 5: Transaction Response

5 October 2002

Skipjack Server is an HTTP-based server that generates an output file for every transaction that is processed, which is a fundamental characteristicof any HTTP server. The actual output type is specified by the MIME Content-Type header which is transmitted before the file itself. Typically,the text/html

MIME type is used, since most applications are designed for browser-based client access. However, any MIME type can be used depending on thetype of transaction and/or client software. In fact, Skipjack Server supports the ability to generate multiple output files for the same transaction,allowing different types of clients to use the same transaction.

NOTE: All of the examples discussed in this section can be found in the following locations:

Web URL http://$SKIPJACK_URL/tutorial/txResponse/

File Path $SKIPJACK_HOME/app/WEB-INF/transaction/tutorial/txResponse/

where $SKIPJACK_URL is the URL for the Skipjack Server ('localhost:8080' for default installations) and $SKIPJACK_HOME is the root location of the Skipjack Server runtime directory ('/tools/skipjack' for default installations).

Default Transaction Response

Consider the following transaction from the previous section (ex1.tdf):

//// ex1.tdf//include "skipjack-common.tdf"

item getDBList extends SQLTableAction { sqlFile = "getDBList.sql";}

item main extends BaseAction { actions = ["getDBList"]; templateName = "ex1.vm";}

Page 45: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

45 of 150 5/11/2007 10:14 AM

that retrieves the list of databases from the database server, referencing the following response template file (ex1.vm):

#### ex1.vm##<body bgcolor="white"><h2>Database List</h2><pre>#foreach ($row in $getDBList.rows)$row.getValue(0)#end</pre>

In this case, the response template is written as an HTML file, which displays the list of databases using standard HTML tags. For mosttransactions, this is all that is needed and the template filename can simply by specified using the main.templateName attribute.

Common Response Templates

Many transactions are used simply to update the database or cause some action to be performed, requiring little or no output. In those cases, thefollowing common response templates may be useful:

COMMON/tx-status.vmDisplays only the transaction status as a plain text string.

COMMON/tx-summary.vmDisplays a single plain text line that contains the transaction completion time, transaction ID, remote user ID, client ID and the transactionresponse time.

COMMON/tx-output.vmExtends the COMMON/tx-summary.vm template to include all of the output item attributes generated by the transaction.

COMMON/tx-success.vmGenerates an HTML display based on main.successMsg and main.successTitle attributes that indicates the outcome of the transaction. The resultingdisplay also includes an "OK" button that executes a subsequent transaction or accesses an arbitrary URL when the user presses the button.See Common Success Response for more details concerning the use of the COMMON/tx-success.vm response template.

Such templates can be used for debug purposes, when developing transactions before a GUI is developed, or as part of a production system.

Common Success Response

Page 46: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

46 of 150 5/11/2007 10:14 AM

The COMMON/tx-success.vm

template allows a transaction author to easily generate output for transactions that only need to display a simple message and then branch to anotherURL when the user acknowledges the message.

Success Message and Title

The message is specified using the main.successMsg and main.successTitle attributes. If either of those attributes is not defined, a default value of"Transaction Successful" will be used.

Success URL

If the main.successURL or input.successURL attributes are defined, then it will be used as the URL invoked by the "OK" button that is displayed beneaththe message. That is, when a browser user presses that button to acknowledge the message, the browser will go to that URL as the next step in theuser interaction. To facilitate sending input parameters to the successURL, all of the input attributes defined when the transaction response is generatedare defined as hidden HTML form parameters, which will cause them to be submitted when the successURL is invoked by the "OK" button. If nomain.successURL attribute is defined, the "OK" button will function just like the "Back" button provided by the browser.

For example, if we modify the previous transaction as follows (ex2.tdf):

//// ex2.tdf//include "skipjack-common.tdf"

item getDBList extends SQLTableAction { sqlFile = "../dbQuery/getDBList.sql";}

item main extends BaseAction { actions = ["getDBList"];

successTitle = "Database List Retrieval"; successMsg = "Found "+getDBList.rowCount+ " Databases";

templateName = "/COMMON/tx-success.vm";}

then it will display the following HTML output when executed from within a browser:

Page 47: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

47 of 150 5/11/2007 10:14 AM

If we define the main.successURL attribute as follows (ex3.tdf):

item main extends BaseAction { actions = ["getDBList"];

successTitle = "Database List Retrieval"; successMsg = "Found "+getDBList.rowCount+ " Databases"; successURL = "/test/showInput.tdf";

templateName = "/COMMON/tx-success.vm";}

then the /test/showInput.tdf transaction will be executed when the "OK" button is pressed, displaying any input parameters from the ex3.tdf transaction passed as hidden parameters to the showInput.tdf transaction. For example, if you enter the following URL in a browser:

http://$SKIPJACK_URL/tutorial/txResponse/ex3.tdf?na me=Fred&salary=123

then the "name" and "salary" input attributes will be displayed (along with some internal attributes) when the "OK" button is pressed.

The tx-success.vm template uses the input.successURL attribute value if the main.successURL is not defined. Therefore,it is possible for a high-level transaction to specify the URL (as a hidden form field, for example) that should beused by a lower-level transaction. In this way, the low-level transaction can be called from different high-leveltransactions and can automatically branch to different destinations when the user acknowledges the message.

Success Redirect

If the main.successRedirect or input.successRedirect attributes are defined as "true", then the HTML output generated by the tx-success.vm template will automatically cause the client browser to be redirected to the success URL. In such cases, the success message and button will not be displayed, butall hidden input fields will be sent to the success URL as if the user had pressed the button themselves. Such a mechanism is usually used whenexecuting a low-level transaction to perform a server-side function, such as deleting a record in the database, and then re-executing the high-leveltransaction, such as a list of all records in the database, without requiring the user to acknowledge the successful outcome.

For example, if the following URL is entered:

Page 48: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

48 of 150 5/11/2007 10:14 AM

http://$SKIPJACK_URL/tutorial/txResponse/ex3.tdf?na me=Fred&salary=123&successRedirect=true

then after the ex3.tdf transaction is executed, the browser will immediately proceed to the ex2.tdf transaction which will display all the inputparameters that were copied from the original transaction URL.

Response Map

The main.templateName

attribute is actually the default value used by the transaction's "response map" which is used to determine the specific template to be used based onthe desired MIME type. The response map is defined by the main.responseMap attribute, which uses the following default setting for all transactions:

responseMap = ("transaction/map", TransMapResponse), (".*", templateName);

templateName = "/COMMON/tx-status.vm";

The main.responseMap is processed from top to bottom, using the first entry in each tuple as a GNU regular expression that is compared to theresponse.contentType

attribute. If a match is found, the second entry in the tuple indicates either the name of a Velocity file to be processed or the name of an action to beperformed. The response.contentType can be defined statically in the TDF file by the transaction author or can be defined dynamically using attributeexpressions or actions. Furthermore, if the input.contentType is defined when the transaction is executed, it will be used to overwrite theresponse.contentType

attribute. This allows users and client applications to specify the desired output content type. If no value is specified, a default value of "text/html"is used.

As can be seen in the default definition above, if the transaction/map MIME type is set, then the TransMapResponse action will be executed, which generates a data output stream that encodes the attribute values for the input, output and tx items. (See Client Application Support for more detailsabout processing transaction output using the transaction/map MIME type.) Otherwise, the wildcard expression .* will match and the template filename (or action name) specified by the templateName attribute will be processed. This provides a convenient mechanism for transaction authors tospecify the most common response mapping (a single template), while allowing them to override the responseMap itself for more involved situations.

For example, if we modify the previous example as follows (ex4.tdf):

item main extends BaseAction { actions = ["getDBList"];

successTitle = "Database List Retrieval"; successMsg = "Found "+getDBList.rowCount+ " Databases"; successURL = "/test/showInput.tdf";

Page 49: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

49 of 150 5/11/2007 10:14 AM

responseMap = ("transaction/map", "TransMapRespon se"), ("text/plain", "/COMMON/tx-sta tus.vm"), (".*", "/COMMON/tx-suc cess.vm");}

then the same HTML success message will be generated by default using the /COMMON/tx-success.vm template. However, if the following URL isexecuted:

http://$SKIPJACK_URL/tutorial/txResponse/ex4.tdf?co ntentType=text/plain

then plain text output will be generated using the /COMMON/tx-status.vm template file.

Error Response

When an exception is generated by a transaction, all action processing is immediately aborted and a transaction response is generated based on thevalue of the response.contentType attribute. Such processing is controlled by the main.errorMap attribute, which is defined as follows by default:

errorMap = (".*ResourceNotFoundException", guiStatus.ResourceNotFound, "/COMMON/NotFoundException.vm"), (".*SQLException", guiStatus.DatabaseException, "/COMMON/SqlException.vm"), (".*UserException", guiStatus.UserException, "/COMMON/UserException.vm"), (".*SecurityException", guiStatus.SecurityException, "/COMMON/SecurityException.vm"), (".*", errorStatus, "/COMMON/UnknownException.vm");

errorStatus = guiStatus.UnknownException + " - " + tx.errorClass;

Much like the main.responseMap attribute, the main.errorMap is processed from top to bottom, looking for a match using the first entry in each tuple as aGNU regular expression. However, unlike the responseMap the regular expression is compared with the Exception Class as designated by thetx.errorClass

attribute, which is automatically defined when the exception is generated. When a match is found, the second entry in the tuple is assigned to thetx.status attribute and the third entry is used to generate the transaction response, which may consist of an action name or Velocity template file.

The main.errorMap attribute is defined for all actions in the COMMON/skipjack-common.tdf file, referencing a set of default HTML template files for various

Page 50: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

50 of 150 5/11/2007 10:14 AM

common exceptions. Transaction authors can override that definition to specify custom error handling information. Typically, even when customerror maps are defined, it is prudent to assign a standard Skipjack or application status value. The standard Skipjack status values are defined by theguiStatus which is specified in the COMMON/skipjack-status.tdf file. Transaction authors are free to override or extend the guiStatus item as needed.

Response Actions

A transaction response can be generated using either a Velocity template file, a generic response action or a custom response action. In all cases,response processing occurs after all other actions referenced by the main action item are processed.

The following response actions are provided by the Skipjack Server:

FileResponseRetrieves a given file from the server's file system and uses it as the transaction response. See Shell Script Processing for more details and anexample of how it can be used.

ShellResponseExecutes an operating system/application shell script/executable and uses the output of that script as the response for the current transaction.See Shell Script Processing for more details.

TxResponseExecutes a sub-transaction on any Skipjack Server, local or remote, and uses the response from that transaction as the response of the currenttransaction. See TxResponse Class for more details.

TransMapResponseGenerates a data stream by encoding all of the attribute values defined by one or more transaction items using an encoding scheme defined bythe navius.toolkit.format.TransactionMap Java class. See TransMapResponse Class for more details.

TransPropResponseGenerates a data stream by encoding all of the attribute values defined by one or more transaction items as a Java properties file. SeeTransPropResponse Class for more details.

In all cases, the response action is responsible for setting an appropriate value for the Content-Type HTTP header that is sent back to the clientapplication. In some cases, such as the TransMapResponse response action, the content type is statically defined, while in other cases, such as theFileResponse and ShellResponse response actions, the transaction author can specify the proper type using the mimeType attribute.

Page 51: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

51 of 150 5/11/2007 10:14 AM

Skipjack Server

Application Development Guide

Section 6: Shell Script Processing

5 October 2002

Truly powerful server applications can be built simply by combining the vast number of tools, scripts and applications that already exist withinmodern operating systems and public-domain warehouses. Since the Skipjack Server itself depends on various packages provided by the operatingsystem, a number of actions are provided to allow transaction authors to easily tap such resources as well. In particular, the following actions can beused to access resources outside of the server:

ShellResponseShellActionFileResponse

These actions can be used separately or combined with other actions as needed.

ShellResponse Action

In many cases, the output generated by a shell script can be directly used as the output of the transaction and the shell script input can be fullyspecified using command line options. In such cases, the ShellResponse response action can be used to execute the script and use the output directlyas the transaction response. For example, the following transaction (test/sysConfig.tdf):

item genResponse extends ShellResponse { shellCmd = skipjack.BINDIR + "SystemCon fig.pl"; mimeType = "text/plain";}

item main extends NOP { templateName = "genResponse";}

executes the standard SystemConfig.pl script that is provided by the Skipjack Server, using the resulting output as a plain text transaction response. Inthis case, the templateName attribute references an action, not a Velocity template filename, as is typical. The transaction engine automatically detectsthis situation and it uses the specified action to generate the transaction response, instead of using the Velocity template engine.

Page 52: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

52 of 150 5/11/2007 10:14 AM

In this example, the main action extends the NOP action because it doesn't need to perform any actions other thanthe genResponse action, which is automatically executed after the main action is done (doing nothing).

The ShellResponse

response action provides a simple and effective mechanism for integrating the Skipjack Server with existing scripts or executables that generate anoutput stream that does not require additional processing.

ShellAction

The ShellAction

allows a transaction author to execute a given shell command and then continue transaction processing. If an optional input file is defined, then thatfile will be processed using Velocity and sent to the standard input stream of the shell command when it is executed. This allows a transaction todynamically construct shell input scripts or control files. Any output required from the shell command can be saved directly to a file by the shellscript, saved to a file by the transaction, appended to a server log file or processed directly by the transaction itself.

For example, the following transaction definition provides a way to restart the Skipjack Server:

//// restart.tdf//include "skipjack-common.tdf"

item main extends ShellAction { shellCmd = "/tools/skipjack/bin/skipjack.sh restart";}

In this case, the shell command is fully specified and there is no need to define the inputFile attribute because the shell script doesn't accept any input.

Note that no templateName attribute is defined in the main item. In this case, the default template file /COMMON/tx-status.vm is used, which simply displaysthe transaction status when it has completed. (In this specific case, however, the transaction will never finish because the server will be restarted bythe shell script.)

Server Environment Variables

Generally it is not a good idea to hard-code paths in transaction definitions if possible, because that may cause problems if the server runtimedirectory is moved in its entirety to another location. To help eliminate such problems, the server automatically defines a set of transaction itemattributes with the current value for various environmental variables. In particular, the skipjack.BINDIR attribute is defined to be $SKIPJACK_HOME/bin.Such environmental attributes can be used to remove hardcoded paths related to the Skipjack Server, as in the following modification of theprevious transaction:

Page 53: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

53 of 150 5/11/2007 10:14 AM

//// restart.tdf//include "skipjack-common.tdf"

item main extends ShellAction { shellCmd = skipjack.BINDIR + "skipjack.sh r estart";}

Note, the paths stored in the skipjack attributes already include a trailing path delimiter.

The test/showRequest.tdf transaction can be executed to display a list of all skipjack attributes defined by the server, as well as all request attributes that are defined as the result of the transaction request being processed.

Shell Input File Processing

As with the database processing actions, the Velocity template engine is used to process any shell input file that is specified. This means that thetransaction author can prepare the input data needed by the shell command in the transaction itself (using attribute expressions or other actions) andthen use Velocity to dynamically construct the actual shell input commands or configuration data.

For example, suppose that we want to generate a chart using the standard gnuplot utility available for most operating systems. The following actionitem definition might be used to control such a process:

item genChart extends ShellAction { shellCmd = "/usr/bin/gnuplot -"; inputFile = "chart.vm"; chartFile = "/tmp/gnuplot." + processID;}

The "-" command line argument to the gnuplot utility instructs it to accept a stream of plotting commands from its standard input stream. Since theinputFile attribute is defined, the "chart.vm" file:

set output '$curAction.chartFile'set terminal png small colorset xrange [0:10]set yrange [0:10]set xlabel "X Axis"set ylabel "Y Axis"set title "Test Chart"set size 1.0,0.8plot '-' title "" with lines0 01 12 23 34 4

Page 54: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

54 of 150 5/11/2007 10:14 AM

5 56 47 38 29 110 0

will be processed by Velocity and the resulting output will be sent to the gnuplot command. Although the input file may look a little cryptic, anyonefamiliar with gnuplot could easily write such a script.

Note how the $curAction.chartFile attribute is referenced in the input file to specify the output file to be generated by gnuplot. Furthermore, by examiningthe item definition above, we see that the chartFile attribute is constructed from a temporary path prefix and the processID attribute, which isautomatically defined to be a unique value whenever a ShellAction is performed. In this way, we can ensure that concurrent executions of the genChart

action don't interfere with each other.

Shell Output File Processing

In some cases, a shell script executed using the ShellAction action will generate an output file that is needed as the response of the current transaction,perhaps after some other processing has been performed. To facilitate such processing, the FileResponse response action can be used in conjunctionwith the ShellAction action to achieve the same results as the ShellResponse response action. For example, a complete chart rendering transaction mightbe defined as follows:

//// test/chart.tdf//include "skipjack-common.tdf"

item genChart extends ShellAction { shellCmd = "/usr/bin/gnuplot -"; inputFile = "chart.vm"; chartFile = "/tmp/gnuplot." + processID;}

item genResponse extends FileResponse { outputFile = genChart.chartFile; mimeType = "image/png"; deleteFile = true;}

item main extends BaseAction { actions = ["genChart"]; templateName = "genResponse";}

The genResponse action extends the FileResponse action, specifying the file to be used as the transaction response as the outputFile attribute. Note thereference to genChart.chartFile which ensures that the genResponse action references the same output file generated by the genChart action. The mimeType

Page 55: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

55 of 150 5/11/2007 10:14 AM

attribute is also used to define the MIME type sent to the user or client application as part of the HTTP response. Finally, the deleteFile attribute is used to remove the output file when the action is done.

Since the purpose of the FileResponse action is to generate the transaction response, we need to reference it from the main.templateName attribute (or override the main.responseMap attribute). See Transaction Response for details about generating a custom transaction response.

Shell Working Directory

Some shell scripts require that they be executed in a specific working directory, which may need to be dynamically determined at run time. Tofacilitate such processing, the shellDir attribute can be used to specify the working directory in which the shell script will be executed. The shellDir

value should be specified as an absolute path in the server's file system. If the shellDir attribute is not defined, then the directory containing thetransaction definition file of the current transaction will be used as the shell working directory.

If the shellCmd specifies a relative pathname for the shell script to be executed, it will be interpreted relative tothe current working directory, as specified by the shellDir attribute.

Shell Working Environment

In order to maintain the highest levels of installation portability, when a shell script is executed the ShellAction automatically defines a collection ofoperating system environment variables that can be used by the shell script as needed. Specifically, the following primary environment variables aredefined:

PATH a collection of common system executable directories, including the Java bin directory used by the Skipjack Server

JAVA_HOME the current value of the 'java.home' System property for the Skipjack Server

CLASSPATH the current value of the 'java.class.path' System property for the Skipjack Server

PERL5LIB the Skipjack Server directory containing Transaction.pm, allowing Perl scripts to easily refer to that module

With those variables defined, the shell script will have access to the same executables and Java resources used by the Skipjack Server.

Page 56: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

56 of 150 5/11/2007 10:14 AM

In addition to the environment variables listed above, all of the transaction attributes defined for the "input", "request", "tx", and "skipjack" itemswill be defined as environment variables, using the format "item_attr" for the variable names. For example, the "skipjack.ROOTDIR" transactionattribute can be accessed by the shell script as the "skipjack_ROOTDIR" environment variable and the "input.X" transaction attribute as the"input_X" environment variable.

Because of operating system environment variable name restrictions, all '-' (dash) characters in the originaltransaction attribute name will be replaced by '_' (underscore) characters. For example, the"request.Accept-Encoding" transaction attribute will be defined as the "request_Accept_Encoding"environment variable.

Shell Exit Status

By convention, shell scripts return an integer exit status that can be used to determine if it succeeded or failed. Usually, a zero value is returned ifsuccessful and all other exit codes are considered as failures. In order to support the widest range of exit status processing, the ShellAction makes use of the following attributes:

_shellStatus

exceptionOnError

exceptionStatus

exceptionMsg

Shell Status Attribute

After a shell script has terminated, the ShellAction stores the resulting numeric exit status in the _shellStatus attribute of the destination item named bythe _destItem attribute. If the _destItem is not defined, then the ShellAction item itself will be used as the destination item.

The destination item is supported by almost all Skipjack Server actions, allowing the transaction author tostore the results for that action in another item. This helps to maintain a clear design distinction between an'action item' and a 'data item', which usually makes transaction definition items easier to debug.

Automatic Error Handling

The exceptionOnError, exceptionStatus and exceptionMsg attributes can be used to easily control the generation of an exception for an unsuccessful exitstatus (ie. non-zero). Specifically, if the exceptionOnError attribute is "true" (the default value) then an exception will be raised whenver the exit statusis non-zero. The exceptionStatus and exceptionMsg attributes can be used to specify the status and message associated with the exception, with default

Page 57: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

57 of 150 5/11/2007 10:14 AM

values of "705 Shell Action Failed" and "Shell Exit Value = xxx", respectively. For example, the following action specifies a custom error message,depending on the _shellStatus value:

item doScript extends ShellAction { shellDir = "/my/working/directory"; shellCmd = "myScript -x 12 -y 23"; exceptionOnError = true;

exceptionMsg = _shellStatus > 0 ? "Bad Shell Status = "+_s hellStatus : "Really Bad Shell Status = "+_shellStatus;}

The exceptionOnError attribute supported by the ShellAction should not be confused with the _ignoreError attribute that is supported for all actions. The _ignoreError attribute causes the action processing engine to ignore any exceptionraised by a given action, thereby allowing the transaction to continue. The exceptionOnError attribute determines ifan exception should be raised because of a non-zero shell exit status, it does not prevent other types of exceptions from being thrown.

Custom Exit Status Processing

If the exceptionOnError

attribute is "false", then no exception will be raised automatically based on the shell exit status. This allows subsequent actions in the transaction touse the _shellStatus as needed to determine how to proceed after a possible shell script failure. The _shellStatus attribute can also be referenced by oneor more error checks defined as the postErrorCheck attribute of the shell action item, as in the following example:

item doScript extends ShellAction { shellDir = "/my/working/directory"; shellCmd = "myScript -x 12 -y 23"; exceptionOnError = false;

postErrorCheck = [ (_shellStatus < 0, guiStatus.ShellActionFailed, "Bad Status From 'myScript' = "+ _shellStatus) ];}

In this case, an exception is raised only if the status is less than zero. Clearly, more complex evaluation criteria can be used and more advancedfailure recovery is possible, based solely on the exit status.

Page 58: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

58 of 150 5/11/2007 10:14 AM

Shell Output Processing

In the previous gnuplot

example, the output of the shell script was written to a file and then the file was used as the transaction response. Such an approach is typical forshell scripts that generate output files as a normal part of their processing task. Other scripts, however, may generate output only for debug purposesor to describe an error condition. In such cases, it may be necessary to capture the output of such scripts and store it in an appropriate place or evenprocess the output of the script as part of the current transaction. For example, the script may generate a sequence of database record identifiers thatshould be deleted for a particular reason.

To support such a wide range of possible alternatives, the ShellAction allows the following attributes to be defined to control how shell script outputis processed:

Attribute Description

outputDest Specifies how the STDOUT output for the process should be processed, with the following values supported:

NONE - all output lines are ignored (default)LOG - each output line is appended to the log file designated by the outputFile attributeFILE - each output line is saved in the file designated by the outputFile attributeACTION - all actions listed in the outputAction attribute will be called just before the shell script is

executed, after completion of the shell script, and once for each output line

outputFile If outputDest is 'LOG', the name of the Skipjack Server log file to be appended by each output line If outputDest is 'FILE', the name of the file to which all output lines are written

outputSeverity If outputDest is 'LOG', this specifies the severity of the log record that is generated (default = DEBUG)

outputPrefix If outputDest is 'LOG', this specifies the prefix for each log record that is generated (default = action name)

outputAction If outputDest is 'ACTION', this specifies the name of an action (or a vector of action names) which should be executedjust before the shell command, just after completion of the shell command, and once for each output line. Thefollowing attributes are defined in the destination item before each action is executed:

_curStep - one of (PRE, POST, LINE) where 'PRE' indicates that the shell command is about to berun; 'POST' indicates that the shell command has just completed; 'LINE' indicates that anoutput line was generated

_curLine - the current output line_shellStatus - the shell exit status (only valid when _curStep = POST)

errorDest Same functionality as outputDest for STDERR output lines

Page 59: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

59 of 150 5/11/2007 10:14 AM

errorFile Same functionality as outputFile for STDERR output lines

errorSeverity Same functionality as outputSeverity for STDERR output lines (default = ERROR)

errorPrefix Same functionality as outputPrefix for STDERR output lines

errorAction Same functionality as outputAction for STDERR output lines

Basic Error Logging

Typically, shell scripts generate output lines on STDERR only when something is wrong. Therefore, it is usually advantageous to append suchoutput directly to one of the Skipjack Server logs for trouble-shooting purposes, as in the following example:

item doScript extends ShellAction { shellDir = "/my/working/directory"; shellCmd = "myScript -x 12 -y 23";

errorDest = "LOG";}

Simply by specifying the errorDest attribute as "LOG", all lines printed to the shell script's STDERR output stream will be appended to the SkipjackServer error log (the default errorFile value). By default, the log entries will be assigned an errorSeverity of 'ERROR' and an errorPrefix of 'myTrans.doScript', where 'myTrans' is the name of the current transaction.

Generating Output Files

In some circumstances, it is more advantageous to print the output lines from either STDERR or STDOUT (or both) to a file for subsequentprocessing or trouble-shooting. In such cases, the 'FILE' type can be specified for the errorDest or outputDest attributes, as in the following example:

item doScript extends ShellAction { shellDir = "/my/working/directory"; shellCmd = "myScript -x 12 -y 23";

errorDest = "LOG";

outputDest = "FILE"; outputFile = "/tmp/myScript.out";}

In this case, the STDERR output lines are appended to the Skipjack Server error log, while the STDOUT output lines are written to the"/tmp/myScript.out" file.

Page 60: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

60 of 150 5/11/2007 10:14 AM

Keep in mind that multiple transactions can be executing concurrently, which usually requires dynamicallygenerated unique filenames to keep different transactions from using the same file. Review the chart exampleabove to see how the processID can be used in such cases.

Processing Output Lines

It is often desirable to process each line generated by a shell script, either on STDERR or STDOUT, within the same transaction. For example, itmay be necessary to generate an alarm for the operator, send an email to a supervisor or otherwise handle one or more failures indicated by the shellscript. Alternatively, the shell script may be used to prepared imported data that then needs to be inserted into the database.

To support arbitrary line-by-line processing of shell script output, the 'ACTION' type can be specified for the outputDest or errorDest attributes, along with one or more actions in the outputAction and errorAction attributes, respectively. For example, the consider the following action definitions:

item doScript extends ShellAction { shellDir = "/my/working/directory"; shellCmd = "myScript -x 12 -y 23";

errorDest = "ACTION"; errorAction = ["genAlarm"]; outputDest = "ACTION"; outputAction = ["deleteRecord"];}

item genAlarm extends TxAction { preCondition = doScript._curStep == "LINE";

_transName = "alarmMgr/insert.tdf"; Severity = "ALARM"; Message = doScript._curLine;}

item deleteRecord extends SQLTableAction { preCondition = doScript._curStep == "LINE";

sqlFile = "deleteMyRecord.sql"; ID = doScript._curLine;}

In this example, an operator alarm is created for every STDERR output line by the genAlarm action. The genAlarm action uses the preCondition attributeto indicate that it should only be executed when the doScript._curStep attribute is "LINE", not for the "PRE" or "POST" action processing steps. It thenuses the output line generated by the shell script as the alarm message.

The deleteRecord

action is used to process each line generated on STDOUT by the shell script. In this example, each line consists of a single database recordidentifier, which is simply passed to the "deleteMyRecord.sql" database script. Here again, the deleteRecord action specifies a preCondition attribute so

Page 61: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

61 of 150 5/11/2007 10:14 AM

that it is not executed for the "PRE" and "POST" steps.

Clearly, by defining additional processing actions most output processing tasks can be performed in this way. If not, the output information canalways be added to a table by the processing actions, for subsequent processing by other transaction actions executed after ShellAction processing is complete.

Background Shell Script Execution

Depending on the amount or type of processing performed by the shell script, it may be necessary to launch the script as a background task,allowing the current transaction to continue processing or respond to the client before the shell script is done. Background processing is easilyspecified using the background boolean attribute of the ShellAction. If the background attribute is "true", then the ShellAction will immediately return afterlaunching the shell script as a background task.

All of the output processing options described above are supported for both foreground and background shell script execution. That is all logging,file generation and output processing actions can still be defined even for background shell executions. In fact, error logging and processing is evenmore important for background shell scripts, since they may complete well after the humans have gone home. Since background shell scripts arenot associated with any current HTTP request, the exceptionOnError attribute is ignored when background is "true". If the 'LOG' destination type isspecified for either the outputDest or errorDest, then the shell exit status will be automatically recorded in the log.

Shell Script Process Management

Since shell scripts are executed as an operating system process outside of the transaction engine, it may be necessary to abort them if they are notworking properly. The Skipjack Server's internal Process Manager is designed to support the analysis and management of all processing taskswithin the server, including shell script processes (see the Process Manager section for more details).

When any ShellAction

action is executed at least one "process" is registered with the Process Manager, associated with the current transaction and action. The processremains registered with the Process Manager until the shell script has terminated. At that point, the process is unregistered and the ShellAction returnscontrol to the transaction for subsequent processing.

Depending on the processing being performed by a given ShellAction, one or more "processes" may be registered with the Process Manager for thesame ShellAction; one each for the STDOUT and STDERR output handler threads, if defined, and another for the thread that checks the shell scriptexit status, which is always created. A complete list of the unique process identifiers assigned to the ShellAction is stored as the _pidList attribute of thedestination item for that action.

In the event that a shell script "hangs" or otherwise should no longer be executed, the Process Manager can be used to abort the shell script, using

Page 62: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

62 of 150 5/11/2007 10:14 AM

the associated process registration. In such cases, the shell exit status will be set to "666" to signify that the shell script was aborted by the ProcessManager.

All ShellAction actions, regardless of the background attribute setting, have at least one process registered with theProcess Manager. This means that even a "foreground" shell script execution can be aborted using the ProcessManager. In that case, an exception will be generated by the ShellAction and the transaction can react accordingly.

Page 63: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

63 of 150 5/11/2007 10:14 AM

Skipjack Server

Application Development Guide

Section 7: Debug Management

5 October 2002

Skipjack provides a number of mechanisms that allow both developers and operators to manage the generation of transaction debug information inthe logs. This section describes the general type of debug information available when a transaction is executed and the mechanisms for controllingthe generation of that information.

Transaction Debug Information

The following debug information is available for every Skipjack transaction:

HTTP Request InformationHTTP Response InformationInput ParametersOutput ParametersSession AttributesAction ProcessingVelocity Processing

The information for all of the items listed above can be found in the $SKIPJACK_HOME/logs/trans.log file, except for the Action Processing information,which can be found in the $SKIPJACK_HOME/logs/action.log file, and Velocity Processing information, which can be found in the$SKIPJACK_HOME/logs/velocity.log file.

Debug information can be enabled by defining certain item attributes in the transaction definition file (or included definition file) or by addingentries to the server-wide DebugControl memory table. Generally, the first approach is used by developers focused on a specific transaction or action,while the second is used by operators focused on monitoring the behavior of a user, transaction or action.

By default, all debug information is disabled.

Page 64: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

64 of 150 5/11/2007 10:14 AM

Transaction Definition File Attributes

The following item attributes within a transaction definition file control the generation of debug information:

debug.requestDebugIf true, HTTP Request information is generated.

debug.responseDebugIf true, HTTP Response information is generated.

debug.inputDebugIf true, all transaction input parameters are printed to the log file.

debug.outputDebugIf true, all transaction output parameters are printed to the log file.

debug.sessionDebugIf true, all transaction session parameters, both incoming and outgoing, are printed to the log file.

debug.velocityDebugIf true, Velocity processing information is generated in the velocity.log file for all templates processed by the current transaction.

*.actionDebugIf true, action processing information is generated in the action.log file for the current action.

The attributes listed above control the generation of specific information about a transaction or action. Additionally, the following item attributesmay be defined to generate debug based on the current user, transaction name or action name(s):

debug.usersIf the current user name is contained in this list of names, then debug information will be generated for each action processed inthe current transaction.

debug.transactionsIf the current transaction identifier is contained in this list, then debug information will be generated for each action processed inthe current transaction.

debug.actionsIf the current action name is contained in this list, then debug information will be generated for the current action.

Page 65: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

65 of 150 5/11/2007 10:14 AM

Generally, these attributes serve as convenient ways to specify a collection of actions, transactions or users to be monitor for a group oftransactions, in which case the 'debug' item may be defined in a common file and included into all transactions in the group.

Velocity Debug Settings

If the debug.velocityDebug

attribute is "true", then Velocity processing errors will be generated for all templates processed by the current transaction. If one or more processingerrors occur, an exception will be thrown (thereby terminating the transaction) and an HTML error display will be generated. The types ofprocessing errors to monitored are specified by the following additional attributes:

debug.velocityNullMethodDebugIf true, generate debug information for calls to methods that don't exist or return a null value. Default is "true".

debug.velocityNullVariableDebugIf true, generate debug information for non-silent references to null-valued variables. Default is "true".

debug.velocityNullSilentVariableDebugIf true, generate debug information for silent references to null-valued variables. Default is "true".

debug.velocityLogErrorsIf true, print the debug information to the velocity.log file. Default is "true".

debug.velocityAccumulateErrorsIf true, then all of the errors generated while processing a template are accumulated before an exception is thrown. Default is"true".

debug.velocityErrorTemplateThe name of the Velocity template to be used to display any exception that is generated while monitoring template processing.Default is "/COMMON/velocity-error.vm".

Server-Wide DebugControl Settings

Independent of attributes that can be set within a transaction definition file, operators can specify a collection of users, transactions or actions to bemonitored by the server. This information is maintained in the DebugControl memory Table, which is automatically loaded from theskipjack.DebugControl database table.

The debugMgr/showList.tdf

Page 66: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

66 of 150 5/11/2007 10:14 AM

transaction can be used to display the current lists of users, transactions and actions being monitored, and to add or remove entries from each list.Whenever the lists are updated in this way, the server will automatically start monitoring transactions accordingly.

During the execution of a given transaction, if the current username is contained in the user list or the current transaction identifier is contained inthe transaction list, then all debug information associated with the transaction will be generated in the trans.log and action.log files. If no user ortransaction match is found, then the settings within the transaction definition file will be used to control debug generation.

During the execution of a given action within a given transaction, if the current action name is contained in the action list, then the action debuginformation will be generated in the action.log file.

The action name entered in the DebugControl action list should always be prefixed by the name of thetransaction. For example, if you wanted to monitor the 'genChart' action defined by the 'test/chart' transaction,then you should add an entry for 'test/chart.genChart' to the action list.

LogAction

The LogAction

can be used by a transaction to append a log message to any of the log files supported by the Skipjack Server. The log message itself is generated byconcatenating the values assigned to the following action item attributes:

GroupIDElementIDEventTraceIDErrorCodeMessage

which are processed as strings. The exact meaning and usage of each field is application-specific and if a given field is not defined, it will beignored.

If the LogFile

attribute is defined, then it will be interpreted as the Log4j Category name for the log file to be appended. The default value is"navius.skipjack.errorlog", which is the Category associated with the $SKIPJACK_HOME/logs/error.log log file. See the$SKIPJACK_HOME/app/WEB-INF/conf/log.cfg configuration file for a list of all Category names supported by the server.

If the Severity attribute is defined using one of the following values:

ERROR

Page 67: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

67 of 150 5/11/2007 10:14 AM

WARNINGINFODEBUG

then it will be used as the severity level of the resulting message when it is written to the log file. If the severity is lower than the filter levelcurrently set for that log file, the message will be ignored. The default severity level is "INFO".

Page 68: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

68 of 150 5/11/2007 10:14 AM

Skipjack Server

Application Development Guide

Section 8: Error Checking

5 October 2002

So far, we have discussed how the inputSchema can be used to perform syntax validation on the input parameters and how the errorMap and sqlErrorMap

attributes can be used to processed any exceptions thrown during transaction processing. However, it is also possible to define one or moresemantic error checks that can be performed either before or after any action is processed. This allows actions to be defined with their ownself-defensemechanisms. That is, if the current value of key attributes are semantically invalid then the transaction can be aborted. Similarly, if the attributeresults of the action don't meet a given criteria, the transaction can be aborted.

Pre-Processing Error Check

The preErrorCheck

attribute can be defined for any action to specify one or more criteria used to determine if the transaction should be aborted prior to executing theaction. For example, the following definition:

item getTable extends SQLTableAction { sqlFile = "getTable.sql"; ID = input.ID; Color = input.Color;

preErrorCheck = [ (ID < 0 || ID > 99, guiStatus.InvalidParameter, "The ID must be between 1 a nd 99"),

(Color in ["red", "white", "blue"] == false, guiStatus.InvalidParameter, "Invalid Color '" + Color + "'") ];}

ensures that the ID attribute is between 1 and 99, and that the Color attribute is either "red", "white", or "blue" before the database action is executed.

The preErrorCheck

attribute can consist of one or more tuples, with the first entry in each tuple used as the error criteria. That is, if the first entry evaluates to "true",then an error exists. In that case, the second entry is assigned as the value of tx.status attribute and the third entry is assigned as the value of the

Page 69: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

69 of 150 5/11/2007 10:14 AM

tx.errorMsg attribute. Error criteria are evaluated from top to bottom until one of the criteria is "true" or until the bottom of the list is reached.

Post-Processing Error Check

The preErrorCheck is used primarily for input validation, while the postErrorCheck is used primarily for result validation. For example, the followingaction item definition:

item getTable extends SQLTableAction { sqlFile = "getTable.sql"; ID = input.ID; Color = input.Color;

postErrorCheck = [ (rowCount == 0, guiStatus.NoRowsFound, "No Color Table Rows Were F ound For ID '"+ID+"' and Color '"+C olor+"'") ];}

ensures that at least one row is returned by the database action, by checking the value of the rowCount attribute that is automatically defined by theSQLTableAction action after the SQL query is processed.

As with the preErrorCheck attribute, multiple error criteria can be defined, accessing local attributes or attributes defined in other items to determine iftransaction processing should be aborted.

Custom Error Messages

The preErrorCheck and postErrorCheck attributes provide a convenient mechanism to detect transaction processing errors and to generate an appropriateerror message. As in the examples above, standard error status strings should be used whenever possible for consistency, while custom errormessages should be defined to precisely explain the error that was encountered. As seen above, it is relatively easy to generate an error message byconcatenating text and attribute values, thereby providing as many details as needed.

If transactions are being executed from a browser, then it may be beneficial to include HTML tags in the error message to better format the messageshown to the user via the standard exception templates. On the other hand, if the transaction is primarily used by non-HTML client applications,then it is probably best to generate simple text string error messages so that they can be easily processed by the client application as needed.

Page 70: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

70 of 150 5/11/2007 10:14 AM

Skipjack Server

Application Development Guide

Section 9: Transaction Security

5 October 2002

The Skipjack Server provides a range of security features to prevent unauthorized execution of transactions and access to controlled resources. Allthe security mechanisms are based on User identities and operational Roles, which are assigned to both Users and Transactions.

User Authentication

By default, all resources and transactions provided by Skipjack require the client or user to provide authentication information for every HTTP orHTTPS request. When connecting to Skipjack via a browser, the information is acquired by the browser using either a standard login pop-upwindow or by the server application using a custom login screen (see Custom Login Screens for details). When connecting to Skipjack using theC++, Java or Perl Client Library, the user authentication information is provided using the setAuthInfo() method defined by the Transaction class. (SeeClient Application Support for more details).

Regardless of how the authentication information is provided, it is used by Skipjack for two security purposes. First, the username and passwordprovided are validated against the Access Control List (ACL) maintained by the server. If the username or password are invalid, access is deniedand an error response is generated accordingly. If the username and password are valid and the user is attempting to access a static file (such as aGIF or HTML file) then no further access control is performed and the resource is returned to the client.

If the client is attempting to execute a transaction, then Skipjack retrieves the list of one or more roles that has been assigned to that user (the UserRole List) and the list of one or more roles that are required by the transaction (the Tx Role List). If the User Role List and the Tx Role Listintersect, then transaction execution is allowed to proceed. If not, an appropriate error message is generated.

Transaction Authorization

Transaction authors can assign one or more required roles to a transaction simply by defining the security.roles action item in the transactiondefinition file. For example, the following definition:

item security { roles = ["Operator", "Supervisor"];}

Page 71: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

71 of 150 5/11/2007 10:14 AM

requires that the user be assigned the "Operator" or "Supervisor" role in order to execute the current transaction.

If the security.roles attribute is not defined, then no security check is performed and every user is allowed toexecute the transaction.

Guest Resources

In many cases, access to certain files and/or transactions need not be controlled and shouldn't require the user or client to provide a valid usernameor password. Such resources are called "Guest Resources" and are supported in Skipjack using a set of wildcard definitions. If a requested file ortransaction path matches one of the wildcard expressions (defined as a GNU regular expression), then access will be granted to the user, regardlessof the validity of the username and password supplied, if any. By default, the user will be granted the "_GUEST" username and the "_Guest" roleduring such accesses, but operators and developers may assign other usernames with different roles as needed.

Standard ACL Tables

The standard Access Control List (ACL) mechanism provided by Skipjack is based on the following set of database tables:

skipjack.ACLUserskipjack.ACLRoleskipjack.ACLUserRoleskipjack.ACLGuestskipjack.ACLLogin

The ACLUser table contains a list of all usernames and passwords supported by the server, while the ACLRole table contains all valid roles. TheACLUserRole table maps users to roles, while the ACLGuest table defines all wildcard expressions and usernames for Guest Resources. The ACLdatabase tables are automatically created during the Skipjack Installation process and are populated with default usernames and passwords.

*** SYSTEM OPERATORS SHOULD CHANGE THE PASSWORDS BEFORE A SYSTEM GOESOPERATIONAL ***

User information can be added, removed and/or updated using User Admin Tool Roles and guest resources can be added or removed from thesystem by modifying the skipjack.ACLRole and skipjack.ACLGuest database tables.

Page 72: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

72 of 150 5/11/2007 10:14 AM

ACLAction Processing

The ACL memory tables are not intended to be accessed directly by transactions. Instead, the ACLAction action item may be used to retrieve data fromthe ACL memory tables. The ACLAction performs a specific function based on the setting of the cmd attribute, with the following valid values:

getRoleListgetUserListgetUserRolesgetUserTablegetGuestTablevalidateRolereloadACL

In most cases, the requested data is stored in an attribute with an appropriate name. See ACLAction Class for more details.

The "reloadACL" command is used to reload the ACL memory tables from the corresponding ACL database tables as defined by the tableACL.cfg

configuration file. This command is executed by the User Admin Tool whenever the ACL database tables are updated.

ACL Configuration

The Skipjack ACL is configured using the security.cfg and tableACL.cfg configuration files found in the $SKIPJACK/app/WEB-INF/conf directory. Thesecurity.cfg file defines the names of the ACL tables, while the tableACL.cfg file defines the standard table definitions for the ACL Memory Tableslisted above.

Application developers may overwrite one or both of these files to install custom ACL tables. For example, an application may overwrite thesecurity.cfg file provided by Skipjack and specify different names for the tables to be used from another table definition file. (See Memory Table Processing for more details.)

Alternately, an application may only overwrite the tableACL.cfg file, to define a different set of source database tables or delimited data files, whilestill using the same names defined in security.cfg. This is most commonly done when the ACL tables will be retrieved from a database other then thestandard "skipjack" database. (See Database Processing for more details about using connections to multiple database servers.)

Finally, applications can simply append their own default authentication information to the standard Skipjack ACL tables when the application isinitially installed.

Page 73: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

73 of 150 5/11/2007 10:14 AM

Applications should refrain from automatically reloading the ACL tables if they already exist, since theoperators may have modified their contents and probably don't want to type it all back in again!

To facilitate the sharing of the ACL tables between applications, each of the ACL tables has an 'AppName' column that may be used to identify theapplication that loaded that entry. For example, all of the default Skipjack entries are marked with an AppName of 'SKIPJACK'. Installation scriptscan make use of the AppName column to determine how existing data should be handled.

Custom Login Forms

By default, user authentication via a browser is handled using the "Basic" HTTP authentication mechanism, which results in a small pop-up loginwindow being displayed automatically by the browser whenever authentication information is required. This is the simplest and most universallysupported approach, although the pop-up windows lack visual appeal in most browsers.

Skipjack supports the use of custom login forms, allowing application developers to generate arbitrarily complex forms, with lots of bells andwhistles. Login forms can be generated using a login form transaction or can be defined as static HTML files. If a login form transaction is used,forms can be customized as needed depending any information available to that transaction when it is executed, such as the specific URL beingrequested by the user.

A specific login form can be assigned to one or more URLs by using GNU regular expressions to define the URLs to be matched. Furthermore,multiple login forms can exist within the same server, servicing different parts of the application URL name space as needed.

ACLLogin Table

Forms-based authentication is configured in Skipjack by inserting one or more records into the ACLLogin database table, which is normally done atinstallation time. The Skipjack Server defines the following default record:

Resource LoginURL AppName

/test/formLogin/.* /skipjack/login-form.tdf SKIPJACK

which specifies that the /skipjack/login-form.tdf transaction should be executed whenever login information is needed to execute any file in the/test/formLogin/ directory.

Application developers may add one or more additional records to define the login transactions (or static files) to be used for other individualtransactions or groups of transactions. For example, the following definition:

Page 74: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

74 of 150 5/11/2007 10:14 AM

Resource LoginURL AppName

/test/formLogin/.* /skipjack/login-form.tdf SKIPJACK

/myapp/.* /myapp/login.tdf MYAPP

would cause the /myapp/login.tdf transaction to be executed for all access attempts in the /myapp/ directory.

Application installation scripts may use the AppName column in the ACLLogin table to determine which records canbe overwritten during re-installation without adversely affecting the settings required by the Skipjack Server oranother application.

ACLGuest Table

For every LoginURL defined in the ACLLogin, a corresponding entry should also be made in the ACLGuest table to indicate that any user can accessthat resource and to specify the internal username associated with that resource. In normal applications, the _GUEST username can be used for this purpose. For example, the following entry in the ACLGuest table

Resource UserName AppName

/myapp/login.tdf _GUEST MYAPP

allows any user to access the login form transaction specified by the previous example.

Login Form Transaction

When a login form transaction is executed, the following session item attributes are defined:

Attribute Description

session.skipjackUsername last username provided, if any

session.skipjackPassword last password provided, if any

session.skipjackRealm realm name as specified in web.xml

Page 75: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

75 of 150 5/11/2007 10:14 AM

session.skipjackOrigURL original URL requested

session.skipjackLoginURL login servlet URL (ie. "/skipjack/login")

The skipjackOrigURL

attribute will include a query string that defines all of the input parameters that were provided (using either the GET or POST methods) for the URLthat was originally requested. Login form transaction authors can use these attributes in any way that they want to display the login form, as well asany other attribute normally available to a transaction. (See Session Management for more details about the session item and related session processing features.)

The default login form is defined by the "/skipjack/login-form.tdf" transaction and the "/skipjack/login-form.vm" and "/skipjack/login-page.vm"templates. If you want to make a custom login form, you can use those files as examples to build your own or can include those files and overrideattributes as needed to build your own login forms and/or pages.

In normal practice, there is no need to define the security.roles attribute for a login form transaction, because itshould be accessible to everyone in order to allow them to log into the server.

HTML Login Form

The HTML form generated by a login form transaction or defined by a static login file can be as simple or as ornate as desired. The onlyrequirements are as follows:

Use the POST method for the form tagDefine the Action URL to be "/skipjack/login" (an internal Skipjack Servlet)Define an input field named "skipjackUsername" (the user's login name)Define an input field named "skipjackPassword" (the user's password)

For example, the following form could serve as a valid (albeit ugly) login form:

<form method="POST" action="/skipjack/login"><INPUT name="skipjackUsername" TYPE=text SIZE=20 MA XLENGTH=17><br><INPUT name="skipjackPassword" TYPE=password SIZE=2 0 MAXLENGTH=17><br><INPUT name="loginButton" TYPE=submit VALUE="Login" ><br></form>

See the /skipjack/login-form.vm and /skipjack/login-page.vm templates for an example of a more useful login form and page layout.

Page 76: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

76 of 150 5/11/2007 10:14 AM

Skipjack Server

Application Development Guide

Section 10: Client Application Support

5 October 2002

The Skipjack Server is an HTTP-based server that can be used to provide Web-services to client applications, other servers or users via a browser.In this section, we describe a number of approaches that can be used to rapidly develop client applications for the Skipjack Server.

Raw HTTP Request

Since the Skipjack Server is based on a standard HTTP server framework, any client or server application can interact with Skipjack simply byopening a connection to the appropriate TCP port and sending a valid HTTP Request. Skipjack will process the HTTP request and will return astandard HTTP Response that includes an output file conforming to a given MIME type.

For example, the following HTTP Request:

GET /test/nop.tdf HTTP/1.0Host: localhost:8080Authorization: Basic YWRtaW46YWRtaW4=

will execute the test/nop.tdf transaction and return the result as a text/html file, which is the default response MIME type for any transaction.

The Authorization header shown above is the encoding for a username and password of "admin/admin". If adifferent login is required, a different Authorization header should be used.

Transaction Map Response

As discussed in the Transaction Response section, Skipjack transactions can generate different output files dynamically based on the contentType

input parameter. This allows client applications to specify the type of output format that is best suited for their purposes. Transaction authors arefree to define as many or as few supported types for each transaction. By default, the text/html MIME type is used to generate the response.

In many cases, client applications simply need to check the status of a transaction that was executed and possibly process one or more output

Page 77: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

77 of 150 5/11/2007 10:14 AM

parameters. To that end, the transaction/map MIME is supported by the Skipjack Server for all transactions. The transaction/map file format consists of a small number of formatted record types that can be used to encode the following types of data:

Scalar ValueAn arbitrary string that represents a single value, representing strings, numbers, dates, etc.

List ValueAn ordered list of scalar values, where each string may represent a different type of value.

Table ValueA two dimensional set of data represented as rows and columns. Each column has an associated name and default value and eachrow contains a value, possibly empty, for each column defined.

Map ValueA hashtable of key/value pairs.

Although the number of record types is small, they are sufficient to transfer all of the output values that can be generated by standard Skipjacktransactions. The transaction/map format is designed to be easily processed by client applications and/or read directly by humans for debuggingpurposes.

Client applications that require different encoding schemes can be easily supported by creating a Velocitytemplate that encodes the necessary transaction results as needed and then assigning that template to a customMIME type in the responseMap for one or more transactions. See Transaction Response for more details.

A transaction/map can be generated for any transaction simply by specifying that MIME type as the value of the contentType input parameter. Forexample, the following raw HTTP request:

GET /test/nop.tdf?contentType=transaction/map HTTP/ 1.0Host: localhost:8080Authorization: Basic YWRtaW46YWRtaW4=

executes the test/nop.tdf transaction, setting the contentType to transaction/map, causing the following server response to be generated:

K|input.contentTypeV|transaction%2FmapK|tx.statusHistoryL|0K|tx.stopTimeV|1019597119992K|tx.startTimeV|1019597119966

Page 78: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

78 of 150 5/11/2007 10:14 AM

K|tx.respTimeV|26K|tx.statusV|100+Transaction+SuccessfulK|tx.clientIDV|UNKNOWNK|tx.errorMsgV|K|tx.TXDIRV|%2Fhome%2Ftools%2Fskipjack%2Fapp%2FWEB-INF%2Ftran saction%2Ftest%2FK|tx.errorClassV|K|tx.identifierV|test%2FnopK|tx.errorTraceV|K|tx.basenameV|nopK|tx.actionTraceL|2V|mainV|TransMapResponse

See the navius.toolkit.format.TransactionMap class for details concerning the encoding scheme.

Skipjack Client Support

Although it is possible to access the Skipjack Server via the raw HTTP interface and process the output accordingly, in most applications it is moreeffective to use one of the Skipjack Client Packages to access the server. Each package provides a convenient set of methods for setting transactionparameters, executing one or more transactions and processing the results. For the most part, a client application need only create a transactionobject, set the transaction input parameters, execute the transaction, and process transaction results as needed. The packages are implemented usingthe standard capabilities provided in the chosen language so that they can be readily added to any application.

Java Client PackageClient applications developed using Java can use the Skipjack Java Client Package to access the Skipjack Server. The JavaClient Package provides complete control over the execution of transactions and the processing of results, using either the HTTPor HTTPS protocols. See Java Client Package for more details.

In addition to synchronous transaction processing, the Java Client Package provides support for the asynchronous processing ofTransaction Events generated by the Event Listening feature provided by the Skipjack Server.

Perl Client PackageClient applications developed using the Perl scripting language can use the Transaction.pm Perl module as an interface to theSkipjack Server. The Transaction.pm module allows Perl scripts to execute one or more transactions, process the results andgenerate status information through a single Perl object. The Perl Client Package supports both the HTTP and HTTPS protocols

Page 79: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

79 of 150 5/11/2007 10:14 AM

when accessing the server. See Perl Client Package for more details.

C++ Client PackageClient applications developed using C++ can use the Skipjack C++ Client Package to access the Skipjack Server. The C++Client Package provides complete control over the execution of transactions and the processing of results, using the HTTPprotocol to access the server. See C++ Client Package for more details.

Page 80: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

80 of 150 5/11/2007 10:14 AM

Skipjack Server

Application Development Guide

Java Client Package

5 October 2002

The Skipjack Server is an HTTP-based server that can be used to provide Web-services to client applications, other servers or users via a browser.In this section, we describe how to access the Skipjack Server using the Skipjack Java Client Package.

The navius.skipjack.client.Transaction class implements a client-side mechanism for accessing the Skipjack Server. It insulates the clientapplication from all HTTP request and response encoding and decoding issues, providing a easy-to-use mechanism that is similar to a RemoteProcedure Call.

The Transaction class is provided as part of the standard Skipjack Server release and is located in the $SKIPJACK/classes/navius/skipjack/client directory, where $SKIPJACK

is the root directory for the Skipjack Server installation. For developers who don't have direct access to the Skipjack Server directory, the Transaction

class is also provided as part of the Skipjack Client Package, located in the $CLIENT/lib/skipjack.jar JAR file, where $CLIENT is the root directory for theSkipjack Client Package.

The Transaction object provides the following basic methods for managing transaction processing:

Configuration public void setAuthInfo (String authinfo)

Specifies the authentication information (in the form "username:password") to beused when submitting each transaction for execution. By default, no authenticationinformation is provided.

public void setClientID (String clientID)

Specifies the client ID for this application, which is used in the Skipjack Server logsto determine the client that executed a given transaction. By default, a client ID basedon the current process ID and the hostname is used.

public void setServerURL (String serverURL)

Specifies the base URL to be used when a relative URL is provided as an inputparameter to the execute() method. By default, no server URL is defined.

public void debugEnable (boolean enabled)

Page 81: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

81 of 150 5/11/2007 10:14 AM

Enables/disables debug output generation for the Transaction object. Disabled bydefault.

Input Parameters

public void setParam (String key, String val)

Sets the value of the given input parameter

public String getParam (String key)

Returns the value of the given input parameter

public Hashtable getParamMap ()

Returns a hash table containing all of the input parameters that are currently defined

Page 82: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

82 of 150 5/11/2007 10:14 AM

Transaction Processing

public void execute (String url)

Executes the given transaction and processes all of the results returned. If a relativeURL is given, then it will be prepended by the current base server URL as specified bythe setServerURL() method. This method automatically clears all existing transactionresults before executing the new transaction.

After this method is called, the tx.status result will contain the transaction status, whichshould be checked by the client application before accessing any other results. If atransaction/map response is returned by the Skipjack Server, then all of the results will beautomatically stored in the result map. Otherwise, the entire file returned by theSkipjack Server will be stored as a string in the respData result.

Results Processing

public Object getResultItem (String key)

Returns the value of the given result.

public String getResultString (String key)

Returns the value of the given result as a String.

public int getResultInt (String key)

Returns the value of the given result as an integer.

public Hashtable getResultMap ()

Returns a hash table containing all of the results that are currently defined.

Additional methods are supported for more advanced processing, as described in the Java API documentation for the Transaction class.

Basic Transaction Execution

The following code segment shows how a transaction can be executed using the Transaction object with only a few method calls:

import navius.skipjack.client.*;

Transaction tx = new Transaction();

tx.setAuthInfo ("admin:admin");

Page 83: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

83 of 150 5/11/2007 10:14 AM

tx.execute ("http://localhost:8080/test/nop.tdf");

int status = tx.getResultInt("tx.status");if (status < 100 || status > 199) throw new Exception ( tx.getResultString("tx.status") + " - " + tx.getResultString("tx.errorMsg") );

In this case, the test/nop.tdf transaction is executed, using "admin:admin" to authenticate this client application. After the transaction is executed, thetx.status

result is examined as an integer to determine if the transaction was successful. (By convention, status values between 100 and 199 inclusive areconsidered successful.) If not, the tx.status and tx.errorMsg results are used as strings to generate an exception message.

Specifying Input Parameters

For transactions that require input parameters or that generate results, the setParam() and getResultXXX() methods are used accordingly. For example, thefollowing code segment:

import navius.skipjack.client.*;

Transaction tx = new Transaction();

tx.setAuthInfo ("admin:admin");tx.setClientID ("myClient");

tx.setParam ("message", "Hello World");

tx.execute ("http://localhost:8080/test/ping.tdf");

int status = tx.getResultInt("tx.status");if (status < 100 || status > 199) throw new Exception ( tx.getResultString("tx.status") + " - " + tx.getResultString("tx.errorMsg") );

System.out.println ("message = "+tx.getResultString ("output.message"));

executes the test/ping.tdf which accepts the message input parameter, specified using the setParam() method, and returns the output.message result, which is accessed using the getResultString() method. In this example, the setClientID() method is used to specify a string that can be used to identify this clientapplication in the server logs. If not specifically defined, a default client ID is generated based on the current process ID and host name.

Processing Results

Page 84: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

84 of 150 5/11/2007 10:14 AM

In the following example, the sqlUtil/adhocSql transaction is executed to retrieve a table containing the names of all databases currently defined:

import navius.skipjack.client.*;import navius.skipjack.table.*;

Transaction tx = new Transaction();

tx.setAuthInfo ("admin:admin");tx.setClientID ("myClient");

tx.setParam ("sqlExpr", "show databases");

tx.execute ("http://localhost:8080/sqlUtil/adhocSql .tdf");

int status = tx.getResultInt("tx.status");if (status < 100 || status > 199) throw new Exception ( tx.getResultString("tx.status") + " - " + tx.getResultString("tx.errorMsg") );

Table tbl = (Table)tx.getResultItem("output.table") ;for (int i=0; i<tbl.size(); i++) System.out.println (tbl.getValue(i,"Databas e"));

In this case, the sqlExpr input parameter is defined, as required by the sqlUtil/adhocSql transaction and the output.table result is accessed. Since databasequeries can return multiple rows and columns, the result is accessed using the getResultItem() method, which returns the object that is actually storedin the result map. In this case, it is known to be a Table object, so that result is cast accordingly and each value in the "Database" column of thattable is printed.

Page 85: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

85 of 150 5/11/2007 10:14 AM

Result Content Type

By default, the Transaction object specifies a contentType of transaction/map so that the results of the transaction can be easily processed. If, however, adifferent output type is required, it can be easily specified using the setParam() method, as in the following example:

import navius.skipjack.client.*;

Transaction tx = new Transaction();

tx.setAuthInfo ("admin:admin");

tx.setParam ("contentType", "text/html");

tx.execute ("http://localhost:8080/test/showTx.tdf" );

int status = tx.getResultInt("tx.status");if (status < 100 || status > 199) throw new Exception ( tx.getResultString("tx.status") + " - " + tx.getResultString("tx.errorMsg") );

System.out.println (tx.getResultString("respData")) ;

In this case, the text/html

content type is specified, which causes the entire output file generated by the server to be stored as the "respData" result. Note, the tx.status value canstill be accessed to determine if the transaction was successful, but no other transaction output parameters will be available.

Page 86: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

86 of 150 5/11/2007 10:14 AM

Skipjack Server

Application Development Guide

Perl Client Package

5 October 2002

The Skipjack Server is an HTTP-based server that can be used to provide Web-services to client applications, other servers or users via a browser.In this section, we describe how to access the Skipjack Server using the Skipjack Perl Client Package.

Client applications that are developed using the Perl scripting language can make use of the Transaction.pm Perl module as a convenient interface tothe Skipjack Server. The Transaction.pm module allows Perl scripts to easily specify one or more input parameters, execute one or more transactions,and process transaction results. Additionally, convenience methods exist to allow Perl client applications to append entries to the Skipjack Servererror log and/or generate Skipjack Server Operator Console alarms or alerts.

The Transaction.pm module is provided as part of the standard Skipjack Server installation and is located in the $SKIPJACK/lib directory, where $SKIPJACK

is the root directory for the Skipjack Server. For developers who don't have direct access to the Skipjack Server directories, the Transaction.pm

module is also included in the Skipjack Client Package and is located in the $CLIENT/lib directory, where $CLIENT is the root directory of the SkipjackClient Package.

The Transaction.pm module depends on the wget-1.8.1 public-domain utility for communication with the server,using either the HTTP or HTTPS protocols. Accordingly, a wget executable suitable for RedHat 7.1 is providedas part of the Skipjack Server Package, located in the $SKIPJACK/bin directory, and as part of the Skipjack ClientPackage, located in the $CLIENT/bin directory. If a more recent version of wget is installed on the system or a different operating system is being used, those executables should be replaced accordingly.

The Transaction.pm module provides the following basic methods for managing transaction processing:

Configuration $tx = new Transaction()

Creates a new Transaction object and returns a reference to it

$tx->setSkipjackRoot (path)

Specifies the root directory for the Skipjack Server or Skipjack Client Package wherethe wget executable can be found. Default is "/tools/skipjack".

$tx->setAuthInfo (authinfo)

Page 87: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

87 of 150 5/11/2007 10:14 AM

Specifies the authentication information (in the form "username:password") to beused when submitting each transaction for execution. By default, no authenticationinformation is provided.

$tx->setClientID (clientID)

Specifies the client ID for this application, which is used in the Skipjack Server logsto determine the client that executed a given transaction. By default, a client ID basedon the current process ID and the hostname is used.

$tx->setServerURL (url)

Specifies the base URL to be used when a relative URL is provided as an inputparameter to the execute() method. By default, "http://localhost:8080" is used.

$tx->debugEnable (enabled)

Enables/disables debug output generation for the Transaction object. Disabled bydefault.

Page 88: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

88 of 150 5/11/2007 10:14 AM

Input Parameters

$tx->setParam (key, val)

Sets the value of the given input parameter

$tx->getParam (key)

Returns the value of the given input parameter

$tx->clearParam (key)

Clears the given input parameter (ie. makes it undefined)

$tx->getParamMap ()

Returns an associative array containing all of the input parameters that are currentlydefined

Transaction Processing

$tx->execute (url)

Executes the given transaction and processes all of the results returned. If a relativeURL is given, then it will be prepended by the current base server URL as specified bythe setServerURL() method. This method automatically clears all existing transactionresults before executing the new transaction.

After this method is called, the tx.status result will contain the transaction status, whichshould be checked by the client application before accessing any other results. If atransaction/map response is returned by the Skipjack Server, then all of the results will beautomatically stored in the result map. Otherwise, the entire file returned by theSkipjack Server will be stored as a string in the respData result.

Results Processing

$tx->setResult (key, type, val)

Sets the type and value of the given result. This method is called automatically by theexecute() method whenever a transaction/map response is returned by the Skipjack Server.

$tx->getResult (key)

Returns the value of the given result.

$tx->getResultType (key)

Returns the data type of the given result (V=value, L=list, T=table). The result typecan be used to determine how the result should be processed by the client.

Page 89: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

89 of 150 5/11/2007 10:14 AM

$tx->getResultMap ()

Returns an associative array containing all of the results that are currently defined.

$tx->printAllResults (FILE)

Prints all results to the given FILE descriptor.

$tx->printResult (FILE, key)

Prints the given result to the given FILE descriptor.

Client Status $tx->log (severity, msg)

Sends the given message to the Skipjack Server log based on the given severity(ERROR, WARNING, INFO, DEBUG)

$tx->alarm (severity, gid, eid, tid, code, msg)

Generates an alarm or alert on the Skipjack Server with the given information. Theseverity may be ALARM or ALERT.

Page 90: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

90 of 150 5/11/2007 10:14 AM

Basic Transaction Execution

The following code segment shows how a transaction can be executed using the Transaction object with only a few method calls:

## PerlClient-ex1.txt#$SKIPJACK_ROOT = "/tools/skipjack";

require "$SKIPJACK_ROOT/lib/Transaction.pm";

$tx = new Transaction();

$tx->setSkipjackRoot ($SKIPJACK_ROOT);$tx->setAuthInfo ("admin:admin");

$tx->execute ("http://localhost:8080/test/nop.tdf") ;

$status = $tx->getResult("tx.status");if ($status ne "100 Transaction Successful") { print "STATUS: $status\n"; print "ERROR: ",$tx->getResult("tx.errorMsg "),"\n"; exit -1;}

In this case, the test/nop.tdf transaction is executed, using "admin:admin" to authenticate this client application. After the transaction is executed, thetx.status result is examined to determine if the transaction was successful. If not, the tx.status and tx.errorMsg results are used to generate an errormessage.

In this example, the $SKIPJACK_ROOT variable is used to specify the location of the Transaction.pm module in the Perl require statement (which loads the named module) and the setSkipjackRoot() method (which specifies the location of the wget executable). The pathname specified for $SKIPJACK_ROOT

should be either the Skipjack Server root directory or the Skipjack Client root directory, depending on which packages are installed on the samemachine as the Perl client application. In both cases, the Transaction.pm module is located in the lib subdirectory and the wget executable is located inthe bin subdirectory.

Scripts Executed By The Skipjack Server

If a Perl client script is being executed directly the Skipjack Server (usually via the ShellAction or ShellResponse actions) then most of the configurationsettings are automatically handled by the Skipjack Server and the Transaction.pm module. Specifically, the following conveniences are provided:

the Perl environment is automatically configured to search the Skipjack Server lib directory for the Transaction.pm,

the Skipjack Server root directory is used to locate the wget executable,

Page 91: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

91 of 150 5/11/2007 10:14 AM

the Skipjack Server URL is used as the default serverURL for all transactions that are specified using relative transaction names, and

the authentication information for the user who executed the transaction that executed the current script is used as the default authenticationinformation for any transactions executed by this script.

As a result of these conveniences, if the previous script example were executed directly by the Skipjack Server it could be written as follows:

## PerlClient-ex2.txt#require "Transaction.pm";

$tx = new Transaction();

$tx->execute ("test/nop.tdf");

$status = $tx->getResult("tx.status");if ($status ne "100 Transaction Successful") { print "STATUS: $status\n"; print "ERROR: ",$tx->getResult("tx.errorMsg "),"\n"; exit -1;}

Note how the require statement and the execute() method make use of relative names, and that no other configuration methods need to be called beforeexecuting the transaction.

Specifying Input Parameters

For transactions that require input parameters or that generate results, the setParam() and getResult() methods are used accordingly. For example, thefollowing code segment:

## PerlClient-ex3.txt#$SKIPJACK_ROOT = "/tools/skipjack";

require "$SKIPJACK_ROOT/lib/Transaction.pm";

$tx = new Transaction();

$tx->setSkipjackRoot ($SKIPJACK_ROOT);$tx->setAuthInfo ("admin:admin");$tx->setClientID ("myClient");

$tx->setParam ("message", "Hello World");

$tx->execute ("http://localhost:8080/test/ping.tdf" );

$status = $tx->getResult("tx.status");

Page 92: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

92 of 150 5/11/2007 10:14 AM

if ($status ne "100 Transaction Successful") { print "STATUS: $status\n"; print "ERROR: ",$tx->getResult("tx.errorMsg "),"\n"; exit -1;}

print "message = ",$tx->getResult("output.message") ,"\n";

executes the test/ping.tdf which accepts the message input parameter, specified using the setParam() method, and returns the output.message result, which is accessed using the getResult() method. In this example, the setClientID() method is used to specify a string that can be used to identify this clientapplication in the server logs. If not specifically defined, a default client ID is generated based on the current process ID and host name.

Processing Results

In the following example, the sqlUtil/adhocSql transaction is executed to retrieve a table containing the names of all databases currently defined:

## PerlClient-ex4.txt#$SKIPJACK_ROOT = "/tools/skipjack";

require "$SKIPJACK_ROOT/lib/Transaction.pm";

$tx = new Transaction();

$tx->setSkipjackRoot ($SKIPJACK_ROOT);$tx->setAuthInfo ("admin:admin");$tx->setClientID ("myClient");

$tx->setParam ("sqlExpr", "show databases");

$tx->execute ("http://localhost:8080/sqlUtil/adhocS ql.tdf");

$status = $tx->getResult("tx.status");if ($status ne "100 Transaction Successful") { print "STATUS: $status\n"; print "ERROR: ",$tx->getResult("tx.errorMsg "),"\n"; exit -1;}

print "Database List\n";print "-------------\n";

@rows = @{$tx->getResult("output.table")};foreach $row (@rows) { %row = %{$row}; print $row{"Database"},"\n";}

In this case, the sqlExpr input parameter is defined, as required by the sqlUtil/adhocSql transaction and the output.table result is accessed. Since databasequeries can return a table of results, the result is referenced as an array of table rows. Each table row is implemented as an associative array, using

Page 93: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

93 of 150 5/11/2007 10:14 AM

the name of each table column as the key. The last loop in the example iterates over all rows, printing the value of the "Database" column, which isa known result column for the given query.

The printAllResults() and printResult() methods can be used to print all currently defined results or a given result fordebug purposes.

Result Content Type

By default, the Transaction.pm module specifies a contentType of transaction/map so that the results of the transaction can be easily processed. If, however,a different output type is required, it can be easily specified using the setParam() method, as in the following example:

## PerlClient-ex5.txt#$SKIPJACK_ROOT = "/tools/skipjack";

require "$SKIPJACK_ROOT/lib/Transaction.pm";

$tx = new Transaction();

$tx->setSkipjackRoot ($SKIPJACK_ROOT);$tx->setAuthInfo ("admin:admin");

$tx->setParam ("contentType", "text/html");

$tx->execute ("http://localhost:8080/test/showTx.td f");

$status = $tx->getResult("tx.status");if ($status ne "100 Transaction Successful") { print "STATUS: $status\n"; print "ERROR: ",$tx->getResult("tx.errorMsg "),"\n"; exit -1;}

print $tx->getResult("respData");

In this case, the text/html

content type is specified, which causes the entire output file generated by the server to be stored as the "respData" result. Note, the tx.status value canstill be accessed to determine if the transaction was successful, but no other transaction output parameters will be available.

Page 94: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

94 of 150 5/11/2007 10:14 AM

Skipjack Server

Application Development Guide

C++ Client Package

5 October 2002

The Skipjack Server is an HTTP-based server that can be used to provide Web-services to client applications, other servers or users via a browser.In this section, we describe how to access the Skipjack Server using the Skipjack C++ Client Package.

The C++ Transaction

class implements a client-side mechanism for accessing the Skipjack Server. It insulates the client application from all HTTP request and responseencoding and decoding issues, providing a easy-to-use mechanism that is similar to a Remote Procedure Call.

The Transaction class is provided as part of the Skipjack Client Package, located in the $CLIENT/lib/libTransaction.a library file, where $CLIENT is the root directory for the Skipjack Client Package. The associated header definition files are located in the $CLIENT/include directory and the source files for allof the library classes are located in the $CLIENT/src directory.

The Transaction object provides the following basic methods for managing transaction processing:

Configuration void setAuthInfo (const char *authinfo)

Specifies the authentication information (in the form "username:password") to beused when submitting each transaction for execution. By default, no authenticationinformation is provided.

void setClientID (const char *clientID)

Specifies the client ID for this application, which is used in the Skipjack Server logsto determine the client that executed a given transaction. By default, a client ID basedon the current process ID and the hostname is used.

void debugEnable (int enabled)

Enables/disables debug output generation for the Transaction object. Disabled bydefault.

Input Parameters

void setParam (const char *key, const char *val)

Page 95: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

95 of 150 5/11/2007 10:14 AM

Sets the value of the given input parameter.

const char *getParam (const char *key)

Returns the value of the given input parameter.

TransactionMap *getParamMap ()

Returns a TransactionMap object containing all of the input parameters that arecurrently defined. The keys(), set(), and get() methods of the TransactionMap object canbe used to process specific parameters contained in the map.

Transaction Processing

void execute (const char *url)

Executes the given transaction and processes all of the results returned. This methodautomatically clears all existing transaction results before executing the newtransaction.

After this method is called, the tx.status result will contain the transaction status, whichshould be checked by the client application before accessing any other results. If atransaction/map response is returned by the Skipjack Server, then all of the results will beautomatically stored in the result map. Otherwise, the entire file returned by theSkipjack Server will be stored as a string in the respData result.

Page 96: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

96 of 150 5/11/2007 10:14 AM

Results Processing

TransactionItem *getResultItem (const char *key)

Returns the value of the given result as a TransactionItem (single string value),TransactionList (list of values) or TransactionTable (table of values).

const char *getResultString (const char *key)

Returns the value of the given result as a String, automatically converting singlevalues, list values and table values to a string.

int getResultInt (const char *key)

Returns the value of the given result as an integer, if possible.

TransactionMap *getResultMap ()

Returns a TransactionMap object containing all of the results that are currentlydefined. The keys(), set(), and get() methods of the TransactionMap object can be used toprocess specific parameters contained in the map.

Basic Transaction Execution

The following code segment shows how a transaction can be executed using the Transaction object with only a few method calls:

#include "Transaction.hh"

try { Transaction *tx = new Transaction();

tx->setAuthInfo ("admin:admin");

tx->execute ("http://localhost:8080/test/no p.tdf");

int txStatus = tx->getResultInt ("tx.status "); if (txStatus < 100 || txStatus > 199) tx->error ("Tx Failure: %s\n%s\n", tx->getResultString("tx.st atus"), tx->getResultString("tx.er rorMsg"));

delete tx;

} catch (TransactionException ex) { printf ("ERROR: %s\n", ex.getMessage()); exit (-1);}

In this case, the test/nop.tdf transaction is executed, using "admin:admin" to authenticate this client application. After the transaction is executed, the

Page 97: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

97 of 150 5/11/2007 10:14 AM

tx.status result is examined as an integer value to determine if the transaction was successful. (By convention, tx.status values between 100 and 199inclusive are considered successful.) If the status is not succesful, then an exception is thrown and the application exits.

Page 98: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

98 of 150 5/11/2007 10:14 AM

Specifying Input Parameters

For transactions that require input parameters or that generate results, the setParam() and getResultXXX() methods are used accordingly. For example, thefollowing code segment:

#include "Transaction.hh"

try { Transaction *tx = new Transaction();

tx->setAuthInfo ("admin:admin"); tx->setClientID ("myClient");

tx->setParam ("message", "Hello World");

tx->execute ("http://localhost:8080/test/pi ng.tdf");

int txStatus = tx->getResultInt ("tx.status "); if (txStatus < 100 || txStatus > 199) tx->error ("Tx Failure: %s\n%s\n", tx->getResultString("tx.st atus"), tx->getResultString("tx.er rorMsg"));

printf ("message = %s\n", tx->getResultString("output.message "));

delete tx;

} catch (TransactionException ex) { printf ("ERROR: %s\n", ex.getMessage()); exit (-1);}

executes the test/ping.tdf which accepts the message input parameter, specified using the setParam() method, and returns the output.message result, which is accessed using the getResultString() method. In this example, the setClientID() method is used to specify a string that can be used to identify this clientapplication in the server logs. If not specifically defined, a default client ID is generated based on the current process ID and host name.

Processing Results

In the following example, the sqlUtil/adhocSql transaction is executed to retrieve a table containing the names of all databases currently defined:

#include "Transaction.hh"#include "TransactionTable.hh"

try { Transaction *tx = new Transaction(); TransactionTable *tbl;

Page 99: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

99 of 150 5/11/2007 10:14 AM

int rowCount, i;

tx->setAuthInfo ("admin:admin"); tx->setClientID ("myClient");

tx->setParam ("sqlExpr", "show databases");

tx->execute ("http://localhost:8080/sqlUtil /adhocSql.tdf");

int txStatus = tx->getResultInt ("tx.status "); if (txStatus < 100 || txStatus > 199) tx->error ("Tx Failure: %s\n%s\n", tx->getResultString("tx.st atus"), tx->getResultString("tx.er rorMsg"));

printf ("Database List\n"); printf ("-------------\n");

tbl = (TransactionTable *) tx->getResultIte m ("output.table"); rowCount = tbl->getRowCount(); for (i=0; i < rowCount; i++) { printf ("%s\n", tbl->getValue(i,"Da tabase")); }

delete tx;

} catch (TransactionException ex) { printf ("ERROR: %s\n", ex.getMessage()); exit (-1);}

In this case, the sqlExpr input parameter is defined, as required by the sqlUtil/adhocSql transaction and the output.table result is accessed. Since databasequeries can return multiple rows and columns, the result is accessed using the getResultItem() method, which returns the object for the output.table

result. In this case, it is known to be a TransactionTable object, so that result is cast accordingly and each value in the "Database" column of that tableis printed.

Result Content Type

By default, the Transaction object specifies a contentType of transaction/map so that the results of the transaction can be easily processed. If, however, adifferent output type is required, it can be easily specified using the setParam() method, as in the following example:

#include "Transaction.hh"

try { Transaction *tx = new Transaction();

tx->setAuthInfo ("admin:admin"); tx->setClientID ("myClient");

tx->setParam ("contentType", "text/html");

Page 100: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

100 of 150 5/11/2007 10:14 AM

tx->execute ("http://localhost:8080/test/sh owTx.tdf");

int txStatus = tx->getResultInt ("tx.status "); if (txStatus < 100 || txStatus > 199) tx->error ("Tx Failure: %s\n%s\n", tx->getResultString("tx.st atus"), tx->getResultString("tx.er rorMsg"));

printf ("%s", tx->getResultString("respData "));

delete tx;

} catch (TransactionException ex) { printf ("ERROR: %s\n", ex.getMessage()); exit (-1);}

In this case, the text/html content type is specified, which causes the entire output file generated by the server to be stored as the respData result. Note,the tx.status value can still be accessed to determine if the transaction was successful, but no other transaction output parameters will be available.

Page 101: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

101 of 150 5/11/2007 10:14 AM

Skipjack Server

Application Development Guide

Section 11: Event Listening

5 October 2002

Skipjack Server provides a low-level mechanism, called Event Listening, that allows applications to easily monitor and/or react to the activity ofone or more transactions. This capability can be used to support a wide range of system requirements, such as system monitoring applications,automated decision making, and adhoc reporting, to name a few.

Event Listening Process

The event listening process is performed by the Event Manager component as depicted by the following diagram:

The process begins with the Event Listener registering itself with the Event Manager (step 1), providing a Filter Criteria, an optional Event Handler Transaction and an optional Delivery Address. If a Delivery Address is specified, then the Event Listener waits to receive one or moreTransaction Events from the Event Manager as they are processed.

In normal operation, a Transaction Client submits a Transaction Request to the Transaction Servlet (step 2) and a Transaction Response is returnedto the Transaction Client (step 3), allowing the Transaction Client to continue processing. Regardless of the number of Transaction Listenersregistered for a given transaction, the transaction will be processed entirely and a response returned to the Transaction Client before any listenerprocessing is begun.

If the transaction was successful (as indicated by a status code of the form '1xx'), then the Transaction State is sent to the Event Manager forsubsequent processing (step 4). The Transaction State consists of all TDF item attributes defined at the time that the transaction was completed.

Page 102: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

102 of 150 5/11/2007 10:14 AM

For each Transaction State received, the Event Manager compares the transaction identifer to the Filter Criteria defined for each TransactionListener that is currently registered. For each match found, an Event Worker thread is launched to process the event on behalf of the Event Listener.

A fixed number of Event Worker threads are created when the Event Manager is initialized and are used on afirst-come-first-served basis to process events on behalf of Event Listeners.

If an Event Handler Transaction was specified when the Event Listener was registered, then it is executed by the Event Worker in order to processthe event. The Event Handler Transaction can perform whatever processing is necessary based on the contents of the event, as will be discussedbelow.

After the Event Handler Transaction has been processed, the Event Worker delivers the event to the Event Listener (step 5). The deliverymechanism, address and format are all specified by the Event Listener at registration time. At that point, the Event Listener application can performadditional processing as needed based on the event information.

Unsuccessful transactions may also be delivered to the listener as needed by setting the ReceiveFailures parameter to "true" when registering the listener. That allows applications to monitor and optionally react to failureconditions for critical transactions.

Listener Registration

The eventMgr/add-listener.tdf transaction is used to register an event listener with the Event Manager, with the following input parameters supported:

TxFilterGNU regular expression that is compared against the transction identifier to determine if the transaction event should beprocessed.

TxNameOptional name of the Event Handler Transaction to be executed when an event is processed. If no TxName attribute is defined,or it is the empty string, then no event handler transaction processing is performed.

TxInput<XXXX>Optional input parameter for the Event Handler Transaction, which is used to define the input.<XXXX> attribute when the EventHandler Transaction is executed (i.e., the leading "TxInput" prefix is stripped). Any number of Event Handler Transactioninput parameters can be specified by changing the value of <XXXX>.

Page 103: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

103 of 150 5/11/2007 10:14 AM

AddrTypeSpecifies the delivery mechanism to be used to send the event to the Event Listener application, with the following typessupported:

TCP (default)PROXYNONE

The specific processing performed for each address type is described below.

HostIf AddrType is 'TCP' or 'PROXY', this attribute specifies the TCP host name or IP address at which the Event Listener resides.

PortIf AddrType is 'TCP', this attribute specifies the TCP port number to at which the Event Listener is waiting.

MaxWaitIf AddrType is 'PROXY', this attribute specifies the maxium time that the Event Worker will wait for the Transaction Listener toconnect before closing the server socket.

OutputType, OutputFormatMIME type that indicates the output format of the Transaction Event sent to this listener, with the following values supported:

transaction/map (default)template/filetemplate/string

The specific processing performed for each output type is described below.

RemoveOnFailureIf "true", then the Listener Registration will be deleted whenever the Event Manager fails to properly deliver a TransactionEvent. Normally, such a failure indicates that the Event Listener application has been halted, so there is little reason to tryagain with subsequent events. The default value is "true".

RemoveOnRestartIf "true", then the Listener Registration will not be stored in the database and will not be automatically re-loaded when theserver restarts. Normally, this is used by Event Listener applications that are automatically restarted when the Skipjack Serverrestarts (such as the internal Process Manager). The default value is "true".

ReceiveFromSelfIf "true", then the Event Listener application will receive Transaction Events that were originated from the same application, as

Page 104: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

104 of 150 5/11/2007 10:14 AM

determined by the ClientID. The default value is "false".

ReceiveFailuresIf "true", then the Event Listener application will receive Transaction Events for all transactions that match the filter criteria,even if they have an unsuccessful status. The default value is "false".

If the registration transaction is successful, a unique ListenerID is returned to the Event Listener application as the output.ListenerID attribute, which can be used to track the registration information while viewing the Event Monitor, Event Table, or Event Log.

Event Handler Transactions

An Event Handler Transaction can be specified for any Event Listener using the TxName input parameter of the eventMgr/add-listener.tdf transaction.Other than a small set of internal limitations (as noted below), event handler transactions can be written to perform a wide range of processingtasks. For example, if detailed, application-level logging is required, an event handler transaction can be registered that listens for all of the keyapplication transaction events. For each event processed, the event handler transaction can extract the key information (possibly pulling additionaldata from the database or other data structures) and generate an appropriate log record in the database or append the information to a file.Alternately, the event handler transaction can be written to determine if a "critical" event has occurred, sending an email notification to a list ofsubscribers defined in the database. Finally, an event handler transaction may be written to summarize processing at various intervals or whenever agiven limit is reached.

Event Items

Prior to executing the event handler transaction, the following items are copied from the event being processed into the event handler transaction:

Event Item Handler Item

request eventRequest

input eventInput

output eventOutput

tx eventTx

This allows the event handler transaction to reference all of the key state values from the original event as needed. For example, the event handlertransaction may want to use the output and transaction status values of the event as input values, as in the following "input" item definition:

Page 105: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

105 of 150 5/11/2007 10:14 AM

item input { status = eventTx.status; myX = eventOutput.X; myY = eventOutput.Y;}

or they can be referenced directly in any attribute expression as needed, as in the following action definition:

item summarizeAsNeeded extends BaseAction { actions = eventOutput.X > 10 && eventOutput .Y > 20 ? ["doSummary"] : [];}

Finally, the event item attributes can be referenced directly by a Velocity template in order to generate a custom SQL expression or a detailedmessage that is emailed to someone, to name a few examples.

Event Handler Input Parameters

In addition to the event items described above, the event handler transaction can use it's own set of input parameters to control processing. Inputparameters for the event handler transaction are specified when the event handler is registered using the add-listener transaction. Specifically, anyinput parameter defined for the add-listener transaction of the form TxInputXXXX will be provided to the event handler transaction as the input.XXXX

attribute whenever it is executed. For example, if the add-listener transaction is executed with the following input parameters:

TxFilter = ".*"TxName = "eventMgr/handler/genAlarm.tdf"TxInputMode = "ONFAILURE"TxInputErrorCode = "s915"AddrType = "NONE"ReceiveFailures = "true"

then the genAlarm transaction will be executed for every transaction event, with the following input parameters:

Mode = "ONFAILURE"ErrorCode = "s915"

In this case, the genAlarm transaction processes only failed transaction events based on the Mode input parameter and uses an error code of "s915"whenever an alarm is generated based on the ErrorCode input parameter.

The exact number and meaning of event handler transaction input parameters depends on the implementation ofeach event handler transaction. Generally, event handler transactions should be designed to use default valuesfor all expected inputs, but the client application is ultimately responsible for specifying the appropriate event

Page 106: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

106 of 150 5/11/2007 10:14 AM

handler input parameters for the process being performed.

Event Handler Processing Context

When the event handler transaction is executed by the Event Manager, it will be executed using the Client ID, Username and Password that wereprovided when the event handler transaction was registered. This allows more-privileged users to register event handler transactions that processtransaction events generated by less-privileged users. For example, a "Supervisor" level event handler transaction may be registered to approve aspecific change after two other "Operator" level transactions have been executed.

Since event handler transactions are executed directly by the Event Manager, there are no HTTP request or response objects associated with them.Consequently, when the event handler transaction is executed, the "request" and "response" items that are normally defined for every transactionwill only contain a subset of the normal request and response information. Specifically, the "request" item will contain a copy of the attributes fromthe HTTP request the generated the transaction event, except for the user related properties as stated above.

Since no HTTP response is associated with an event handler transaction, no transaction response (either template-based or action-based) isgenerated for the event handler transaction. Any error generated by the transaction will be recorded by the Transaction Manager in the trans.log logfile and by the Event Manager in the event.log log file.

Event Listeners that need to generate output should either do so directly by executing an appropriate action inthe Event Handler Transaction (e.g., ShellAction, LogAction, DeliveryAction, etc.) or specify an appropriatedelivery address and format in the listener registration.

Event Handler Initialization

It is often desirable to register one or more event handler transactions when the Skipjack Server is started, allowing them to process all eventsgenerated while the server is running. This can be easily accomplished using the mechanism provided by the Process Manager.

Event Delivery

Independent of any Event Handler Transaction processing performed for a given event, the event can be delivered to a user or client application at agiven address specified using the AddrType input parameters of the eventMgr/add-listener.tdf transaction. The AddrType parameter defines the type of delivery mechanism to be used and other address-specific parameters are used to define the delivery address itself.

TCP Event Delivery

Page 107: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

107 of 150 5/11/2007 10:14 AM

When the 'TCP' address type is specified in a listener registration, the Event Worker will attempt to connect to a given IP address and port in orderto deliver the event, based on the Host and Port registration parameters. If a successful connection is made, the Event Worker will format the eventbased on the OutputType and OutputFormat attributes and will send the resulting output stream to the Event Listener via the connection. After the outputhas been sent, the Event Worker shuts down the TCP connection.

If an error occurs at any time during the delivery process, the RemoveOnFailure is used to determine if the listener registration should be retained orremoved.

PROXY Event Delivery

There are times when the 'connection-per-event' approach used for 'TCP' delivery is not appropriate, either because of excessive network overheadcaused by too many connections or because security constraints prevent the server from connecting to the client (which is the case for Java appletsrunning inside of a browser). To support these situations, the 'PROXY' address type can be used to create a Proxy Listener that resides on the server and maintains a single open connection to the client, over which all Transaction Events are sent, as depicted by the following diagram:

When the eventMgr/add-listener.tdf transaction is executed, it creates a new server thread, called the Proxy Listener, that opens a TCP Server Socket andstores the corresponding port in the Transaction Response that is returned for the add-listener.tdf transaction. The Proxy Listener then waits for aconnection from the Transaction Listener application (the reverse of the approach described above). When the Proxy Listener receives aTransaction Event for delivery from an Event Worker, it relays it to the Event Listener application over the open connection.

When registering a proxy listener, the MaxWait parameter can be used to specify the maximum time period in seconds that the Proxy Listener willwait for a connection from the Event Listener before aborting the process.

Custom Event Delivery

Page 108: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

108 of 150 5/11/2007 10:14 AM

The TxFilter

parameter provides the basic mechanism for specifying by name the transaction events that are desired by a given listener. However, in addition tothat filtering, an event handler transaction can be used for customized or more advanced event transaction filtering. Specifically, if the eventhandler transaction determines that the given event should not be delivered to the listener, then it need only set the tx.abortEvent attribute to true to abort event delivery.

For example, the following event handler transaction aborts delivery if the user who generated the transaction event is not "fred":

item abortEvent extends ComputeAction { preCondition = eventRequest.RemoteUser != "fred"; _destItem = "tx"; abortEvent = true;}

item main extends BaseAction { actions = ["abortEvent"];}

In this case, a preCondition is used to determine if the tx.abortEvent flag should be set to true to abort delivery of the event. Alternatively, the eventhandler transaction can simply throw an error, using an ErrorAction or main.preErrorCheck, which will also abort event delivery, as in the followingexample:

item main extends NOP { preErrorCheck = [ (eventRequest.RemoteUser != "fred", guiStatus.InvalidPara meter, "The Event Was Not Ge nerated By Fred") ];}

The only difference between this approach and the previous one is that the error is appended to the event log, whereas the use of the tx.abortEvent flag aborts the event delivery without recording any log information.

Event Formatting

Whenever an event is delivered to an Event Listener, the Event Worker formats the event in the manner specified by the OutputType and OutputFormat

attributes defined in the listener registration. This allows different applications to receive the same event in whatever format is convenient for thatapplication.

If the OutputType

is 'template/map', then the "input", "output", and "tx" event items will be encoded using the TransMapResponse class, which generates an ASCIIencoding of scalar values, lists and tables. This is useful for applications that want to perform additional processing based on the transaction item

Page 109: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

109 of 150 5/11/2007 10:14 AM

attributes and are using one of the Skipjack Client libraries discussed below.

If the OutputType is 'template/file', then the OutputFormat attribute is interpreted as the name of a Velocity template which is used to format theTransaction Event output stream. This is commonly used by applications that are generating event reports or that require a standard output format.

If the OutputType is 'template/string', then the OutputFormat attribute is processed directly by Velocity as the template expression used to format theTransaction Event output stream. This allows applications to specify custom event formatting templates.

If an Event Handler Transaction is specified for a given listener then the "input", "output", and "tx" items of the Event Handler Transaction are used for output formatting, not the corresponding items from the originaltransaction event. This allows Event Handler Transactions to generate appropriate values as needed. If the itemsfrom the original event are required for output formatting, then either the output template should referenced the"eventInput", "eventOutput" and "eventTx" items or the Event Handler Transaction should copy the necessaryitem attributes into its own "input", "output" and/or "tx" items.

Removing Listener Registrations

The following transactions are provided to remove one or more event listener registrations associated with a given Event Listener:

eventMgr/remove-listener.tdfRemoves all registrations that are associated with the current clientID and that match the given filter criteria and deliveryaddress.

eventMgr/remove-client.tdfRemoves all registrations that are associated with the current clientID. Normally, this transaction is executed when the EventListener is being terminated, cleanly removing all associated registrations.

Note, in all cases, the clientID associated with the Event Listener application is used to identify the corresponding listeners. Therefore, it is importantfor applications to use the same clientID when adding and removing listeners. By default, the Java, Perl and C++ Client Packages adhere to this approach.

Java Event Listener Support

Page 110: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

110 of 150 5/11/2007 10:14 AM

The TransactionMonitor class (provided as part of the Java Client Package) implements a background thread that monitors transactions executed bythe Skipjack Server and supports a collection of methods that allow client applications to easily register event listeners and process events as theyare received. When a Transaction Event is received by the TransactionMonitor it is automatically converted into a Transaction object and passed toone or more TransactionObserver objects that have been registered with the TransactionMonitor. The TransactionMonitor object isolates the clientapplication from all of the network and encoding tasks required to monitor one or more transactions executed on a given Skipjack Server.

For example, the following Java application uses the TransactionMonitor to print the transaction identifier for every transaction that is executed fora period of two minutes.

import navius.skipjack.client.*;import navius.toolkit.util.*;import org.apache.log4j.*;

public class SimpleMonitor implements TransactionOb server{

public void transactionCompleted (Transaction tx){ System.out.println ("Tx = "+tx.getResultStr ing("tx.identifier"));}

public static void main (String[] args){ try { BasicConfigurator.configure();

TransactionMonitor tm = new Transac tionMonitor ("tm.cfg"); SimpleMonitor sm = new SimpleM onitor();

tm.addObserver (sm); tm.start();

tm.addEventRequest (".*");

Thread.sleep(120000);

} catch (Exception e) { e.printStackTrace(); }}

} // End of Class

The main method begins by initializing the Log4j properties using the BasicConfigurator, which is used internally by the TransactionMonitor for debuggeneration. It then creates a TransactionMonitor object, based on the "tm.cfg" configuration file, which is defined as follows:

_debugEnabled: false_transMapDebug: false_serverURL: http://localhost:8080/_authInfo: test:PASSWORD_clientID: test.SM_useProxy: false

Page 111: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

111 of 150 5/11/2007 10:14 AM

RemoveOnRestart: trueRemoveOnFailure: trueReceiveFromSelf: true

The "tm.cfg" file specifies the server to be monitored, along with the authentication information needed. It also defines the listener registrationparameters that are used when each addEventRequest() method is executed.

The SimpleMonitor class implements the TransactionObserver interface, which allows it to be added as an observer of the TransactionMonitor object.In this case, it simply prints the transaction identifier when each transaction event is received.

C++ Event Listener Support

The C++ Client Package does not provide a TransactionMonitor class similar to that provided by the Java Client Package. Therefore, if C++client applications need to listen to transaction events, they must create their own TCP socket to receive those events and manage them accordingly.However, once a connection has been made to the TCP socket, the client can execute the Transaction::loadResultMap() method to process thetransaction/map data stream that is sent for every transaction event. The loadResultMap() method accepts a file/socket descriptor and reads in all of thedata until the end of the file or the end of the transaction/map data is found. After the loadResultMap() method has completed, the client application canaccess any or all of the results defined for the received transaction event using the getResultXXX() methods.

The loadResultMap() method does not automatically clear the result map prior to processing the new results. Thisallows it to be used to accumulate results from multiple transaction events as needed. If the client applicationdoes not want the results from different transaction events to be merged, it should clear the result map beforecalling the loadResultMap() method.

Event Monitor Java Applet

The eventMgr/event-monitor.tdf transaction executes a Java applet in the browser that displays event information based on a set of user configurableparameters. By default, it listens for all events and uses the eventMgr/event-summary.vm template to display a line of information for each event received.The Event Monitor is based on the TransactionApplet class which provides a convenient mechanism for generating a scrolling output list based ontransaction events. The Event Monitor uses the template formatting feature supported by the Event Manager to format the event information on theserver, allowing the TransactionApplet to simply copy the output received into a text display. This keeps the client code relatively simple, whilestill providing flexible formatting.

Event Table HTML Display

Page 112: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

112 of 150 5/11/2007 10:14 AM

The eventMgr/show-table.tdf

transaction can be used to display the current contents of the Event Listener Table in a browser for trouble-shooting purposes. The display showsthe ListenerID, ClientID, Address and Criteria associated with each active listener.

Event Log File

The Event Manager generates log information that is stored in the $SKIPJACK_HOME/logs/event.log. The event log shows listener registration activities,event processing activities and proxy activities based on the debug settings defined in the Event Manager Configuration File.

Event Manager Configuration File

The $SKIPJACK_HOME/app/WEB-INF/event.cfg configuration controls various aspects of the Event Manager, including debug generation, thread activity andthe database table and fields used to store listener registrations. By default, most debug output is disabled.

Page 113: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

113 of 150 5/11/2007 10:14 AM

Skipjack Server

Application Development Guide

Section 12: Process Manager

5 October 2002

The Process Manageris an internal component of the Skipjack Server that performs a set of functions primarily concerned with initializing server applications andmanaging background threads created for various purposes. Specifically, the Process Manager provides the following services:

registers Transaction Event Handlers for one or more applications when the server is started,executes Startup Transactions for one or more applications when the server is started,maintains a server-wide Process Table that can be used to monitor and/or terminate background server threads.

Process Definition Files

The Process Manager is responsible for performing all application-specific startup processing whenever the Skipjack Server is started. Thisprovides a convenient mechanism for all application initialization and a single point of control for server initialization. The Process Managerdetermines the startup processing to be performed by processing all of the Process Definition Files found in a directory specified in the ProcessManager's configuration file (see Process Manager Configuration below for configuration details).

Each Process Definition File can specify one or more of the following types of items:

Event Handler ItemsTransaction Items

to define the startup processing needed by a given application. Usually, a single Process Definition File suffices for a given application, but anynumber of Process Definition Files can be specified for a given application or group of applications, and each Process Definition File can defineany number of event handler transactions. No restrictions are placed on the specific distribution of event handler definitions across the collection ofProcess Definition Files, allowing application developers to organize them as needed.

Event Handler Items

As described in the Event Listening section, one or more Event Handler Transactions can be registered to process a given set of transaction events. Event

Page 114: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

114 of 150 5/11/2007 10:14 AM

handler transactions can be used for a wide range of application purposes, including application-level logging, database maintenance, operatornotification, and application process constraints, to name a few. In many cases, such event handler transactions need to be registered when theSkipjack Server is started, thereby allowing them to process all transaction events whenever the server is running. This is easily done by specifyingone or more Event Handler Items in a Process Definition File.

Each Process Definition File can define one or more Event Handler Items that are referenced by name in the main.processList attribute. For every itemname found in that list, the Process Manager will register a Transaction Event Handler using the eventMgr/add-listener.tdf transaction based on theattributes defined in the Event Handler Item. That is, each event handler is specified as an item that defines a set of input parameters for theeventMgr/add-listener.tdf transaction, with the following attributes supported:

Attribute DescriptionTxFilter Defines one or more GNU regular expressions that are applied to the transaction

identifier of each transaction event. If a match is found, the event listener isexecuted for that transaction.

TxName If defined, this attribute specifies the event handler transaction to be executedwhenever an event is processed. See the EventHandler class for more details.

AddrType If defined, this attribute specifies the address to which the event should be sent.If the AddrType attribute is not defined, it will be set to "NONE". See theEventAddress class for more details.

_clientID If the _clientID attribute is defined, it will be used as the client ID when the eventhandler transaction is registered and subsequently executed. Otherwise, thedefault client ID specified in the process.cfg configuration file will be used.

_authInfo If the _authInfo attribute is defined, it will be used as the username and passwordwhen the event handler transaction is registered and subsequently executed.Otherwise, the default authentication information specified in the process.cfg

configuration file will be used.Other Attributes

All attributes defined in the item that do not start with an underscore are copiedinto the input item when the eventMgr/add-listener.tdf transaction is executed,allowing arbitrary parameters to be passed to that transaction.

For example, the following Process Definition File defines two process items, which specify a total of five event handler transactions:

item notifyProcess { TxName = "myapp/notifyOperator.tdf"; TxFilter = [ "myapp/addUser", "myapp/delUser" ];}

Page 115: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

115 of 150 5/11/2007 10:14 AM

item accountProcess { TxName = "accounting/logActivty.tdf"; TxFilter = [ "accounting/.*Credit", "accounting/.*Debit", "accounting/Deduction" ];}

item main { processList = ["notifyProcess", "accountPro cess"];}

The notifyProcess process item specifies that the myapp/notifyOperater.tdf transaction should be executed whenever the myapp/addUser or myapp/delUser

transaction events are generated. The notifyOperator transaction could send an email message to a list of subscribers, possibly defined in the database,or could record the event activity in an application-level log table or file.

The accountProcess process item specifies that the accounting/logActivity.tdf transaction should be executed whenever any accounting transaction endingwith "Credit" or "Debit" generates an event, or when the accounting/Deduction transaction event is generated.

The TxFilter attribute uses GNU Regular Expressions to specify matching criteria for transaction eventidentifiers.

Transaction Items

Each Process Definition File can define a list of transaction items as the main.startupList attribute to be executed when the Process Manager isinitialized. Such transactions can be used for the initialization of application data structures, to log initial server information or any other serverinitialization purpose.

Each Transaction Item specifies the name of the transaction to be executed, the meta information needed to execute the transaction and all inputparameters for the transaction. In addition, each transaction item can specify one or more error checks, with associated error messages, that can beused to verify the correctness of the transaction output. Specifically, the following transaction item attributes are supported:

Attribute Description_transName The _transName attribute specifies the identifier of the transaction to be executed._clientID If the _clientID attribute is defined, it will be used as the client ID when the

transaction is executed. Otherwise, the default client ID specified in theprocess.cfg configuration file will be used.

Page 116: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

116 of 150 5/11/2007 10:14 AM

_authInfo If the _authInfo attribute is defined, it will be used as the username and passwordwhen the transaction is executed. Otherwise, the default authenticationinformation specified in the process.cfg configuration file will be used.

Other Attributes

All attributes defined in the item that do not start with an underscore are passedalong as input parameters when the transaction is executed.

For example, the following Transaction Items could be added to the previous Process Definition file to execute an initialization transaction andsend an alarm to the operator when the server is restarted:

item notifyProcess { TxName = "myapp/notifyOperator.tdf"; TxFilter = [ "myapp/addUser", "myapp/delUser" ];}

item accountProcess { TxName = "accounting/logActivty.tdf"; TxFilter = [ "accounting/.*Credit", "accounting/.*Debit", "accounting/Deduction" ];}

item myInit { _transName = "myapp/initialize.tdf"; Param1 = "try this"; Param2 = 12;}

item genAlert { _transName = "alarmMgr/insert.tdf"; Severity = "ALERT"; Message = "Server Restarted";}

item main { processList = ["notifyProcess", "accountPro cess"];

startupList = ["myInit", "genAlert"];}

Process Table

All threads that are dynamically created by server applications (including all background actions and startup processing threads) are registered inthe Process Tablethat is maintained internally by the Process Manager. The Process Table can be used by operators and developers to monitor internal thread activity.

Page 117: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

117 of 150 5/11/2007 10:14 AM

The Process Table can also be used to manually terminate a thread that may not be working properly or that otherwise isn't needed anymore.

The Process Table can be viewed by executing the processMgr/show-table.tdf transaction. When viewed in a browser, the table will be displayed as anHTML table, with one line per internal thread. Each thread is assigned a unique PID which can be used to track the thread over time. The PID canalso be used to kill a thread using the processMgr/kill-process.tdf transaction. As a convenience, the HTML Process Table display includes a "delete"button on each row which can be used to kill the thread represented by that row.

Threads registered in the Process Table should not normally be terminated manually, since they areautomatically terminated when there work is done. The ability to kill a thread registered in the Process Table isprovided primarily for advanced trouble-shooting purposes and should only be used by experienced operators.

The HTML Process Table display also provides a "Reload" button that may be used to reload all Process Definition Files defined in the ProcessManager configuration directory. This is provided primarily for developers working on Process Definition Files so that they can be tested withoutrestarting the server.

Process Observers

External applications and applets can monitor the progress of any Skipjack process by registering an Event Listener using a transaction filter of"processTable/PID", where PID is the numeric ID associated with the process being monitored. After such a listener is registered, whenever the processtable entry associated with the given process is added, modified or removed, the process observer will be notified.

The navius.skipjack.client.ProcessObserver applet provides a convenient mechanism for monitoring one or more processes within an HTML page. Bydefault, when all of the processes being monitored have been removed from the process table, then the browser will branch to a given URL.Generally, such a URL would then check to ensure that the process was successful or not, displaying an appropriate next page. The ProcessObserver

applet can also be used to automatically kill the processes being monitored if the user leaves or overwrites the current page.

See Event Listening for more details and examples about event handlers and listeners in Skipjack.

Process Manager Configuration

The Process Manager is controlled by the process.cfg configuration file which is located in the $SKIPJACK/app/WEB-INF/conf directory, where $SKIPJACK is the runtime directory for the Skipjack Server. The process.cfg file is updated automatically by the Skipjack configuration and installation scripts, andshould not normally be updated manually.

The processDir property that is defined in the process.cfg configuration file specifies the directory to be processed by the Process Manager when the

Page 118: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

118 of 150 5/11/2007 10:14 AM

Skipjack Server is started. All files ending in ".gdf" that are located in the directory will be processed as Process Definition Files. By default, thedirectory is defined to be $SKIPJACK/app/WEB-INF/process where $SKIPJACK is the Skipjack runtime directory. Application installation scripts need onlycopy Process Definition Files into that directory to have the corresponding event handlers registered when the server is started again.

The standard $SKIPJACK/bin/CopyApp.pl application installation script automatically copies all files found in theprocess sub-directory of the application installation directory to the appropriate server runtime directory.

Among the configuration variables specified in the process.cfg file are the default client ID and user authentication information that are used whenregistering and executing all event handler transactions. In most situations, the default configuration settings are sufficient for all event handlertransactions. However, in some cases, it is necessary to use a different client ID, username or password to ensure that the event handler transactionworks properly or can be more easily tracked in the server logs. In such cases, specific information can be defined using the _clientID and _authInfo

attributes in a given process item. For example, the following definition:

item notifyProcess { TxName = "myapp/notifyOperator.tdf"; TxFilter = [ "myapp/addUser", "myapp/delUser" ];

_clientID = "NotifyProcess"; _authInfo = "notifier:mypassword";}

overrides the default client ID and authentication information for the notifyOperator event handler transaction. That is, when that event handler isregistered and executed, it will be assigned a client ID of "NotifyProcess" and will use the username of "notify" and a password of "mypassword".

The process.cfg file also specifies the default settings for the RemoveOnRestart, RemoveOnFailure and ReceiveFromSelf attributes that are accepted by theeventMgr/add-listener

transaction. The default settings have been chosen to be consistent with the way the Process Manager operates and should not need to be adjustedor customized for a given event handler.

Page 119: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

119 of 150 5/11/2007 10:14 AM

Skipjack Server

Application Development Guide

Section 13: Session Management

5 October 2002

Skipjack supports the use of "sessions" to automatically track the activities of a user. Sessions are automatically maintained by the browser and theTomcat server (in which Skipjack resides), using a number of standard client/server information storage techniques. Session information can beread or written by any transaction processed during the client session through the session item. Transaction authors are free to use or update any ofthe session information as needed to perform any session-based task.

Session Item

The session item is automatically created when using login forms (see Custom Login Forms for more details) or can be created by any transactionthat needs to maintain client information across multiple transactions in the same session.

If a session exists when an HTTP request is made, it will appear as an HttpSession object associated with that request when it is processed by theSkipjack Server. In such cases, the Skipjack Server will automatically create the session item and will assign a reference to the HttpSession object to the session.object attribute. Furthermore, it will copy all HttpSession attributes into the session item. Transactions can access any of the session attributessimply by referencing the session item attributes.

If a transaction defines the session item in the transaction definition file or modifies the session item during the execution of the transaction, thenany attributes defined for that item will be stored in the HttpSession object when transaction processing has been completed. If the session is defined, but no HttpSession object currently exists, a new HttpSession object will be created and associated with the current client session. This allowstransactions to pass information from one transaction to another as the user travels around the site.

Since the transaction definition file is processed before the HttpSession object, any session item attributes definedin the transaction definition file itself will be overwritten by HttpSession attributes with the same name.Transaction authors should use the ComputeAction to dynamically update session parameters sometime duringtransaction processing to ensure that those values will be assigned to the session when the transactionprocessing is completed.

For example, the following transaction demonstrates how a session value can be modified:

Page 120: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

120 of 150 5/11/2007 10:14 AM

//// test/sessionTest.tdf//include "skipjack-common.tdf"

item session { curValue = 0;}

item updateSession extends ComputeAction { _destItem = "session"; curValue = integer(session.curValue) + 10; curTime = date("now");}

item main extends BaseAction { actions = ["updateSession"]; templateName = "sessionTest.vm";}

The first time the transaction is executed during a browser session, a new session object will be created, with the curValue attribute set to 0. Then,when the updateSession action is executed, the curValue session attribute will be incremented by 10 and the curTime session attribute will be set to thecurrent date and time. Every time that the transaction is subsequently executed during the browser session, the curValue attribute will be incrementedand returned to the browser.

Keep in mind, even though the transaction definition always sets the session.curValue attribute to zero in the previous example, that value is overwritten by the current value defined in the session object provided by theclient, if any. That is, the session item values defined in the transaction definition file are the initial values used whenever a session is created. The ComputeAction should be used update session values for existing sessions.

Session Timeout

The information stored in a session item can be automatically erased if the user does not perform any session activity in a certain time period. Thedefault session inactivity timeout value can be specified in the $SKIPJACK_HOME/app/WEB-INF/conf/transaction.cfg file by the sessionTimeout property (in seconds), which is configured for a default value of 604,800 seconds (ie. 7 days). If a negative value is specified, then sessions will not timeout.

In addition to the default timeout setting, any transaction can modify the timeout value for the current session by setting the _timeout attribute of thesession

item. When the transaction response is generated, any value specified by that attribute will be used as the timeout value for the session. If a negativevalue is specified, the session will not timeout.

Page 121: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

121 of 150 5/11/2007 10:14 AM

Session Invalidation

There are times when a transaction author needs to immediately invalidate a session. For example, the application may require the user to "logout"in order to safeguard information or the user may want to "empty" their shopping cart. In such cases the _invalidate attribute of the session item can be used. If that attribute is set to "true", then the session will be invalidated when the transaction response is generated. Any subsequent access madeby the user will cause a new session to be created.

For example, the following transaction causes the current user session to be invalidated:

//// test/formLogin/logout.tdf//include "skipjack-common.tdf"

item session { _invalidate = true;}

item main extends BaseAction { actions = []; successMsg = "You Have Been Logged Out Of Your Current Session"; templateName = "/COMMON/tx-success.vm";}

Notice that no actions are actually performed by this transaction, only the session._invalidate is set to "true", which causes the current session to beinvalidated.

If the current session was created as the result of a forms-based login screen and it is invalidated, then when theuser attempts to execute another transaction the login form will automatically appear again, requiring them toprovide their username and password.

Session Debugging

Session debugging is enabled for a given transaction by setting the debug.sessionDebug attribute to "true", as in the following example:

item debug { sessionDebug = true;}

When session debugging is enabled, the incoming and outgoing value of all session attributes will be logged in the $SKIPJACK_HOME/logs/trans.log file.See Debug Management for server-wide debug management techniques.

Page 122: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

122 of 150 5/11/2007 10:14 AM

Skipjack Server

Application Development Guide

Section 14: Data Importing

5 October 2002

The Skipjack Server provides a flexible mechanism for importing data in various formats from various sources using the ImportAction. This sectiondescribes the features provided by that action and shows examples of how it can be used for various importing tasks.

Import Processing Phases

All imported data is processed by the ImportAction as an ASCII data stream containing one or more records, which consist of one or more fields. Datastream processing is broken into distinct phases: data stream access, record parsing, record validation and record processing.

The access phase determines where and how the data stream is to be accessed. During the record parsing phase, the data stream is broken into oneor more records, containing one or more fields. Each record found is then validated against a given schema and a list of business rules. Finally, therecord is processed by transaction. The ImportAction provides mechanisms for each of these processing phases that are controlled by a small set ofitems and attributes.

Data Stream Access

The inputType attribute is used to determine how to access the desired data stream, with the following types currently supported:

FILEA file in the server's local file system, designated by the fileInputFile attribute, is used as the data stream. If the filename starts with '/', then itwill be treated as an absolute filename. Otherwise, the directory containing the current transaction will be prepended to the specified file path.

FTPThe data stream file will be accessed using FTP from any server accessible on the network, using the following attributes:

Attribute Description

ftpInputHost host name or IP Address

Page 123: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

123 of 150 5/11/2007 10:14 AM

ftpInputPort IP port (default = 21)

ftpInputUsername FTP account username

ftpInputPassword FTP account password

ftpInputMode binary or ascii (default = binary)

ftpInputFile remote file path

If the file path specified by the ftpInputFile attribute starts with '/', then it will be treated as an absolute path on the remote file system.Otherwise, the file path will be treated as a path relative to the default directory for the remote user specified by the ftpInputUsername attribute.

VELOCITYThe data stream is generated by the Velocity template engine, using the template specified by the velocityTemplate attribute and the currenttransaction state.

Record Parsing

The parseType attribute is used to determine how the data stream should be broken into records and fields, with the following types supported:

DELIMITEDThe data stream is broken into records based on the following attributes:

Attribute Description Default ValuedelimRecord Delimiter used between records, consisting of one or more characters. \n (newline)delimField Delimiter used between fields within a record, consisting of one or more characters. If the

keyword "FIXED_WIDTH" is specified then all records are assumed to contain fixedwidth fields as defined by the fieldWidths attribute of each record definition item (discussedbelow).

| (pipe)

delimComment Delimiter used to denote the start of a comment, consisting of one or more characters. Allcharacters following a comment delimiter will be ignored up to the next record delimiter.

// (double-slash)

delimEscape Delimiter used to escape another delimiter, consisting of one or more characters. Anycharacter following the escape delimiter will not be considered as part of anotherdelimiter.

\ (back-slash)

delimTrim If true, then leading and trailing whitespace for all fields will be removed. true

Page 124: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

124 of 150 5/11/2007 10:14 AM

Additional parse types will be supported in the future.

Record Validation

To support the validation of heterogeneous record formats defined in the same file, the recordMap attribute is used to specify the names of one ormore record definition items that determine how each record should be validated, processed and stored for further processing.

Each record definition item may specify the following attributes:

acceptExprschemaNameactionsfieldWidths

For every record found in the data record stream, the following processing will be performed for every record definition item defined in therecordMap list:

A temporary item named curRecord will be created using the attributes defined by the schema item referenced by the schemaName attribute, assigning the values found in the current input fields to each attribute. For example, if the schema defines three attributes: A, B and C, thenthe curRecord item will also have three attributes named A, B and C, with values assigned from the input record. Additionally, the RecordType, RecordNumber, RecordString and RecordFile meta attributes will be defined as described below.

If "FIXED_WIDTH" was specified as the delimField value in the import action item, then the fieldWidths attribute must be specified in eachrecord definition item, defining a list of field widths. As each record definition item in the recordMap is processed for a given input record, thefield width list associated with that record definition item will be used to break the record into fields. Otherwise, the field delimiter specifiedby the delimField attribute of the import action item will be used to determine the field values for all record definition items.

1.

The acceptExpr of the record definition item will be evaluated as a boolean value. If it is false, then no further processing of the curRecord willbe performed for the current record definition item. If it is true, then the current record is "accepted" by the current record definition item andno subsequent record definition items will be processed for that record.

2.

If the acceptExpr is true, then the schema action defined by the schemaName attribute will be executed to validate all of the attributes in thecurRecord item. If a validation exception is thrown, then no further processing will be performed for the current record definition item.

3.

If schema validation was successful, then all of the actions defined in the actions list (if any) will be performed. Each action can reference thecurRecord

4.

Page 125: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

125 of 150 5/11/2007 10:14 AM

as needed to perform additional validation or custom data conversion. If any of the actions throws an exception, then no further processingwill be performed for the current record definition item.

If the curRecord is accepted by a record definition item, the schema validation was successful and the actions list was successfully executed, then thecurRecord is appended to the Table object specified by the _destItem and _destTable attributes of the record definition item. If those attributes are notdefined, the record definition item itself will be used as the value of the _destItem attribute and "table" will be used as the value of _destTable attribute.

If the curRecord

is not accepted by any record definition item or an exception is thrown during schema validation or action list processing, then an error entry willbe added to a Table object that is stored as the value of the errorTable attribute of the import action item itself.

Record Table Format

All of the Table objects used to store records that have been accepted by a given record definition item will have column names defined accordingto the schema referenced by the schemaName attribute of that record definition item. For example, if the validation schema defines three attributes, A,B and C, then the Table object will have three columns named A, B and C. Each row in the table will consist of one of the records that wasaccepted by the record definition item.

In addition to the attributes defined by the schema, the following meta columns will be defined in the record table:

Column Name Description

RecordFile File that defined the record

RecordNumber Record number in the defining file

RecordString Record definition string from the file

RecordType Name of the record definition item that accepted the record

The meta columns can be used by the transaction for subsequent record processing as needed.

Error Table Format

If a record is not accepted by any record definition item or a validation or processing errored occurred, then an entry is appended to the Table objectstored as the errorTable attribute of the import action item. The errorTable is automatically created by the import action item prior to processing anyrecords. Applications should check the size of that table after import action processing has been completed to determine if any errors weregenerated during the import process.

Page 126: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

126 of 150 5/11/2007 10:14 AM

Unlike most actions, the ImportAction does not automatically cause the transaction to abort as soon as anexception is raised. Rather, all exceptions raised while processing records are captured and stored in theerrorTable, thereby allowing transactions to deal with each error individually if necessary.

The error table consists of all of the meta columns defined above, as well as the following error columns:

Column Name Description

ErrorStatus Value of the tx.status attribute at the time the error was generated

ErrorMessage Value of the tx.errorMsg attribute at the time the error was generated or the message string of any exception that wasthrown

Record Processing

All of records imported using the ImportAction can be processed either by specifying a list of one or more actions for the actions attribute of each record definition item or by executing transactions after the ImportAction that directly access the record tables. In either case, the transaction author isfree to specify whatever processing is necessary to perform custom validation or record processing.

The only real distinction between an action that is performed as part of the actions list for a record definition item and an action that is performedafter the ImportAction

has completed is how errors are handled. In the former case, any exception that is thrown will automatically cause an entry to be appended to theerror table and the current record to be discarded. In the latter case, the transaction author must handle exceptions themselves.

Record processing actions defined in the actions list of the record definition item also have the benefit of accessing the curRecord item directly, instead of having to access fields in the Table object. Usually, this makes record processing easier to specify.

The curRecord item is appended to the record table associated with a given record definition item after allactions defined in the actions list for that record definition item are executed. Therefore, if any of the actionsalter the contents of the curRecord item (using the ComputeAction for example), then those changes will be stored inthe record table, which may or may not be desirable depending on the application.

Basic Import Example

The ImportAction defined in the skipjack-common.tdf include file is the basis for all import processing. The default attributes for the ImportAction are

Page 127: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

127 of 150 5/11/2007 10:14 AM

defined so that it is relatively easy to extend that action and import a file containing records with the same format. That is, the ImportAction item itself(or any item extended from it) can be used as both the import action item and the record definition item.

For example, consider the following data file:

//// tutorial/dataImport/ex1.dat//Fred Smith|78000|410-555-1212|Bldg 8, Rm 301Sally Jane|84000|410-555-7878Oscar Van-Pelt|87350.56|301-444-1867|Home

In this example, a collection of employee records are being imported from the ex1.dat file from the server's local file system. (Accessing a file usingFTP will be shown in a subsequent example.) Since the data file contains only one type of record, we can combine the import action item and therecord definition item into a single item, as in the following transaction:

//// tutorial/dataImport/ex1.tdf//include "skipjack-common.tdf"

item importData extends ImportAction { inputType = "FILE"; fileInputFile = "ex1.dat"; schemaName = "recordSchema";}

schema recordSchema extends BaseSchema { attrs = [ ("Name", "string", "nonempty"), ("Salary", "double", "nonempty"), ("Phone", "phoneno", "nonempty"), ("Office", "string", "optional") ];}

item recordList { table = importData.table; hiddenFields = ["RecordFile", "RecordNum ber", "RecordString", "RecordT ype"]; borderColor = "black"; borderWidth = 1;}

item main extends BaseAction { actions = ["importData"]; templateName = "ex1.vm";}

The importData action item is defined to perform the import processing, extending the standard ImportAction defined in the skipjack-common.tdf include file. The importData item specifies that the "FILE" input type will be used to access the file and that the recordSchema item will be used to validate allrecords contained in that file.

Page 128: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

128 of 150 5/11/2007 10:14 AM

The ImportAction specifies a parseType of DELIMITED and a set of default delimiters to be used, which suffices forthis example.

The ImportAction specifies a default recordMap list which contains only a reference to itself and a default acceptExpr

equal to "true". This allows the import action item to serve as the record definition item as well.

When the importData action is executed by the main action, it accesses the designated file and parses it using the designated delimiters. For eachrecord found, the recordSchema item is used to validate the record. The recordSchema item requires the record to contain the Name, Salary and Phoneattributes, with an optional Office attribute. If record validation is successful, that record will be added to the importData.table record table. Otherwise,an error entry will be added to the importData.errorTable error table.

The item used to store the record and error tables can be changed in this example by specifying theimportData._destItem attribute.

In this example, all of the records are valid and are stored in the importData.table record table. The recordList item references that table so that thelistShow() macro in the ex1.vm template can display the table of records.

#### tutorial/dataImport/ex1.vm###htmlPageHeader("Data Import Example 1")<center>#listShow($recordList)</center>#htmlPageFooter()

Note how the hiddenFields attribute is used to hide the meta table columns when the table is displayed. (The output can be seen at Data Import Example 1 if you are viewing this documentation directly from a Skipjack Server.)

FTP Import Example

Data files can be imported from different data sources simply by modifying a few attributes in the importData action. For example, if the data fileprocessed in the previous example was located on a remote server, then the following modifications would suffice:

item importData extends ImportAction { inputType = "FTP"; ftpInputHost = "myServer"; ftpInputUsername = "myName";

Page 129: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

129 of 150 5/11/2007 10:14 AM

ftpInputPassword = "myPassword"; ftpInputFile = "ex1.dat"; schemaName = "recordSchema";}

Fixed Width Fields

Consider the data file from the previous example formatted using fixed width fields, as in the following example:

//// tutorial/dataImport/ex5.dat//Fred Smith 78000 410-555-1212Bldg 8, Rm 301 / /ENDSally Jane 84000 410-555-7878//ENDOscar Van-Pelt87350.56301-444-1867Home / /END

In this case, there is no field delimiter used to separate the field values, only a predefined width for each field. To accomplish such import parsing,the delimField attribute should be defined as "FIXED_WIDTH" and the fieldWidths attribute should be defined as a list of integer field widths, asfollows:

item importData extends ImportAction { inputType = "FILE"; fileInputFile = "ex5.dat"; schemaName = "recordSchema"; delimField = "FIXED_WIDTH"; fieldWidths = [14, 8, 12, 16];}

With only these modifications, the fixed width import file can be processed as in the previous example.

Custom Validation Example

The schema item provides a set of attribute types that can be used to specify the syntax of the values expected. Semantic validation, however, isintrinsically dependent on the task being performed, requiring custom expressions and processing to be written.

Schema Post Error Checks

The easiest way to specify custom validation criteria, and the associated error messages, is to define them using the postErrorCheck list attribute of therecord schema item. For example, consider the following modification to the schema item from the previous example:

Page 130: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

130 of 150 5/11/2007 10:14 AM

//// tutorial/dataImport/ex2.tdf//schema recordSchema extends BaseSchema { attrs = [ ("Name", "string", "nonempty"), ("Salary", "double", "nonempty"), ("Phone", "phoneno", "nonempty"), ("Office", "string", "optional") ];

postErrorCheck = [ (curRecord.Salary < 80000, guiStatus.InvalidParameter, "The Salary Field In Record #" + curRecord.RecordNumber + " From The Import File " + curRecord.RecordFile + " Is Too Small, Give " + curRecord.Name + " A Raise."),

(curRecord.Phone->startsWith("410") == false, guiStatus.InvalidParameter, "Invalid Area Code") ];

}

In this case, two error checks are performed based on various fields in the curRecord item. Specifically, an error is generated for a given record if theSalary field is less than 80,000 or the Phone field does not begin with the 410 area code.

If an error is generated by the postErrorCheck criteria for a given record, then the resulting error status and error message will be appended to theimportData.errorTable error table and the record will not be added to the importData.table record table.

Note how the curRecord meta fields are used to generate a very specific salary error message. Usually, when morespecific information is provided in error messages it is easier to resolve the problem.

Custom Validation Actions

Although the postErrorCheck list of the schema action is convenient for checking many types of error conditions, there are times when additionalprocessing must be performed in order to validate a record. For example, the application may require that the employee name specified in the Name

field already exist in the Employee table in the database. In that case, we may need to execute a SQLRecordAction to verify the value in the Name field, as in the following example:

item importData extends ImportAction { inputType = "FILE"; fileInputFile = "ex1.dat"; schemaName = "recordSchema"; actions = ["checkName"];}

Page 131: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

131 of 150 5/11/2007 10:14 AM

item checkName extends SQLRecordAction { sqlFile = "checkName.sql"; Name = curRecord.Name; zeroRowsMsg = "Invalid Employee Name '" + Name + "' Found In Record #" + cur Record.RecordNumber; _destItem = "employeeRecord";}

In this case, the checkName SQL action has been defined to validate the Name of each record processed. If the name is invalid, then the error thrownby the checkName action will cause all further processing to be aborted for that record and the error status and message will be appended to theimportData.errorTable error table.

Any number of custom validation actions can be specified in the actions list of the record definition item. Eachaction will be performed in the order given, until all actions have completed successfully or until the first actionthrows an exception. Each action can access the curRecord item as needed to accomplish its task (as well as anyother transaction item defined).

Custom Processing Example

There are no restrictions on the number or type of actions that can be executed while records are being imported. The previous examples showedhow validation processing could be performed, but other types of processing may be done as well. For example, consider the following action listdefinition:

//// tutorial/importData/ex3.tdf//item importData extends ImportAction { inputType = "FILE"; fileInputFile = "ex1.dat"; schemaName = "recordSchema"; actions = ["checkName", "formatSalary" ];}

item checkName extends SQLRecordAction { sqlFile = "checkName.sql"; Name = curRecord.Name; zeroRowsMsg = "Invalid Employee Name '" + Name + "' Found In Record #" + cur Record.RecordNumber; _destItem = "employeeRecord";}

item formatSalary extends ComputeAction { Salary = decimalFormat(curRecord.Sal ary, "$,000.00"); _destItem = "curRecord";}

Page 132: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

132 of 150 5/11/2007 10:14 AM

In this case, the formatSalary action is used to format the value of the Salary field as a money field and store the result in the curRecord item, so that it is subsequently stored in the importData.table data table. Since the formatSalary action is listed after the checkName action in the actions list, it will only beperformed for records that have been successfully validated by both the recordSchema action (including any custom error checks) and the checkName

action.

Similar formatting could be performed by either defining a storage format expression for the Salary attribute (see Input Validation for an example) or by executing the TableFormatAction after all import processing has beencompleted. Each approach has different advantages depending on the application and transaction developerpreferences.

Multi-Record Import Example

If the data file being imported contains two or more different types of records, the recordMap attribute of the import action can be used to specifydifferent record definition items for each record type expected. Each record definition item can specify a different acceptance criteria, validationschema, and set of record processing actions as needed for that type of record. Furthermore, each record definition item can specify a differentrecord table to contain all of the records of that type that have been imported.

Consider a data file that may contain any combination of EMPLOYEE and SUPERVISOR records, as in the following example:

//// tutorial/dataImport/ex4.dat//EMPLOYEE|Fred Smith|78000|410-555-1212|Bldg 8, Rm 3 01EMPLOYEE|Sally Jane|84000|410-555-7878EMPLOYEE|Oscar Van-Pelt|87350.56|301-444-1867|Home//SUPERVISOR|Joe Brown|Dept 3|410-555-8765SUPERVISOR|Alice Summers|Accounting|410-555-2356

Usually, when different records are defined in the same data file they contain one or more fields that are used to determine the appropriate recordtype. In this example, the first field contains the record type, thereby making the acceptance criteria very easy to specify, such as:

item importData extends ImportAction { ... recordMap = ["empDefn", "supDefn"];}

item empDefn { acceptExpr = curRecord.Type == "EMPLOYEE"; ...}

item supDefn {

Page 133: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

133 of 150 5/11/2007 10:14 AM

acceptExpr = curRecord.Type == "SUPERVISOR" ; ...}

The actual field names used for the curRecord item being processed by each record definition item depend on thelist of attributes defined in the corresponding schema. Usually, the record type field is assigned the same namein all schemas to avoid confusion, but that's not a requirement.

Clearly, each record type needs a different schema definition in order to properly name and validate all of the record fields. In this example, thefollowing schema definitions suffice:

item empDefn { acceptExpr = curRecord.Type == "EMPLOYEE"; schemaName = "empSchema"; ...}

schema empSchema extends BaseSchema { attrs = [ ("Type", ["EMPLOYEE"], "nonempty" ), ("Name", "string", "nonempty" ), ("Salary", "double", "nonempty" ), ("Phone", "phoneno", "nonempty" ), ("Office", "string", "optional" ) ];}

item supDefn { acceptExpr = curRecord.Type == "SUPERVISOR" ; schemaName = "supSchema"; ...}

schema supSchema extends BaseSchema { attrs = [ ("Type", ["SUPERVISOR"], "nonempt y"), ("Name", "string", "nonempt y"), ("Dept", "string", "nonempt y"), ("Phone", "phoneno", "nonempt y") ];}

Note how the Type field is defined by each schema, specifying a single enumerated value as a valid input. (In this case, the Type field can never be invalid, because the acceptExpr ensures that only the proper record type is accepted, but that might not always be the case.)

Note also how the schemas define record fields with different types and names, as well as a different number of fields. This allows transactionauthors to process and store records using the most appropriate names and types, instead of having to invent generic field names like "field1","field2", etc.

Since multiple records are being imported, we need to store them in different tables. By default, the resulting data tables are stored as the table

Page 134: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

134 of 150 5/11/2007 10:14 AM

attribute of the corresponding record definition item. In the following example we specify a common results item, with appropriate table names forboth of the data tables:

item empDefn { acceptExpr = curRecord.Type == "EMPLOYEE"; schemaName = "empSchema"; _destItem = "results"; _destTable = "empTable";}

item supDefn { acceptExpr = curRecord.Type == "SUPERVISOR "; schemaName = "supSchema"; _destItem = "results"; _destTable = "supTable";}

Clearly, this example can be expanded to any number of different record types relatively easily.

Page 135: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

135 of 150 5/11/2007 10:14 AM

Skipjack Server

Application Development Guide

Section 15: HTML Form Macros

5 October 2002

In this section we discuss how the standard form macro provided by the Skipjack Server can be used to quickly generate basic input forms. Thevarious features provided the macro are controlled by specifying a Form Definition Item in the transaction definition file, which is referenced whenthe form macro is invoked. This greatly simplifies transaction response templates, while adding all the flexibility that comes from item attributeexpressions and transaction processing.

HTML Form Macro

The HTML Form Macro is defined in the form-macros-01.vm file which resides in the $SKIPJACK/app/WEB-INF/transaction/MACROS runtime directory. Themacro file is loaded automatically whenever the server is started, allowing all transaction templates to use the macro.

The form macro can be invoked from a Velocity template file using the following syntax:

#formShow($defItem $dataItem)

where \$defItem references a Form Definition Item and \$dataItem references a data item that are both defined in the transaction definition file. Theform definition item specifies the display characteristics and behaviors associated with the form, while the data item specifies the initial value forsome or all of the entry fields defined by the form.

For example, consider the following transasction definition file:

//// tutorial/formMacro/simpleForm.tdf//include "skipjack-common.tdf"

item formItem extends FormAction { title = "My Form"; schema = "mySchema"; boxWidth = 400;}

schema mySchema extends BaseSchema { attrs = [

Page 136: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

136 of 150 5/11/2007 10:14 AM

("FirstName", "string", "nonempty" ), ("LastName", "string", "nonempty" ), ("Age", "integer", "nonempty" ), ("Married", "boolean", "default", "yes"), ("State", stateList, "default", ""), ("Zipcode", "zipcode", "nonempty" ) ];

stateList = UnitedStates("ABBR LIST");}

item myInfo { FirstName = "Fred"; LastName = "Smith"; Age = 27; Married = "no"; State = "MD"; Zipcode = "21401";}

item main extends BaseAction { actions = ["formItem"];

templateName = "simpleForm.vm";}

and the corresponding Velocity template file:

#htmlPageHeader("/tutorial/formMacro/simpleForm.tdf ")<center>#formShow($formItem $myInfo)</center>#htmlPageFooter()

The formItem defines a simple form that consists of the given title and one entry field for each of the six attributes defined in the mySchema schema item, with the following output:

Page 137: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

137 of 150 5/11/2007 10:14 AM

The overall width of the form is constrained to be 400 pixels by the formItem.boxWidth attribute and is centered on the page by the <center> HTML tag in the template file. Since the myInfo data item was referenced in the formShow() macro invocation, the attribute values defined in that item will beused to override any default attribute values specified by the schema item.

If the second argument to the formShow() macro is specified as the empty string (""), then the default attributevalues defined in the schema item will be used as the default values for the form fields.

Form Action

The previous example defined the formItem form definition item as an extension of the FormAction action item defined in the skipjack-common.tdf file. TheFormAction

action item defines a default set of attributes for all form items and it performs various form initialization functions when it is executed. As shownin the main item of the previous example:

item main extends BaseAction { actions = ["formItem"];

templateName = "simpleForm.vm";}

the formItem

is executed as part of the main action list. (Usually, form items are executed last, after all other transaction actions have been performed, therebyallowing the form to access all information generated during the transaction.)

Page 138: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

138 of 150 5/11/2007 10:14 AM

If the form definition item is not executed by the transaction then an alert box will be displayed on the user'sbrowser when the transaction response page is loaded indicating that the form definition item was notinitialized properly.

Form Field Labels

By default, the label displayed for every form field is the same as the attribute name defined in the schema referenced by that form. One or more ofthe form field labels can be customized by defining the guiLabel item, as in the following example:

item guiLabel overrides guiLabel { _readonly = true; FirstName = "First Name"; LastName = "Last Name"; Zipcode = "Postal Zip Code";}

Since the guiLabel

item is defined in the standard Skipjack definition files, the "overrides" directive is used to modify that item in the current transaction file. In thiscase, we define three labels by specifying the form field name as an attribute name in the guiLabel item and the form field label as the correspondingattribute value, resulting in the following form being displayed:

The guiLabel item is used by a number of Skipjack features to specify labels for such things as form fields,database table columns and HTML table columns. In general, applications should define a single guiLabel item that defines all of the labels needed for that application and then include that file in all transaction definition

Page 139: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

139 of 150 5/11/2007 10:14 AM

files to maintain consistency across all displays.

Form Display Attribues

The following form definition item attributes are supported to customize the display properties of a form:

Attribute Description

title If defined, the given title is displayed inside of the form border, centered at the top of the form.

instructions If defined, the given set of instructions is displayed at the top of the form, just below the title, if any.

schema If defined, this attribute should reference an item that extends the BaseSchema item, defining all of the input fields to bedisplayed in the form as schema attributes. The type of HTML widget used for each form field will depend on the typeof attribute specified in the schema. See Form Field Types below for more details.

If the inputItem macro parameter is defined when the formShow() macro is invoked and it contains an attribute with thesame name as a given field, then the value of that inputItem attribute will be used as the default value of the field.Otherwise, any default value for the field defined in the schema will be used.

buttons If defined, this attribute should define a Vector of one or more button item names, where each string value in the listshould reference a button definition item. See Button Definition Items below for more details.

readonlyFields If defined, this attribute should define a Vector of schema attribute names. Each field referenced in the list will bedisplayed as a readonly field if a default value is defined for that field, either by the inputItem macro parameter or by thedefault value in the schema definition item. This allows transaction authors to prevent the user from updating criticalfields, such as the unique ID of a database record.

hiddenFields If defined, this attribute should define a Vector of schema attribute names. Each field referenced in the list will begenerated as a HTML hidden form field if a default value is defined for that field, either by the inputItem macroparameter or by the default value in the schema definition item. This allows tranasction authors to hide form fieldsfrom the user, while still POSTing that information when the form is submitted.

NOTE: Additional hidden fields can be defined for a form by using the hiddenItems attribute as described in the Form Control Attributes section below.

fieldSize The field size (in columns) for all input fields displayed in the form. The default value is 40.

Page 140: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

140 of 150 5/11/2007 10:14 AM

focusField If defined, the form field name referenced by this attribute will be given the focus as soon as the form is loaded.

boxWidth The overall width of the form in pixels. If not defined, the form will be as wide as necessary to accomodate all fields.

NOTE: If an instruction is defined, then it may span the entire page width by default. In that case, use this attribute tolimit the total width of the form.

outerWidthouterColor

The width (in pixels) and color of the form border.

innerWidthinnerColor

The gap width (in pixels) between the outer border and the form components, and the background color of the form.

Form Field Types

The form macro automatically generates HTML form fields based on the type of each attribute defined in the form schema item, using the followingconversion table:

Attribute Type HTML Field Type

Comments

string, int, double, datetime, duration, url, id,phoneno, zipcode, email, ipaddress, regular expression

text Any text can be entered in the form field, with syntax validationperformed on the server when the form is submitted

password password All input characters are displayed as '*'

text textarea The number of rows and columns can be controlled by definingaddition schema item attributes. See below for details.

enumeration selection list or radio buttons

Display depends on various "Choice" properties that may bedefined for the attribute. See below for details.

boolean checkbox Displayed using image buttons which are dynamically updated byJavaScript, thereby providing the same look and feel across allbrowser types

file file Displays an editable field and a browse button that allows theuser to browse the local file system and select a filename foruploading to the server

Page 141: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

141 of 150 5/11/2007 10:14 AM

Check Box Values

When a boolean check box is displayed in the form, the box will be initially checked if the default value equals "on" (case insensitive) or starts witha 't' or 'y' (case insensitive). All other values will be interpreted as false and the box will not be checked. When a check box field is POSTed to atransaction, the value will be set to "on" or "off". Unlike normal HTML check boxes, the check box provided by the form macro always POSTs avalue when the form is submitted.

Text Area Properties

When a "textarea" form field is displayed, the number of rows and columns can be specified by defining the xxxRows and xxxColumns attributes in the schema item, where xxx is the name of the field. For example, the following schema item defines a text area field with 10 rows of 40 columns:

schema formSchema extends BaseSchema { attrs = [ ("Comment", "text", "default", "") ];

CommentRows = 10; CommentColumns = 40;}

Choice Properties

When an enumerated list is specified as the attribute type in a schema item, a choice field will be generated in the form as either a selection list (theHTML <SELECT> tag) or a set of radio buttons. By default, a set of radio buttons is displayed if the number of choices is six or less, and aselection list is displayed if more than six choices are available. For example, consider the following schema definition and resulting form:

schema formSchema extends BaseSchema { attrs = [ ("ColorList", colorList, "default" , ""), ("StateList", stateList, "default" , "") ];

colorList = ["red", "yellow", "blue", "gold ", "green"]; stateList = UnitedStates("ABBR LIST");}

By default, the short color list is displayed as a set of radio buttons, with three columns of buttons per row. The number of columns can be specifiedusing the xxxRadioCols schema item attribute, where xxx is the attribute name.

The long state list is displayed by default as a drop-down choice list. If a selection list is desired, then the xxxChoiceSize schema item attribute can beused to specify the number of choices to be displayed at a time, where xxx is the attribute name. For example, the following attribute definitions

Page 142: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

142 of 150 5/11/2007 10:14 AM

result in the following form:

schema formSchema extends BaseSchema { attrs = [ ("ColorList", colorList, "default" , ""), ("StateList", stateList, "default" , "") ];

colorList = ["red", "yellow", "blue", "gold ", "green"]; stateList = UnitedStates("ABBR LIST");

StateListChoiceSize = 5; ColorListRadioCols = 2;}

Choice Labels

The xxxChoiceLabels

schema item attribute can be used to define a different set of labels to be displayed in a choice field, while still reporting the actual choice valuewhen the form is submitted. For example, if we want the color values to be displayed as upper case labels, while still reporting them as lower case,we could modify the previous example as follows:

schema formSchema extends BaseSchema { attrs = [ ("ColorList", colorList, "default" , ""), ("StateList", stateList, "default" , "") ];

colorList = ["red", "yellow", "blue", "gold ", "green"]; stateList = UnitedStates("ABBR LIST");

StateListChoiceSize = 5; ColorListRadioCols = 2;

ColorListChoiceLabels = ["RED", "YELLOW", " NAVY BLUE", "NAVY GOLD", "ARMY GREEN"];}

The label list must be in the same order as the value list specified for the corresponding attribute in the schemaitem.

Page 143: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

143 of 150 5/11/2007 10:14 AM

Choice Type

The xxxChoiceType

schema item attribute can be used to force a choice field to be displayed in a specific way ("select" or "radio", regardless of the number of choiceitems. For example, we can reverse the types of choice fields displayed in the previous example as follows:

schema formSchema extends BaseSchema { attrs = [ ("ColorList", colorList, "default" , ""), ("StateList", stateList, "default" , "") ];

colorList = ["red", "yellow", "blue", "gold ", "green"]; stateList = UnitedStates("ABBR LIST");

StateListChoiceSize = 5; ColorListRadioCols = 2;

ColorListChoiceLabels = ["RED", "YELLOW", " NAVY BLUE", "NAVY GOLD", "ARMY GREEN"];

StateListChoiceType = "radio"; StateListRadioCols = 5; ColorListChoiceType = "select";}

Multiple Choice Type

Choice fields that allow multiple selections can be specified by setting the xxxChoiceMulti attribute to "true". In that case, an HTML selection list willbe generated, using the xxxChoiceSize attribute as the number of items to be displayed. For example, we could modify the previous example to allowmultiple states to be selected:

Page 144: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

144 of 150 5/11/2007 10:14 AM

schema formSchema extends BaseSchema { attrs = [ ("ColorList", colorList, "default" , ""), ("StateList", stateList, "default" , "") ];

colorList = ["red", "yellow", "blue", "gold ", "green"]; stateList = UnitedStates("ABBR LIST");

StateListChoiceSize = 5; ColorListRadioCols = 2;

ColorListChoiceLabels = ["RED", "YELLOW", " NAVY BLUE", "NAVY GOLD", "ARMY GREEN"];

StateListChoiceMulti = true; StateListChoiceSize = 10; ColorListChoiceType = "select";}

In most browsers, the user should hold the Control key when selecting an item in order to select or deselect thatitem without changing the other selections. The Shift key can also be used to select all items between the lastitem selected and the current item being selected.

Choice Change Function

The xxxChoiceOnChange

attribute can be used to specify a JavaScript command to be executed whenever a choice is selected in a choice field. Usually, this is used to eitherprovide custom browser-side validation or automatically fill in another field as needed.

The xxxChoiceOnChange attribute is ignored for multiple choice fields.

Button Definition Items

The buttons

attribute of the form definition item can be used to specify one or more buttons to be displayed at the bottom of the row. Buttons are displayed astwo HTML images, which are automatically toggled when the button is "pressed". This provides the same look and feel across all browsers.

Page 145: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

145 of 150 5/11/2007 10:14 AM

Button image files can be created using any graphics program, thereby allowing a wide range of look and feels.Basic rectangular buttons can also be generated using the navius.apps.ButtonMaker application.

Each item in the buttons

Vector should be the name of a Button Definition Item which specifies the properties and behavior of each button, with the following attributessupported:

Attribute DescriptionbuttonName Name of the button

buttonImage Specifies the prefix of the image files to be used to represent the button. If buttonImage is not defined, then the buttonName is used. The actual image file names are determined by appending "-button.gif" and "-recess.gif" to the specified imagename.

actionURL URL to which the form should be submitted when the button is pressed.

actionFunc JavaScript command to be executed when the button is pressed. If this attribute is specified, the actionURL attribute isignored.

helpMsg Message to be displayed on the browser status line when the mouse hovers over the button

Form Control Attributes

In addition to the various display properties described in the previous sections, the behavior of the form generated by the form macro can becontrolled by the following form definition item attributes:

Attribute DescriptionactionURL Specifies the 'action' property of the HTML <FORM> tag

target Specifies the 'target' property of the HTML <FORM> tag

enctype Specifies the 'enctype' property of the HTML <FORM> tag

hiddenItems Specifies a Vector of one or more item names. For each item referenced in the list, all of the attributes defined in thatitem will be created as hidden form fields. In each case, the attribute name will be used as the form field name and theattribute value will be used as the form field value. This allows transaction authors to pass hidden data to the actionwhen the form is submitted.

Page 146: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

146 of 150 5/11/2007 10:14 AM

hiddenInputItem Specifies the name of an item that should be used to define hidden fields for all of the input parameters of thetransaction that generated the form. When the form action item is executed, it will automatically create the itemreferenced by this attribute and copy all input attribute names and values into that item. When the HTML form isgenerated, hidden form fields will be created for each attribute copied into that item.

When copying the input attributes, the form action will not copy any input attributes that are already defined as eithernormal or hidden form fields. That is, it will skip any input attribute that has the same name as any of the form fieldsspecified in the form schema attribute list or any of the form fields specified in the items specified by the hiddenItems list.This allows transaction authors to make use of whatever fields are needed by the form, while passing all inputparameters through the form to the next transaction.

formID If this attribute is defined, a hidden field named '_formID' will be created with the value given. The _formID field can beused by transactions to determine from which form they were executed.

formStack If this attribute is defined, then a hidden field named '_formStack' will be created with that value. The _formStack field is used by the standard JavaScript functions created with every form to automatically execute the "previous" form.Specifically, the form stack maintains a chain of transaction identifiers that can be used to "return" from a form to theform that originally executed it.

The _formStack field is automatically maintained by the Form Action. This attribute is used to "set" the stack to a knownstarting transaction. Generally, top level forms will set this attribute and all lower-level forms will use the automaticsettings.

HTML Form Menu Macro

The formMenu()

Velocity macro can be used to generate vertical or horizontal menus of buttons. Any number of button menus can be displayed anywhere on a givenpage containing one or more forms, with each menu associated with possibly a different form.

The form menu macro can be invoked from a Velocity template file using the following syntax:

#formMenu($formItem $menuItem)

where the $formItem references a form definition item and the $menuItem references a menu definition item. Each button displayed in the menu will beassociated with the form generated by the referenced form definition item.

The following attributes are supported by Menu Definition Items:

Page 147: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

147 of 150 5/11/2007 10:14 AM

Attribute Descriptionlayout If "vertical" is specified, then all buttons will be displayed as one or more vertical columns. Otherwise, all buttons will be

displayed as one or more horizontal rows. The default value is "horizontal".

buttons Vector of one or more Button Definition Item names. If the special name "BREAK" is specified, then a blank space willbe inserted in vertical layout mode and a new line of buttons will be started in horizontal layout mode.

formItem If this attribute is defined, then it should specify the name of a form definition item to be used for all menu buttons insteadof the formItem parameter specified when the macro was invoked.

For example, the following menu definition item results in the following menu being displayed:

item formMenu { layout = "horizontal"; buttons = ["insertButton", "deleteButton", "editButton", "BREAK", "okButton", "cancelButton"];}

HTML Form Message Box Macro

The formMsgBox()

macro can be used to display a given message in a box, with a given background color and a black border. Usually this is used to alert the user tosome problem.

The message box macro can be invoked from a Velocity template file using the following syntax:

#formMsgBox($msg $bgcolor)

where $msg is the message to be displayed and $bgcolor is the background color.

HTML Form Header Macro

The formPageHeader()

macro should be executed at the top of any page that makes use of the form macros. It creates data structures and functions that are used during

Page 148: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

148 of 150 5/11/2007 10:14 AM

page loading. Specifically, it generates the necessary HTML tags to include the "skipjackForm.js" file, which defines all of the JavaScript functionsused by the form macros.

This macro is automatically invoked by the default htmlPageHeader() macro that is used by all Skipjack Serverpage templates.

HTML Form Page Loader Macro

The formPageLoader()

macro should be used whenever an HTML body tag is generated for a page containing a form macro. When executed the macro generates an HTML"onload" attribute definition for the <BODY> tag that executes the formPageLoad() JavaScript function which initializes all forms on the page.

Since only one <BODY> tag can exist for an HTML page and only one "onload" attribute can be specified, if a custom onload function is requiredfor a given page, then the $pageOnloadFunc Velocity variable can be defined prior to executing the formPageLoader() to specify a custom onload function.In that case, the custom onload function is responsible for executing the formPageLoad() function before returning.

This macro is automatically invoked by the default htmlPageHeader() macro that is used by all Skipjack Serverpage templates.

Default Input Form

As was discussed in Section 2, when a transaction is invoked using the .form suffix an HTML Default Input Form is returned as the trasaction response. The default input form allows the user to enter all of the input parameters expected by the transaction, as specified by the inputSchema item.When used for development or testing purposes, the default characteristics of the input are usually sufficient. Nonetheless, all of the featuressupported by the HTML form macro can be used to customize the default input form as needed, simply by overriding the standard inputForm item that is created for all transactions.

For example, consider the default input form for the last example in Section 2 when invoked as tutorial/helloWorld/ex5.form:

Page 149: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

149 of 150 5/11/2007 10:14 AM

Although the form is functional, we might want to specify a custom set of field labels using the guiLabel item as follows:

item guiLabel overrides guiLabel { _readonly = true; who = "To Whom"; fontSize = "Size of Font"; bgColor = "BG Color";}

and perhaps specify a bunch of display properties (doesn't everyone love being a graphics expert!) by overriding the inputForm item as follows:

item inputForm overrides inputForm { title = "Hello World Input Form";

instructions = "Please fill out the followi ng fields and press" + " OK to display your message:";

buttons = ["inputFormSubmitButton", "r eturnButton"];

boxWidth = 250; outerColor = "black"; outerWidth = 1; innerColor = "lightgreen"; fieldSize = 10;}

item returnButton { buttonName = "return"; actionFunc = "history.back()"; helpMsg = "Return To Previous Page";}

In addition to the cosmetic changes, we also re-defined the list of buttons displayed on the form to include a "return" button. The resultingcustomized input form would be displayed as follows:

Page 150: Skipjack Server Application Development Guide

Skipjack Server Application Development Guide http://205.177.219.178/doc/appDevGuide/printable.html

150 of 150 5/11/2007 10:14 AM