DB2 Web Service Enabler User Guide

The DB2 Web Service Enabler (DB2WSE) from KRENGELTECH is a program which runs on the IBM i (AS/400, iSeries, System i), which enables external applications to access data on the IBM i, by running SQL statements over tables in the IBM i database, retrieving row-level data and returning it in an XML document.

DB2WSE can be called as a web service by external applications to perform a DB2WSE 'request', which will access one or more tables (as specified in the SQL statement passed in the request) and will return the data in those rows or will insert, update or delete one or more rows in the table, depending on the SQL statement used.

A full request consists of XML which defines the SQL statement to execute (which can be a SELECT, UPDATE, DELETE or INSERT statement), a user name and password, and various options which specify the format of the response, as in the following example:

<DB2WSEREQ>
  <STATEMENT RSPTYPE="basic" FIRSTROW="1">
    select * from petstore/item where itemid = 'EST-1'
  </STATEMENT>
  <USER>DEMO</USER>
  <PASSWORD>DEMO</PASSWORD>
</DB2WSEREQ>

A simple request consists simply of a URL in the REST format, which can be used to perform an SQL SELECT statement only, requesting all or a keyed subset of the rows in a table, as in the following example:

http://red.rpg-xml.com/db2wse/demo:demo/petstore/item/est-1

DB2WSE will process the request (including checking the existence of the user name, the validity of the password and the authority of the user to perform the specified operation on the specified table(s)), perform the requested action on the table and return the requested information as XML. See the SQL/XML Examples section for examples of DB2WSE requests and responses for all types of SQL statements.

Additionally, DB2WSE allows you to

DB2WSE was created on an IBM i running V5R3M0 of OS/400 but has been compiled to run at all releases from V5R1M0 onwards.

DB2WSE requires the Apache HTTP Server, which is typically installed as part of the base i5/OS Operating System:

-- 5722DG1 *BASE IBM HTTP Server

DB2WSE does not require any separately licensable components of i5/OS, nor does it require any 3rd-party software.

DB2WSE does not require that an Application Server be installed.

DB2WSE is written entirely in RPGIV, CLLE and C and does not use Java (although it can be used by applications written in Java).

Before installing DB2WSE, read the license agreement titled 'License Agreement.pdf'. By installing this software, you declare that you agree to abide by the license agreement.

To install DB2WSE, follow these steps:

  1. Unzip the downloaded DB2WSE.zip file to a folder on your PC, such as C:\TEMP and extract the DB2WSE.SAVF file (Note: the file may be called DB2WSEnnn.zip, where nnn denotes a version number)
  2. FTP the DB2WSE.SAVF file from your PC to the iSeries using the following steps:
    1. Open a DOS prompt (Start -> Run -> type 'cmd' and hit Enter)
    2. Type the following FTP commands into the DOS prompt and press Enter after each one (replace {ip-address}, {user-profile} and {password} with the IP address of your iSeries and a valid iSeries user profile/password which has authority to FTP).
      • FTP {ip-address}
      • {user-profile}
      • {password}
      • BINARY
      • LCD C:/TEMP
      • CD QGPL
      • QUOTE SITE NAMEFMT 0
      • PUT DB2WSE.SAVF
      • QUIT
  3. Execute the following steps to install DB2WSE on your iSeries:
    1. Restore the DB2WSE library from the DB2WSE save file
      RSTLIB SAVLIB(DB2WSE) DEV(*SAVF) SAVF(QGPL/DB2WSE)
    2. Add the DB2WSE library to the top of your library list
      ADDLIBLE LIB(DB2WSE) POSITION(*FIRST)
    3. Run the INSTDB2WSE (Install DB2WSE) command to configure DB2WSE and create an HTTP server instance. By default, the HTTP server instance will have the same name as the DB2WSE library. The default port used for DB2WSE is 8282, but you can change this to suit your needs.
      INSTDB2WSE DB2WSELIB(DB2WSE) PORT(8282) HTTPSVR(*DB2WSELIB)
  4. Product Registration
    • Temporary Product Registration
      When you originally downloaded DB2WSE, a temporary license key should have been created for you. This license key is a 32-character string, which should be applied using the APYKTILIC (Apply KTI License) command as follows:
      APYKTILIC LICKEY(license-key)

    • Permanent Product Registration
      You can request a permanent license key from KRENGELTECH. This license key will cover this release of DB2WSE (including any fixes that become available) only. To obtain a license key, you will need to provide the serial number and model number of your IBM i and the logical partition number (LPAR) on which DB2WSE will be installed. You can obtain this information by executing the following commands from an IBM i command line:
      • DSPSYSVAL SYSVAL(QSRLNBR)
      • DSPSYSVAL SYSVAL(QSRLNBR)
      • DSPSRVAGT TYPE(*SRVREGINF)
      Details of license fees can be obtained at http://www.rpg-xml.com. License details can be found in the 'License Agreement.pdf' document.
  5. Start the DB2WSE Apache HTTP Server instance by typing in the STRTCPSVR (Start TCP/IP Server) command below.
    STRTCPSVR SERVER(*HTTP) HTTPSVR(DB2WSE)

Before using DB2WSE, you should read the DB2WSE Configuration Values section and (if you choose to use the DB2WSE Authority Model) set up user profiles and authorities, as described below.

If you wish to create the example PETSTORE library, you should run the commands below. This will create both the PETSTORE library and the tables in it and also populate those tables with data. These tables are used in many of the examples in this user guide.

  • CRTLIB LIB(PETSTORE) TYPE(*TEST) TEXT('PETSTORE library for DB2WSE testing')
  • RUNSQLSTM SRCFILE(DB2WSE/QSQLSRC) SRCMBR(PETSTRDDL) COMMIT(*NONE) NAMING(*SYS) ERRLVL(20)
  • RUNSQLSTM SRCFILE(DB2WSE/QSQLSRC) SRCMBR(PETSTRPOP) COMMIT(*NONE) NAMING(*SYS) ERRLVL(20)

The following will setup a new user named DEMO using the DB2WSE Authority Model (DAM) and give DEMO authority to display data from the PETSTORE tables.

  • CRTDWEPRF USRNAM(DEMO) PASSWD(DEMO) PRFSTS(*ACTIVE) AUTLVL(*DFT)
  • CRTDWEAUT USRNAM(DEMO) TBLLIB(PETSTORE) TBLNAM(*ALL) AUTINS(*NO) AUTDLT(*NO) AUTUPD(*NO) AUTDSP(*YES)

Now you should be set to try the browser application shipped with DB2WSE which tests the data access functionality by putting a simple interface over the XML transactions. To use the browser application, point your browser at http://<ibmi>:<port> where <ibmi> should be replaced with the IP address or domain name of your IBM i and <port> should be replaced with the port number you specified in the INSTDB2WSE command when installing DB2WSE.

DB2WSE is controlled by a number of configuration values, which are held in the DB2WSECFG table. The configuration values are all shipped with default values, but they may be changed where required. The following are the current valid configuration values:

CONVERT_PASSWD_CASE

The CONVERT_PASSWD_CASE configuration value controls the conversion of passwords to upper-case for creation/checking purposes.

If CONVERT_PASSWD_CASE is set to *YES, any DB2WSE profiles created or changed will have the password value specified in the PASSWD parameter to the CRTDWEPRF (Create DB2WSE Profile) command converted to upper-case prior to being stored. Additionally, when a password is passed in a DB2WSE request, it will be converted to upper-case before profile checking is performed.

If CONVERT_PASSWD_CASE is set to *NO, any DB2WSE profiles created or changed will use the password value specified in the PASSWD parameter to the CRTDWEPRF command with no conversion to upper-case prior to being stored. Additionally, when a password is passed in a DB2WSE request, it will be used exactly as it was passed when DB2WSE performs profile checking.

The default value of CONVERT_PASSWD_CASE is *YES.

DEFAULT_AUTH_LEVEL

The DEFAULT_AUTH_LEVEL configuration value specifies the default value that should be used for newly-created DB2WSE profiles and queries. The DEFAULT_AUTH_LEVEL configuration value can take any value from 1 to 999. See the details of the CRTDWEPRF and CRTDWEQRY (Create DB2WSE Query) commands for more details on how this configuration value is used.

The default value of DEFAULT_AUTH_LEVEL is 500

DEFAULT_PROFILE_ID

The DEFAULT_PROFILE_ID configuration value specifies whether a particular DB2WSE profile should be used as the default - if no user name and password were passed in the request. It is only valid if the USE_SYSTEM_AUTHORITY configuration value is set to *NO.

If DEFAULT_PROFILE_ID has a value other than 0 (zero) and a user name and password are not passed in a DB2WSE request, the specified profile will be used when checking the authority to the specified table.

Note that you should not set DEFAULT_PROFILE_ID to a value other than 0 unless you are certain that the specified profile has only limited authority.

The default value of DEFAULT_PROFILE_ID is 0.

MAX_SELECT_ROWS

The MAX_SELECT_ROWS configuration value specifies the maximum number of rows that can be returned as the result of a SELECT request.

If a SELECT statement is specified which does not include a WHERE clause and which does not specify the FORROWS attribute to the SELECT statement (in other words, if all the rows in the table are requested), DB2WSE will immediately return an error if the number of rows in the table exceeds this value.

If a SELECT statement is specified which includes either a WHERE clause or the FORROWS attribute to the SELECT statement, DB2WSE will return up to this number of rows. No error will be signaled.

The default value of MAX_SELECT_ROWS is 2500.

USE_SYSTEM_AUTHORITY

The USE_SYSTEM_AUTHORITY configuration value controls the 'authority model' used by DB2WSE.

If USE_SYSTEM_AUTHORITY is *YES, DB2WSE will use the System Authority Model. If USE_SYSTEM_AUTHORITY is *NO, DB2WSE will use the DB2WSE Authority Model. See the DB2WSE Authority Models chapter for details of the two different authority models.

The default value of USE_SYSTEM_AUTHORITY is *NO.

DB2WSE can use either of two separate authority 'models' to determine the authority of a user to access a table. They are known as the System Authority Model (SAM) and the DB2WSE Authority Model (DAM). The authority model which is used is controlled by the USE_SYSTEM_AUTHORITY configuration value in table DB2WSE/DB2WSECFG.

System Authority Model (SAM)

If DB2WSE is using SAM, a DB2WSE request must include a valid IBM i user name and password. DB2WSE will use system API's to validate the user name and password and check the authority of the user profile to the table. DB2WSE will run under that user profile while the request is being processed. DB2WSE profiles and authorities are not used for the request.

DB2WSE Authority Model (DAM)

If DB2WSE is using DAM, a DB2WSE request must include a user name and password that have previously been created with the CRTDWEPRF command. The authority of the profile to access the table is controlled by the authority previously created for the profile using the CRTDWEAUT command. DB2WSE will run under the QSYS user profile. The user name and password do not have to be a valid IBM i user profile. If the DEFAULT_PROFILE_ID configuration value is set to a value other than 0, then no user name/password need to be passed to DB2WSE, but the default profile will be used when checking table authorities.

Differences between DB2WSE authority models

Using SAM is easier to set up than using DAM, since there is no need to create DB2WSE profiles and authorities. However, each request will include a clear text user profile and password, so should not be saved for repeated use. Additionally, unless HTTPS is being used to communicate between the client and the IBM i, the user profile and password will be sent unencrypted from the client to the IBM i. SAM works well in an environment where DB2WSE will be used to make ad-hoc queries and where the users already have specific authority created for them on the IBM i.

By contrast, if DAM is used, a finer control can be gained over the specific types of table access (read, update, write and delete) which are allowed for each user. Additionally, DB2WSE profiles can be created which have limited access to only a few tables, allowing them to be stored with the request and limiting the problems that could occur if they are discovered by unauthorized persons. If the DEFAULT_PROFILE_ID value is also used, then queries can be created which do not need to pass a user name and password at all.

DB2WSE includes a number of commands which allow you to install, configure and report on DB2WSE. It also includes two licensing commands, which are used by all KRENGELTECH products.

DB2WSE-specific commands

CRTDWEPRF (Create DB2WSE Profile)

The Create DB2WSE Profile (CRTDWEPRF) command allows you to create a new profile (or update an existing profile) for use by DB2WSE. These profiles are only needed if DB2WSE is running under the DB2WSE Authority Model (DAM).

If an existing profile is specified for the USRNAM parameter, it will be updated with the PASSWD and PRFSTS values. Otherwise, a new profile will be created.

CRTDWEPRF has the following parameters:

USRNAM (User name)

Specifies the user name for the profile. IBM i naming rules must be used for this parameter.

PASSWD (Password)

Specifies the password for the profile.

If the CONVERT_PASSWD_CASE configuration value is set to *YES, then the password will be converted to upper-case before being saved. When a password is passed in a request, it will be converted to upper-case before being checked.

If the CONVERT_PASSWD_CASE configuration value is set to *NO, the password can be mixed-case. Care must be taken that the password passed in a request exactly matches this password.

PRFSTS (Profile status)

Specifies the status of the profile. Can take values of either *ACTIVE or *INACTIVE

AUTLVL (Authority level)

Specifies the authority level of the user profile. The authority level of a profile specifies the maximum authority level of predefined queries that can be run by the profile. AUTLVL can be specified as any value from 1 to 999. If the special value of *DFT is used, the value held in the DEFAULT_AUTH_LEVEL configuration value is used.

CRTDWEPRF Example
CRTDWEPRF USRNAM(DEMO) PASSWD(DEMO) PRFSTS(*ACTIVE) AUTLVL(*DFT)

This will create a DB2WSE profile called DEMO with a password of DEMO. The profile will be active and will use the default authority level (as held in the DEFAULT_AUTH_LEVEL configuration value).

CRTDWEAUT (Create DB2WSE Authority)

The Create DB2WSE Authority (CRTDWEAUT) command allows you to create an authority row which will be associated with a DB2WSE profile. These authorities are only needed if DB2WSE is running under the DB2WSE Authority Model (DAM).

A DB2WSE authority specifies the authority that the associated DB2WSE profile has to a specific table or tables. The authority can specify whether the profile can read, update, delete or write to the table.

The associated DB2WSE profile must already have been created using the CRTDWEPRF command.

USRNAM (User name)

Specifies the user name for the profile. IBM i naming rules must be used for this parameter.

TBLLIB (Table library)

Specifies the name of the library where the specified table (file) exists. The library does not need to exist when this command is run.

TBLNAM (Table name)

Specifies the name of the table (file) to which the profile should be granted authority. The table (file) does not need to exist when this command is run.

AUTINS (Insert authority)

Specifies whether the specified user has write authority to the table (file) specified in the TBLLIB and TBLNAM parameters. This equates to the ability to run INSERT statements over the table. It can take values of either *NO or *YES

AUTDLT (Delete authority)

Specifies whether the specified user has delete authority to the table (file) specified in the TBLLIB and TBLNAM parameters. This equates to the ability to run DELETE statements over the table. It can take values of either *NO or *YES

AUTUPD (Update authority)

Specifies whether the specified user has update authority to the table (file) specified in the TBLLIB and TBLNAM parameters. This equates to the ability to run UPDATE statements over the table. It can take values of either *NO or *YES

AUTDSP (Display authority)

Specifies whether the specified user has display authority to the table (file) specified in the TBLLIB and TBLNAM parameters. This equates to the ability to run SELECT statements over the table. It can take values of either *YES or *NO

CRTDWEAUT Example
CRTDWEAUT USRNAM(DEMO) TBLLIB(PETSTORE) TBLNAM(*ALL) AUTINS(*NO) AUTDLT(*NO) AUTUPD(*NO) AUTDSP(*YES)

This will create a DB2WSE authority which will allow DB2WSE profile DEMO to access any of the tables in the PETSTORE library using an SQL SELECT statement. However, DEMO will not be able to insert, delete or update any rows in any tables in the PETSTORE library.

CRTDWEQRY (Create DB2WSE Query)

The Create DB2WSE Query (CRTDWEQRY) command allows you to create a predefined SQL query, which consists of a single SQL SELECT statement. This SQL statement can be run from a DB2WSE request by specifying the QUERYID attribute to the STATEMENT element in a full DB2WSE request or by specifying the query number instead of the library and table name in a simple REST-format DB2WSE request. When a DB2WSE query is created, it is assigned a unique number.

AUTLVL (Authority level)

Specifies the authority level of the query. The authority level of a query specifies the minimum authority level of DB2WSE profiles that can run the query. AUTLVL can be specified as any value from 1 to 999. If the special value of *DFT is used, the value held in the DEFAULT_AUTH_LEVEL configuration value is used.

QRYSTR (Query statement)

Specifies the SQL SELECT statement that should be run when this query is invoked.

CRTDWEQRY Example
CRTDWEQRY AUTLVL(*DFT) QRYSTR('select * from petstore/item')

This will create a DB2WSE query which will run the specified SELECT statement. Any DB2WSE profile with an AUTLVL greater than or equal to the *DFT level will be able to run the query. When the above statement is run, the query is created and a completion message is issue stating query identifier.

DLTDWEPRF (Delete DB2WSE Profile)

The Delete DB2WSE Profile (DLTDWEPRF) command allows you to delete an existing DB2WSE profile. Both the profile and all authority rows associated with the profile will be deleted.

USRNAM (User name)

Specifies the user name for the profile. IBM i naming rules must be used for this parameter.

DLTDWEPRF Example
DLTDWEPRF USRNAM(DEMO)

This will delete the DEMO DB2WSE profile, and any authority rows which have been created for the DEMO DB2WSe profile.

INSTDB2WSE (Install DB2WSE)

The Install DB2WSE (INSTDB2WSE) command allows you to install DB2WSE on your IBM i.

DB2WSELIB (DB2WSE library)

Specifies the name of the DB2WSE library which is being installed.

PORT (HTTP server instance port)

Specifies the port number to use for the HTTP server instance which will be used by DB2WSE. When the HTTP server instance is started (either through the STRTCP or the STRTCPSVR command), the HTTP server instance will listen at the specified port number for client requests.

HTTPSVR (HTTP server instance

Specifies the name of the HTTP server instance which will be created.

INSTDB2WSE Example
INSDB2WSE DB2WSELIB(DB2WSE) PORT(8282) HTTPSVR(*DB2WSELIB)

This will initialize the DB2WSE library, and create an HTTP server instance called DB2WSE, which will listen for requests on port 8282.

PRTDWECFG (Print DB2WSE Configuration)

This command allows you to print a list of the DB2WSE configuration, profile and authority rows. This command has no parameters.

KRENGELTECH Licensing commands

APYKTILIC (Apply KTI License)

The Apply KTI License (APYKTILIC) command allows the user to apply a license key for one or more KRENGELTECH products.

A license key for a product allows you to use that product, according to the terms of the license, until the license expiration date.

A license key consists of a 32-character string composed of valid hexadecimal characters (0-9, A-F). All 32 characters must be entered into the LICKEY field.

After executing this command, the license key is automatically validated and the list of component products to which it applies are displayed, showing the expiration date for the license.

LICKEY (License key

A license key consists of valid hexadecimal characters (0-9, A-F) only.

APYKTILIC Example
APYKTILIC LICKEY(ABCDEFA1234567890ABCDEF123456789)

Note: The above license key value is for example purposes only and is not a valid license key.

DSPKTILIC (Display KTI License)

This command allows you to display the license code for DB2WSE, showing the expiration date.

  • {required-string} A required string (may be a single value or multiple options)
  • [optional-string] An optional string (may be a single value or multiple options)
  • option-1|option-2 Separate options are separated by a vertical bar (|)
  • repeated-string... Repeated strings are suffixed with an ellipsis (...)

The general format of a DB2WSE request (full format) is as follows:

<DB2WSEREQ>
  <STATEMENT [attributes]>
    {sql-statement}
  </STATEMENT>
  <USER>{username}</USER>
  <PASSWORD>{password}</PASSWORD>
</DB2WSEREQ>

which would be sent in an HTML document form using the HTTP or HTTPS protocol as follows:

http[s]://{server-address}[:{port}]/db2wse/

Examples of valid SQL statements are as follows:

select * from PETSTORE/ITEM
select * from petstore/item where itemid = 'EST-1'
select productid, name from PetStore/Product where category like '%IS%'
insert into petstore/product values('RP-LI-03', 'REPTILES', 'Gecko', '<image src="../images/lizard3.gif">Cool green lizard')
update petstore/item set attr2 = 'INVALID' where attr2 is null
delete from petstore/product where category = 'REPTILE'

DB2WSE request elements, attributes and attribute values are case-independent. SQL statements are case-independent, except for quoted strings.

  • {required-string} A required string (may be a single value or multiple options)
  • [optional-string] An optional string (may be a single value or multiple options)
  • option-1|option-2 Separate options are separated by a vertical bar (|)
  • repeated-string... Repeated strings are suffixed with an ellipsis (...)

Note: Unless specified otherwise, the attributes for the STATEMENT element are valid only for SELECT statements, and are ignored where an INSERT, UPDATE or DELETE statement is specified.

STATEMENT attributes and attribute values are case-independent.

FIRSTROW

For SELECT statements, specifies the first matching row to return. If not specified or specified as <=0, defaults to 1

Example

<STATEMENT FIRSTROW='2'>

LASTROW

For SELECT statements, specifies the last matching row to return. If not specified or specified as <=0, defaults to last matching row.

Limitations

Example

<STATEMENT FIRSTROW='2' LASTROW='14'>

FORROWS

For SELECT statements, specifies the maximum number of matching rows to return. If not specified or specified as <=0, defaults to the value of the MAX_SELECT_ROWS configuration value.

Limitations

Example

<STATEMENT FIRSTROW='2' FORROWS='10'>

NAMING

For all statements, specifies naming type. Must be either 'SYS' (library/file) or 'SQL' (library.table). If not specified, defaults to 'SYS'.

Example

<STATEMENT NAMING='SQL'>

COLHDRS

For SELECT statements, specifies column headers. Must be either 'FLDNAM', 'SQLLABEL' or 'ANY'. If not specified, defaults to 'FLDNAM'. This attribute is ignored if RSPTYPE is specified.

Limitations

Example

<STATEMENT COLHDRS='FLDNAM'>

RSPTYPE

For SELECT statements, specifies the response type. Must be one of the following values: 'BASIC', 'FULL', 'DATAONLY', 'COLDEFS'. If not specified, defaults to 'BASIC'. This attribute will override any value specified for the COLHDRS attribute.

See SELECT statement response format for details of the formats of the different response types, both for SELECT statements with different RSPTYPE values and also for non-SELECT statements.

Limitations

Example

<STATEMENT RSPTYPE='FULL'>

QUERYID

If a predefined query (which was previously created with the CRTDWEQRY command) should be run, the QUERYID attribute should be specified, with a value of the query identifier.

If QUERYID is specified, the STATEMENT element must be defined as a null element and no SQL statement should be specified.

Limitations

Example

<STATEMENT queryid='43'/>
  • {required-string} A required string (may be a single value or multiple options)
  • [optional-string] An optional string (may be a single value or multiple options)
  • option-1|option-2 Separate options are separated by a vertical bar (|)
  • repeated-string... Repeated strings are suffixed with an ellipsis (...)

In addition to full format DB2WSE requests, which can specify any SQL statement type (SELECT, INSERT, UPDATE or DELETE), DB2WSE can also be invoked using a simple URL in the REST format. REST-format DB2WSE requests can only be SELECT statements.

The generic format of a REST DB2WSE URL is as follows:

http[s]://{server-address}[:{port}]/db2wse/[{userid}:{password}/]{library}/{file}[/{key}[:{key}...]

where each {key} is a value for a key column in the order they are defined for the table being accessed.

The number of key values specified (if any) must be less than or equal to the number of key columns defined for the table being accessed. DB2WSE parses any key values specified and maps them to the correct key column in the table.

Values specified for character key columns will automatically be converted to upper-case - DB2WSE does not currently support mixed-case or lower-case key column values.

When a REST-style URL is used to access DB2WSE, a BASIC response is returned.

Examples

Example 1

The following REST-format URL:

http://red.rpg-xml.com/db2wse/demo:demo/petstore/item/est-1

can be specified instead of the following full DB2WSE request:

<DB2WSEREQ>
  <STATEMENT>
    select * from petstore/item where itemid = 'EST-1'
  </STATEMENT>
  <USER>DEMO</USER>
  <PASSWORD>DEMO</PASSWORD>
</DB2WSEREQ>

This example assumes that ITEMID is the first key column specified for the PETSTORE/ITEM table.

Example 2

The following REST-format URL:

http://red.rpg-xml.com/db2wse/demo:demo/petstore/lineitem/1:2

can be specified instead of the following full DB2WSE request:

<DB2WSEREQ>
  <STATEMENT>
    select * from PETSTORE/LINEITEM where ORDERID = 1 and LINENUM = 2
  </STATEMENT>
  <USER>DEMO</USER>
  <PASSWORD>DEMO</PASSWORD>
</DB2WSEREQ>

This example assumes that ORDERID and LINENUM are the first and second key columns specified for the PETSTORE/LINEITEM table.

  • {required-string} A required string (may be a single value or multiple options)
  • [optional-string] An optional string (may be a single value or multiple options)
  • option-1|option-2 Separate options are separated by a vertical bar (|)
  • repeated-string... Repeated strings are suffixed with an ellipsis (...)

When a DB2WSE request is made, DB2WSE will return data to the requestor as XML data. The returned data will generically consist of an outer DB2WSERSP section containing a HEADER section and a data section, e.g.:

<DB2WSERSP>
  <HEADER>
    {header-information}
  </HEADER>
  {data}
</DB2WSERSP>

The HEADER section itself contains a copy of the original DB2WSE request, but without the USER or PASSWORD XML elements, e.g.:


...
<HEADER>
  <DB2WSEREQ>
    <STATEMENT [attributes]>
      {sql-statement}
    </STATEMENT>
  </DB2WSEREQ>
<HEADER>
...

Throughout this chapter, the DB2WSE request returned in the HEADER will simply be displayed as {db2wse-request}, e.g.:

<DB2WSERSP>
  <HEADER>
    {db2wse-request}
  </HEADER>
...

If the DB2WSE request SQL statement is a SELECT statement, the HEADER section will also include the following elements (after {db2wse-request}), which contain further information about the response data:

SELECT statement response format

The DB2WSE response to a SELECT statement depends on the value of the RSPTYPE attribute to the STATEMENT element in the DB2WSE request. The response will consist of either information about the columns (column attributes), the actual row and column data (column data) or both column attributes and column data.

BASIC response

A BASIC response (where RSPTYPE='basic' was specified) will return a HEADER section followed by row and column data as follows:

<DB2WSERSP>
  <HEADER>
    {db2wse-request}
    <RETURNEDROWS>{number of rows returned}</RETURNEDROWS>
    <MOREROWS>{YES|NO}</MOREROWS>
  </HEADER>
  <ROW ROWNBR="{returned-row-number}">
    <{column-name}>{column-value}</{column-name}>
    ...
  </ROW>
  ...
</DB2WSERSP>

The ROWNBR value refers to the row number within the set of rows returned in the DB2WSE response. This may therefore be different to the relative record number (RRN) of the row in the underlying physical table.

For null-capable columns where the column has the null indicator set, the format of the column will be:

<{column-name}/>

See the SQL/XML Examples chapter for an example of such a response.

FULL response

A FULL response (where RSPTYPE='full' was specified) will return separate HEADER and COLDEFS sections containing header information and column definitions, followed by row and column data as follows:

<DB2WSERSP>
  <HEADER>
    {db2wse-request}
    <RETURNEDROWS>{number of rows returned}</RETURNEDROWS>
    <MOREROWS>{YES|NO}</MOREROWS>
  </HEADER>
  <COLDEFS>
    <COLDEF {attributes}/>
    ...
  </COLDEFS>
  <ROW ROWNBR="{returned-row-number}">
    <F{column-sequence}>{column-value}</F{column-sequence}>
    ...
  </ROW>
  ...
</DB2WSERSP>

For null-capable columns where the column has the null indicator set, the format of the column will be:

<C{column-sequence}/>

The COLDEF attributes string is made up of the following:

COLSEQ='{column-sequence}' COLNAME='{column-name}' COLTEXT='{column-description}' COLTYPE='{column-type}' COLLENGTH='{column-length}' [COLDECPOS='{column-decimal-positions}']

The COLDECPOS attribute is only included with numeric columns.

The COLSEQ attribute is the order of the column in the table: the first column has column-sequence 1, the next column has column-sequence 2 and so on.

The COLTYPE attribute will have one of the following values:

The value may also have 'with nulls' appended (e.g. 'Fixed character with nulls') if the column is null-capable.

DATAONLY response

A DATAONLY response (where RSPTYPE='dataonly' was specified) will return row and column data in the same format as would be returned for a FULL response, but without the COLDEFS section.

See the FULL response section above for details

COLDEFS response

A COLDEFS response (where RSPTYPE='flddefs' was specified) will return the Header and COLDEFS sections that would be returned with a FULL response, but without the ROW sections.

See the FULL response section above for details

Non-SELECT statement response format

For non-SELECT statements, the DB2WSE response will have the following format:

<DB2WSERSP>
  <HEADER>
    {db2wse-request}
  </HEADER>
  <RSPCODE>
    {response-code}
  </RSPCODE>
  <RSPTEXT>
    {number-of-rows} {'row(s)'} {'inserted into'|'updated in'|'deleted from'} {qualified-file-name}
  </RSPTEXT>
</DB2WSERSP>

The RSPCODE value indicates the number of succsessful database updates (i.e. it will have the same value as number-of-rows).

ERROR response format

If an error occurs in the DB2WSE program, the DB2WSE response will have the following format:

<DB2WSERSP>
  <HEADER>
    {db2wse-request}
  </HEADER>
  <ERRTEXT>
    <CODE>{error-code}</CODE>
    <SEVERITY>{error-severity}</SEVERITY>
    <PGM>{error-program}</PGM>
    <TEXT>{error-text}</TEXT>
  </ERRTEXT>
<DB2WSERSP>

The PGM value will always be 'DB2WSE'.

The SEVERITY value will be between 0 and 100.

The following is a list of the possible CODE values. A value in parentheses after the explanatory text for each error code specifies the message identifier of the actual text that will be displayed for the TEXT value. The message identifier begins with 'DWE' or 'RX', then the message is held in the KTIMSGF message file. If the message identifier has a value of 'CPF*', then one of several messages specified in the QCPFMSG message file may be used.

Example 1 - simple SELECT statement

Request

<DB2WSEREQ>
  <STATEMENT>
    select * from PETSTORE/ORDERS
  </STATEMENT> 
  <USER>DEMO</USER>
  <PASSWORD>DEMO</PASSWORD>
</DB2WSEREQ>

or, in REST format

http://red.rpg-xml.com/db2wse/demo:demo/petstore/orders

Response

<DB2WSERSP>
  <HEADER>
    <DB2WSEREQ>
      <STATEMENT>
        select * from PETSTORE/ORDERS
      </STATEMENT>
    </DB2WSEREQ>
    <RETURNEDROWS>1</RETURNEDROWS>
    <MOREROWS>NO</MOREROWS>
  </HEADER>
  <ROW ROWNBR="1">
    <ORDERID>1</ORDERID>
    <USERID>ACID</USERID>
    <ORDERDATE>2009-02-01</ORDERDATE>
    <SHIPADDR1>1st St</SHIPADDR1>
    <SHIPADDR2 />
    <SHIPCITY>York</SHIPCITY>
    <SHIPSTATE>PA</SHIPSTATE>
    <SHIPZIP>17404</SHIPZIP>
    <SHIPCOUNTRY>USA</SHIPCOUNTRY>
    <BILLADDR1>1st St</BILLADDR1>
    <BILLADDR2 />
    <BILLCITY>York</BILLCITY>
    <BILLSTATE>PA</BILLSTATE>
    <BILLZIP>17404</BILLZIP>
    <BILLCOUNTRY>USA</BILLCOUNTRY>
    <COURIER>FED-EX</COURIER>
    <TOTALPRICE>1,093.43</TOTALPRICE>
    <BILLTOFIRSTNAME>Dave</BILLTOFIRSTNAME>
    <BILLTOLASTNAME>Smith</BILLTOLASTNAME>
    <SHIPTOFIRSTNAME>Dave</SHIPTOFIRSTNAME>
    <SHIPTOLASTNAME>Smith</SHIPTOLASTNAME>
    <CREDITCARD>123456789</CREDITCARD>
    <EXPRDATE>201201</EXPRDATE>
    <CARDTYPE>VISA</CARDTYPE>
    <LOCALE>US</LOCALE>
  </ROW>
</DB2WSERSP>

Example 2 - complex SELECT statement

Request

<DB2WSEREQ>
  <STATEMENT>
    select * from petstore/product where category = 'FISH'
  </STATEMENT>
  <USER>DEMO</USER>
  <PASSWORD>DEMO</PASSWORD>
</DB2WSEREQ>

Response

<DB2WSERSP>
  <HEADER>
    <DB2WSEREQ>
      <STATEMENT>
        select * from petstore/product where category = 'FISH'
      </STATEMENT>
    </DB2WSEREQ>
    <RETURNEDROWS>4</RETURNEDROWS>
    <MOREROWS>NO</MOREROWS>
  </HEADER>
  <ROW ROWNBR="1">
    <PRODUCTID>FI-SW-01</PRODUCTID>
    <CATEGORY>FISH</CATEGORY>
    <NAME>Angelfish</NAME>
    <DESCN>Salt Water fish from Australia</DESCN>
  </ROW>
  <ROW ROWNBR="2">
    <PRODUCTID>FI-SW-02</PRODUCTID>
    <CATEGORY>FISH</CATEGORY>
    <NAME>Tiger Shark</NAME>
    <DESCN>Salt Water fish from Australia</DESCN>
  </ROW>
  <ROW ROWNBR="3">
    <PRODUCTID>FI-FW-01</PRODUCTID>
    <CATEGORY>FISH</CATEGORY>
    <NAME>Koi</NAME>
    <DESCN>Fresh Water fish from Japan</DESCN>
  </ROW>
  <ROW ROWNBR="4">
    <PRODUCTID>FI-FW-02</PRODUCTID>
    <CATEGORY>FISH</CATEGORY>
    <NAME>Goldfish</NAME>
    <DESCN>Fresh Water fish from China</DESCN>
  </ROW>
</DB2WSERSP>

Example 3 - simple SELECT statement using FIRSTROW and FORROWS attributes

Request

<DB2WSEREQ>
  <STATEMENT FIRSTROW="3" FORROWS="2">
    select itemid, status from petstore/item
  </STATEMENT>
  <USER>DEMO</USER>
  <PASSWORD>DEMO</PASSWORD>
</DB2WSEREQ>

Response

<DB2WSERSP>
  <HEADER>
    <DB2WSEREQ>
      <STATEMENT FIRSTROW="3" FORROWS="2">
        select itemid, status from petstore/item
      </STATEMENT>
    </DB2WSEREQ>
    <RETURNEDROWS>2</RETURNEDROWS>
    <MOREROWS>YES</MOREROWS>
  </HEADER>
  <ROW ROWNBR="3">
    <ITEMID>EST-3</ITEMID>
    <STATUS>P</STATUS>
  </ROW>
  <ROW ROWNBR="4">
    <ITEMID>EST-4</ITEMID>
    <STATUS>P</STATUS>
  </ROW>
</DB2WSERSP>

Example 4 - complex SELECT statement using inner join

Request

<DB2WSEREQ>
  <STATEMENT>
    select o.orderid, o.userid, o.orderdate, o.totalprice, o.billtolastname, i.linenum, i.itemid, i.quantity, i.unitprice     from petstore/orders o, petstore/lineitem i where o.orderid = i.orderid
  </STATEMENT>
  <USER>DEMO</USER>
  <PASSWORD>DEMO</PASSWORD>
</DB2WSEREQ>

Response

<DB2WSERSP>
  <HEADER>
    <DB2WSEREQ>
      <STATEMENT FIRSTROW="3">
        select o.orderid, o.userid, o.orderdate, o.totalprice, o.billtolastname, i.linenum, i.itemid, i.quantity, i.unitprice         from petstore/orders o, petstore/lineitem i where o.orderid = i.orderid
      </STATEMENT>
    </DB2WSEREQ>
    <RETURNEDROWS>2</RETURNEDROWS>
    <MOREROWS>NO</MOREROWS>
  </HEADER>
  <ROW ROWNBR="1">
    <ORDERID>73</ORDERID>
    <USERID>ACID</USERID>
    <ORDERDATE>02/01/09</ORDERDATE>
    <TOTALPRICE>1093.43</TOTALPRICE>
    <BILLTOLASTNAME>Smith</BILLTOLASTNAME>
    <LINENUM>1</LINENUM>
    <ITEMID>EST-1</ITEMID>
    <QUANTITY>2</QUANTITY>
    <UNITPRICE>9.45</UNITPRICE>
  </ROW>
  <ROW ROWNBR="2">
    <ORDERID>73</ORDERID>
    <USERID>ACID</USERID>
    <ORDERDATE>02/01/09</ORDERDATE>
    <TOTALPRICE>1093.43</TOTALPRICE>
    <BILLTOLASTNAME>Smith</BILLTOLASTNAME>
    <LINENUM>2</LINENUM>
    <ITEMID>EST-8</ITEMID>
    <QUANTITY>2</QUANTITY>
    <UNITPRICE>11.23</UNITPRICE>
  </ROW>
</DB2WSERSP>

Example 5 - simple SELECT statement using FULL response type

Request

<DB2WSEREQ>
  <STATEMENT RSPTYPE="full">
    select * from petstore/lineitem
  </STATEMENT>
  <USER>DEMO</USER>
  <PASSWORD>DEMO</PASSWORD>
</DB2WSEREQ>

Response

<DB2WSERSP>
  <HEADER>
    <DB2WSEREQ>
      <STATEMENT RSPTYPE="full">
        select * from petstore/lineitem
      </STATEMENT>
    </DB2WSEREQ>
    <RETURNEDROWS>2</RETURNEDROWS>
    <MOREROWS>NO</MOREROWS>
  </HEADER>
  <COLDEFS>
    <COLDEF COLSEQ="1" COLNAME="ORDERID" COLTEXT="Order identifier" COLTYPE="Large integer" COLLENGTH="4" />
    <COLDEF COLSEQ="2" COLNAME="LINENUM" COLTEXT="Line number" COLTYPE="Large integer" COLLENGTH="4" />
    <COLDEF COLSEQ="3" COLNAME="ITEMID" COLTEXT="Item identifier" COLTYPE="Varying character" COLLENGTH="10" />
    <COLDEF COLSEQ="4" COLNAME="QUANTITY" COLTEXT="Quantity" COLTYPE="Large integer" COLLENGTH="4" />
    <COLDEF COLSEQ="5" COLNAME="UNITPRICE" COLTEXT="Unit price" COLTYPE="Packed decimal" COLLENGTH="10" COLDECPOS="2" />
  </COLDEFS>
  <ROW ROWNBR="1">
    <F1>1</F1>
    <F2>1</F2>
    <F3>EST-1</F3>
    <F4>2</F4>
    <F5>9.45</F5>
  </ROW>
  <ROW ROWNBR="2">
    <F1>1</F1>
    <F2>2</F2>
    <F3>EST-8</F3>
    <F4>7</F4>
    <F5>11.23</F5>
  </ROW>
</DB2WSERSP>

Example 6 - DELETE statement

Request

<DB2WSEREQ>
  <STATEMENT>
    delete from petstore/item where category = 'REPTILE'
  </STATEMENT>
  <USER>DEMO</USER>
  <PASSWORD>DEMO</PASSWORD>
</DB2WSEREQ>

Response

<DB2WSERSP>
  <HEADER>
    <DB2WSEREQ>
      <STATEMENT>
        delete from petstore/item where category = 'REPTILE'
      </STATEMENT>
    </DB2WSEREQ>
  </HEADER>
  <RSPCODE>
    2
  </RSPCODE>
  <RSPTEXT>
    2 rows deleted from PETSTORE/ITEM
  </RSPTEXT>
</DB2WSERSP>

Example 7 - INSERT statement

Request

<DB2WSEREQ>
  <STATEMENT>
    insert into petstore/product values('RP-LI-03', 'REPTILES', 'Gecko', '<image src="../images/lizard3.gif">Cool green lizard')
  </STATEMENT>
  <USER>DEMO</USER>
  <PASSWORD>DEMO</PASSWORD>
</DB2WSEREQ>

Response

<DB2WSERSP>
  <HEADER>
    <DB2WSEREQ>
      <STATEMENT>
        insert into petstore/product values('RP-LI-03', 'REPTILES', 'Gecko', '<image src="../images/lizard3.gif">Cool green lizard')
      </STATEMENT>
    </DB2WSEREQ>
  </HEADER>
  <RSPCODE>
    1
  </RSPCODE>
  <RSPTEXT>
    1 row inserted into PETSTORE/PRODUCT
  </RSPTEXT>
</DB2WSERSP>

Example 8 - UPDATE statement

Request

<DB2WSEREQ>
  <STATEMENT>
    update petstore/item set attr2 = 'INVALID' where attr2 is null
  </STATEMENT>
  <USER>DEMO</USER>
  <PASSWORD>DEMO</PASSWORD>
</DB2WSEREQ>

Response

<DB2WSERSP>
  <HEADER>
    <DB2WSEREQ>
      <STATEMENT>
        update petstore/item set attr2 = 'INVALID' where attr2 is null
      </STATEMENT>
    </DB2WSEREQ>
  </HEADER>
  <RSPCODE>
    28
  </RSPCODE>
  <RSPTEXT>
    28 rows updated in PETSTORE/ITEM
  </RSPTEXT>
</DB2WSERSP>

Java Example 1

Source code

/*
 * This example program is meant to show a very simple usage of DB2WSE so that a Java
 * programmer can be up and running quickly without a lot of environment setup.  Simply
 * load this program into your IDE of choice (i.e. Eclipse) and invoke the Java program.
 */
package com.krengeltech.db2wse.example;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class Example1 {

    public static void main(String[] args) {

        // The server red.rpg-xml.com is KrengelTech's. Change this value
        // to communicate with DB2WSE on your IBM i.
        String db2wseURL = "http://red.rpg-xml.com/db2wse/";

        // Simple SQL SELECT statement
        String xmlReq = "<DB2WSEREQ><STATEMENT>select * from QIWS/QCUSTCDT</STATEMENT><USER>demo</USER><PASSWORD>demo</PASSWORD></DB2WSEREQ>";

        execURL(db2wseURL, xmlReq);
    }

    static void execURL(String urlString, String postContent) {
        try {
            // Create the HTTP connection
            URL url = new URL(urlString);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setRequestMethod("POST");

            // Write the XML request to the OutputStream
            OutputStream outStream = conn.getOutputStream();
            outStream.write(postContent.getBytes());
            outStream.close();

            // Convert the response InputStream to a string and write it to the console.
            System.out.println(streamToString(conn.getInputStream()));
        } catch (Exception e) {
            System.out.println(e);
        }
    }

    // "Ease of use" method that will convert an InputStream to a string.
    static String streamToString(InputStream is) {
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        StringBuilder sb = new StringBuilder();
        String line = null;
        try {
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return sb.toString();
    }
}

Console Result (formatted for easier viewing)

<DB2WSERSP>
  <HEADER>
    <DB2WSEREQ>
      <STATEMENT>select * from QIWS/QCUSTCDT</STATEMENT>
    </DB2WSEREQ>
    <RETURNEDROWS>12</RETURNEDROWS>
    <MOREROWS>NO</MOREROWS>
  </HEADER>
  <ROW ROWNBR="1">
    <CUSNUM>938472</CUSNUM>
    <LSTNAM>Henning</LSTNAM>
    <INIT>G K</INIT>
    <STREET>4859 Elm Ave</STREET>
    <CITY>Dallas</CITY>
    <STATE>TX</STATE>
    <ZIPCOD>75217</ZIPCOD>
    <CDTLMT>5000</CDTLMT>
    <CHGCOD>3</CHGCOD>
    <BALDUE>37.00</BALDUE>
    <CDTDUE></CDTDUE>
  </ROW>
  <ROW ROWNBR="2">
    <CUSNUM>839283</CUSNUM>
    <LSTNAM>Jones</LSTNAM>
    <INIT>B D</INIT>
    <STREET>21B NW 135 St</STREET>
    <CITY>Clay</CITY>
    <STATE>NY</STATE>
    <ZIPCOD>13041</ZIPCOD>
    <CDTLMT>400</CDTLMT>
    <CHGCOD>1</CHGCOD>
    <BALDUE>100.00</BALDUE>
    <CDTDUE></CDTDUE>
  </ROW>
  <ROW ROWNBR="3">
    <CUSNUM>392859</CUSNUM>
    <LSTNAM>Vine</LSTNAM>
    <INIT>S S</INIT>
    <STREET>PO Box 79</STREET>
    <CITY>Broton</CITY>
    <STATE>VT</STATE>
    <ZIPCOD>5046</ZIPCOD>
    <CDTLMT>700</CDTLMT>
    <CHGCOD>1</CHGCOD>
    <BALDUE>439.00</BALDUE>
    <CDTDUE></CDTDUE>
  </ROW>
  <ROW ROWNBR="4">
    <CUSNUM>938485</CUSNUM>
    <LSTNAM>Johnson</LSTNAM>
    <INIT>J A</INIT>
    <STREET>3 Alpine Way</STREET>
    <CITY>Helen</CITY>
    <STATE>GA</STATE>
    <ZIPCOD>30545</ZIPCOD>
    <CDTLMT>9999</CDTLMT>
    <CHGCOD>2</CHGCOD>
    <BALDUE>3,987.50</BALDUE>
    <CDTDUE>33.50</CDTDUE>
  </ROW>
  <ROW ROWNBR="5">
    <CUSNUM>397267</CUSNUM>
    <LSTNAM>Tyron</LSTNAM>
    <INIT>W E</INIT>
    <STREET>13 Myrtle Dr</STREET>
    <CITY>Hector</CITY>
    <STATE>NY</STATE>
    <ZIPCOD>14841</ZIPCOD>
    <CDTLMT>1000</CDTLMT>
    <CHGCOD>1</CHGCOD>
    <BALDUE></BALDUE>
    <CDTDUE></CDTDUE>
  </ROW>
  <ROW ROWNBR="6">
    <CUSNUM>389572</CUSNUM>
    <LSTNAM>Stevens</LSTNAM>
    <INIT>K L</INIT>
    <STREET>208 Snow Pass</STREET>
    <CITY>Denver</CITY>
    <STATE>CO</STATE>
    <ZIPCOD>80226</ZIPCOD>
    <CDTLMT>400</CDTLMT>
    <CHGCOD>1</CHGCOD>
    <BALDUE>58.75</BALDUE>
    <CDTDUE>1.50</CDTDUE>
  </ROW>
  <ROW ROWNBR="7">
    <CUSNUM>846283</CUSNUM>
    <LSTNAM>Alison</LSTNAM>
    <INIT>J S</INIT>
    <STREET>787 Lake Dr</STREET>
    <CITY>Isle</CITY>
    <STATE>MN</STATE>
    <ZIPCOD>56342</ZIPCOD>
    <CDTLMT>5000</CDTLMT>
    <CHGCOD>3</CHGCOD>
    <BALDUE>10.00</BALDUE>
    <CDTDUE></CDTDUE>
  </ROW>
  <ROW ROWNBR="8">
    <CUSNUM>475938</CUSNUM>
    <LSTNAM>Doe</LSTNAM>
    <INIT>J W</INIT>
    <STREET>59 Archer Rd</STREET>
    <CITY>Sutter</CITY>
    <STATE>CA</STATE>
    <ZIPCOD>95685</ZIPCOD>
    <CDTLMT>700</CDTLMT>
    <CHGCOD>2</CHGCOD>
    <BALDUE>250.00</BALDUE>
    <CDTDUE>100.00</CDTDUE>
  </ROW>
  <ROW ROWNBR="9">
    <CUSNUM>693829</CUSNUM>
    <LSTNAM>Thomas</LSTNAM>
    <INIT>A N</INIT>
    <STREET>3 Dove Circle</STREET>
    <CITY>Casper</CITY>
    <STATE>WY</STATE>
    <ZIPCOD>82609</ZIPCOD>
    <CDTLMT>9999</CDTLMT>
    <CHGCOD>2</CHGCOD>
    <BALDUE></BALDUE>
    <CDTDUE></CDTDUE>
  </ROW>
  <ROW ROWNBR="10">
    <CUSNUM>593029</CUSNUM>
    <LSTNAM>Williams</LSTNAM>
    <INIT>E D</INIT>
    <STREET>485 SE 2 Ave</STREET>
    <CITY>Dallas</CITY>
    <STATE>TX</STATE>
    <ZIPCOD>75218</ZIPCOD>
    <CDTLMT>200</CDTLMT>
    <CHGCOD>1</CHGCOD>
    <BALDUE>25.00</BALDUE>
    <CDTDUE></CDTDUE>
  </ROW>
  <ROW ROWNBR="11">
    <CUSNUM>192837</CUSNUM>
    <LSTNAM>Lee</LSTNAM>
    <INIT>F L</INIT>
    <STREET>5963 Oak St</STREET>
    <CITY>Hector</CITY>
    <STATE>NY</STATE>
    <ZIPCOD>14841</ZIPCOD>
    <CDTLMT>700</CDTLMT>
    <CHGCOD>2</CHGCOD>
    <BALDUE>489.50</BALDUE>
    <CDTDUE>.50</CDTDUE>
  </ROW>
  <ROW ROWNBR="12">
    <CUSNUM>583990</CUSNUM>
    <LSTNAM>Abraham</LSTNAM>
    <INIT>M T</INIT>
    <STREET>392 Mill St</STREET>
    <CITY>Isle</CITY>
    <STATE>MN</STATE>
    <ZIPCOD>56342</ZIPCOD>
    <CDTLMT>9999</CDTLMT>
    <CHGCOD>3</CHGCOD>
    <BALDUE>500.00</BALDUE>
    <CDTDUE></CDTDUE>
  </ROW>
</DB2WSERSP>