IBM I Programming IBM Toolbox For Java Rzahh
IBM I Programming IBM Toolbox For Java Rzahh
IBM i
Note Before using this information and the product it supports, read the information in Notices, on page 759.
This edition applies to IBM i 7.1 (product number 5770-SS1) and to all subsequent releases and modifications until otherwise indicated in new editions. This version does not run on all reduced instruction set computer (RISC) models nor does it run on CISC models. Copyright IBM Corporation 1999, 2010. US Government Users Restricted Rights Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
Contents
IBM Toolbox for Java . . . . . . . . . 1
What's new for IBM i 7.1 . . . . . . . . . . 1 PDF file for IBM Toolbox for Java . . . . . . . 2 Installing and managing IBM Toolbox for Java . . . 2 Managing your IBM Toolbox for Java installation 3 Installing IBM Toolbox for Java . . . . . . . 3 System properties . . . . . . . . . . . 12 IBM Toolbox for Java classes. . . . . . . . . 21 Access classes . . . . . . . . . . . . 21 Commtrace classes . . . . . . . . . . 183 HTML Classes . . . . . . . . . . . . 191 ReportWriter classes . . . . . . . . . . 224 Resource classes . . . . . . . . . . . 226 Security classes . . . . . . . . . . . . 229 Servlet classes . . . . . . . . . . . . 232 Utility classes . . . . . . . . . . . . 239 Vaccess classes . . . . . . . . . . . . 249 Graphical Toolbox and PDML . . . . . . . . 290 Setting up the Graphical Toolbox . . . . . . 296 Creating your user interface . . . . . . . 298 Displaying your panels at runtime . . . . . 301 Editing help documents generated by GUI Builder . . . . . . . . . . . . . . 305 Using the Graphical Toolbox in a browser . . . 308 GUI Builder Panel Builder toolbar . . . . . 312 IBM Toolbox for Java beans . . . . . . . . 314 JDBC . . . . . . . . . . . . . . . . 315 Enhancements to IBM Toolbox for Java JDBC support for IBM i 7.1 . . . . . . . . . . 315 Enhancements to IBM Toolbox for Java JDBC support for IBM i 6.1 . . . . . . . . . . 319 Enhancements to IBM Toolbox for Java JDBC support for IBM i 5.4 . . . . . . . . . . 322 IBM Toolbox for Java JDBC properties . . . . 327 JDBC SQL Types . . . . . . . . . . . 344 Proxy Support . . . . . . . . . . . . . 345 Secure Sockets Layer and Java Secure Socket Extension. . . . . . . . . . . . . . . 350 IBM Toolbox for Java 2 Micro Edition . . . . . 350 ToolboxME requirements . . . . . . . . 350 Downloading and setting up ToolboxME . . . 351 Concepts important for using ToolboxME . . . 351 ToolboxME classes. . . . . . . . . . . 352 Creating and running a ToolboxME program 363 ToolboxME working examples. . . . . . . 377 Extensible Markup Language components . . . . 378 Program Call Markup Language . . . . . . 378 Graphical Toolbox and PDML . . . . . . . 400 Record Format Markup Language . . . XML parser and XSLT processor . . . . Extensible Program Call Markup Language Frequently asked questions (FAQ) . . . . Tips for programming . . . . . . . . Shutting down your Java program . . . Integrated file system path names for server objects. . . . . . . . . . . . . Managing connections in Java programs . IBM i Java virtual machine . . . . . . Independent auxiliary storage pool (ASP) . Exceptions . . . . . . . . . . . Error events . . . . . . . . . . . Trace class . . . . . . . . . . . IBM i optimization . . . . . . . . Performance improvements. . . . . . Client installation and update classes . . AS400ToolboxJarMaker . . . . . . . Java national language support . . . . Service and support for the IBM Toolbox for Java . . . . . . . . . . . . . Code examples . . . . . . . . . . . Examples: Access classes . . . . . . Examples: JavaBeans . . . . . . . . Examples: Commtrace classes . . . . . Graphical Toolbox examples . . . . . Examples from the HTML classes . . . Examples: Program Call Markup Language (PCML) . . . . . . . . . . . . Examples: ReportWriter classes . . . . Examples: Resource classes . . . . . . Examples: RFML . . . . . . . . . Example: Using a profile token credential to swap the IBM i thread identity . . . . Examples from the servlet classes . . . Simple programming examples . . . . Examples: Tips for programming . . . . Examples: ToolboxME . . . . . . . Examples: Utility classes. . . . . . . Examples: Vaccess classes . . . . . . Examples: XPCML . . . . . . . . Related information for IBM Toolbox for Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 406 415 416 443 443 443 443 445 451 455 456 457 458 460 462 463 464 465 465 466 467 553 560 560 594 617 626 643 647 648 649 676 693 694 714 715 745 755
| |
iii
iv
v The IBM Toolbox for Java JAR files are installed in the integrated file system of IBM i, under directory /QIBM/ProdData/OS400/jt400/. v IBM Toolbox for Java is also available in an open source version. You can download the code and get more information from the JTOpen Web site.
Other information
You can also download a zipped package of the IBM Toolbox for Java topic that includes the Javadocs at the IBM Toolbox for Java and JTOpen Web site .
Note: The information in the zipped package has links to documents that are not included in the zipped package, so these links do not work.
v The QUSER user profile must be enabled in order to start the host servers. v Host servers listen for and accept connection requests from clients. IBM i Host Servers option is included with the base option of IBM i. For more information, see Host server administration. v TCP/IP support, which is integrated into IBM i, allows you to connect your server to a network. For more information, see TCP/IP. Starting required IBM i options From a command line, start the required IBM i options by completing the following steps: 1. Ensure that the QUSER profile is enabled. 2. To start the IBM i host servers, use the CL Start Host Server command. Type STRHOSTSVR *ALL and press ENTER. 3. To start the TCP/IP distributed data management (DDM) server, use the CL Start TCP/IP Server command. Type STRTCPSVR SERVER(*DDM) and press ENTER. Determining if IBM Toolbox for Java is installed on your system: To see if IBM Toolbox for Java is already installed on your IBM i server, complete the steps in this topic. 1. In System i Navigator, select and sign on to the system that you want to use. 2. In the Function Tree (the left pane), expand the system, then expand Configuration and Service. 3. Expand Software, then expand Installed Products. | 4. In the Details pane (the right pane), see if product 5770-SS1 option 3 is installed. If you see this | product and option combination, the IBM Toolbox for Java is installed on the selected server. Note: You can also find out if IBM Toolbox for Java is installed by using the CL Go to Menu command (GO MENU(LICPGM)), Option 11. | If IBM Toolbox for Java is not installed, you can install the IBM Toolbox for Java by installing option 3 of | product 5770-SS1. Checking the QUSER profile: The IBM i Host Servers start under the QUSER user profile, so you first need to ensure that the QUSER profile is enabled in order to run IBM Toolbox for Java in a client/server environment. Check the QUSER profile To use the command line to check the QUSER profile, complete the following steps: 1. On a command line, type DSPUSRPRF USRPRF(QUSER) and press Enter. 2. Make sure that the Status is *ENABLED. If the profile status is not *ENABLED, change the QUSER profile. Changing the QUSER user profile: If the QUSER profile is not *ENABLED, you must enable it to start the IBM i Host Servers. Also, the QUSER profile password cannot be *NONE. If this is true, you must reset it. To use the command line to enable the QUSER profile, complete the following steps: 1. Type CHGUSRPRF USRPRF(QUSER) and press ENTER. 2. Change the Status field to *ENABLED and press ENTER. The QUSER user profile is now ready to start the IBM i Host Servers.
Dependencies on other licensed programs: Depending on how you want to use IBM Toolbox for Java, you may need to install other licensed programs. Spooled file viewer When you want to use the spooled file viewer functions (SpooledFileViewer class) of IBM Toolbox for Java, ensure that you have installed host option 8 (AFP Compatibility Fonts) on your server. Note: SpooledFileViewer, PrintObjectPageInputStream, and PrintObjectTransformedInputStream classes work only when connecting to V4R4 or later systems. Secure Sockets Layer When you want to use Secure Sockets Layer (SSL), ensure that you have installed the following: v IBM HTTP Server for i licensed program, 5770-DG1 v IBM i Option 34 (Digital Certificate Manager) For more information about SSL, see Secure Sockets Layer and Java Secure Socket Extension on page 350. HTTP server for using applets, servlets, or SSL If you want to use applets, servlets, or SSL on the IBM i server, you must set up an HTTP server and install the class files on the system. For more information about the IBM HTTP Server for i, see the HTTP Server Web site.
For information about the Digital Certificate Manager and how to create and work with digital certificates using the IBM HTTP Server, see Digital Certificate Management. Compatibility with different levels of IBM i: Because you can use IBM Toolbox for Java both on your server and your client, the compatibility issues affect both running on a server and connecting from a client back to a server. Using IBM Toolbox for Java to connect from a client back to the server You can use different versions of IBM Toolbox for Java on a client and on the server to which you are connecting. To use IBM Toolbox for Java to access data and resources on an IBM i server, the server to which you are connecting must be running one of the following: | v IBM i 7.1 v IBM i 6.1 v IBM i 5.4 The following table shows the compatibility requirements for connecting back to different versions of IBM i. Note: IBM Toolbox for Java does not support forward compatibility. You cannot install IBM Toolbox for Java on or use it to connect to a server that runs a more recent version of IBM i. For example, if you are using the version of IBM Toolbox for Java that ships with IBM i 5.2, you cannot connect to a server that runs IBM i 5.4.
Connects back to IBM i 5.1 and later 5.2 and later 5.3 and later 5.4 and later
5770-SS1
Native optimizations when running on the IBM i JVM: Native optimizations are a set of functions that make the IBM Toolbox for Java classes work the way a user would expect them to work when running on IBM i. The optimizations affect operation of IBM Toolbox for Java only when running on the IBM i JVM. The IBM Toolbox for Java optimizations when running on IBM i are: v Signon: When no userid or password is specified in the AS400 object, the userid and password of the current job are used v Directly calling IBM i APIs instead of making socket calls to host servers: Record-level database access, data queues and user space when security requirements are met. Program call and command call when security requirements and thread safety requirements are met. Note: For best performance, set your JDBC driver property to use the native driver when the Java program and database file are on the same server. No change to the Java application is needed to get the optimizations. IBM Toolbox for Java automatically enables the optimizations when appropriate. In order to gain the performance improvements, you need to make sure to use the JAR file that includes IBM i native optimizations. For more information, see Note 1 in JAR files. When you do not use the JAR file that includes IBM i native optimizations, IBM Toolbox for Java works as if it is running on a client. ToolboxME requirements: Your workstation, wireless device, and server must meet certain requirements (listed below) for developing and running IBM Toolbox for Java 2 Micro Edition applications. Although Toolbox ME is considered a part of IBM Toolbox for Java, it is not included in the licensed product. ToolboxME (jt400Micro.jar) is included in the open source version of Toolbox for Java, called JTOpen. You must separately download and set up ToolboxME, which is contained in JTOpen. Requirements To use ToolboxME, your workstation, Tier0 wireless device, and server must meet the following requirements. Workstation requirements Workstation requirements for developing ToolboxME applications: v A supported version of Java Standard Edition v Java virtual machine for wireless devices v Wireless device simulator or emulator
Wireless device requirements The only requirement for running ToolboxME applications on your Tier0 device is using a Java virtual machine for wireless devices. Server requirements Server requirements for using ToolboxME applications: v MEServer class, which is included in IBM Toolbox for Java or the latest version of JTOpen v IBM i requirements for IBM Toolbox for Java
Although Toolbox ME is considered a part of IBM Toolbox for Java, it is not included in the licensed product. ToolboxME (jt400Micro.jar) is included in the open source version of Toolbox for Java, called JTOpen. You must separately download and set up ToolboxME, which is contained in JTOpen. Requirements To use ToolboxME, your workstation, Tier0 wireless device, and server must meet the following requirements. Workstation requirements Workstation requirements for developing ToolboxME applications: v A supported version of Java Standard Edition v Java virtual machine for wireless devices v Wireless device simulator or emulator Wireless device requirements The only requirement for running ToolboxME applications on your Tier0 device is using a Java virtual machine for wireless devices. Server requirements Server requirements for using ToolboxME applications: v MEServer class, which is included in IBM Toolbox for Java or the latest version of JTOpen v IBM i requirements for IBM Toolbox for Java Workstation Swing requirements for IBM Toolbox for Java: IBM Toolbox for Java switched to support Swing 1.1 in V4R5, and this release continues that support. Switching to Swing required programming changes in the IBM Toolbox for Java classes. So, if your programs use the Graphical Toolbox or the vaccess classes from releases before V4R5, you will need to change your programs as well. In addition to a programming change, the Swing classes must be in the CLASSPATH when the program is run. The Swing classes are part of the Java 2 Platform. If you don't have the Java 2 Platform, you can download the Swing 1.1 classes from Sun Microsystems, Inc.
1. 2. 3. 4. 5. | |
In System i Navigator, sign on to the system that you want to use. In the Function Tree (the left pane), expand My Connections. Under My Connections, right click the system where you want to install IBM Toolbox for Java. Select Run command. In the Restore Licensed Program (RSTLICPGM) dialog, type the following information, then click OK: v Product: 5770-SS1 v Device: The name of the device or save file v Optional part to be restored: 3 Note: For more information, click Help in the Restore Licensed Program (RSTLICPGM) dialog,
You can use System i Navigator to view the status of the resulting Management Central Command task by completing the following steps: 1. Expand Management Central. 2. Expand Task Activity. 3. Under Task Activity, select Commands. 4. In the Detail pane, click on the appropriate Run Command task. Using the command line to install IBM Toolbox for Java To install IBM Toolbox for Java from a command line, complete the following steps: 1. On a command line, use the CL Go to Menu command. Type GO MENU(LICPGM) and press ENTER. 2. Select 11. Install licensed program. | 3. Select 5770-SS1 3 Extended Base Directory Support. For more information about installing licensed programs, see Managing software and licensed programs.
Note: Using the IBM Toolbox for Java classes in your application also requires that your system meets the requirements for IBM i. The IBM Toolbox for Java class files are packaged in several JAR files, consequently you need to copy one or more of these JAR files to your workstation. For more information about which JAR files are required for specific IBM Toolbox for Java functions, see JAR files.
IBM Toolbox for Java
Example: Copying jt400.jar The following example assumes you want to copy jt400.jar, which contains the core IBM Toolbox for Java classes. To manually copy the JAR file, complete the following steps: 1. Find the jt400.jar file in the following directory: /QIBM/ProdData/HTTP/Public/jt400/lib 2. Copy jt400.jar from the server to your workstation. You can do this in a variety of ways: v Use IBM i Access for Windows to map a network drive on your workstation to the server, then copy the file. v Use file transfer protocol (FTP) to send the file (in binary mode) to your workstation. 3. Update the CLASSPATH environment variable of your workstation. v For example, if you are using Windows NT and you copied jt400.jar to C:\jt400\lib, add the following string to the end of your CLASSPATH:
;C:\jt400\lib\jt400.jar
You also have the option of using the open source version of IBM Toolbox for Java, called JTOpen. For more information about JTOpen, see the IBM Toolbox for Java and JTOpen Web site JAR files: The IBM Toolbox for Java is shipped as a set of JAR files. Each JAR file contains Java packages that provide specific functions. You can reduce the amount of required storage space by using only the JAR files required to enable the specific functions that you want. To use a JAR file, make sure that you include an entry for it in your CLASSPATH. The following chart indicates which JAR files you must add to your CLASSPATH to use the associated function or package.
IBM Toolbox for Java package or function Access classes CommandHelpRetriever class on page 246 CommandPrompter Note 3 Commtrace classes HTML classes HTMLDocument class JCA classes JDBC Data Source GUI NLS system and error messages PCML (development and run-time, parsed) PCML (run-time, serialized) PDML (development) Note 3
Note 7
JAR files required to be in your CLASSPATH jt400.jar (client) or jt400Native.jar (server) jt400Proxy.jar in a proxy environment jt400.jar (client) or jt400Native.jar (server) XML parser and XSLT processor Note 3 jt400.jar, jui400.jar, util400.jar
3 Note 4 Note 1
, or and an
Note
Note 1
jt400.jar Note 1 plus jt400Servlet.jar (client), or jt400Native.jar (server) Note 1 The same JAR files required for HTML classes, plus an XML parser and XSLT processor Note 3 jt400.jar (client) or jt400Native.jar (server) jt400.jar (client) Note 1 and jui400.jarNote 5 jt400Mri_lang_cntry.jar Note 6 jt400.jar (client) or jt400Native.jar (server) an XML parser Note 3 jt400.jar (client) or jt400Native.jar (server) uitools.jar, jui400.jar, util400.jar
Note 3 Note 4 Note 1 Note 8 Note 1
, and
Note 1 Note 8
10
Note 3
jt400.jar (client) or jt400Native.jar (server) Note 1, reportwriter JAR files Note 9, and an XML parser and XSLT processor Note 3 jt400.jar (client) or jt400Native.jar (server) jt400.jar (client) or jt400Native.jar (server) XML parser Note 3 jt400.jar (client) or jt400Native.jar (server) jt400Proxy.jar in a proxy environment
Note 1 Note 1
, and an
Note 1
, or
jt400.jar Note 1 plus jt400Servlet.jar (client), or jt400Native.jar (server) Note 1 jt400.jar (client)
Note 1
and tes.jar
IBM Toolbox for Java 2 Micro Edition on page 350 Vaccess classes XPCML
jt400Micro.jar (client) Note 10 and jt400.jar (server) or jt400Native.jar (server)Note 1 jt400.jar (client) Note 1 jt400.jar (client) or jt400Native.jar (server) XML parser and XSLT processor Note 3
Note 1
, and an
Note 1: Do not put both jt400.jar and jt400Native.jar in your CLASSPATH. Choose the JAR file most appropriate for your environment and use only that JAR in your CLASSPATH. Note 2: Some of the IBM Toolbox for Java classes are in more than one JAR file: v jt400.jar - Access, commtrace, JCA, JDBC support, MEServer, PCML, resource, RFML, security, utilities, vaccess, and XPCML. v jt400.zip - Use jt400.jar instead of jt400.zip. jt400.zip is shipped to retain compatibility with previous releases of IBM Toolbox for Java. v jt400Access.zip - The same classes that are in jt400.jar minus the vaccess classes. jtAccess400.zip is shipped to retain compatibility with previous releases of IBM Toolbox for Java. Use jt400.jar or jt400Native.jar instead of jt400Access.zip. v jt400Native.jar - Access, HTML, MEServer, PCML, resource, RFML, security, XPCML, and native optimizations. Native optimizations is a set of classes (fewer than 20) that take advantage of IBM i function when running on the IBM i JVM. Because jt400Native.jar contains the native optimizations, when running on theIBM i JVM, use jt400Native.jar instead of jt400.jar. jt400Native.jar ships with IBM i and resides in directory /QIBM/ProdData/OS400/jt400/lib. v jt400Native11x.jar - Use jt400Native.jar instead of jt400Native11x.jar. jt400Native11x.jar is shipped to retain compatibility with previous releases of IBM Toolbox for Java. Note 3: When you must use an XML parser or XSLT processor, make sure that they are JAXP-compliant. For more information, see the following page: XML parser and XSLT processor on page 415 Note 4: Using CommandPrompter, PDML, or the System i Debugger also requires one additional JAR file that is not part of IBM Toolbox for Java: jhall.jar. For more information about downloading jhall.jar, see the Sun JavaHelp Web site .
11
Note 5: util400.jar contains IBM i-specific classes for formatting input and for using the command line prompter. Using the CommandPrompter class requires util400.jar. Using PDML does not require util400.jar, but it is useful. Note 6: jui400.jar contains the classes necessary to use the JDBC DataSource GUI interface. jt400.jar ( Note 1) contains the classes necessary for all other JDBC functions. Note 7: jt400Mri_xx_yy.jar contains translated messages, including strings contained in exception messages, dialogs, and output from other normal processing. In jt400Mri_lang_cntry.jar, lang = the ISO Language Code and cntry = the ISO Country or Region Code used to translate the contained text. In some cases, the ISO Country or Region Code is not used. Installing a particular national language version of the IBM Toolbox for Java licensed program on the system installs the appropriate jt400Mri_lang_cntry.jar file. If the language is not supported, the install defaults to the English version, which is included in the IBM Toolbox for Java JAR files. | v For example, installing the German language version of licensed program 5770-SS1 installs the German | language JAR file, jt400Mri_de.jar. You can add support for other languages by adding more than one of these JAR files to the classpath. Java loads the correct string based on the current locale. Note 8: Serializing your PCML file during development has two benefits: 1. You need to parse the PCML file only during development and not during run-time 2. Users need fewer JAR files in their CLASSPATH to run the application To parse the PCML file during development, you need both the PCML run-time in data.jar or jt400.jar and the PCML parser in x4j400.jar. To run the serialized application , users need only jt400.jar. For more information, see Building IBM i program calls with PCML on page 379. Note 9: Use jt400.jar and jt400Native.jar instead of data400.jar. data400.jar contains the PCML runtime classes, which are now also in jt400.jar and jt400Native.jar (Note 1). data400.jar is shipped to retain compatibility with previous releases of IBM Toolbox for Java. Note 10: Copies of the ReportWriter classes are in more than one JAR file: v composer.jar v outputwriter.jar v reportwriters.jar If your application streams PCL data to an IBM i spooled file, you must make the access classes available by using the appropriate JAR file ( Note 1). Creating a spooled file to hold PCL data requires the AS400, OutputQueue, PrintParameterList, and SpooledFileOutputStream classes. For more information, see the ReportWriter classes. Note 11: jt400Micro.jar does not contain the classes needed to run MEServer, which reside in both jt400.jar and jt400Native.jar (Note 1). jt400Micro.jar is available only from the IBM Toolbox for Java and JTOpen Web site .
System properties
You can specify system properties to configure various aspects of the IBM Toolbox for Java. For example, you can use system properties to define a proxy server or a level of tracing. System properties are useful for convenient runtime configuration without needing to recompile code. System properties work like environment variables in that when you change a system property during runtime, the change is generally not reflected until the next time you run the application.
12
There are several ways that you can set system properties: v Using the java.lang.System.setProperties() method You can set system properties programmatically by using the java.lang.System.setProperties() method. For example, the following code sets the com.ibm.as400.access.AS400.proxyServer property to hqoffice:
Properties systemProperties = System.getProperties(); systemProperties.put ("com.ibm.as400.access.AS400.proxyServer", "hqoffice"); System.setProperties (systemProperties);
v Using the -D option of the java command Many environments allow you to set system properties when running applications from a command line by using the -D option of the java command. For example, the following program runs the application called Inventory with the com.ibm.as400.access.AS400.proxyServer property set to hqoffice:
java -Dcom.ibm.as400.access.AS400.proxyServer=hqoffice Inventory
v Using a jt400.properties file In some environments, it may be inconvenient to instruct all users to set their own system properties. As an alternative, you can specify IBM Toolbox for Java system properties in a file called jt400.properties that is searched for as if it is part of the com.ibm.as400.access package. In other words, place the jt400.properties file in a com/ibm/as400/access directory pointed to by the classpath. For example, set the com.ibm.as400.access.AS400.proxyServer property to hqoffice by inserting the following line into the jt400.properties file:
com.ibm.as400.access.AS400.proxyServer=hqoffice
The backslash character (\) functions as an escape character in properties files. Specify a literal backslash character by using two backslashes (\\). Modify this sample of a jt400.properties file for your environment. v Using a Properties class Some browsers do not load properties files without explicitly changing security settings. However, most browsers do allow properties in .class files, so IBM Toolbox for Java system properties can also be specified by a class called com.ibm.as400.access.Properties which extends java.util.Properties. For example, to set the com.ibm.as400.access.AS400.proxyServer property to hqoffice, use the following Java code:
package com.ibm.as400.access; public class Properties extends java.util.Properties { public Properties () { put ("com.ibm.as400.access.AS400.proxyServer", "hqoffice"); } }
Modify and compile this sample of a Properties.java source file for your environment. If an IBM Toolbox for Java system property is set using more than one of the mechanisms described above, then the precedence is as follows (in order of decreasing precedence): 1. The system property set programmatically using java.lang.System.setProperties() 2. The system property set using the -D option of the java command 3. The system property set using a Properties class 4. The system property set using a jt400.properties file IBM Toolbox for Java supports the following system properties: v Proxy server properties on page 14
IBM Toolbox for Java
13
v v v v
Trace properties CommandCall/ProgramCall properties FTP properties on page 15 Connection properties on page 15
com.ibm.as400.access.TunnelProxyServer.clientLifetime
Trace properties
Trace property com.ibm.as400.access.Trace.category Description Specifies which trace categories to enable. This is a comma-delimited list containing any combination of trace categories. The complete list of trace categories is defined in the Trace class. Specifies the file to which trace output is written. The default is to write trace output to System.out. Specifies which trace categories to start on the JDBC server job. For information about supported values, see the JDBC server trace property.
com.ibm.as400.access.Trace.file com.ibm.as400.access.ServerTrace.JDBC
CommandCall/ProgramCall properties
CommandCall/ProgramCall property com.ibm.as400.access.CommandCall.threadSafe Description Specifies whether CommandCalls might be assumed to be thread-safe. If true, all CommandCalls are assumed to be thread-safe. If false, all CommandCalls are assumed to be non-thread-safe. This property is ignored for a given CommandCall object if either CommandCall.setThreadSafe() or AS400.setMustUseSockets(true) has been performed on the object.
14
Description Specifies whether ProgramCalls might be assumed to be thread-safe. If true, all ProgramCalls are assumed to be thread-safe. If false, all ProgramCalls are assumed to be non-thread-safe. This property is ignored for a given ProgramCall object if either ProgramCall.setThreadSafe() or AS400.setMustUseSockets(true) has been performed on the object.
FTP properties
FTP property com.ibm.as400.access.FTP.reuseSocket Description Specifies whether the socket is reused for multiple file transfers (through a single FTP instance), when in "active" mode. If true, the socket is reused. If false, a new socket is created for each file transfer. This property is ignored for a given FTP object if FTP.setReuseSocket() has been performed on the object.
Connection properties
Connection property Description Indicates whether the current environment has GUI capability. If true, prompting may occur during signon to display error conditions, to prompt for additional information, or to prompt for change password. If false, error conditions or missing information will result in exceptions. Applications that are running as IBM i applications or want to control the signon user interface may want to run with prompting mode set to false. The default is true. Indicates whether AS400 objects should attempt to add the appropriate secondary language library to the library list when running on the system. Setting the language library will ensure that any system error messages that are returned, will be returned in the appropriate national language for the client locale. If true, AS400 objects will attempt to add the secondary language library to the library list when running on the system. If false, no attempt is made by AS400 objects to add the secondary language library to the library list. The default is false. Specifies whether AS400 objects should use Internet domain sockets only. When your Java program runs on the system, some IBM Toolbox for Java classes create UNIX domain socket connections. If true, only Internet domain sockets will be used by AS400 objects. If false, AS400 objects may use UNIX domain socket connections in addition to Internet domain sockets. The default is false.
| | | | | | | | | | | | | | | | | | | | | | | | | | |
com.ibm.as400.access.AS400.guiAvailable
com.ibm.as400.access.AS400.mustAddLanguageLibrary
com.ibm.as400.access.AS400.mustUseNetSockets
15
Connection property
Description Specifies whether AS400 objects should use sockets. When your Java program runs on the system, some IBM Toolbox for Java classes access data by calling an API instead of making a socket call to the system. There are minor differences in the behavior of the classes when API calls are used instead of socket calls. If your program is affected by these differences you can force the classes to use socket calls instead of API calls by setting this property to true. The default is false. Specifies whether AS400 objects should use a supplied profile only. When your Java program runs on the system, the information from the currently signed-on user profile (*CURRENT) can be used. If true, a user profile must be supplied. If false, AS400 objects retrieves the current user profile information if a user profile is not supplied. . The default is false. Specifies the default signon handler. This property is ignored for a given AS400 object if AS400.setSignonHandler() has been performed on the object, or if AS400.setDefaultSignonHandler() has been called. Specifies whether AS400 objects use threads in communication with the host servers. Letting the IBM Toolbox for Java use threads may be beneficial to performance; turning threads off may be necessary if your application needs to be compliant with the Enterprise Java Beans specification. The default is true.
| | | | | | | | | | | | | | | |
com.ibm.as400.access.AS400.mustUseSockets
com.ibm.as400.access.AS400.mustUseSuppliedProfile
com.ibm.as400.access.AS400.signonHandler
| | | | | |
com.ibm.as400.access.AS400.threadUsed
16
# starts a thread to look for clients that are no longer # communicating. Use this property to set long a client can # be idle before it is cleaned up. com.ibm.as400.access.TunnelProxyServer.clientLifetime=2700 #---------------------------------------------------------# # Trace system properties # #---------------------------------------------------------# # This system property specifies which trace categories to enable. # This is a comma-delimited list containing any combination of trace # categories. The complete list of trace categories is defined in # the Trace class. com.ibm.as400.access.Trace.category=error,warning,information # This system property specifies the file to which trace output # is written. The default is to write trace output to System.out. com.ibm.as400.access.Trace.file=c:\\temp\\trace.out #---------------------------------------------------------# # Command Call system properties # #---------------------------------------------------------# # This system property specifies whether CommandCalls should # be assumed to be thread-safe. If true, all CommandCalls are # assumed to be thread-safe. If false, all CommandCalls are # assumed to be non-thread-safe. This property is ignored # for a given CommandCall object if either # CommandCall.setThreadSafe(true/false) or # AS400.setMustUseSockets(true) has been performed on the object. com.ibm.as400.access.CommandCall.threadSafe=true #---------------------------------------------------------# # Program Call system properties # #---------------------------------------------------------# # This system property specifies whether ProgramCalls should # be assumed to be thread-safe. If true, all ProgramCalls are # assumed to be thread-safe. If false, all ProgramCalls are # assumed to be non-thread-safe. This property is ignored # for a given ProgramCall object if either # ProgramCall.setThreadSafe(true/false) or # AS400.setMustUseSockets(true) has been performed on the object. com.ibm.as400.access.ProgramCall.threadSafe=true #---------------------------------------------------------# # FTP system properties # #---------------------------------------------------------# # This system property specifies whether the socket is reused # for multiple file transfers (through a single FTP instance), # when in "active" mode. # If true, the socket is reused. If false, a new socket is # created for each file transfer. # This property is ignored for a given FTP object if # FTP.setReuseSocket(true/false) has been performed on the object. com.ibm.as400.access.FTP.reuseSocket=true #---------------------------------------------------------# # Connection system properties # #---------------------------------------------------------#
17
# This system property specifies the default signon handler. # This property is ignored for a given AS400 object if # AS400.setSignonHandler() has been performed on # the object, or if AS400.setDefaultSignonHandler() # has been called. com.ibm.as400.access.AS400.signonHandler=mypackage.MyHandler
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
# This system property specifies whether the Toolbox should # assume that the current environment has GUI capability. # This property is ignored for a given AS400 object if # AS400.setGuiAvailable() has been performed on the object. com.ibm.as400.access.AS400.guiAvailable=true # This system property specifies whether the appropriate # secondary language library must be added to the library list, # when running on the system. By default the library is not added. # This property is ignored for a given AS400 object if # AS400.setMustAddLanguageLibrary() has been performed # on the object. com.ibm.as400.access.AS400.mustAddLanguageLibrary=true # This system property specifies whether sockets # must be used when communicating with the system. # Setting this property to true directs the Toolbox to refrain # from exploiting native optimizations, when running directly on # the system. # By default, when running directly on the system the Toolbox # will exploit native optimizations if they are available, # and bypass sockets. # This property is ignored for a given AS400 object if # AS400.setMustUseSockets() has been performed on the object. com.ibm.as400.access.AS400.mustUseSockets=true # This system property specifies whether Internet domain sockets # must be used when communicating with the system. # Setting this property to true directs the Toolbox to refrain # from exploiting Unix sockets, when running directly on # the system. # By default, when running directly on the system the Toolbox # will exploit Unix sockets if they are available, # rather than Internet domain sockets. # This property is ignored for a given AS400 object if # AS400.setMustUseNetSockets() has been performed on the object. com.ibm.as400.access.AS400.mustUseNetSockets=true # This system property specifies whether the explicitly supplied # profile must be used when communicating with the system. # Setting this property to true directs the Toolbox to # refrain from exploiting the currently signed-on profile # by default, when running directly on the system. # This property is ignored for a given AS400 object if # AS400.setMustUseSuppliedProfile() has been performed on the object. com.ibm.as400.access.AS400.mustUseSuppliedProfile=true # This system property specifies whether threads are used # when communicating with the host servers. # By default, the AS400 object creates separate threads # to listen on communication sockets to the host servers. # Setting this property to false directs the Toolbox to refrain # from creating separate threads for host server communications. # This property is ignored for a given AS400 object if # AS400.setThreadUsed() has been performed on the object. com.ibm.as400.access.AS400.threadUsed=true # End
18
19
/*---------------------------------------------------------*/ /* Program Call system properties */ /*---------------------------------------------------------*/ // This system property specifies whether ProgramCalls should // be assumed to be thread-safe. If true, all ProgramCalls are // assumed to be thread-safe. If false, all ProgramCalls are // assumed to be non-thread-safe. This property is ignored // for a given ProgramCall object if either // ProgramCall.setThreadSafe(true/false) or // AS400.setMustUseSockets(true) has been performed on the object. put ("com.ibm.as400.access.ProgramCall.threadSafe", "true"); /*---------------------------------------------------------*/ /* FTP system properties */ /*---------------------------------------------------------*/ // This system property specifies whether the socket is reused // for multiple file transfers (through a single FTP instance), // when in "active" mode. If true, the socket is reused. // If false, a new socket is created for each file transfer. // This property is ignored for a given FTP object if // FTP.setReuseSocket(true/false) has been performed on the object. put ("com.ibm.as400.access.FTP.reuseSocket", "true"); /*---------------------------------------------------------*/ /* Connection system properties */ /*---------------------------------------------------------*/ // This system property specifies the default signon handler. // This property is ignored for a given AS400 object if // AS400.setSignonHandler() has been performed on // the object, or if AS400.setDefaultSignonHandler() // has been called. put ("com.ibm.as400.access.AS400.signonHandler", "mypackage.MyHandler");
| | | | | | | | | | | | | | | | | | | | | | | | | | | |
// This system property specifies whether the Toolbox should // assume that the current environment has GUI capability. // This property is ignored for a given AS400 object if // AS400.setGuiAvailable() has been performed on the object. put ("com.ibm.as400.access.AS400.guiAvailable", "true"); // This system property specifies whether the appropriate // secondary language library must be added to the library list, // when running on the system. By default the library is not added. // This property is ignored for a given AS400 object if // AS400.setMustAddLanguageLibrary() has been performed // on the object. put ("com.ibm.as400.access.AS400.mustAddLanguageLibrary", "true"); // This system property specifies whether sockets // must be used when communicating with the system. // By default, when running directly on the system the Toolbox // will exploit native optimizations if they are available, // and bypass sockets. // This property is ignored for a given AS400 object if // AS400.setMustUseSockets() has been performed on the object. put ("com.ibm.as400.access.AS400.mustUseSockets", "true"); // // // // // This system property specifies whether Internet domain sockets must be used when communicating with the system. Setting this property to true directs the Toolbox to refrain from exploiting Unix sockets, when running directly on the system.
20
| | | | | | | | | | | | | | | | | | | | | | | | |
} }
// By default, when running directly on the system the Toolbox // will exploit Unix sockets if they are available, // rather than Internet domain sockets. // This property is ignored for a given AS400 object if // AS400.setMustUseNetSockets() has been performed on the object. put ("com.ibm.as400.access.AS400.mustUseNetSockets", "true"); // This system property specifies whether the explicitly supplied // profile must be used when communicating with the system. // Setting this property to true directs the Toolbox to // refrain from exploiting the currently signed-on profile // by default, when running directly on the system. // This property is ignored for a given AS400 object if // AS400.setMustUseSuppliedProfile() has been performed on the object. put ("com.ibm.as400.access.AS400.mustUseSuppliedProfile", "true"); // This system property specifies whether threads are used // when communicating with the host servers. // By default, the AS400 object creates separate threads // to listen on communication sockets to the host servers. // Setting this property to false directs the Toolbox to refrain // from creating separate threads for host server communications. // This property is ignored for a given AS400 object if // AS400.setThreadUsed() has been performed on the object. put ("com.ibm.as400.access.AS400.threadUsed", "true");
Access classes
The IBM Toolbox for Java access classes represent IBM i data and resources. Note: IBM Toolbox for Java provides a second set of classes, called the resource classes, for working with IBM i objects and lists. The resource classes present a generic framework and consistent programming interface for working with various IBM i objects and lists. Related information EventLog classes Javadoc Provides a way to log exceptions and messages independent of the device used to display them. Access package summary Resource package summary
21
AS400 class
The IBM Toolbox for Java AS400 class manages a set of socket connections to the server jobs on server and sign-on behavior for the server, including prompting the user for sign-on information, password caching, and default user management. The Java program must provide an AS400 object when the Java program uses an instance of a class that accesses the IBM i system. For example, the CommandCall object requires an AS400 object before it can send commands to the system. The AS400 object handles connections, user IDs, and passwords differently when it is running in the IBM i Java virtual machine. For more information, see IBM i Java virtual machine on page 451. AS400 objects now support Kerberos authentication, using the Java Generic Security Service Application Programming Interface (JGSS API) to authenticate to the server, instead of using a user ID and password. Note: Using Kerberos tickets requires that you install J2SDK, v1.4 and configure the Java Generic Security Services (JGSS) Application Programming Interface. For more information about JGSS, see the J2SDK, v1.4 Security Documentation .
22
See managing connections for information about managing connections to the server through the AS400 object. See the AS400ConnectionPool Javadoc for information about reducing initial connect time by requesting connections from a connection pool. The AS400 class provides the following sign-on functions: v Authenticate the user profile v Get a profile token credential and authenticate the associated user profile v Set a profile token credential v Manage default user IDs v Cache passwords v Prompt for user ID v Change a password v Get the version and release of the operating system For information about using an AS400 object when sending or receiving encrypted data, see the SecureAS400 class. Related information AS400ConnectionPool Javadoc AS400 Javadoc Managing default user IDs: To minimize the number of times a user has to sign on, use a default user ID. The Java program uses the default user ID when a the program does not provide a user ID. The default user ID can be set either by the Java program or through the user interface. If the default user ID has not been established, the Sign-On dialog allows the user to set the default user ID. Once the default user ID is established for a given server, the Sign-On dialog does not allow the default user ID to be changed. When an AS400 object is constructed, the Java program can supply the user ID and password. When a program supplies the user ID to the AS400 object, the default user ID is not affected. The program must explicitly set the default user ID setUseDefaultUser() if the program wants to set or change the default user ID. See Prompting, default user ID, and password caching summary for more information. The AS400 object has methods to get, set, and remove the default user ID. The Java program can also disable default user ID processing through the setUseDefaultUser() method. If default user ID processing is disabled and the Java application does not supply a user ID, the AS400 object prompts for user ID every time a connection is made to the server. All AS400 objects that represent the same IBM i system within a Java virtual machine use the same default user ID. In the following example, two connections to the server are created by using two AS400 objects. If the user checked the Default User ID box when signing on, the user is not prompted for a user ID when the second connection is made.
// Create two AS400 objects to the same system. AS400 sys1 = new AS400("mySystem.myCompany.com"); AS400 sys2 = new AS400("mySystem.myCompany.com"); // Start a connection to the command call service. // The user is prompted for user ID and password. sys1.connectService(AS400.COMMAND);
23
// Start another connection to the command call service. // The user is not prompted. sys2.connectService(AS400.COMMAND);
The default user ID information is discarded when the last AS400 object for the server is garbage collected. Using a password cache: The password cache allows the IBM Toolbox for Java to save password and user ID information so that it does not prompt the user for that information every time a connection is made. Use the methods provided by the AS400 object to do the following: v Clear the password cache and disable the password cache v Minimize the number of times a user must type sign-on information The password cache applies to all AS400 objects that represent an IBM i system within a Java virtual machine. Java does not allow sharing information between virtual machines, so a cached password in one Java virtual machine is not visible to another virtual machine. The cache is discarded when the last AS400 object is garbage collected. The Sign-on dialog has a checkbox that gives the user the option to cache the password. When an AS400 object is constructed, the Java program has the option to supply the user ID and password. Passwords supplied on constructors are not cached. The AS400 object provides methods to clear the password cache and disable the password cache . See Prompting, default user ID, and password caching summary for more information. Prompting for user IDs and passwords: When you are using the AS400 class, prompting for user ID and password may occur when connecting to the server. Prompting can be turned off by your Java program. Java programs can turn off user ID and password prompting and message windows displayed by the AS400 object. An example of when this may be needed is when an application is running on a gateway on behalf of many clients. If prompts and messages are displayed on the gateway machine, the user has no way of interacting with the prompts. These types of applications can turn off all prompting by using the setGuiAvailable() method on the AS400 object. See Prompting, default user ID, and password caching summary for more information. Prompting, default user ID, and password caching summary: Java programs can control when prompting for user ID and password caching occurs. The information from the Sign-On dialog can be used to set the default user ID and cache the password. The following table summarizes when prompting takes place, what information is retrieved, and what information is set. This table assumes that the Java program allows default user ID processing and password caching, and that you checked the Default User ID box and the Save Password box on the Sign-On dialog. Use this table for client connections, not for running Java on your server.
24
Password in Result of using cache for user ID marked settings User is prompted for system name, user ID, and password. Default user ID is established and password is cached.
Yes
User is prompted for user ID and password. System name is displayed but cannot be changed. Default user ID is established and password is cached. Yes User is prompted for password. User ID is displayed and can be changed. System name is displayed but cannot be changed. Default user ID is not changed. Password is cached. Yes No prompt. Default user ID is not changed. Password is not cached. Yes User is prompted for system name and password. User ID is displayed and can be changed. Changing the user ID will not change the default user ID. Password is cached.
Yes
Yes
Yes
25
Password in Result of using cache for user ID marked settings Prompt for password for the default user ID. User ID is displayed and can be changed. System name is displayed but cannot be changed. Password is cached. Yes No prompt. Connect using default user ID and password from cache. No prompt. Connect as specified user using password from cache. No prompt. Connect as specified user using password from cache. No prompt. Connect as specified user.
Yes
Yes
Yes
Yes
Yes
Yes
Yes
Yes
Yes
Yes
Yes
Yes
Yes
SecureAS400 class
The SecureAS400 class enables you to use an AS400 object when sending or receiving encrypted data. When an AS400 object communicates with the server, user data (except the user password) is sent unencrypted to the server. So, IBM Toolbox for Java objects associated with an AS400 object exchange data with the server over a normal connection. When you want to use IBM Toolbox for Java to exchange sensitive data with the server, you can encrypt data by using Secure Sockets Layer (SSL). Use the SecureAS400 object to designate which data you want to encrypt. IBM Toolbox for Java objects associated with a SecureAS400 object exchange data with the server over a secure connection. For more information, see Secure Sockets Layer and Java Secure Socket Extension. The SecureAS400 class is a subclass of the AS400 class. You can set up a secure server connection by creating an instance of a SecureAS400 object in the following ways: v SecureAS400(String systemName, String userID) prompts you for sign-on information v SecureAS400(String systemName, String userID, String password) does not prompt you for sign-on information
26
The following example shows you how to use CommandCall to send commands to the server using a secure connection:
// Create a secure AS400 object. This is the only statement that changes // from the non-SSL case. SecureAS400 sys = new SecureAS400("mySystem.myCompany.com"); // Create a command call object CommandCall cmd = new CommandCall(sys, "myCommand"); // Run the commands. A secure connection is made when the // command is run. All the information that passes between the // client and server is encrypted. cmd.run();
AS400JPing class
The IBM Toolbox for Java AS400JPing class allows your Java program to query the host servers to see which services are running and which ports are in service. To query the servers from a command line, use the JPing class. The AS400JPing class provides several methods: v Ping the server v Ping a specific service on the server v Set a PrintWriter object to which you want to log ping information v Set the time out for the ping operation
BidiTransform class
The IBM Toolbox for Java BidiTransform class provides layout transformations that enable you to convert bidirectional text in IBM i format (after first converting it to Unicode) to bidirectional text in Java format, or from Java format to IBM i format. AS400BidiTransform class The AS400BidiTransform class allows you to: v Get and set the system CCSID v Get and set the string type of IBM i data v Get and set the string type of Java data v Convert data from a Java layout to IBM i v Convert data from an IBM i layout to Java
IBM Toolbox for Java
27
Note: Read the Code example disclaimer for important legal information.
BidiConversionProperties class
The BidiConversionProperties class provides a set of properties that can be used to control the conversion of character set data. Related information BidiConversionProperties Javadoc
CallStackEntry class
The CallStackEntry class represents an entry in the call stack of a specific thread of a server job. Objects of this type are generated by calling Job.getCallStack(). Related information CallStackEntry Javadoc
ClusteredHashTable classes
The IBM Toolbox for Java ClusteredHashTable classes enable your Java programs to use highly available clustered hash tables to share and replicate data to nonpersistent storage among the nodes in a cluster. To use the ClusteredHashTable classes, ensure that you can use nonpersistent storage for the data. Replicated data is not encrypted. Note: The following information assumes that you understand the concepts and terminology common to IBM i cluster technology. See IBM i cluster technology for details. Using the ClusteredHashTable class requires that you have defined and activated a cluster on the systems. You must also start a clustered has table server. For more information, see Configure clusters and Clustered Hash Table APIs. Required parameters are the name of the clustered hash table server and the AS400 object, which represents the system that contains the clustered hash table server. In order to store data in a clustered hash table server, you need a connection handle and a key: v When you open a connection, the clustered hash table server assigns the connection handle that you must specify on subsequent requests to the clustered hash table server. This connection handle is good only for the instantiated AS400 object, so you must open another connection if you use a different AS400 object. v You must specify the key to access and change data in the clustered hash table. Duplicate keys are not supported. The ClusteredHashTable class provides methods that enable you to perform the following actions: v Open a connection to the clustered hash table server job v Generate a unique key to store data into the clustered hash table v Close the active connection to the clustered hash table server job
28
Some methods in the ClusteredHashTable class use the ClusteredHashTableEntry class to perform the following actions: v Get an entry from the clustered hash table v Store an entry in the clustered hash table v Get a list of entries from the clustered hash table for all user profiles
Using the ClusteredHashTable class causes the AS400 object to connect to the server. For more information, see Managing connections.
CommandCall class
The CommandCall class allows a Java program to call a non-interactive IBM i command. Results of the command are available in a list of AS400Message objects. Input to CommandCall is as follows: v The command string to run v The AS400 object that represents the system that will run the command
29
The command string can be set on the constructor, through the CommandCall setCommand() method, or on the run() method. After the command is run, the Java program can use the getMessageList() method to retrieve any IBM i messages resulting from the command. Using the CommandCall class causes the AS400 object to connect to the system. See managing connections for information about managing connections. When the Java program and the IBM i command are on the same server, the default IBM Toolbox for Java behavior is to look up the thread safety for the command on the system. If threadsafe, the command is run on-thread. You can suppress the run-time lookup by explicitly specifying thread-safety for the command by using the setThreadSafe() method.
Examples
The following examples show ways you can use the CommandCall class to run different kinds of commands. Note: Read the Code example disclaimer for important legal information. Example: Running a command The following example shows how to use the CommandCall class to run a command on the system:
// Create an AS400 object. AS400 sys = new AS400("mySystem.myCompany.com"); // Create a command call object. This // program sets the command to run later. // It could set it here on the constructor. CommandCall cmd = new CommandCall(sys); // Run the CRTLIB command cmd.run("CRTLIB MYLIB"); // Get the message list which // contains the result of the command. AS400Message[] messageList = cmd.getMessageList(); // ... process the message list. // Disconnect since I am done sending // commands to the server sys.disconnectService(AS400.COMMAND);
Example: Running a user-specified command Example: Using CommandCall on page 470 shows how to run a command that is specified by the user. Related information CommandCall Javadoc AS400Message Javadoc AS400 Javadoc
Connection pooling
Use connection pools to share connections and manage sets (pools) of connections to an IBM i system. For example, an application can retrieve a connection from a pool, use it, then return it to the pool for reuse. The AS400ConnectionPool class manages a pool of AS400 objects. The AS400JDBCConnectionPool class represents a pool of AS400JDBCConnections that are available for use by a Java program as part of IBM
30
Toolbox for Java support for the JDBC 2.0 Optional Package API. The JDBC ConnectionPool interface is also supported in the JDBC 3.0 API, which is bundled with the Java 2 Platform, Standard Edition, version 1.4. A connection pool of either type keeps track of the number of connections it creates. Using methods inherited from ConnectionPool, you can set several connection pool properties, including: v the maximum number of connections that can be given out by a pool v the maximum lifetime of a connection v the maximum inactivity time of a connection In terms of performance, connecting to the server is an expensive operation. Using connection pools can improve performance by avoiding repeated connection times. For example, create connections when you create the connection pool by filling the pool with active (preconnected) connections using the AS400ConnectionPool class. Instead of creating new connections, you can use a connection pool to easily retrieve, use, return, and reuse the connection objects. Retrieve a connection using an AS400ConnectionPool by specifying the system name, user id, the password, and (optionally) the service. To specify the service to which you want to connect, use constants from the AS400 class (FILE, PRINT, COMMAND, and so on). After retrieving and using the connection, applications return connections to the pool. It is the responsibility of each application to return connections to the pool for reuse. When connections are not returned to the pool, the connection pool continues to grow in size and connections are not reused. See managing connections for more information about managing when a connection to the system is opened when using the AS400ConnectionPool classes.
Data area
The IBM Toolbox for Java DataArea class is an abstract base class that represents an IBM i data area object. This base class has four subclasses that support the following: character data, decimal data, logical data, and local data areas that contain character data. Using the DataArea class, you can do the following: v v v v v Get the size of the data area Get the name of the data area Return the AS400 system object for the data area Refresh the attributes of the data area Set the system where the data area exists
Using the DataArea class causes the AS400 object to connect to the server. See managing connections for information about managing connections.
31
CharacterDataArea
The CharacterDataArea class represents a data area on the server that contains character data. Character data areas do not have a facility for tagging the data with the proper CCSID; therefore, the data area object assumes that the data is in the user's CCSID. When writing, the data area object converts from a string (Unicode) to the user's CCSID before writing the data to the server. When reading, the data area object assumes that the data is the CCSID of the user and converts from that CCSID to Unicode before returning the string to the program. When reading data from the data area, the amount of data read is by number of characters, not by the number of bytes. Using the CharacterDataArea class, you can do the following: v Clear the data area so that it contains all blanks. v Create a character data area on the system using default property values v Create a character data area with specific attributes v Delete the data area from the system where the data area exists v Return the IFS path name of the object represented by the data area. v Read all of the data that is contained in the data area v v v v Read a specified amount of data from the data area starting at offset 0 or the offset that you specified Set the fully qualified integrated file system path name of the data area Write data to the beginning of the data area Write a specified amount of data to the data area starting at offset 0 or the offset that you specified
DecimalDataArea
The DecimalDataArea class represents a data area on the server that contains decimal data. Using the DecimalDataArea class, you can do the following: v Clear the data area so that it contains 0.0 v Create a decimal data area on the system using default property values v v v v v v Create a decimal data area with specified attributes Delete the data area from the server where the data area exists Return the number of digits to the right of the decimal point in the data area Return the IFS path name of the object represented by the data area. Read all of the data that is contained in the data area Set the fully qualified integrated file system path name of the data area
v Write data to the beginning of the data area Example: Using DecimalDataArea The following example shows how to create and to write to a decimal data area: Note: Read the Code example disclaimer for important legal information.
// Establish a connection to the server "MyServer". AS400 system = new AS400("MyServer"); // Create a DecimalDataArea object. QSYSObjectPathName path = new QSYSObjectPathName("MYLIB", "MYDATA", "DTAARA"); DecimalDataArea dataArea = new DecimalDataArea(system, path.getPath()); // Create the decimal data area on the server using default values. dataArea.create(); // Clear the data area. dataArea.clear(); // Write to the data area. dataArea.write(new BigDecimal("1.2"));
32
// Read from the data area. BigDecimal data = dataArea.read(); // Delete the data area from the server. dataArea.delete();
LocalDataArea
The LocalDataArea class represents a local data area on the server. A local data area exists as a character data area on the server, but the local data area does have some restrictions of which you should be aware. The local data area is associated with a server job and cannot be accessed from another job. Therefore, you cannot create or delete the local data area. When the server job ends, the local data area associated with that server job is automatically deleted, and the LocalDataArea object that is referring to the job is no longer valid. You should also note that local data areas are a fixed size of 1024 characters on the server. Using the LocalDataArea class, you can do the following: v Clear the data area so that it contains all blanks v Read all of the data that is contained in the data area v Read a specified amount of data from the data area starting at offset that you specified v Write data to the beginning of the data area v Write a specified amount of data to the data area where the first character is written to offset
LogicalDataArea
The LogicalDataArea class represents a data area on the server that contains logical data. Using the LogicalDataArea class, you can do the following: v Clear the data area so that it contains false v Create a character data area on the server using default property values v v v v v v Create a character data area with specified attributes Delete the data area from the server where the data area exists Return the IFS path name of the object represented by the data area. Read all of the data that is contained in the data area Set the fully qualified integrated file system path name of the data area Write data to the beginning of the data area
DataAreaEvent
The DataAreaEvent class represents a data area event. You can use the DataAreaEvent class with any of the DataArea classes. Using the DataAreaEvent class, you can do the following: v Get the identifier for the event
DataAreaListener
The DataAreaListener class provides an interface for receiving data area events. You can use the the DataAreaListener class with any of the DataArea classes. You can invoke the DataAreaListener class when any of the following are performed: v Clear
IBM Toolbox for Java
33
v v v v
Create Delete Read Write DataArea Javadoc CharacterDataArea Javadoc DecimalDataArea Javadoc LocalDataArea Javadoc LogicalDataArea Javadoc DataAreaEvent Javadoc DataAreaListener Javadoc
Data types
The AS400DataType is an interface that defines the methods required for data conversion. A Java program uses data types when individual pieces of data need to be converted. Conversion classes exist for the following types of data: v Numeric v Text (character) v Composite (numeric and text) Example: Using AS400DataType classes The following example illustrates using AS400DataType classes with ProgramCall to supply data for program parameters and to interpret the data returned in program parameters. Example: Using AS400DataType classes with ProgramCall
34
Record format conversion can be useful when you are working with data from the program call, data queue, and record-level access classes. The input and output from these classes are byte arrays that can contain many fields of various types. Record format converters can make it easier to convert this data between IBM i format and Java format. Conversion through record format uses three classes: v v v v FieldDescription classes identify a field or parameter with a data type and a name. A RecordFormat class describes a group of fields. A Record class joins the description of a record (in the RecordFormat class) with the actual data. A LineDataRecordWriter class writes a record to an OutputStream in line data format
Examples: Using record format conversion classes The following examples illustrate using the record format conversion classes with data queues: Using the Record and RecordFormat classes to put data on a queue Using the FieldDescription, RecordFormat, and Record classes AS400DataType Javadoc Conversion classes for numeric data: Conversion classes for numeric data convert numeric data from the format used on the IBM i (called system format in the following table) to the Java format. Supported types are shown in the following table:
Numeric Type AS400Bin2 AS400Bin4 AS400ByteArray Description Converts between a signed two-byte number in the system format to a Java Short object. Converts between a signed four-byte number in the system format and a Java Integer object. Converts between two byte arrays. This is useful because the converter correctly zero-fills and pads the target buffer. Converts between a signed four-byte floating point number in the system format and a Java Float object. Converts between a signed eight-byte floating point number in the system format and a Java Double object. Converts between a packed-decimal number in the system format and a Java BigDecimal object. Converts between an unsigned two-byte number in the system format and a Java Integer object. Converts between an unsigned four-byte number in the system format and a Java Long object. Converts between a zoned-decimal number in the system format and a Java BigDecimal object.
Examples The following examples show data conversions that use a numeric type in the system format and a Java int:
IBM Toolbox for Java
35
Text conversion: Character data is converted through the IBM Toolbox for Java AS400Text class. This class converts character data between an EBCDIC code page and character set (CCSID), and Unicode. When the AS400Text object is constructed, the Java program specifies the length of the string to be converted and the server CCSID or encoding. The CCSID of the Java program is assumed to be 13488 Unicode. The toBytes() method converts from Java form to byte array inIBM i format. The toObject() method converts from a byte array in IBM i format to Java format. The AS400BidiTransform class provides layout transformations that allow the conversion of bidirectional text in IBM i format (after its conversion to Unicode) to bidirectional text in Java format, or from Java format to IBM i format. The default conversion is based on the CCSID of the job. To alter the direction and shaping of the text, specify a BidiStringType. Note that where IBM Toolbox for Java objects perform the conversion internally, as in the DataArea class, the objects have a method to override the string type. For example, the DataArea class has addVetoableChangeListener() method that you can specify to listen for a veto changes to certain properties, including string type. Example: Converting text data The following example assumes that a DataQueueEntry object returns text in EBCDIC. The example converts the EBCDIC data to Unicode, so that the Java program can use data:
// Assume the data queue work has already been done to // retrieve the text from the system and the data has been // put in the following buffer. int textLength = 100; byte[] data = new byte[textLength]; // Create a converter for the system data type. Note a default // converter is being built. This converter assumes the IBM i // EBCDIC code page matches the client's locale. If this is not
36
// true the Java program can explicitly specify the EBCDIC // CCSID to use. However, it is recommended that you specify a // CCSID whenever possible (see the Notes: below). AS400Text textConverter = new AS400Text(textLength) // Note: Optionally, you can create a converter for a specific // CCSID. Use an AS400 object in case the program is running // as an IBM Toolbox for Java proxy client. int ccsid = 37; AS400 system = ...; // AS400 object AS400Text textConverter = new AS400Text(textLength, ccsid, system); // Note: You can also create a converter with just the AS400 object. // This converter assumes the IBM i code page matches // the CCSID returned by the AS400 object. AS400Text textConverter = new AS400Text(textLength, system); // Convert the data from EBCDIC to Unicode. If the length of // the AS400Text object is longer than the number of // converted characters, the resulting String will be // blank-padded out to the specified length. String javaText = (String) textConverter.toObject(data);
Related information AS400Text Javadoc AS400BidiTransform Javadoc BidiStringType Javadoc Conversion classes for composite types: This topic describes IBM Toolbox for Java conversion classes for composite types. v AS400Array - Allows the Java program to work with an array of data types. v AS400Structure - Allows the Java program to work with a structure whose elements are data types. Example: Converting composite data types The following example shows conversion from a Java structure to a byte array and back again. The example assumes that the same data format is used for both sending and receiving data.
// Create a structure of data types that corresponds to a structure // that contains: - a four-byte number // - four bytes of pad // - an eight-byte number // - 40 characters AS400DataType[] myStruct = { new AS400Bin4(), new AS400ByteArray(4), new AS400Float8(), new AS400Text(40) }; // Create a conversion object using the structure. AS400Structure myConverter = new AS400Structure(myStruct); // Create the Java object Object[] myData = { new Integer(88), new byte[0], new Double(23.45), "This is my structure" }; that holds the data to send to the server. // // // // the the the the four-byte number pad (let the conversion object 0 pad) eight-byte floating point number character string
37
// Convert from Java object to byte array. byte[] myAS400Data = myConverter.toBytes(myData); // ... send the byte array to the server. Get data back from the // server. The returned data will also be a byte array. // Convert the returned data from IBM i to Java format. Object[] myRoundTripData = (Object[])myConverter.toObject(myAS400Data,0); // Pull the third object out of the structure. This is the double. Double doubleObject = (Double) myRoundTripData[2]; // Extract the simple Java type from the Java object. double d = doubleObject.doubleValue();
AS400Array Javadoc AS400Structure Javadoc FieldDescription classes: The field description classes allow the Java program to describe the contents of a field or parameter with a data type and a string containing the name of the field. If the program is working with data from record-level access, it can also specify any IBM i data definition specification (DDS) keywords that further describe the field. Field description classes The field description classes are as follows: v BinaryFieldDescription v CharacterFieldDescription v DateFieldDescription v v v v v v v v v v DBCSEitherFieldDescription DBCSGraphicFieldDescription DBCSOnlyFieldDescription DBCSOpenFieldDescription FloatFieldDescription HexFieldDescription PackedDecimalFieldDescription TimeFieldDescription TimestampFieldDescription ZonedDecimalFieldDescription
Example: Creating field descriptions The following example assumes that the entries on a data queue have the same format. Each entry has a message number (AS400Bin4), a time stamp (8 characters), and message text (50 characters) that you can describe with field descriptions:
// Create a field description for the numeric data. Note it uses the // AS400Bin4 data type. It also names the field so it can be accessed by // name in the record class. BinaryFieldDescription bfd = new BinaryFieldDescription(new AS400Bin4(), "msgNumber"); // Create a field description for the character data. Note it uses the // AS400Text data type. It also names the field so it can be accessed by // name by the record class.
38
CharacterFieldDescription cfd1 = new CharacterFieldDescription(new AS400Text(8), "msgTime"); // Create a field description for the character data. Note it uses the // AS400Text data type. It also names the field so it can be accessed by // name by the record class. CharacterFieldDescription cfd2 = new CharacterFieldDescription(new AS400Text(50), "msgText");
You can now group the field descriptions in an instance of the RecordFormat class. To see how to add the field descriptions to a RecordFormat object, see the example on the following page: RecordFormat class RecordFormat class: The IBM Toolbox for Java RecordFormat class allows the Java program to describe a group of fields or parameters. A record object contains data described by a RecordFormat object. If the program is using record-level access classes, the RecordFormat class also allows the program to specify descriptions for key fields. A RecordFormat object contains a set of field descriptions. The field description can be accessed by index or by name. Methods exist on the RecordFormat class to do the following: v Add field descriptions to the record format. v Add key field descriptions to the record format. v Retrieve field descriptions from the record format by index or by name. v Retrieve key field descriptions from the record format by index or by name. v Retrieve the names of the fields that make up the record format. v Retrieve the names of the key fields that make up the record format. v Retrieve the number of fields in the record format. v Retrieve the number of key fields in the record format. v Create a Record object based on this record format. Example: Adding field descriptions to a record format The following example adds the field descriptions created in the field description example to a record format:
// Create a record format object, then fill it with field descriptions. RecordFormat rf = new RecordFormat(); rf.addFieldDescription(bfd); rf.addFieldDescription(cfd1); rf.addFieldDescription(cfd2);
To see how to create a record from the record format, see the example on the following page: Record class RecordFormat Javadoc Record class: The IBM Toolbox for Java record class allows the Java program to process data described by the record format class. Data is converted between byte arrays containing the server data and Java objects. Methods are provided in the record class to do the following: v Retrieve the contents of a field, by index or by name, as a Java object. v Retrieve the number of fields in the record.
IBM Toolbox for Java
39
v v v v
Set the contents of a field, by index or by name, with a Java object. Retrieve the contents of the record as server data into a byte array or output stream. Set the contents of the record from a byte array or an input stream. Convert the contents of the record to a String.
Example: Reading a record The following example uses the record format created in the record format example:
// Assume data queue setup work has already been done. Now read a // record from the data queue. DataQueueEntry dqe = dq.read(); // The data from the data queue is now in a data queue entry. Get // the data out of the data queue entry and put it in the record. // We obtain a default record from the record format object and // initialize it with the data from the data queue entry. Record dqRecord = rf.getNewRecord(dqe.getData()); // Now that the data is in the record, pull the data out one // field at a time, converting the data as it is removed. The result // is data in a Java object that the program can now process. Integer msgNumber = (Integer) dqRecord.getField("msgNumber"); String msgTime = (String) dqRecord.getField("msgTime"); String msgText = (String) dqRecord.getField("msgText");
Related information Record Javadoc Retrieving the contents of a field: Retrieve the contents of a Record object by having your Java program either get one field at a time or get all the fields at once. Use the getField() method of the Record class to retrieve a single field by name or by index. Use the getFields() method to retrieve all of the fields as an Object[]. The Java program must cast the Object (or element of the Object[]) returned to the appropriate Java object for the retrieved field. The following table shows the appropriate Java object to cast based on the field type.
Field Type (DDS) BINARY (B), length <= 4 BINARY (B), length >= 5 CHARACTER (A) DBCS Either (E) DBCS Graphic (G) DBCS Only (J) DBCS Open (O) DATE (L) FLOAT (F), single precision FLOAT (F), double precision HEXADECIMAL (H) PACKED DECIMAL (P) TIME (T) Field Type (FieldDescription) BinaryFieldDescription BinaryFieldDescription CharacterFieldDescription DBCSEitherFieldDescription DBCSGraphicFieldDescription DBCSOnlyFieldDescription DBCSOpenFieldDescription DateFieldDescription FloatFieldDescription FloatFieldDescription HexFieldDescription PackedDecimalFieldDescription TimeDecimalFieldDescription Java Object Short Integer String String String String String String Float Double byte[] BigDecimal String
40
Related information Record Javadoc Setting the contents of a field: Set the contents of a Record object by using the setField() method in your Java program. The Java program must specify the appropriate Java object for the field being set. The following table shows the appropriate Java object for each possible field type.
Field Type (DDS) BINARY (B), length <= 4 BINARY (B), length >= 5 CHARACTER (A) DBCS Either (E) DBCS Graphic (G) DBCS Only (J) DBCS Open (O) DATE (L) FLOAT (F), single precision FLOAT (F), double precision HEXADECIMAL (H) PACKED DECIMAL (P) TIME (T) TIMESTAMP (Z) ZONED DECIMAL (P) Field Type (FieldDescription) BinaryFieldDescription BinaryFieldDescription CharacterFieldDescription DBCSEitherFieldDescription DBCSGraphicFieldDescription DBCSOnlyFieldDescription DBCSOpenFieldDescription DateFieldDescription FloatFieldDescription FloatFieldDescription HexFieldDescription PackedDecimalFieldDescription TimeDecimalFieldDescription TimestampDecimalFieldDescription ZonedDecimalFieldDescription Java Object Short Integer String String String String String String Float Double byte[] BigDecimal String String BigDecimal
Related information Record Javadoc LineDataRecordWriter class: The LineDataRecordWriter class writes the record data, in line data format, to an OutputStream. The class translates the data into bytes by using the specified CCSID. The record format associated with the record determines the format of the data. LineDataRecordWriter Using LineDataRecordWriter requires that the following record format attributes be set: v Record format ID v Record format type In conjunction with the Record or the RecordFormat classes, the LineDataRecordWriter takes a record as input to the writeRecord() method. (Record takes a RecordFormat as input when you instantiate it.)
41
The LineDataRecordWriter class provides methods that allow you to: v Get the CCSID v Get the name of the encoding v Write the record data, in line data format, to an OutputStream Example: Using the LineDataRecordWriter class Note: Read the Code example disclaimer for important legal information. The following example shows one way to use the LineDataRecordWriter class to write a record:
// Example using the LineDataRecordWriter class. try { // create a ccsid ccsid_ = system_.getCcsid(); // create output queue and specify spooled file data to be *LINE OutputQueue outQ = new OutputQueue(system_, "/QSYS.LIB/RLPLIB.LIB/LDRW.OUTQ"); PrintParameterList parms = new PrintParameterList(); parms.setParameter(PrintObject.ATTR_PRTDEVTYPE, "*LINE"); // initialize the record format for writing data RecordFormat recfmt = initializeRecordFormat(); // create a record and assign data to be printed... Record record = new Record(recfmt); createRecord(record); SpooledFileOutputStream os = null; try { // create the output spooled file to hold the record data os = new SpooledFileOutputStream(system_, parms, null, outQ); } catch (Exception e) { System.out.println("Error occurred creating spooled file"); e.printStackTrace(); } // create the line data record writer LineDataRecordWriter ldw; ldw = new LineDataRecordWriter(os, ccsid_, system_); // write the record of data ldw.writeRecord(record); // close the outputstream os.close(); } catch(Exception e) { failed(e, "Exception occurred."); }
Data queues
The DataQueue classes allow the Java program to interact with server data queues. IBM i data queues have the following characteristics:
42
v The data queue allows for fast communications between jobs. Therefore, it is an excellent way to synchronize and pass data between jobs. v Many jobs can simultaneously access the data queues. v Messages on a data queue are free format. Fields are not required as they are in database files. v The data queue can be used for either synchronous or asynchronous processing. v The messages on a data queue can be ordered in one the following ways: Last-in first-out (LIFO). The last (newest) message that is placed on the data queue is the first message that is taken off the queue. First-in first-out (FIFO). The first (oldest) message that is placed on the data queue is the first message that is taken off the queue. Keyed. Each message on the data queue has a key associated with it. A message can be taken off the queue only by specifying the key that is associated with it. The data queue classes provide a complete set of interfaces for accessing server data queues from your Java program. It is an excellent way to communicate between Java programs and programs on the server that are written in any programming language. A required parameter of each data queue object is the AS400 object that represents the server that has the data queue or where the data queue is to be created. Using the data queue classes causes the AS400 object to connect to the server. See managing connections for information about managing connections. Each data queue object requires the integrated file system path name of the data queue. The type for the data queue is DTAQ. See integrated file system path names for more information.
43
// read data from the queue DataQueueEntry dqData = dq.read(); // get the data out of the DataQueueEntry object. byte[] data = dqData.getData(); // ... process the data // Disconnect since I am done using data queues sys.disconnectService(AS400.DATAQUEUE);
Related information BaseDataQueue Javadoc DataQueue Javadoc KeyedDataQueue Javadoc DataQueueEntry Javadoc KeyedDataQueueEntry Javadoc Sequential data queues: Entries on a sequential data queue on the server are removed in first-in first-out (FIFO) or last-in first-out (LIFO) sequence. The BaseDataQueue and DataQueue classes provide the following methods for working with sequential data queues: v Create a data queue on the server. The Java program must specify the maximum size of an entry on the data queue. The Java program can optionally specify additional data queue parameters (FIFO vs LIFO, save sender information, specify authority information, force to disk, and provide a queue description) when the queue is created. v Peek at an entry on the data queue without removing it from the queue. The Java program can wait or return immediately if no entry is currently on the queue. v Read an entry off the queue. The Java program can wait or return immediately if no entry is available on the queue. v Write an entry to the queue. v Clear all entries from the queue. v Delete the queue. The BaseDataQueue class provides additional methods for retrieving the attributes of the data queue. Examples: Working with sequential data queues The following sequential data queue examples illustrate how a producer puts items on a data queue and how a consumer takes the items off the queue and processes them: Example: Using DataQueue classes to put data on a queue on page 485 Example: Using DataQueue classes to read entries off a data queue on page 488 BaseDataQueue Javadoc DataQueue Javadoc Keyed data queues: The BaseDataQueue and KeyedDataQueue classes provide methods for working with keyed data queues.
44
v Create a keyed data queue on the system. The Java program must specify key length and maximum size of an entry on the queue. The Java program can optionally specify authority information, save sender information, force to disk, and provide a queue description. v Peek at an entry based on the specified key without removing it from the queue. The Java program can wait or return immediately if no entry is currently on the queue that matches the key criteria. v Read an entry off the queue based on the specified key. The Java program can wait or return immediately if no entry is available on the queue that matches the key criteria. v Write a keyed entry to the queue. v Clear all entries or all entries that match a specified key. v Delete the queue. The BaseDataQueue and KeyedDataQueue classes also provide additional methods for retrieving the attributes of the data queue. Examples: Working with keyed data queues The following keyed data queue examples illustrate how a producer puts items on a data queue, and how a consumer takes the items off the queue and processes them: Example: Using KeyedDataQueue on page 493 Example: Using KeyedDataQueue classes to read entries off a data queue on page 496 BaseDataQueue Javadoc KeyedDataQueue Javadoc
Digital certificates
Digital certificates are digitally-signed statements used for secured transactions over the internet. To make a secure connection using the Secure Sockets Layer (SSL), a digital certificate is required. Digital certificates comprise the following: v The public encryption key of the user v The name and address of the user v The digital signature of a third-party certification authority (CA). The authority's signature means that the user is a trusted entity. v The issue date of the certificate v The expiration date of the certificate As an administrator of a secured server, you can add a certification authority's "trusted root key" to the server. This means that your server will trust anyone who is certified through that particular certification authority. Digital certificates also offer encryption, ensuring a secure transfer of data through a private encryption key. You can create digital certificates through the javakey tool. (For more information about javakey and Java security, see the Sun Microsystems, Inc., Java Security page that administer digital certificates on the system. .) The IBM Toolbox for Java has classes
The AS400Certificate classes provide methods to manage X.509 ASN.1 encoded certificates. Classes are provided to do the following: v Get and set certificate data.
IBM Toolbox for Java
45
v List certificates by validation list or user profile. v Manage certificates, for example, add a certificate to a user profile or delete a certificate from a validation list. Using a certificate class causes the AS400 object to connect to the server. See managing connections for information about managing connections. On the server, certificates belong to a validation list or to a user profile. v The AS400CertificateUserProfileUtil class has methods for managing certificates on a user profile. v The AS400CertificateVldlUtil class has methods for managing certificates in a validation list. Using AS400CertificateUserProfileUtil and AS400CertificateVldlUtil requires that you install base operating system option 34 (Digital Certificate Manager). These two classes extend AS400CertificateUtil, which is an abstract base classes that defines methods common to both subclasses. The AS400Certificate class provides methods to read and write certificate data. Data is accessed as an array of bytes. The Java.Security package in Java virtual machine 1.2 provides classes that can be used to get and set individual fields of the certificate.
Listing certificates
To get a list of certificates, the Java program must do the following: 1. Create an AS400 object. 2. Construct the correct certificate object. Different objects are used for listing certificates on a user profile (AS400CertificateUserProfileUtil) versus listing certificates in a validation list (AS400CertificateVldlUtil). 3. Create selection criteria based on certificate attributes. The AS400CertificateAttribute class contains attributes used as selection criteria. One or more attribute objects define the criteria that must be met before a certificate is added to the list. For example, a list might contain only certificates for a certain user or organization. 4. Create a user space on the server and put the certificate into the user space. Large amounts of data can be generated by a list operation. The data is put into a user space before it can be retrieved by the Java program. Use the listCertificates() method to put the certificates into the user space. 5. Use the AS400CertificateUtil getCertificates() method to retrieve certificates from the user space.
46
// The user space must exist before calling this API. int count = certificateList.listCertificates(attributeList, "/QSYS.LIB/MYLIB.LIB/MYSPACE.USRSPC"); // Retrieve the certificates from the user space. AS400Certificates[] certificates = certificateList.getCertificates("/QSYS.LIB/MYLIB.LIB/MYSPACE.USRSPC", 0, 8); // Process the certificates
EnvironmentVariable class
The IBM Toolbox for Java EnvironmentVariable class and the EnvironmentVariableList class enable you to access and set IBM i system-level environment variables. Each variable has unique identifiers: the system name and the environment variable name. Each environment variable is associated with a CCSID, which is by default the CCSID of the current job, which describes where the contents of the variable are stored. Note: Environment variables are different than system values, although they are often used for the same purpose. See SystemValues for more information on how to access system values. Use an EnvironmentVariable object to perform the following actions on an environment variable: v Get and set the name v Get and set the system v Get and set the value (which allows you to change the CCSID) v Refresh the value
Exceptions
The IBM Toolbox for Java access classes throw exceptions when device errors, physical limitations, programming errors, or user input errors occur. The exception classes are based upon the type of error that occurs instead of the location where the error originates. Most exceptions contain the following information: v Error type: The exception object that is thrown indicates the type of error that occurred. Errors of the same type are grouped together in an exception class.
47
v Error details: The exception contains a return code to further identify the cause of the error that occurred. The return code values are constants within the exception class. v Error text: The exception contains a text string that describes the error that occurred. The string is translated in the locale of the client Java virtual machine.
FileAttributes class
The IBM Toolbox for Java FileAttributes class represents the set of file attributes that can be retrieved and set through the Get Attributes (Qp0lGetAttr) and Set Attributes (Qp0lSetAttr) APIs. To obtain the attributes of an object, the object must exist and the caller must have authority to it. Only attributes supported by the specific file system, object type, and system operating release can be retrieved or set. You can find a complete list of the available attributes in the FileAttributes Javadoc.
48
Related information FileAttributes Javadoc Get Attributes (Qp0lGetAttr) API Set Attributes (Qp0lSetAttr) API
FTP class
The IBM Toolbox for Java FTP class provides a programmable interface to FTP functions. You are no longer required to use java.runtime.exec() or tell your users to run FTP commands in a separate application. That is, you can program FTP functions directly into your application. So, from within your program, you can do the following: v Connect to an FTP server v Send commands to the server v List the files in a directory v Get files from the server and put files to the server Example: Using FTP to copy files from a server Note: Read the Code example disclaimer for important legal information. For example, with the FTP class, you can copy a set of files from a directory on a server:
FTP client = new FTP("myServer", "myUID", "myPWD"); client.cd("/myDir"); client.setDataTransferType(FTP.BINARY); String [] entries = client.ls(); for (int i = 0; i < entries.length; i++) { System.out.println("Copying " + entries[i]); try { client.get(entries[i], "c:\\ftptest\\" + entries[i]); } catch (Exception e) { System.out.println(" copy failed, likely this is a directory"); } } client.disconnect();
FTP is a generic interface that works with many different FTP servers. Therefore, it is up to the programmer to match the semantics of the server.
AS400FTP subclass
While the FTP class is a generic FTP interface, the AS400FTP subclass is written specifically for the FTP server on the server. That is, it understands the semantics of the FTP server on the IBM i. For example, this class understands the various steps needed to transfer a save file to the server and performs these steps automatically. AS400FTP also ties into the security facilities of the IBM Toolbox for Java. As with other IBM Toolbox for Java classes, AS400FTP depends on the AS400 object for system name, user ID, and password. Example: Using AS400FTP to save a file to the server Note: Read the Code example disclaimer for important legal information.
49
The following example puts a save file to the server. Note the application does not set data transfer type to binary or use CommandCall to create the save file. Since the extension is .savf, AS400FTP class detects the file to put is a save file so it does these steps automatically.
AS400 system = new AS400(); AS400FTP ftp = new AS400FTP(system); ftp.put("myData.savf", "/QSYS.LIB/MYLIB.LIB/MYDATA.SAVF");
v Cache the contents of a directory to improve performance by limiting calls to the server v Determine the number of bytes available on the server file system v Allow a Java applet to access files in the server file system v Read and write data as text instead of as binary data v Determine the type of the file object (logical, physical, save, and so on) when the object is in the QSYS.LIB file system Through the integrated file system classes, the Java program can directly access stream files on the system. The Java program can still use the java.io package, but the client operating system must then provide a method of redirection. For example, if the Java program is running on a Windows 95 or Windows NT operating system, the Network Drives function of IBM i Access for Windows is required to redirect java.io calls to the system. With the integrated file system classes, you do not need IBM i Access for Windows. A required parameter of the integrated file system classes is the AS400 object that represents the system that contains the file. Using the integrated file system classes causes the AS400 object to connect to the system. See managing connections for information about managing connections. The integrated file system classes require the hierarchical name of the object in the integrated file system. Use the forward slash as the path separator character. The following example shows how to access FILE1 in directory path DIR1/DIR2:
/DIR1/DIR2/FILE1
Examples: Using integrated file system classes Example: Using IFS classes to copy a file from one directory to another on page 504 shows how to use the integrated file system classes to copy a file from one directory to another on the system. Example: Using the IFS classes to list the contents of a directory on page 506 shows how to use the integrated file system classes to list the contents of a directory on the system.
50
IFSFile class: The IBM Toolbox for Java IFSFile class represents an object in the IBM i integrated file system. The methods on IFSFile represent operations that are done on the object as a whole. You can use IFSFileInputStream, IFSFileOutputStream, and IFSRandomAccessFile to read and write to the file. The IFSFile class allows the Java program to do the following: v Determine if the object exists and is a directory or a file v Determine if the Java program can read from or write to a file v v v v v v v Determine the length of a file Determine the permissions of an object and set the permissions of an object Create a directory Delete a file or directory Rename a file or directory Get or set the last modification date of a file List the contents of a directory
v List the contents of a directory and save the attribute information to a local cache v Determine the amount of space available on the system v Determine the type of the file object when it is in the QSYS.LIB file system You can get the list of files in a directory by using either the list() method or the listFiles() method: v The listFiles() method caches information for each file on the initial call. After calling listFiles(), using other methods to query file details results in better performance because the information is retrieved from the cache. For example, calling isDirectory() on an IFSFile object returned from listFiles() does not require a call to the server. v The list() method retrieves information about each file in a separate request to the server, making it slower and more demanding of server resources. Note: Using listFiles() means that the information in the cache may eventually become stale, so you may need to refresh the data by calling listFiles() again. Examples The following examples show how to use the IFSFile class: v Example: Creating a directory on page 500 v Example: Using IFSFile exceptions to track errors on page 500 v Example: Listing files with a .txt extension on page 501 v Example: Using the IFSFile listFiles() method to list the contents of a directory on page 501 Related information IFSFile Javadoc IFSJavaFile class: This IBM Toolbox for Java class represents a file in the IBM i integrated file system and extends the java.io.File class. IFSJavaFile allows you to write files for the java.io.File interface that access integrated file systems. IFSJavaFile makes portable interfaces that are compatible with java.io.File and uses only the errors and exceptions that java.io.File uses. IFSJavaFile uses the security manager features from java.io.File, but unlike java.io.File, IFSJavaFile uses security features continuously.
51
You use IFSJavaFile with IFSFileInputStream and IFSFileOutputStream. It does not support java.io.FileInputStream and java.io.FileOutputStream. IFSJavaFile is based on IFSFile; however, its interface is more like java.io.File than IFSFile. IFSFile is an alternative to the IFSJavaFile class. You can get the list of files in a directory by using either the list() method or the listFiles() method: v The listFiles() method performs better because it retrieves and caches information for each file on the initial call. After that, information about each file is retrieved from the cache. v The list() method retrieves information about each file in a separate request, making it slower and more demanding of server resources. Note: Using listFiles() means that the information in the cache eventually become stale, so you may need to refresh the data. Example: Using IFSJavaFile Note: Read the Code example disclaimer for important legal information. The following example shows how to use the IFSJavaFile class:
// Work with /Dir/File.txt on the system flash. AS400 as400 = new AS400("flash"); IFSJavaFile file = new IFSJavaFile(as400, "/Dir/File.txt"); // Determine the parent directory of the file. String directory = file.getParent(); // Determine the name of the file. String name = file.getName(); // Determine the file size. long length = file.length(); // Determine when the file was last modified. Date date = new Date(file.lastModified()); // Delete the file. if (file.delete() == false) { // Display the error code. System.err.println("Unable to delete file."); } try { IFSFileOutputStream os = new IFSFileOutputStream(file.getSystem(), file, IFSFileOutputStream.SHARE_ALL, false); byte[] data = new byte[256]; int i = 0; for (; i < data.length; i++) { data[i] = (byte) i; os.write(data[i]); } os.close(); } catch (Exception e) { System.err.println ("Exception: " + e.getMessage()); }
52
Related information IFSJavaFile Javadoc IFSFileInputStream: The IBM Toolbox for Java IFSFileInputStream class represents an input stream for reading data from a file on the server. As in the IFSFile class, methods exist in IFSFileInputStream that duplicate the methods in FileInputStream from the java.io package. In addition to these methods, IFSFileInputStream has additional methods specific to the IBM i platform. The IFSFileInputStream class allows a Java program to do the following: v Open a file for reading. The file must exist since this class does not create files on the server. You can use a constructor that allows you to specify the file sharing mode. v Determine the number of bytes in the stream. v Read bytes from the stream. v Skip bytes in the stream. v Lock or unlock bytes in the stream. v Close the file. As in FileInputStream in java.io, this class allows a Java program to read a stream of bytes from the file. The Java program reads the bytes sequentially with only the additional option of skipping bytes in the stream. In addition to the methods in FileInputStream, IFSFileInputStream gives the Java program the following options: v Locking and unlocking bytes in the stream. See IFSKey for more information. v Specifying a sharing mode when the file is opened. See sharing modes for more information. Example: Using IFSFileInputStream The following example shows how to use the IFSFileInputStream class.
// Create an AS400 object. AS400 sys = new AS400("mySystem.myCompany.com"); // Open a file object that represents the file. IFSFileInputStream aFile = new IFSFileInputStream(sys,"/mydir1/mydir2/myfile"); // Determine the number of bytes in the file. int available = aFile.available(); // Allocate a buffer to hold the data byte[] data = new byte[10240]; // Read the entire file 10K at a time for (int i = 0; i < available; i += 10240) { aFile.read(data); } // Close the file. aFile.close();
53
Related information IFSFileInputStream Javadoc IFSTextFileInputStream class: IFSTextFileInputStream has been deprecated and replaced by class IFSFileReader. The IFSTextFileInputStream class represents a stream of character data read from a file. The data read from the IFSTextFileInputStream object is supplied to the Java program in a Java String object, so it is always Unicode. When the file is opened, the IFSTextFileInputStream object determines the CCSID of the data in the file. If the data is stored in an encoding other than Unicode, the IFSTextFileInputStream object converts the data from the file's encoding to Unicode before giving the data to the Java program. If the data cannot be converted, an UnsupportedEncodingException is thrown. The following example shows how to use the IFSTextFileInputStream:
// Work with /File on the system mySystem. AS400 as400 = new AS400("mySystem"); IFSTextFileInputStream file = new IFSTextFileInputStream(as400, "/File"); // Read the first four characters of the file. String s = file.read(4); // Display the characters read. Read the first four // characters of the file. If necessary, the data is // converted to Unicode by the IFSTextFileInputStream object. System.out.println(s); // Close the file. file.close();
Related reference IFSFileReader Use this class for reading character files in the integrated file system. IFSFileReader: Use this class for reading character files in the integrated file system. IFSFileReader is meant for reading streams of characters. IFSFileReader replaces IFSTextFileOutputStream. Example: Using IFSFileReader The following example illustrates the use of IFSFileReader:
import java.io.BufferedReader; // Work with /File1 on the system eniac. AS400 system = new AS400("eniac"); IFSFile file = new IFSFile(system, "/File1"); BufferedReader reader = new BufferedReader(new IFSFileReader(file)); // Read the first line of the file, converting characters. String line1 = reader.readLine(); // Display the String that was read. System.out.println(line1); // Close the reader. reader.close();
54
Related information IFSFileReader Javadoc IFSFileOutputStream class: The IFSFileOutputStream class represents an output stream for writing data to a file on the server. As in the IFSFile class, methods exist in IFSFileOutputStream that duplicate the methods in FileOutputStream from the java.io package. IFSFileOutputStream also has additional methods specific to the server. The IFSFileOutputStream class allows a Java program to do the following: v Open a file for writing. If the file already exists, it is replaced. Constructors are available that specify the file sharing mode and whether the contents of an existing file have been appended. v Write bytes to the stream. v Commit to disk the bytes that are written to the stream. v Lock or unlock bytes in the stream. v Close the file. As in FileOutputStream in java.io, this class allows a Java program to sequentially write a stream of bytes to the file. In addition to the methods in FileOutputStream, IFSFileOutputStream gives the Java program the following options: v Locking and unlocking bytes in the stream. See IFSKey for more information. v Specifying a sharing mode when the file is opened. See sharing modes for more information. Example: Using IFSFileOutputStream The following example shows how to use the IFSFileOutputStream class:
// Create an AS400 object AS400 sys = new AS400("mySystem.myCompany.com"); // Open a file object that represents the file. IFSFileOutputStream aFile = new IFSFileOutputStream(sys,"/mydir1/mydir2/myfile"); // Write to the file byte i = 123; aFile.write(i); // Close the file. aFile.close();
IFSFileOutputStream Javadoc IFSTextFileOutputStream class: IFSTextFileOutputStream has been deprecated and replaced by class IFSFileWriter. The IFSTextFileOutputStream class represents a stream of character data being written to a file. The data supplied to the IFSTextFileOutputStream object is in a Java String object so the input is always Unicode. The IFSTextFileOutputStream object can convert the data to another CCSID as it is written to the file, however. The default behavior is to write Unicode characters to the file, but the Java program can set the target CCSID before the file is opened. In this case, the IFSTextFileOutputStream object converts the characters from Unicode to the specified CCSID before writing them to the file. If the data cannot be converted, an UnsupportedEncodingException is thrown.
55
Example: Using IFSTextFileOutputStream The following example shows how to use IFSTextFileOutputStream:
// Work with /File on the system mySystem. AS400 as400 = new AS400("mySystem"); IFSTextFileOutputStream file = new IFSTextFileOutputStream(as400, "/File"); // Write a String to the file. Because no CCSID was // specified before writing to the file, Unicode // characters will be written to the file. The file // will be tagged as having Unicode data. file.write("Hello world"); // Close the file. file.close();
Related reference IFSFileWriter Use IFSFileWriter for writing character files in the integrated file system. IFSFileWriter is meant for writing streams of characters. IFSFileWriter: Use IFSFileWriter for writing character files in the integrated file system. IFSFileWriter is meant for writing streams of characters. IFSFileWriter is the replacement of IFSTextFileOutputStream. Example: Using IFSFileWriter The following example illustrates the use of IFSFileWriter:
import java.io.PrintWriter; import java.io.BufferedWriter; // Work with /File1 on the system mysystem. AS400 as400 = new AS400("mysystem"); IFSFile file = new IFSFile(system, "/File1"); PrintWriter writer = new PrintWriter(new BufferedWriter(new IFSFileWriter(file))); // Write a line of text to the file, converting characters. writer.println(text); // Close the file. writer.close();
Related information IFSFileWriter Javadoc IFSRandomAccessFile: The IBM Toolbox for Java IFSRandomAccessFile class represents a file on the server for reading and writing data. The Java program can read and write data sequentially or randomly. As in IFSFile, methods exist in IFSRandomAccessFile that duplicate the methods in RandomAccessFile from the java.io package. In addition to these methods, IFSRandomAccessFile has additional methods specific to IBM i. Through IFSRandomAccessFile, a Java program can do the following: v Open a file for read, write, or read/write access. The Java program can optionally specify the file sharing mode and the existence option.
56
v v v v
Read data at the current offset from the file. Write data at the current offset to the file. Get or set the current offset of the file. Close the file.
In addition to the methods in java.io RandomAccessFile, IFSRandomAccessFile gives the Java program the following options: v v v v v Committing to disk bytes written. Locking or unlocking bytes in the file. Locking and unlocking bytes in the stream. See IFSKey for more information. Specifying a sharing mode when the file is opened. See sharing modes for more information. Specify the existence option when a file is opened. The Java program can choose one of the following: Open the file if it exists; create the file if it does not. Replace the file if it exists; create the file if it does not. Fail the open if the file exists; create the file if it does not. Open the file if it exists; fail the open if it does not. Replace the file if it exists; fail the open if it does not. Example: Using IFSRandomAccessFile The following example shows how to use the IFSRandomAccessFile class to write four bytes at 1K intervals to a file.
// Create an AS400 object. AS400 sys = new AS400("mySystem.myCompany.com"); // Open a file object that represents the file. IFSRandomAccessFile aFile = new IFSRandomAccessFile(sys,"/mydir1/myfile", "rw"); // Establish the data to write. byte i = 123; // Write to the file 10 times at 1K intervals. for (int j=0; j<10; j++) { // Move the current offset. aFile.seek(j * 1024); // Write to the file. The current offset advances // by the size of the write. aFile.write(i); } // Close the file. aFile.close();
Related information IFSRandomAccessFile Javadoc IFSFileDialog: The IBM Toolbox for Java IFSFileDialog class allows you to traverse the file system and select a file. This class uses the IFSFile class to traverse the list of directories and files in the IBM i integrated file system. Methods on the class allow a Java program to set the text on the push buttons of the dialog and to set filters. Note that an IFSFileDialog class based on Swing 1.1 is also available.
57
You can set filters through the FileFilter class. If the user selects a file in the dialog, the getFileName() method can be used to get the name of the file that was selected. The getAbsolutePath() method can be used to get the path and name of the file that was selected. Example: Using IFSFileDialog The following example shows how to set up a dialog with two filters and to set the text on the push buttons of the dialog.
// Create an AS400 object. AS400 sys = new AS400("mySystem.myCompany.com"); // Create a dialog object setting the text of the dialog's title // bar and the server to traverse. IFSFileDialog dialog = new IFSFileDialog(this, "Title Bar Text", sys); // Create a list of filters then set the filters in the dialog. The // first filter will be used when the dialog is first displayed. FileFilter[] filterList = {new FileFilter("All files (*.*)", "*.*"), new FileFilter("HTML files (*.HTML", "*.HTM")}; dialog.setFileFilter(filterList, 0); // Set the text on the buttons of the dialog. dialog.setOkButtonText("Open"); dialog.setCancelButtonText("Cancel"); // Show the dialog. If the user selected a file by pressing the // Open button, get the file the user selected and display it. if (dialog.showDialog() == IFSFileDialog.OK) System.out.println(dialog.getAbsolutePath());
Related information FileFilter Javadoc IFSFileDialog Javadoc IFSKey class: If the Java program allows other programs access to a file at the same time, the Java program can lock bytes in the file for a period of time. During that time, the program has exclusive use of that section of the file. When a lock is successful, the integrated file system classes return an IFSKey object. This object is supplied to the unlock() method to indicate which bytes to unlock. When the file is closed, the system unlocks all locks that are still on the file (the system does an unlock for every lock that the program did not unlock). Example: Using IFSKey The following example shows how to use the IFSKey class.
// Create an AS400 object. AS400 sys = new AS400("mySystem.myCompany.com"); // Open an input stream. This constructor opens with // share_all so other programs can open this file. IFSFileInputStream aFile = new IFSFileInputStream(sys,"/mydir1/mydir2/myfile"); // Lock the first 1K bytes in the file. Now no other // instance can read these bytes. IFSKey key = aFile.lock(1024); // Read the first 1K of the file. byte data[] = new byte[1024];
58
aFile.read(data); // Unlock the bytes of the file. aFile.unlock(key); // Close the file. aFile.close();
Related information IFSKey Javadoc File sharing mode: The Java program can specify a sharing mode when a file is opened. The program either allows other programs to open the file at the same time or has exclusive access to the file. The following example shows how to specify a file sharing mode.
// Create an AS400 object. AS400 sys = new AS400("mySystem.myCompany.com"); // Open a file object that represents the file. Since // this program specifies share-none, all other open // attempts fail until this instance is closed. IFSFileOutputStream aFile = new IFSFileOutputStream(sys, "/mydir1/mydir2/myfile", IFSFileOutputStream.SHARE_NONE, false); // Perform operations on the file. // Close the file. Now other open requests succeed. aFile.close();
IFSSystemView: IFSSystemView provides a gateway to the IBM i integrated file system, for use when constructing javax.swing.JFileChooser objects. JFileChooser is a standard Java way to build dialogs for navigating and choosing files. Example: Using IFSSystemView The following example demonstrates the use of IFSSystemView:
import import import import import com.ibm.as400.access.AS400; com.ibm.as400.access.IFSJavaFile; com.ibm.as400.access.IFSSystemView; javax.swing.JFileChooser; java.awt.Frame;
// Work with directory /Dir on the system myAS400. AS400 system = new AS400("myAS400"); IFSJavaFile dir = new IFSJavaFile(system, "/Dir"); JFileChooser chooser = new JFileChooser(dir, new IFSSystemView(system)); Frame parent = new Frame(); int returnVal = chooser.showOpenDialog(parent); if (returnVal == JFileChooser.APPROVE_OPTION) { IFSJavaFile chosenFile = (IFSJavaFile)(chooser.getSelectedFile()); System.out.println("You selected the file named " + chosenFile.getName()); }
IBM Toolbox for Java
59
ISeriesNetServer class
The ISeriesNetServer class represents the NetServer service on a server. This class allows the user to query and modify the state and configuration of the NetServer. ISeriesNetServer replaces the NetServer class. Related information ISeriesNetServer Javadoc
JavaApplicationCall class
The JavaApplicationCall class provides you with the ability to have your client use the server JVM to run a Java program that resides on the server. After establishing a connection to the server from the client, the JavaApplicationCall class lets you configure the following: 1. Set the CLASSPATH environment variable on the server with the setClassPath() method 2. Define your program's parameters with the setParameters() method 3. Run the program with run() 4. Send input from the client to the Java program. The Java program reads the input via standard input which is set with the sendStandardInString() method. You can redirect standard output and standard error from the Java program to the client via the getStandardOutString() and getStandardErrorString(). JavaApplicationCall is a class you call from your Java program. However, the IBM Toolbox for Java also provides utilities to call Java programs that reside on the server. These utilities are complete Java programs you can run from your workstation. See RunJavaApplication class for more information.
Example
The example in the JavaApplicationCall Javadoc reference documentation shows how to run a program on the server (that outputs "Hello World!") from the client: JavaApplicationCall Related information JavaApplicationCall Javadoc
JDBC classes
JDBC is an application programming interface (API) included in the Java platform that enables Java programs to connect to a wide range of databases.
Supported interfaces
The following table lists the supported JDBC interfaces and the API required to use them:
Supported JDBC interface Blob provides access to binary large objects (BLOBs). CallableStatement runs SQL stored procedures. Clob provides access to character large objects (CLOBs). Connection represents a connection to a specific database. ConnectionPool represents a pool of Connection objects. API required JDBC 2.1 core, enhanced support in JDBC 4.0 JDK 1.1, enhanced support in JDBC 4.0 JDBC 2.1 core, enhanced support in JDBC 4.0 JDK 1.1, enhanced support in JDBC 4.0 JDBC 2.0 Optional Package
60
Supported JDBC interface ConnectionPoolDataSource represents a factory for pooled AS400JDBCPooledConnection objects. DatabaseMetaData provides information about the database as a whole.
API required JDBC 2.0 Optional Package JDK 1.1, enhanced support in JDBC 4.0
DataSource represents a factory for database connections. JDBC 2.0 Optional Package, enhanced support in JDBC 4.0 Driver creates the connection and returns information about the driver version. ParameterMetaData provides the ability to get information about the types and properties of the parameters in a PreparedStatement object. PooledConnection provides hooks for connection pool management. PreparedStatement runs compiled SQL statements. JDK 1.1 JDBC 3.0 API, enhanced support in JDBC 4.0
JDBC 2.0 Optional Package, enhanced support in JDBC 4.0 JDK 1.1, enhanced support in JDBC 4.0
ResultSet provides access to a table of data that is JDK 1.1, enhanced support in JDBC 4.0 generated by running a SQL query or DatabaseMetaData catalog method. ResultSetMetaData provides information about a specific ResultSet. RowId represents an SQL ROWID value. RowSet is a connected row set that encapsulates a ResultSet. Savepoint provides finer grained control within transactions JDK 1.1, enhanced support in JDBC 4.0 JDBC 4.0 JDBC 2.0 Optional Package JDBC 3.0 API JDBC 4.0 JDK 1.1, enhanced support in JDBC 4.0
SQLXML represents an SQL XML value. Statement runs SQL statements and obtains the results. StatementEvent is sent to all StatementEventListeners which were registered with a PooledConnection. This occurs when the driver determines that a PreparedStatement that is associated with the PooledConnection has been closed or is determined by the driver to be invalid. StatementEventListener registers to be notified of events that occur on PreparedStatements that are in the Statement pool. XAConnection is a database connection which participates in global XA transactions. XAResource is resource manager for use in XA transactions.
JDBC 4.0
61
Related reference JDBC on page 315 JDBC is an application programming interface (API) included in the Java platform that enables Java programs to connect to a wide range of databases. Example: Using JDBCPopulate to create and populate a table on page 509 This program uses the IBM Toolbox for Java JDBC driver to create and populate a table. Example: Using JDBCQuery to query a table on page 520 This program uses the IBM Toolbox for Java JDBC driver to query a table and output its contents. Related information JTOpen: The Open Source version of the IBM Toolbox for Java AS400JDBCConnectionPoolDataSource Javadoc AS400JDBCPooledConnection Javadoc RowID AS400JDBCBlob class: You can use a AS400JDBCBlob object to access binary large objects (BLOBs), such as sound byte (.wav) files or image (.gif) files. The key difference between the AS400JDBCBlob class and the AS400JDBCBlobLocator class is where the blob is stored. With the AS400JDBCBlob class, the blob is stored in the database, which inflates the size of the database file. The AS400JDBCBlobLocator class stores a locator (think of it as a pointer) in the database file that points to where the blob is located. With the AS400JDBCBlob class, the lob threshold property can be used. This property specifies the maximum large object (LOB) size (in kilobytes) that can be retrieved as part of a result set. LOBs that are larger than this threshold are retrieved in pieces using extra communication to the server. Larger LOB thresholds reduce the frequency of communication to the server, but they download more LOB data, even if it is not used. Smaller lob thresholds may increase frequency of communication to the server, but they only download LOB data as it is needed. See JDBC properties for information about additional properties that are available. Using the AS400JDBCBlob class, you can do the following: v v v v v Return the entire blob as a stream of uninterpreted bytes Return part of the contents of the blob Return the length of the blob Create a binary stream to write to the blob Write a byte array to the blob
v Write all or a portion of byte array to the blob v Truncate the blob Examples The following examples show how to use the AS400JDBCBlob class to read from a blob and update a blob: Example: Using the AS400JDBCBlob class to read from a blob
Blob blob = resultSet.getBlob(1); long length = blob.length(); byte[] bytes = blob.getBytes(1, (int) length);
62
ResultSet rs = statement.executeQuery ("SELECT BLOB FROM MYTABLE"); rs.absolute(5); Blob blob = rs.getBlob(1); // Change the bytes in the blob, starting at the seventh byte // of the blob blob.setBytes (7, new byte[] { (byte) 57, (byte) 58, (byte) 98}); //Update the blob in the result set, changing the blob starting // at the seventh byte of the blob (1-based) and truncating the // blob at the end of the updated bytes (the blob now has 9 bytes). rs.updateBlob(1, blob); // Update the database with the change. This will change the blob // in the database starting at the seventh byte of the blob, and // truncating at the end of the updated bytes. rs.updateRow(); rs.close();
AS400JDBCBlobLocator class You can use a AS400JDBCBlobLocator object to access a binary large objects. Using the AS400JDBCBlobLocator class, you can do the following: v Return the entire blob as a stream of uninterpreted bytes v Return part of the contents of the blob v Return the length of the blob v Create a binary stream to write to the blob v Write a byte array to the blob v Write all or a portion of byte array to the blob v Truncate the blob AS400JDBCBlob Javadoc AS400JDBCBlobLocator Javadoc CallableStatement interface: Use a CallableStatement object to run SQL stored procedures. The stored procedure being called must already be stored in the database. CallableStatement does not contain the stored procedure, it only calls the stored procedure. A stored procedure can return one or more ResultSet objects and can use IN parameters, OUT parameters, and INOUT parameters. Use Connection.prepareCall() to create new CallableStatement objects. The CallableStatement object allows you to submit multiple SQL commands as a single group to a database through the use of batch support. You may get better performance by using batch support because processing a group of operations is usually faster than processing them one at a time. For more information about using batch support, see Enhancements to JDBC support. CallableStatement allows you to get and set parameters and columns by name, although using the column index results in better performance. Example: Using CallableStatement The following example shows how to use the CallableStatement interface.
63
// Connect to the server. Connection c = DriverManager.getConnection("jdbc:as400://mySystem"); // Create the CallableStatement object. It precompiles the // specified call to a stored procedure. The question marks // indicate where input parameters must be set and where output // parameters can be retrieved. The first two parameters are // input parameters, and the third parameter is an output parameter. CallableStatement cs = c.prepareCall("CALL MYLIBRARY.ADD (?, ?, ?)"); // Set input parameters. cs.setInt (1, 123); cs.setInt (2, 234); // Register the type of the output parameter. cs.registerOutParameter (3, Types.INTEGER); // Run the stored procedure. cs.execute (); // Get the value of the output parameter. int sum = cs.getInt (3); // Close the CallableStatement and the Connection. cs.close(); c.close();
AS400JDBCCallableStatement Javadoc AS400JDBCClob class: You can use a AS400JDBCClob object to access character large objects (CLOBs), such as large documents. The key difference between the AS400JDBCClob class and the AS400JDBCClobLocator class is where the blob is stored. With the AS400JDBCClob class, the clob is stored in the database, which inflates the size of the database file. The AS400JDBCClobLocator class stores a locator (think of it as a pointer) in the database file that points to where the clob is located. With the AS400JDBCClob class, the lob threshold property can be used. This property specifies the maximum large object (LOB) size (in kilobytes) that can be retrieved as part of a result set. LOBs that are larger than this threshold are retrieved in pieces using extra communication to the server. Larger LOB thresholds reduce the frequency of communication to the server, but they download more LOB data, even if it is not used. Smaller lob thresholds may increase frequency of communication to the server, but they only download LOB data as it is needed. See IBM Toolbox for Java JDBC properties on page 327 for information about additional properties that are available. Using the AS400JDBCClob class, you can do the following: v Return the entire clob as a stream of ASCII characters v Return the contents of the clob as a character stream v Return a part of the contents of the clob v Return the length of the clob v Create a Unicode character stream or an ASCII character stream to write to the clob v Write a String to the clob v Truncate the clob Examples The following examples show how to use the AS400JDBCClob class to read from a clob and update a clob:
64
AS400JDBCClobLocator class You can use a AS400JDBCClobLocator object to access character large objects (CLOBs). Using the AS400JDBCClobLocator class, you can do the following: v Return the entire clob as a stream of ASCII characters v Return the entire clob as a character stream v v v v v Return a part of the contents of the clob Return the length of the clob Create a Unicode character stream or an ASCII character stream to write to the clob Write a String to the clob Truncate the clob AS400JDBCClob Javadoc AS400JDBCClobLocator Javadoc AS400JDBCConnection class: The AS400JDBCConnection class provides a JDBC connection to a specific DB2 for IBM i database. Use DriverManager.getConnection() to create new AS400JDBCConnection objects. For more information, see Registering the JDBC driver on page 78. There are many optional properties that can be specified when the connection is created. Properties can be specified either as part of the URL or in a java.util.Properties object. See IBM Toolbox for Java JDBC properties on page 327 for a complete list of properties supported by the AS400JDBCDriver. Note: A connection may contain at most 9999 open statements. AS400JDBCConnection includes support for savepoints and statement-level holdability, and limited support for returning auto-generated keys. For more information about these and other enhancements, see Enhancements to JDBC support for Version 5 Release 3 on page 324.
IBM Toolbox for Java
65
To use Kerberos tickets, set only the system name (and not the password) on your JDBC URL object. The user identity is retrieved through the Java Generic Security Services (JGSS) framework, so you also do not need to specify a user on your JDBC URL. You can set only one means of authentication in an AS400JDBCConnection object at a time. Setting the password clears any Kerberos ticket or profile token. For more information, see the AS400 class on page 22 and J2SDK, v1.4 Security Documentation Using the AS400JDBCConnection class, you can do the following: v Create a statement (Statement, PreparedStatement, or CallableStatement objects) v Create a statement that has a specific result set type and concurrency (Statement, PreparedStatement, or CallableStatement objects) v Commit and rollback changes to the database and release database locks currently held v Close the connection, closing server resources immediately instead of waiting for them to be automatically released v v v v v Set holdability and get holdability for the Connection Set the transaction isolation and get the transaction isolation for the Connection Get the meta data for the Connection Set auto commit on or off Get the job identifier of the host server job that corresponds to the Connection .
If you use JDBC 3.0 and connect to a server running IBM i 5.2 or later, you can use AS400JDBCConnection to perform the following actions: v Create a statement with a specific result set holdability (Statement, PreparedStatement, or CallableStatement object) v Create a prepared statement that returns any auto-generated keys (when getGeneratedKeys() is called on the Statement object) v Use savepoints, which offer more granular control over transactions: Set savepoints Rollback savepoints Release savepoints AS400JDBCConnection Javadoc AS400JDBCConnectionPool: The AS400JDBCConnectionPool class represents a pool of AS400JDBCConnection objects that are available for use by a Java program as part of IBM Toolbox for Java support for the JDBC 2.0 Optional Package API. You can use an AS400JDBCConnectionPoolDataSource to specify properties for the connections that are created in the pool, as in the following example. You cannot change the connection pool data source after you have requested a connection and the pool is in use. To reset the connection pool data source, first call close() on the pool. Return connections to an AS400JDBCConnectionPool by using close() on the AS400JDBCConnection object. Note: When connections are not returned to the pool, the connection pool continues to grow in size and connections are not reused.
66
Set properties on the pool by using methods inherited from ConnectionPool. Some of the properties that you can set include: v maximum number of connections to allow in the pool v maximum lifetime of a connection v maximum inactivity time of a connection. You can also register AS400JDBCConnectionPoolDataSource objects by using a Java Naming and Directory Interface (JNDI) service provider. For more information about JNDI service providers, see IBM Toolbox for Java reference links. Example: Using connection pool The following example gets a connection pool data source from JNDI and uses it to create a connection pool with 10 connections:
// Obtain an AS400JDBCConnectionPoolDataSource object from JNDI // (assumes JNDI environment is set). Context context = new InitialContext(environment); AS400JDBCConnectionPoolDataSource datasource = (AS400JDBCConnectionPoolDataSource)context.lookup("jdbc/myDatabase"); // Create an AS400JDBCConnectionPool object. AS400JDBCConnectionPool pool = new AS400JDBCConnectionPool(datasource); // Adds 10 connections to the pool that can be used by the // application (creates the physical database connections based on // the data source). pool.fill(10); // Get a handle to a database connection from the pool. Connection connection = pool.getConnection(); // ... Perform miscellaneous queries/updates on the database. // Close the connection handle to return it to the pool. connection.close(); // ... Application works with some more connections from the pool. // Close the pool to release all resources. pool.close();
AS400JDBCConnectionPool Javadoc AS400JDBCConnectionPool Javadoc AS400JDBCConnectionPoolDataSource Javadoc AS400JDBCManagedConnectionPoolDataSource class: The JDBC connection pool is a managed connection pool that allows you to reuse connections. The AS400JDBCManagedConnectionPoolDataSource class simplifies connection pool maintenance by eliminating the need for user applications to implement their own management code. The connection pool is used in combination with the JDBC DataSource interface mechanism. The class AS400JDBCManagedConnectionPoolDataSource contains an implementation of the javax.sql.DataSource interface. This class manages the functionality of the connection pooling mechanism and allows you to access it like a normal DataSource. Setting up and using self-managed JDBC connection pool manager involves the usage of Java Naming and Directory Interface (JNDI) to bind the connection pool managed datasource. In order for self-managed JDBC connection pooling to function, JNDI is necessary. These properties allow you to configure the attributes of the connection pool:
IBM Toolbox for Java
67
v v v v v
v PropertyCycle v ReuseConnections For more information, see the Javadocs on setX() methods where X is the property. Examples: Using AS400JDBCManagedConnectionPoolDataSource class: These examples demonstrate the use of the AS400JDBCManagedConnectionPoolDataSource class. The AS400JDBCManagedConnectionPoolDataSource class simplifies connection pool maintenance by eliminating the need for user applications to implement their own management code. Note: By using the code examples, you agree to the terms of the Code license and disclaimer information on page 758. Example 1 This brief example shows the basic use of the AS400JDBCManagedConnectionPoolDataSource class.
import javax.naming.Context; import javax.naming.InitialContext; import javax.sql.DataSource; import com.ibm.as400.access.AS400JDBCManagedConnectionPoolDataSource; import com.ibm.as400.access.AS400JDBCManagedDataSource; public class TestJDBCConnPoolSnippet { void test() { AS400JDBCManagedConnectionPoolDataSource cpds0 = new AS400JDBCManagedConnectionPoolDataSource(); // Set general datasource properties. Note that both connection pool datasource (CPDS) and managed // datasource (MDS) have these properties, and they might have different values. cpds0.setServerName(host); cpds0.setDatabaseName(host);//iasp can be here cpds0.setUser(userid); cpds0.setPassword(password); cpds0.setSavePasswordWhenSerialized(true); // Set connection pooling-specific properties. cpds0.setInitialPoolSize(initialPoolSize_); cpds0.setMinPoolSize(minPoolSize_); cpds0.setMaxPoolSize(maxPoolSize_); cpds0.setMaxLifetime((int)(maxLifetime_/1000)); // convert to seconds cpds0.setMaxIdleTime((int)(maxIdleTime_/1000)); // convert to seconds cpds0.setPropertyCycle((int)(propertyCycle_/1000)); // convert to seconds //cpds0.setReuseConnections(false); // do not re-use connections // Set the initial context factory to use. System.setProperty(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory"); // Get the JNDI Initial Context. Context ctx = new InitialContext(); // Note: The following is an alternative way to set context properties locally: // Properties env = new Properties(); // env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory"); // Context ctx = new InitialContext(env); ctx.rebind("mydatasource", cpds0); // We can now do lookups on cpds, by the name "mydatasource".
68
// Create a standard DataSource object that references it. AS400JDBCManagedDataSource mds0 = new AS400JDBCManagedDataSource(); mds0.setDescription("DataSource supporting connection pooling"); mds0.setDataSourceName("mydatasource"); ctx.rebind("ConnectionPoolingDataSource", mds0); DataSource dataSource_ = (DataSource)ctx.lookup("ConnectionPoolingDataSource"); AS400JDBCManagedDataSource mds_ = (AS400JDBCManagedDataSource)dataSource_; boolean isHealthy = mds_.checkPoolHealth(false); //check pool health Connection c = dataSource_.getConnection(); } }
Example 2 This example shows more details about how to use the AS400JDBCManagedConnectionPoolDataSource class.
import import import import import import import import import import import import import import import import import import import import import import java.awt.TextArea; java.io.BufferedReader; java.io.File; java.io.FileReader; java.io.FileInputStream; java.io.FileOutputStream; java.io.OutputStream; java.io.PrintStream; java.util.Vector; java.util.Properties; java.sql.Connection; javax.sql.DataSource; java.sql.ResultSet; java.sql.Statement; javax.naming.*; java.util.Date; java.util.ArrayList; java.util.Random; com.ibm.as400.access.AS400; com.ibm.as400.access.AS400JDBCManagedConnectionPoolDataSource; com.ibm.as400.access.AS400JDBCManagedDataSource; com.ibm.as400.access.Trace;
public class TestJDBCConnPool { private static final boolean DEBUG = false; // If you turn this flag on, be sure to also turn on the following flag: // AS400JDBCConnection.TESTING_THREAD_SAFETY. private static final boolean TESTING_THREAD_SAFETY = false; private static String userid; private static String password; private static String host; // Note: For consistency, all private int initialPoolSize_; private int minPoolSize_; private int maxPoolSize_; private long maxLifetime_; private long maxIdleTime_; private long propertyCycle_; private private private private private time values are stored units of milliseconds. // initial # of connections in pool // max # of connections in pool // max # of connections in pool // max lifetime (msecs) of connections in pool // max idle time (msecs) of available connections in pool // pool maintenance frequency (msecs)
int numDaemons_; // # of requester daemons to create static long timeToRunDaemons_; // total duration (msecs) to let the daemons run long daemonMaxSleepTime_; // max time (msecs) for requester daemons to sleep each cycle long daemonMinSleepTime_; // min time (msecs) for requester daemons to sleep each cycle long poolHealthCheckCycle_; // # of msecs between calls to checkPoolHealth()
69
private boolean keepDaemonsAlive_ = true; // When this is false, the daemons shut down. private DataSource dataSource_; private AS400JDBCManagedDataSource mds_; private final Object daemonSleepLock_ = new Object(); private Random random_ = new Random(); static { try { Class.forName("com.ibm.as400.access.AS400JDBCDriver"); } catch(Exception e){ System.out.println("Unable to register JDBC driver."); System.exit(0); } } public static void main(String[] args) { host = args[0]; userid = args[1]; password = args[2]; timeToRunDaemons_ = (new Integer(args[3])).intValue() * 1000; //milliseconds //args[3]=time to run in seconds TestJDBCConnPool cptest = new TestJDBCConnPool(); cptest.setup(); cptest.runTest(); } public void setup() { try { if (DEBUG) System.out.println("TESTING_THREAD_SAFETY flag is " + (TESTING_THREAD_SAFETY ? "true" : "false")); if (TESTING_THREAD_SAFETY) { // Adjust values for performing thread-intensive stress testing. // NOTE: This assumes that the AS400JDBCConnection class has also been modified to // not make actual connections to an actual server. // To do this, edit AS400JDBCConnection.java, changing its TESTING_THREAD_SAFETY // flag to 'false', and recompile. minPoolSize_ = 100; maxPoolSize_ = 190; initialPoolSize_ = 150; // this should get reset to maxPoolSize_ numDaemons_ = 75; if (timeToRunDaemons_ == 0) { timeToRunDaemons_ = 180*1000; // 180 seconds == 3 minutes } } else { // Set more conservative values, as we'll be making actual connections to an // actual server, and we don't want to monopolize the server. minPoolSize_ = 5; maxPoolSize_ = 15; initialPoolSize_ = 9; numDaemons_ = 4; if (timeToRunDaemons_ == 0) { timeToRunDaemons_ = 15*1000; // 15 seconds } } maxLifetime_ = (int)timeToRunDaemons_ / 3; maxIdleTime_ = (int)timeToRunDaemons_ / 4; propertyCycle_ = timeToRunDaemons_ / 4; poolHealthCheckCycle_ = Math.min(timeToRunDaemons_ / 4, 20*60*1000); // at least once every 20 minutes (more frequently if shorter run-time) daemonMaxSleepTime_ = Math.min(timeToRunDaemons_ / 3, 10*1000); // at most 10 seconds (less if shorter run-time) daemonMinSleepTime_ = 20; // milliseconds if (DEBUG) System.out.println("setup: Constructing " + "AS400JDBCManagedConnectionPoolDataSource (cpds0)");
70
AS400JDBCManagedConnectionPoolDataSource cpds0 = new AS400JDBCManagedConnectionPoolDataSource(); // Set datasource properties. Note that both CPDS and MDS have these // properties, and they might have different values. cpds0.setServerName(host); cpds0.setDatabaseName(host);//iasp can be here cpds0.setUser(userid); cpds0.setPassword(password); cpds0.setSavePasswordWhenSerialized(true); // Set connection pooling-specific properties. cpds0.setInitialPoolSize(initialPoolSize_); cpds0.setMinPoolSize(minPoolSize_); cpds0.setMaxPoolSize(maxPoolSize_); cpds0.setMaxLifetime((int)(maxLifetime_/1000)); // convert to seconds cpds0.setMaxIdleTime((int)(maxIdleTime_/1000)); // convert to seconds cpds0.setPropertyCycle((int)(propertyCycle_/1000)); // convert to seconds //cpds0.setReuseConnections(false); // don't re-use connections // Set the initial context factory to use. System.setProperty(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory"); // Get the JNDI Initial Context. Context ctx = new InitialContext(); // Note: The following is an alternative way to set context properties locally: // Properties env = new Properties(); // env.put(Context.INITIAL_CONTEXT_FACTORY, // "com.sun.jndi.fscontext.RefFSContextFactory"); // Context ctx = new InitialContext(env); ctx.rebind("mydatasource", cpds0); // We can now do lookups on cpds, by the name"mydatasource". if (DEBUG) System.out.println("setup: lookup(\"mydatasource\"" + ")"); // AS400JDBCManagedConnectionPoolDataSource cpds1 = // (AS400JDBCManagedConnectionPoolDataSource)ctx.lookup("mydatasource"); // if (DEBUG) System.out.println("setup: cpds1.getUser() == |" + cpds1.getUser() + "|"); // Create a standard DataSource object that references it. if (DEBUG) System.out.println("setup: Constructing AS400JDBCManagedDataSource (mds0)"); AS400JDBCManagedDataSource mds0 = new AS400JDBCManagedDataSource(); mds0.setDescription("DataSource supporting connection pooling"); mds0.setDataSourceName("mydatasource"); ctx.rebind("ConnectionPoolingDataSource", mds0); if (DEBUG) System.out.println("setup: lookup(\"ConnectionPoolingDataSource\"" + ")"); dataSource_ = (DataSource)ctx.lookup("ConnectionPoolingDataSource"); //dataSource_.setLogWriter(output_); if (DEBUG) System.out.println("setup: dataSource_.getUser() == |" + ((AS400JDBCManagedDataSource)dataSource_).getUser() + "|"); mds_ = (AS400JDBCManagedDataSource)dataSource_; } catch (Exception e) { e.printStackTrace(); System.out.println("Setup error during Trace file creation."); } } void displayConnectionType(Connection conn, boolean specifiedDefaultId) { if (conn instanceof com.ibm.as400.access.AS400JDBCConnectionHandle) System.out.print("("+ (specifiedDefaultId ? "+" : "-") + "P)"); else System.out.print("("+ (specifiedDefaultId ? "+" : "-") + "NP)"); } /**
71
* Gets and returns connections from and to a connection pool for a while. **/ public void runTest() { boolean ok = true; try { System.out.println("Started test run at " + new Date()); if (DEBUG) System.out.println("Checking health just after datasource creation " + "(we expect that the pool does not exist yet) ..."); if (mds_.checkPoolHealth(true)) { ok = false; System.out.println("\nERROR: Pool exists prior to first getConnection()."); } // Verify some setters/getters for JDBC properties. System.out.println("Verifying setters/getters ..."); mds_.setAccess("read only"); if (!mds_.getAccess().equals("read only")) { ok = false; System.out.println("\nERROR: getAccess() returned unexpected value: " + "|" + mds_.getAccess()+"|"); } boolean oldBool = mds_.isBigDecimal(); boolean newBool = (oldBool ? false : true); mds_.setBigDecimal(newBool); if (mds_.isBigDecimal() != newBool) { ok = false; System.out.println("\nERROR: isBigDecimal() returned unexpected value: " + "|"+mds_.isBigDecimal()+"|"); } mds_.setBigDecimal(oldBool); int oldInt = mds_.getBlockCriteria(); int newInt = (oldInt == 2 ? 1 : 2); mds_.setBlockCriteria(newInt); if (mds_.getBlockCriteria() != newInt) { ok = false; System.out.println("\nERROR: getBlockCriteria() returned unexpected value: " + "|"+mds_.getBlockCriteria()+"|"); } mds_.setBlockCriteria(oldInt); // Verify some setters and getters for socket properties. oldBool = mds_.isKeepAlive(); newBool = (oldBool ? false : true); mds_.setKeepAlive(newBool); if (mds_.isKeepAlive() != newBool) { ok = false; System.out.println("\nERROR: isKeepAlive() returned unexpected value: " + "|"+mds_.isKeepAlive()+"|"); } mds_.setKeepAlive(oldBool); oldInt = mds_.getReceiveBufferSize(); newInt = (oldInt == 256 ? 512 : 256); mds_.setReceiveBufferSize(newInt); if (mds_.getReceiveBufferSize() != newInt) { ok = false; System.out.println("\nERROR: getReceiveBufferSize() returned unexpected value: " + "|"+mds_.getReceiveBufferSize()+"|"); } mds_.setReceiveBufferSize(oldInt); System.out.println("CONNECTION 1"); Object o = dataSource_.getConnection(); System.out.println(o.getClass()); System.out.println("******LOOK ABOVE*******"); Connection c1 = dataSource_.getConnection(); if (DEBUG) displayConnectionType(c1, true);
72
if (DEBUG) System.out.println("Checking health after first getConnection() ..."); if (!mds_.checkPoolHealth(true)) { ok = false; System.out.println("\nERROR: Pool is not healthy after first getConnection()."); } if (!TESTING_THREAD_SAFETY) { try { c1.setAutoCommit(false); if (DEBUG) System.out.println("SELECT * FROM QIWS.QCUSTCDT"); Statement s = c1.createStatement(); ResultSet rs = s.executeQuery("SELECT * FROM QIWS.QCUSTCDT"); while(rs.next()){ if (DEBUG) System.out.println(rs.getString(2)); } rs.close(); s.close(); } catch (Exception e) { e.printStackTrace(); if (DEBUG) System.out.println("Checking health after fatal connection error ..."); if (!mds_.checkPoolHealth(true)) { ok = false; System.out.println("\nERROR: Pool is not healthy after fatal connection " + "error."); } } } System.out.println("CONNECTION 2"); Connection c2 = dataSource_.getConnection(userid, password); if (DEBUG) displayConnectionType(c2, false); System.out.println("CONNECTION 3"); Connection c3 = dataSource_.getConnection(); if (DEBUG) displayConnectionType(c3, true); c1.close(); if (DEBUG) System.out.println("Checking health after first close() ..."); if (!mds_.checkPoolHealth(true)) { ok = false; System.out.println("\nERROR: Pool is not healthy after first close()."); } System.out.println("CONNECTION 4"); Connection c4 = dataSource_.getConnection(); if (DEBUG) displayConnectionType(c4, true); c1.close(); // close this one again c2.close(); c3.close(); c4.close(); if (DEBUG) System.out.println("Checking health after last close() ..."); if (!mds_.checkPoolHealth(true)) { ok = false; System.out.println("\nERROR: Pool is not healthy after last close()."); } // Start the test daemons. System.out.println("Starting test daemons"); startThreads(); // Run the test daemons for a while; check pool health periodically. long startTime = System.currentTimeMillis(); long endTime = startTime + timeToRunDaemons_; while (System.currentTimeMillis() < endTime) { System.out.print("h"); // Let the daemons run for a while, then check pool health.
73
try { Thread.sleep(poolHealthCheckCycle_); } catch (InterruptedException ie) {} if (!mds_.checkPoolHealth(true)) { ok = false; System.out.println("\nERROR: Pool is not healthy after test daemons started."); } } // Stop the test daemons. System.out.println("\nStopping test daemons"); stopThreads(); if (DEBUG) System.out.println("Checking health after connectionGetter daemons have run..."); if (!mds_.checkPoolHealth(true)) { ok = false; System.out.println("\nERROR: Pool is not healthy after test daemons stopped."); } if (!TESTING_THREAD_SAFETY) { System.out.println("CONNECTION 5"); Connection c = dataSource_.getConnection(); if (DEBUG) displayConnectionType(c, true); c.setAutoCommit(false); if (DEBUG) System.out.println("SELECT * FROM QIWS.QCUSTCDT"); Statement s = c.createStatement(); ResultSet rs = s.executeQuery("SELECT * FROM QIWS.QCUSTCDT"); while(rs.next()){ if (DEBUG) System.out.println(rs.getString(2)); } rs.close(); s.close(); c.close(); } System.out.println("\nClosing the pool..."); mds_.closePool(); if (DEBUG) System.out.println("Checking health after pool closed ..."); Trace.setTraceJDBCOn(true); // make sure the final stats get printed out Trace.setTraceOn(true); if (!mds_.checkPoolHealth(true)) { ok = false; System.out.println("\nERROR: Pool is not healthy after pool closed."); } System.out.println(); if(ok==true) System.out.println("test ran ok"); else System.out.println("test failed"); } catch (Exception e) { System.out.println(e); e.printStackTrace(); } finally { System.out.println("Ended test at " + new Date()); } } void startThreads() { // Create a bunch of threads that call getConnection(). Thread[] threads = new Thread[numDaemons_]; for (int i=0; i<numDaemons_; i++) { ConnectionGetter getter; // Flip a coin to see if this daemon will specify the default uid, or unique uid. if (random_.nextBoolean()) { getter = new ConnectionGetter(userid,password); if (TESTING_THREAD_SAFETY) { // we can use fictional userid getter = new ConnectionGetter("Thread"+i, "Pwd"+i);
74
} else { // must use a real userid getter = new ConnectionGetter(userid,password); } } else getter = new ConnectionGetter(null, null); threads[i] = new Thread(getter, "["+i+"]"); threads[i].setDaemon(true); } // Start the threads. for (int i=0; i<numDaemons_; i++) { threads[i].start(); } } void stopThreads() { // Tell the threads to stop. keepDaemonsAlive_ = false; synchronized (daemonSleepLock_) { daemonSleepLock_.notifyAll(); } // Wait for the daemons to stop. try { Thread.sleep(3000); } catch (InterruptedException ie) {} } // ConnectionGetter -------------------------------------------------------------------/** Helper class. This daemon wakes up at random intervals and either gets another connection from the connection pool or returns a previously-gotten connection to the pool. **/ private final class ConnectionGetter implements Runnable { private String uid_; private String pwd_; private boolean useDefaultUid_; private long maxSleepTime_; private String threadName_; private boolean firstConnection_ = true; ArrayList connections_ = new ArrayList(); // list of connections that this getter currently 'owns'. ConnectionGetter(String uid, String pwd) { uid_ = uid; pwd_ = pwd; if (uid_ == null) useDefaultUid_ = true; else useDefaultUid_ = false; maxSleepTime_ = daemonMaxSleepTime_; // our own copy that we can adjust } public void run() { threadName_ = Thread.currentThread().getName(); if (DEBUG) System.out.println("ConnectionGetter("+threadName_+") Starting up"); try { while (keepDaemonsAlive_) { try { // Pick a random sleep-time, between min and max values. long sleepTime = Math.max((long)(maxSleepTime_ * random_.nextFloat()), daemonMinSleepTime_); // Note: Must never call wait(0), because that waits forever. synchronized (daemonSleepLock_) { try { daemonSleepLock_.wait(sleepTime);
75
System.out.print("."); } catch (InterruptedException ie) {} } if (!keepDaemonsAlive_) break; // Decide by chance whether to request another connection or return a // previously-obtained connection. Connection conn; if (random_.nextBoolean()) // Leave the decision to chance. { // Request another connection. if (useDefaultUid_) { if (DEBUG) System.out.println("ConnectionGetter("+threadName_+") - get()"); conn = dataSource_.getConnection(); } else { if (DEBUG) System.out.println("ConnectionGetter("+threadName_+") - " + "get("+uid_+",***)"); conn = dataSource_.getConnection(uid_, pwd_); } if (conn == null) { System.out.println("ConnectionGetter("+threadName_+") ERROR: " + "getConnection() returned null"); } else { // Occasionally "forget" that we own a connection, and neglect to // close it. // Orphaned connections should eventually exceed their maximum // lifetime and get "reaped" by the connection manager. float val = random_.nextFloat(); if (firstConnection_ || val < 0.1) { // 'orphan' a few gotten connections firstConnection_ = false; } else { connections_.add(conn); } if (DEBUG) displayConnectionType(conn, useDefaultUid_); if (conn instanceof com.ibm.as400.access.AS400JDBCConnectionHandle) { // We got a pooled connection. Try speeding up our cycle time. if (maxSleepTime_ > 100) maxSleepTime_--; else maxSleepTime_ = 100; } else { // We didn't get a pooled connection. That means that the pool // must be at capacity. Slow down our cycle time a bit. maxSleepTime_ = maxSleepTime_ + 50; } } } else { // Close a connection that we currently own. if (connections_.size() != 0) { conn = (Connection)connections_.remove(0); conn.close(); } } } // inner try catch (Exception e) { e.printStackTrace(); } } // outer while } // outer try finally { if (DEBUG) System.out.println("ConnectionGetter("+threadName_+") Stopping"); // Return all the connections that I still have in my list. for (int i=0; i<connections_.size(); i++) { Connection conn = (Connection)connections_.remove(0); try { conn.close(); } catch (Exception e) { e.printStackTrace(); }
76
DatabaseMetaData interface: You can use a DatabaseMetaData object to obtain information about the database as a whole as well as catalog information. The following example shows how to return a list of tables, which is a catalog function:
// Connect to the server. Connection c = DriverManager.getConnection("jdbc:as400://mySystem"); // Get the database metadata from the connection. DatabaseMetaData dbMeta = c.getMetaData(); // Get a list of tables matching the following criteria. String catalog = "myCatalog"; String schema = "mySchema"; String table = "myTable%"; // % indicates search pattern String types[] = {"TABLE", "VIEW", "SYSTEM TABLE"}; ResultSet rs = dbMeta.getTables(catalog, schema, table, types); // Iterate through the ResultSet to get the values. // Close the Connection. c.close();
Related information AS400JDBCDatabaseMetaData Javadoc AS400JDBCDataSource class: The AS400JDBCDataSource class represents a factory for IBM i database connections. The AS400JDBCConnectionPoolDataSource class represents a factory for AS400JDBCPooledConnection objects. You can register either kind of data source object by using a Java Naming and Directory Interface (JNDI) service provider. For more information about JNDI service providers, see Related information for IBM Toolbox for Java on page 755. Examples The following examples demonstrate ways to create and use AS400JDBCDataSource objects. The last two examples show how to register an AS400JDBCDataSource object with JNDI and then use the object returned from JNDI to obtain a database connection. Notice that even when using different JNDI service providers, the code is very similar. Example: Creating an AS400JDBCDataSource object The following example shows you how to create an AS400JDBCDataSource object and connect it to a database:
// Create a data source for making the connection. AS400JDBCDataSource datasource = new AS400JDBCDataSource("myAS400"); datasource.setUser("myUser"); datasource.setPassword("MYPWD"); // Create a database connection to the server. Connection connection = datasource.getConnection();
IBM Toolbox for Java
77
Example: Creating an AS400JDBCConnectionPoolDataSource object that can be used to cache JDBC connections The following example shows how you can use an AS400JDBCConnectionPoolDataSource to cache JDBC connections.
// Create a data source for making the connection. AS400JDBCConnectionPoolDataSource dataSource = new AS400JDBCConnectionPoolDataSource("myAS400"); datasource.setUser("myUser"); datasource.setPassword("MYPWD"); // Get the PooledConnection. PooledConnection pooledConnection = datasource.getPooledConnection();
Example: Using JNDI service provider classes to store an AS400JDBCDataSource object The following example shows how you can use JNDI service provider classes to store a DataSource object directly to the integrated file system on the server:
// Create a data source to the IBM i database. AS400JDBCDataSource dataSource = new AS400JDBCDataSource(); dataSource.setServerName("myAS400"); dataSource.setDatabaseName("myAS400 Database"); // Register the datasource with the Java Naming and Directory Interface (JNDI). Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory"); Context context = new InitialContext(env); context.bind("jdbc/customer", dataSource); // Return an AS400JDBCDataSource object from JNDI and get a connection. AS400JDBCDataSource datasource = (AS400JDBCDataSource) context.lookup("jdbc/customer"); Connection connection = datasource.getConnection("myUser", "MYPWD");
Example: Using AS400JDBCDataSource objects and IBM SecureWay Directory classes with a Lightweight Directory Access Protocol (LDAP) directory server The following examples shows how you can use IBM SecureWay Directory classes to store an object to a Lightweight Directory Access Protocol (LDAP) directory server:
// Create a data source to the IBM i database. AS400JDBCDataSource dataSource = new AS400JDBCDataSource(); dataSource.setServerName("myAS400"); dataSource.setDatabaseName("myAS400 Database"); // Register the datasource with the Java Naming and Directory Interface (JNDI). Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.ibm.jndi.LDAPCtxFactory"); Context context = new InitialContext(env); context.bind("cn=myDatasource, cn=myUsers, ou=myLocation,o=myCompany,c=myCountryRegion", dataSource); // Return an AS400JDBCDataSource object from JNDI and get a connection. AS400JDBCDataSource datasource = (AS400JDBCDataSource) context.lookup( "cn=myDatasource, cn=myUsers, ou=myLocation,o=myCompany,c=myCountryRegion"); Connection connection = datasource.getConnection("myUser", "MYPWD");
AS400JDBCDataSource Javadoc AS400JDBCConnectionPoolDataSource Javadoc AS400JDBCPooledConnection Javadoc Registering the JDBC driver:
78
Before using JDBC to access data in a server database file, you need to register the IBM Toolbox for Java JDBC driver with the DriverManager. You can register the driver either by using a Java system property or by having the Java program register the driver: v Register by using a system property Each virtual machine has its own method of setting system properties. For example, the Java command from the JDK uses the -D option to set system properties. To set the driver using system properties, specify the following:
"-Djdbc.drivers=com.ibm.as400.access.AS400JDBCDriver"
v Register by using the Java program To load the IBM Toolbox for Java JDBC driver, add the following to the Java program before the first JDBC call:
Class.forName("com.ibm.as400.access.AS400JDBCDriver");
The IBM Toolbox for Java JDBC driver registers itself when it is loaded, which is the preferred way to register the driver. You can also explicitly register the IBM Toolbox for Java JDBC driver by using the following:
java.sql.DriverManager.registerDriver (new com.ibm.as400.access.AS400JDBCDriver ());
Calling DriverManager.registerDriver() results in the IBM Toolbox for Java JDBC driver getting registered twice. Once when AS400JDBCDriver is loaded by the JVM and once for the explicit call to the registerDriver() method. This is a result of the DriverManager implementation, which IBM Toolbox for Java has no control over. Having a driver being listed twice in the DriverManager's registry is normally not a problem. Although there may be situations where both registered driver listings get used. For example, this could happen when trying to get a connection with an incorrect password. The DriverManager will fail on the first registered driver to obtain a connection and so it will then try the second registered driver. The IBM Toolbox for Java JDBC driver does not require an AS400 object as an input parameter like the other IBM Toolbox for Java classes that get data from a server. An AS400 object is used internally, however, to manage default user and password caching. When a connection is first made to the server, the user may be prompted for user ID and password. The user has the option to save the user ID as the default user ID and add the password to the password cache. As in the other IBM Toolbox for Java functions, if the user ID and password are supplied by the Java program, the default user is not set and the password is not cached. See Managing connections in Java programs on page 445 for information about managing connections. Using the JDBC driver to connect to a database on the server You can use the DriverManager.getConnection() method to connect to the server database. DriverManager.getConnection() takes a uniform resource locator (URL) string as an argument. The JDBC driver manager attempts to locate a driver that can connect to the database that is represented by the URL. When using the IBM Toolbox for Java driver, use the following syntax for the URL:
"jdbc:as400://systemName/defaultSchema;listOfProperties"
Note: Either systemName or defaultSchema can be omitted from the URL. To use Kerberos tickets, set only the system name (and not the password) on your JDBC URL object. The user identity is retrieved through the Java Generic Security Services (JGSS) framework, so you also do not need to specify a user on your JDBC URL. You can set only one means of authentication in an AS400JDBCConnection object at a time. Setting the password clears any Kerberos ticket or profile token. For more information, see AS400 class on page 22 and J2SDK, v1.4 Security Documentation .
79
Examples: Using the JDBC driver to connect to a server Example: Using a URL in which a system name is not specified This example results in the user being prompted to type in the name of the system to which he or she wants to connect.
// Connect to unnamed system. // User receives prompt to type system name. Connection c = DriverManager.getConnection("jdbc:as400:");
Example: Connecting to the server database; no default SQL schema or properties specified
// Connect to system 'mySystem'. No // default SQL schema or properties are specified. Connection c = DriverManager.getConnection("jdbc:as400://mySystem");
Example: Connecting to the server database and using java.util.Properties to specify properties The Java program can specify a set of JDBC properties either by using the java.util.Properties interface or by specifying the properties as part of the URL. See IBM Toolbox for Java JDBC properties on page 327 for a list of supported properties. For example, to specify properties using the Properties interface, use the following code as an example:
// Create a properties object. Properties p = new Properties(); // Set the properties for the connection. p.put("naming", "sql"); p.put("errors", "full"); // Connect using the properties object. Connection c = DriverManager.getConnection("jdbc:as400://mySystem",p);
Example: Connecting to the server database and using a uniform resource locator (URL) to specify properties
// Connect using properties. The // properties are set on the URL // instead of through a properties object. Connection c = DriverManager.getConnection( "jdbc:as400://mySystem;naming=sql;errors=full");
Example: Connecting to the server database and specifying user ID and password
// Connect using properties on the // URL and specifying a user ID and password Connection c = DriverManager.getConnection( "jdbc:as400://mySystem;naming=sql;errors=full", "auser", "apassword");
Example: Disconnecting from the database To disconnect from the server, use the close() method on the Connecting object. Use the following statement to close the connection created in the previous example:
c.close();
80
AS400JDBCDriver Javadoc AS400JDBCParameterMetaData class: The AS400JDBCParameterMetaData class enables your programs to retrieve information about the properties of parameters in PreparedStatement and CallableStatement objects. AS400JDBCParameterMetaData provides methods that allow you to perform the following actions: v Get the class name of the parameter v Get the number of parameters in the PreparedStatement v Get the SQL type of the parameter v Get the database-specific type name for the parameter v Get the precision or the scale of the parameter Example: Using AS400JDBCParameterMetaData The following example shows one way to use AS400JDBCParameterMetaData to retrieve parameters from a dynamically generated PreparedStatement object:
// Get a connection from the driver. Class.forName("com.ibm.as400.access.AS400JDBCDriver"); Connection connection = DriverManager.getConnection("jdbc:as400://myAS400", "myUserId", "myPassword"); // Create a prepared statement object. PreparedStatement ps = connection.prepareStatement("SELECT STUDENTS FROM STUDENTTABLE WHERE STUDENT_ID= ?"); // Set a student ID into parameter 1. ps.setInt(1, 123456); // Retrieve the parameter meta data for the prepared statement. ParameterMetaData pMetaData = ps.getParameterMetaData(); // Retrieve the number of parameters in the prepared statement. // Returns 1. int parameterCount = pMetaData.getParameterCount(); // Find out what the parameter type name of parameter 1 is. // Returns INTEGER. String getParameterTypeName = pMetaData.getParameterTypeName(1);
Related information AS400JDBCParameterMetaData Javadoc PreparedStatement interface: You can use a PreparedStatement object when an SQL statement is going to be run many times. A prepared statement is an SQL statement that has been precompiled. This approach is more efficient than running the same statement multiple times using a Statement object, which compiles the statement each time it is run. In addition, the SQL statement contained in a PreparedStatement object may have one or more IN parameters. Use Connection.prepareStatement() to create PreparedStatement objects. The PreparedStatement object allows you to submit multiple SQL commands as a single group to a database through the use of batch support. You may improve performance by using batch support because processing a group of operations is typically faster than processing them one at a time. For more information about using batch support, see Enhancements to JDBC support.
IBM Toolbox for Java
81
Example: Using PreparedStatement The following example shows how to use the PreparedStatement interface.
// Connect to the server. Connection c = DriverManager.getConnection("jdbc:as400://mySystem"); // Create the PreparedStatement object. It precompiles the // specified SQL statement. The question marks indicate where // parameters must be set before the statement is run. PreparedStatement ps = c.prepareStatement("INSERT INTO MYLIBRARY.MYTABLE (NAME, ID) VALUES (?, ?)"); // Set parameters and run the statement. ps.setString(1, "JOSH"); ps.setInt(2, 789); ps.executeUpdate(); // Set parameters and run the statement again. ps.setString(1, "DAVE"); ps.setInt(2, 456); ps.executeUpdate(); // Close PreparedStatement and the Connection. ps.close(); c.close();
Related information AS400JDBCPreparedStatement Javadoc ResultSet class: You can use a ResultSet object to access a table of data that was generated by running a query. The table rows are retrieved in sequence. Within a row, column values can be accessed in any order. The data stored in ResultSet is retrieved by using the various get methods, depending on the type of data being retrieved. The next() method is used to move to the next row. ResultSet allows you to get and update columns by name, although using the column index results improves performance. Cursor movement A cursor, which is an internal pointer, is used by a result set to point the row in the result set that is being accessed by the Java program. The performance of the getRow() method has been improved. Before V5R2, using ResultSet.last(), ResultSet.afterLast(), and ResultSet.absolute() with a negative value made the current row number not available. The previous restrictions are lifted, which makes the getRow() method fully functional. JDBC 2.0 and later JDBC specifications provide additional methods for accessing specific positions within a database:
Scrollable cursor positions absolute afterLast beforeFirst first getRow isAfterLast isBeforeFirst isFirst isLast last moveToCurrentRow moveToInsertRow previous relative
82
Scrolling capabilities If a result set is created by executing a statement, you can move (scroll) backward (last-to-first) or forward (first-to-last) through the rows in a table. A result set that supports this movement is called a scrollable result set. Scrollable result sets also support absolute positioning. Absolute positioning allows you to move directly to a row by specifying its position in the result set. With JDBC 2.0 and later JDBC specifications, you have two additional scrolling capabilities available to use when working with the ResultSet class: scroll-insensitive and scroll-sensitive result sets. A scroll-insensitive result set is not usually sensitive to changes that are made while it is open, while the scroll-sensitive result set is sensitive to changes. Note: IBM i only allows read-only access for scrollable insensitive cursors. IBM Toolbox for Java supports a scroll-insensitive cursor if the result set concurrency is read-only. If the result set type is specified as insensitive and the concurrency is specified as updateable, the result set type changes to sensitive and issues a warning to you. Updateable result sets In your application, you can use result sets that use either read-only concurrency (no updates can be made to the data) or updateable concurrency (allows updates to the data and uses database write locks to control access to the same data item by different transactions). In an updateable result set, rows can be updated, inserted, and deleted. Numerous update methods are available for you to use in your program, for example: v Update ASCII stream v Update Big Decimal v Update binary stream See Method Summary in the AS400JDBCResultSet Javadoc for a complete listing of the update methods available through the ResultSet interface. Example: Updatable result sets The following example shows how to use a result set that allows updates to the data (update concurrency) and allows changes to be made to the result set while it is open (scroll sensitive).
// Connect to the server. Connection c = DriverManager.getConnection("jdbc:as400://mySystem"); // Create a Statement object. Set the result set // concurrency to updatable. Statement s = c.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); // Run a query. The result is placed in a ResultSet object. ResultSet rs = s.executeQuery ("SELECT NAME,ID FROM MYLIBRARY.MYTABLE FOR UPDATE"); // Iterate through the rows of the ResultSet. // As we read the row, we will update it with a new ID. int newId = 0; while (rs.next ()) { // Get the values from the ResultSet. The first value // is a string, and the second value is an integer.
IBM Toolbox for Java
83
String name = rs.getString("NAME"); int id = rs.getInt("ID"); System.out.println("Name = " + name); System.out.println("Old id = " + id); // Update the id with a new integer. rs.updateInt("ID", ++newId); // Send the updates to the server. rs.updateRow (); System.out.println("New id = " + newId); } // Close the Statement and the Connection. s.close(); c.close();
ResultSetMetaData The ResultSetMetaData interface determines the types and properties of the columns in a ResultSet. When connecting to a server running IBM i 5.2 or later, using the extended metadata property enables you to increase the accuracy of the following ResultSetMetaData methods: v getColumnLabel(int) v isReadOnly(int) v isSearchable(int) v isWriteable(int) Additionally, setting this property to true enables support for the ResultSetMetaData.getSchemaName(int) method. Be aware that using the extended metadata property may degrade performance because it requires retrieving more information from the server. AS400JDBCResultSet Javadoc AS400ResultSetMetaData Javadoc AS400JDBCRowSet class: The AS400JDBCRowSet class represents a connected rowset that encapsulates a JDBC result set. The methods on AS400JDBCRowSet are very similar to those of the AS400JDBCResultSet. The database connection is maintained while in use. You can use an instance of AS400JDBCDataSource or AS400JDBCConnectionPoolDataSource to create the connection to the database that you want to use to access the data for the AS400JDBCRowSet. Examples The following examples show how you can use the AS400JDBCRowSet class. Example: Creating, populating, and updating an AS400JDBCRowSet object
DriverManager.registerDriver(new AS400JDBCDriver()); // Establish connection by using a URL. AS400JDBCRowSet rowset = new AS400JDBCRowSet("jdbc:as400://mySystem","myUser", "myPassword"); // Set the command used to populate the list. rowset.setCommand("SELECT * FROM MYLIB.DATABASE"); // Populate the rowset. rowset.execute();
84
// Update the customer balances. while (rowset.next()) { double newBalance = rowset.getDouble("BALANCE") + july_statements.getPurchases(rowset.getString("CUSTNUM")); rowset.updateDouble("BALANCE", newBalance); rowset.updateRow(); }
Example: Creating and populating an AS400JDBCRowSet object, while getting the data source from JNDI
// Get the data source that is registered in JNDI (assumes JNDI environment is set). Context context = new InitialContext(); AS400JDBCDataSource dataSource = (AS400JDBCDataSource) context.lookup("jdbc/customer"); AS400JDBCRowSet rowset = new AS400JDBCRowSet(); // Establish connection by setting the data source name. rowset.setDataSourceName("jdbc/customer"); rowset.setUsername("myuser"); rowset.setPassword("myPasswd"); // Set the prepared statement and initialize the parameters. rowset.setCommand("SELECT * FROM MYLIBRARY.MYTABLE WHERE STATE = ? AND BALANCE > ?"); rowset.setString(1, "MINNESOTA"); rowset.setDouble(2, MAXIMUM_LIMIT); // Populate the rowset. rowset.execute();
AS400JDBCRowSet Javadoc AS400JDBCResultSet Javadoc AS400JDBCSavepoint class: The IBM Toolbox for Java AS400JDBCSavepoint class represents a logical breaking point in a transaction. Using savepoints gives you more granular control over which changes are affected when you roll back a transaction. Figure 1: Using savepoints to control rollbacks in a transaction
For example, Figure 1 shows a transaction that includes two savepoints, A and B. Rolling back the transaction to either savepoint undoes (or reverses) only those changes from the point a rollback is called
85
to the savepoint. This prevents having to undo all the changes in the entire transaction. Note that once you rollback to savepoint A, you cannot later rollback to savepoint B. You cannot access savepoint B after work is rolled back past it. Example: Using savepoints In this scenario, assume that your application updates student records. At the end of updating a certain field in every student record, you perform a commit. Your code detects a particular error associated with updating this field and rolls back the work done when this error occurs. You know that this particular error affects only the work performed on the current record. So, you set a savepoint between each update of student records. Now, when this error occurs, you rollback only the last update in the student table. Instead of having to roll back a large amount of work, you can now roll back only a small amount of work. The following example code helps illustrate how you can use savepoints. The example assumes that the student ID for John is 123456 and the student ID for Jane is 987654.
// Get a connection from the driver Class.forName("com.ibm.as400.access.AS400JDBCDriver"); // Get a statement object Statement statement = connection.createStatement(); // Update John's record with his 'B' grade in gym. int rows = statement.executeUpdate( "UPDATE STUDENTTABLE SET GRADE_SECOND_PERIOD = 'B' WHERE STUDENT_ID= '123456'"); // Set a savepoint marking an intermediate point in the transaction Savepoint savepoint1 = connection.setSavepoint("SAVEPOINT_1"); // Update Jane's record with her 'C' grade in biochemistry. int rows = statement.executeUpdate( "UPDATE STUDENTTABLE SET GRADE_SECOND_PERIOD = 'C' WHERE STUDENT_ID= '987654'"); // An error is detected, so we need to roll back Jane's record, but not John's. // Rollback the transaction to savepoint 1. The change to Jane's record is // removed while the change to John's record remains. connection.rollback(savepoint1); // Commit the transaction; only John's 'B' grade is committed to the database. connection.commit();
Considerations and restrictions Using savepoints requires that you be aware of the following considerations and restrictions: Considerations IBM Toolbox for Java follows database rules regarding how rollbacks affect cursors and retained locks. For example, when you set the connection option to keep cursors open after a traditional rollback, cursors also remain open after a rollback to a savepoint. In other words, when a rollback request happens involving savepoints, IBM Toolbox for Java does not move or close the cursor when the underlying database does not support this. Using a savepoint to roll back a transaction undoes only the actions performed from the point where you start the roll back to the savepoint. Actions performed before that savepoint remain. As in the previous example, be aware that you can commit a transaction that includes work performed before a particular savepoint but does not include work performed after the savepoint.
86
All savepoints are released and become invalid when the transaction is committed or when the entire transaction is rolled back. You can also release savepoints by calling Connection.releaseSavepoint(). Restrictions The following restrictions apply when using savepoints: v Named savepoints must be unique. v You cannot reuse a savepoint name until the savepoint is released, committed, or rolled back. v Auto-commit must be set to 'OFF' for savepoints to be valid. You can set auto-commit 'OFF' by using Connection.setAutoCommit(false). Enabling auto-commit when using savepoints throws an exception. v Savepoints are not valid across XA connections. Using an XA connection with savepoints throws an exception. v Your server must be running IBM i Version 5 Release 2 or later. Using savepoints when connecting (or already connected) to a server running V5R1 or earlier version of IBM i throws an exception. AS400JDBCSavePoint Javadoc Running SQL statements with Statement objects: Use a Statement object to run an SQL statement and optionally obtain the ResultSet produced by it. PreparedStatement inherits from Statement, and CallableStatement inherits from PreparedStatement. Use the following Statement objects to run different SQL statements: v Statement interface on page 88: Runs a simple SQL statement that has no parameters. v PreparedStatement interface on page 81 - Runs a precompiled SQL statement that may or may not have IN parameters. v CallableStatement interface on page 63 - Runs a call to a database stored procedure. A CallableStatement may or may not have IN, OUT, and INOUT parameters. The Statement object allows you to submit multiple SQL commands as a single group to a database through the use of batch support. You may improve performance by using batch support because processing a group of operations is typically faster than processing them one at a time. For more information about using batch support, see Enhancements to JDBC support. When using batch updates, typically you turn off auto-commit. Turning off auto-commit allows your program to determine whether to commit the transaction if an error occurs and not all of the commands have executed. In JDBC 2.0 and later JDBC specifications, a Statement object can keep track of a list of commands that can be successfully submitted and executed together in a group. When this list of batch commands is executed by the executeBatch() method, the commands are executed in the order in which they were added to the list. AS400JDBCStatement provides methods that enable you to perform many actions, including the following: v Execute different kinds of statements v Retrieve the values for different parameters of the Statement object, including: The connection Any auto-generated keys created as a result of executing the Statement The fetch size and fetch direction The maximum field size and maximum row limit The current result set, the next result set, the type of result set, the result set concurrency, and the result set cursor holdability v Add an SQL statement to the current batch v Run the current batch of SQL statements
IBM Toolbox for Java
87
Statement interface Use Connection.createStatement() to create new Statement objects. The following example shows how to use a Statement object.
// Connect to the server. Connection c = DriverManager.getConnection("jdbc:as400://mySystem"); // Create a Statement object. Statement s = c.createStatement(); // Run an SQL statement that creates a table in the database. s.executeUpdate("CREATE TABLE MYLIBRARY.MYTABLE (NAME VARCHAR(20), ID INTEGER)"); // Run an SQL statement that inserts a record into the table. s.executeUpdate("INSERT INTO MYLIBRARY.MYTABLE (NAME, ID) VALUES ('DAVE', 123)"); // Run an SQL statement that inserts a record into the table. s.executeUpdate("INSERT INTO MYLIBRARY.MYTABLE (NAME, ID) VALUES ('CINDY', 456)"); // Run an SQL query on the table. ResultSet rs = s.executeQuery("SELECT * FROM MYLIBRARY.MYTABLE"); // Close the Statement and the Connection. s.close(); c.close();
AS400JDBCStatement Javadoc JDBC XA Distributed Transaction Management: The JDBC XA distributed transaction management classes enable you to use the IBM Toolbox for Java JDBC driver within a distributed transaction. Using the XA classes to enable the IBM Toolbox for Java JDBC driver allows it to participate in transactions that span multiple data sources. Typically, XA distributed transaction management classes are used and controlled directly by a transaction manager, which is separate from the JDBC driver. The distributed transaction management interfaces are defined as part of the JDBC 2.0 Optional Package and the Java Transaction API (JTA). Both are available from Sun as JAR files. The distributed transaction management interfaces are also supported in the JDBC 3.0 API, which is bundled with the Java 2 Platform, Standard Edition, version 1.4. For more information, see the Sun Web sites for JDBC and the JTA .
Use the following objects to enable the IBM Toolbox for Java JDBC driver to participate in XA distributed transactions: v AS400JDBCXADataSource - A factory for AS400JDBCXAConnection objects. This is a subclass of AS400JDBCDataSource. AS400JDBCXACConnection - A pooled connection object that provides hooks for connection pool management and XA resource management. v AS400JDBCXAResource - A resource manager for use in XA transaction management. v Note: Prior to V5R3, the database host server used XA APIs for Job Scoped Locks (XA model). In V5R3 and subsequent releases, the database host server uses XA APIs for Transaction Scoped Locks (NTS model) for all MTS functions. For more information about how these APIs differ, see XA APIs.
88
Example: Using XA classes The following example shows simple usage of the XA classes. Keep in mind that the details would be filled in with work using other data sources. This type of code usually appears within a transaction manager.
// Create an XA data source for making the XA connection. AS400JDBCXADataSource xaDataSource = new AS400JDBCXADataSource("myAS400"); xaDataSource.setUser("myUser"); xaDataSource.setPassword("myPasswd"); // Get an XAConnection and get the associated XAResource. // This provides access to the resource manager. XAConnection xaConnection = xaDataSource.getXAConnection(); XAResource xaResource = xaConnection.getXAResource(); // Generate a new Xid (this is up to the transaction manager). Xid xid = ...; // Start the transaction. xaResource.start(xid, XAResource.TMNOFLAGS); // ...Do some work with the database... // End the transaction. xaResource.end(xid, XAResource.TMSUCCESS); // Prepare for a commit. xaResource.prepare(xid); // Commit the transaction. xaResource.commit(xid, false); // Close the XA connection when done. // closes the XA resource. xaConnection.close(); This implicitly
Jobs classes
The IBM Toolbox for Java Jobs classes, which are in the access package, allow a Java program to retrieve and change job information. Use the Jobs classes to work with the following type of job information: v Date and Time Information v Job Queue v Language Identifiers v Message Logging v Output Queue v Printer Information
Examples
The following examples show some of the ways you can use the Job, JobList, and JobLog classes. The first example shows one way to use a cache with the Job class. Links to other examples immediately follow the sample code. Note: Read the Code example disclaimer for important legal information. Example: Using a cache when setting a value and getting a value
89
try { // Creates AS400 object. AS400 as400 = new AS400("systemName"); // Constructs a Job object byte[] internalJobID = "xxxxxxxxxxxxxxxx".getBytes(); Job job = new Job(as400, internalJobID); // Gets job information System.out.println("User of this job :" + job.getUser()); System.out.println("CPU used : " + job.getCPUUsed()); System.out.println("Job enter system date : " + job.getJobEnterSystemDate()); // Sets cache mode job.setCacheChanges(true); // Changes will be store in the cache. job.setRunPriority(66); job.setDateFormat("*YMD"); // Commit changes. This will change the value on the system. job.commitChanges(); // Set job information to system directly(without cache). job.setCacheChanges(false); job.setRunPriority(60); } catch (Exception e) { System.out.println("error :" + e); }
The following examples show how to list the jobs belonging to a specific user, list jobs with the job status information, and display the messages in a job log: Example: Using JobList to list job identification information on page 522 Example: Using JobList to get a list of jobs on page 524 Example: Using JobLog to display messages in the job log on page 528 Access package Javadoc Job class: The Job class (in the access package) allows a Java program to retrieve and change server job information. The following type of job information can be retrieved and changed with the Job class: v Job queues v Output queues v Message logging v Printer device v Country or region identifier v Date format The job class also allows the ability to change a single value at a time, or cache several changes using the setCacheChanges(true) method and committing the changes using the commitChanges() method. If caching is not turned on, you do not need to do a commit.
90
Example For a code example, see the Javadoc reference documentation for the Job class. The example shows how to set and get values to and from the cache in order to set the run priority with the setRunPriority() method and set the date format with the setDateFormat() method. Job Javadoc JobList class: You can use the JobList class (in the access package) to list IBM i jobs. With the JobList class, you can retrieve the following: v All jobs v Jobs by name, job number, or user Use the getJobs() method to return a list of jobs or the getLength() method to return the number of jobs retrieved with the last getJobs(). Example: Using JobList The following example lists all active jobs on the system:
// Create an AS400 object. List the // jobs on this server. AS400 sys = new AS400("mySystem.myCompany.com"); // Create the job list object. JobList jobList = new JobList(sys); // Get the list of active jobs. Enumeration list = jobList.getJobs(); // For each active job on the system // print job information. while (list.hasMoreElements()) { Job j = (Job) list.nextElement(); System.out.println(j.getName() + "." + j.getUser() + "." + j.getNumber()); }
Job Javadoc JobLog class: TheJobLog class (in the access package) retrieves messages in the job log of a server job by calling getMessages(). Example: Using JobLog The following example prints all messages in the job log for the specified user:
// ... Setup work to create an AS400 // object and a jobList object has // already been done // Get the list of active jobs on the server Enumeration list = jobList.getJobs(); // Look through the list to find a
IBM Toolbox for Java
91
// job for the specified user. while (list.hasMoreElements()) { Job j = (Job) list.nextElement(); if (j.getUser().trim().equalsIgnoreCase(userID)) { // A job matching the current user // was found. Create a job log // object for this job. JobLog jlog = new JobLog(system, j.getName(), j.getUser(), j.getNumber()); // Enumerate the messages in the job // log then print them. Enumeration messageList = jlog.getMessages(); while (messageList.hasMoreElements()) { AS400Message message = (AS400Message) messageList.nextElement(); System.out.println(message.getText()); } } }
Job Javadoc
Message classes
The IBM Toolbox for Java AS400Message class and its associated classes represent a message returned from a server.
AS400Message
The AS400Message object allows the Java program to retrieve an IBM i message that is generated from a previous operation (for example, from a command call). From a message object, the Java program can retrieve the following: v The IBM i library and message file that contain the message v The message ID v v v v The The The The message message message message type severity text help text
The following example shows how to use the AS400Message object: Note: Read the Code example disclaimer for important legal information.
// Create a command call object. CommandCall cmd = new CommandCall(sys, "myCommand"); // Run the command cmd.run(); // Get the list of messages that are // the result of the command that I just ran AS400Message[] messageList = cmd.getMessageList(); // Iterate through the list displaying the messages for (int i = 0; i < messageList.length; i++) { System.out.println(messageList[i].getText()); }
92
QueuedMessage
The QueuedMessage class extends the AS400Message class. The QueuedMessage class accesses information about a message on an IBM i message queue. With this class, a Java program can retrieve: v Information about where a message originated, such as program, job number, and user. v The message queue v The message key v The message reply status The following example prints all messages in the message queue of the current (signed-on) user: Note: Read the Code example disclaimer for important legal information.
// The message queue is on this system. AS400 sys = new AS400(mySystem.myCompany.com); // Create the message queue object. // This object will represent the // queue for the current user. MessageQueue queue = new MessageQueue(sys, MessageQueue.CURRENT); // Get the list of messages currently in this user's queue. Enumeration e = queue.getMessages(); // Print each message in the queue. while (e.hasMoreElements()) { QueuedMessage msg = e.getNextElement(); System.out.println(msg.getText()); }
MessageFile
The MessageFile class allows you to receive a message from an IBM i message file. The MessageFile class returns an AS400Message object that contains the message. Using the MessageFile class, you can do the following: v Return a message object that contains the message v Return a message object that contains substitution text in the message The following example shows how to retrieve and print a message: Note: Read the Code example disclaimer for important legal information.
AS400 system = new AS400("mysystem.mycompany.com"); MessageFile messageFile = new MessageFile(system); messageFile.setPath("/QSYS.LIB/QCPFMSG.MSGF"); AS400Message message = messageFile.getMessage("CPD0170"); System.out.println(message.getText());
93
MessageQueue
The MessageQueue class allows a Java program to interact with an IBM i message queue. The MessageQueue class acts as a container for the QueuedMessage class. The getMessages() method, in particular, returns a list of QueuedMessage objects. The MessageQueue class can do the following: v Set message queue attributes v Get information about a message queue v Receive messages from a message queue v Send messages to a message queue v Reply to messages The following example lists messages in the message queue for the current user: Note: Read the Code example disclaimer for important legal information.
// The message queue is on this system. AS400 sys = new AS400(mySystem.myCompany.com); // Create the message queue object. // This object will represent the // queue for the current user. MessageQueue queue = new MessageQueue(sys, MessageQueue.CURRENT); // Get the list of messages currently in this user's queue. Enumeration e = queue.getMessages(); // Print each message in the queue. while (e.hasMoreElements()) { QueuedMessage msg = e.getNextElement(); System.out.println(msg.getText()); }
AS400Message Javadoc QueuedMessage Javadoc Access package summary MessageFile Javadoc MessageQueue Javadoc
NetServer class
The NetServer class has been deprecated and replaced by the ISeriesNetServer class. The NetServer class represents the NetServer service on the server. NetServer objects allow you to query and modify the state and configuration of the NetServer service. For example, you can use the NetServer class to: v Start or stop the NetServer v Get a list of all current file shares and print shares v Get a list of all current sessions v Query and change attribute values (using methods inherited from ChangeableResource) Note: In order to use the NetServer class, you need a server user profile that has *IOSYSCFG authority. The NetServer class is an extension of ChangeableResource and Resource, so it provides a collection of "attributes" to represent the various NetServer values and settings. You query or change the attributes in order to access or change the configuration of your NetServer. Some of the NetServer attributes are:
94
v v v v v
v CCSID v WINS_PRIMARY_ADDRESS
Pending attributes
Many of the NetServer attributes are pending (for example, NAME_PENDING). Pending attributes represent NetServer values that take effect the next time you start (or restart) the NetServer on the server. When you have a pair of related attributes and one attribute is pending while the other is nonpending: v The pending attribute is read/write, so you can change it v The nonpending attribute is read-only, so you can query it but you cannot change it
ObjectReferences class
The IBM Toolbox for Java ObjectReferences class represents the set of information about integrated file system references on an object that can be retrieved through the Retrieve Object References (QP0LROR) API. A reference is an individual type of access or lock obtained on the object when using integrated file system interfaces. An object may have multiple references concurrently held, provided that the reference types do not conflict with one another. This class will not return information about byte range locks that may currently be held on an object.
95
The user must have execute (*X) data authority to each directory preceding the object whose references are to be obtained. The user must have read (*R) data authority to the object whose references are to be obtained. For more information, see the ObjectReferences Javadoc. Related information ObjectReferences Javadoc Retrieve Object References (QP0LROR) API
Permission classes
The IBM Toolbox for Java permission classes allow you to get and set object authority information. Object authority information is also known as permission. The Permission class represents a collection of many users' authority to a specific object. The UserPermission class represents a single user's authority to a specific object.
Permission class
The Permission class allows you to retrieve and change object authority information. It includes a collection of many users who are authorized to the object. The Permission object allows the Java program to cache authority changes until the commit() method is called. Once the commit() method is called, all changes made up to that point are sent to the server. Some of the functions provided by the Permission class include: v addAuthorizedUser(): Adds an authorized user. v commit(): Commits the permission changes to the server. v v v v v getAuthorizationList(): Returns the authorization list of the object. getAuthorizedUsers(): Returns an enumeration of authorized users. getOwner(): Returns the name of the object owner. getSensitivityLevel(): Returns the sensitivity level of the object. getType(): Returns the object authority type (QDLO, QSYS, or Root).
v getUserPermission(): Returns the permission of a specific user to the object. v getUserPermissions(): Returns an enumeration of permissions of the users to the object. v setAuthorizationList(): Sets the authorization list of the object. v setSensitivityLevel(): Sets the sensitivity level of the object. Example: Using Permission Note: Read the Code example disclaimer for important legal information. The following example shows you how to create a permission and add an authorized user to an object.
// Create AS400 object AS400 as400 = new AS400(); // Create Permission passing in the AS400 and object Permission myPermission = new Permission(as400, "QSYS.LIB/myLib.LIB"); // Add a user to be authorized to the object myPermission.addAuthorizedUser("User1");
UserPermission class
The UserPermission class represents the authority of a single, specific user. UserPermission has three subclasses that handle the authority based on the object type: v DLOPermission
96
v QSYSPermission v RootPermission The UserPermission class allows you to do the following: v Determine if the user profile is a group profile v Return the user profile name v Indicate whether the user has authority v Set the authority of authorization list management Example: Using UserPermission Note: Read the Code example disclaimer for important legal information. The following example shows you how to retrieve the users and groups that have permission on an object and print them out one at a time.
// Create a system object. AS400 sys = new AS400("MYAS400", "USERID", "PASSWORD"); // Represent the permissions to an object on the system, such as a library. Permission objectInQSYS = new Permission(sys, "/QSYS.LIB/FRED.LIB"); // Retrieve the various users/groups that have permissions set on that object. Enumeration enum = objectInQSYS.getUserPermissions(); while (enum.hasMoreElements()) { // Print out the user/group profile names one at a time. UserPermission userPerm = (UserPermission)enum.nextElement(); System.out.println(userPerm.getUserID()); }
Permission Javadoc UserPermission Javadoc DLOPermission class: The DLOPermission class is a subclass of UserPermission. DLOPermission allows you to display and set the authorities a user has (called permissions) to a document library object (DLO). DLOs are stored in QDLS. One of the following authority values is assigned to each user.
Authority value *ALL Description The user can perform all operations except those operations that are controlled by authorization list management. The authorization list is used to determine the authority for the document. The user can change and perform basic functions on the object. The user cannot access the object. The user has object operational authority, read authority, and execute authority.
You must use one of the following methods to change or determine the user's authority: v Use getDataAuthority() to display the authority value of the user
IBM Toolbox for Java
97
v Use setDataAuthority() to set the authority value of the user After setting permissions, it is important that you use the commit() method from the Permissions class to send the changes to the server. For more information about permissions and authorities, see the Security reference topic. Example: Using DLOPermission The following example shows how to retrieve and print the DLO permissions, including the user profiles for each permission.
// Create a system object. AS400 sys = new AS400("MYAS400", "USERID", "PASSWORD"); // Represent the permissions to a DLO object. Permission objectInQDLS = new Permission(sys, "/QDLS/MyFolder"); // Print the object pathname and retrieve its permissions. System.out.println("Permissions on " + objectInQDLS.getObjectPath() + " are as follows:"); Enumeration enum = objectInQDLS.getUserPermissions(); while (enum.hasMoreElements()) { // For each of the permissions, print out the user profile name // and that user's authorities to the object. DLOPermission dloPerm = (DLOPermission)enum.nextElement(); System.out.println(dloPerm.getUserID() + ": " + dloPerm.getDataAuthority()); }
Related information DLOPermission Javadoc QSYSPermission: QSYSPermission is a subclass of the UserPermission class. QSYSPermission allows you to display and set the permission a user has for an object in the traditional IBM i library structure stored in QSYS.LIB. You can set authority for an object stored in QSYS.LIB by setting a system-defined authority value or by setting the individual object and data authorities. The following table lists and describes the valid system-defined authority values:
System-defined authority value *ALL Description The user can perform all operations except those operations that are controlled by authorization list management. The authorization list is used to determine the authority for the document. The user can change and perform basic functions on the object. The user cannot access the object. The user has object operational authority, read authority, and execute authority.
Each system-defined authority value actually represents a combination of the individual object authorities and data authorities. The following table illustrates the relationships of system-defined authorities to the individual object and data authorities:
98
Table 1. Y refers to those authorities that can be assigned. n refers to those authorities that cannot be assigned. Systemdefined authority All Change Exclude Use Autl Object authority Opr Y Y n Y Mgt Y n n n Exist Y n n n Alter Y n n n Ref Y n n n Data authority Read Y Y n Y Add Y Y n n Upd Y Y n n Dlt Y Y n n Exe Y Y n Y
Only valid with user (*PUBLIC) and a specified authorization list that determines the individual object and data authorities.
Specifying a system-defined authority automatically assigns the appropriate individual authorities. Likewise, specifying various individual authorities changes the appropriate individual authority values. When a combination of individual object authorities and data authorities does not map to a single system-defined authority value, then the single value becomes "User Defined." Use the getObjectAuthority() method to display the current system-defined authority. Use the setObjectAuthority() method to set the current system-defined authority using a single value. Use the appropriate set method to set individual object authority values on or off: v v v v setAlter() setExistence() setManagement() setOperational()
v setReference() Use the appropriate set method to set individual data authority values on or off: v setAdd() v setDelete() v setExecute() v setRead() v setUpdate() For more information about the different authorities, see the Security reference topic. For information about using CL commands to grant and edit object authorities, see the CL commands Grant Object Authority (GRTOBJAUT) and Edit Object Authority (EDTOBJAUT). Example This example shows you how to retrieve and print the permissions for a QSYS object.
// Create a system object. AS400 sys = new AS400("MYAS400", "USERID", "PASSWORD"); // Represent the permissions to a QSYS object. Permission objectInQSYS = new Permission(sys, "/QSYS.LIB/FRED.LIB"); // Print the object pathname and retrieve its permissions. System.out.println("Permissions on "+objectInQSYS.getObjectPath()+" are as follows:"); Enumeration enum = objectInQSYS.getUserPermissions(); while (enum.hasMoreElements()) { // For each of the permissions, print out the user profile name
IBM Toolbox for Java
99
// and that user's authorities to the object. QSYSPermission qsysPerm = (QSYSPermission)enum.nextElement(); System.out.println(qsysPerm.getUserID()+": "+qsysPerm.getObjectAuthority()); }
QSYSPermission Javadoc UserPermission class on page 96 RootPermission: The RootPermission class represents a user's authority to objects contained in the root directory structure. RootPermissions objects are those objects not contained in QSYS.LIB or QDLS. RootPermission is a subclass of the UserPermission class. The RootPermission class allows you to display and set the permissions for the user of an object contained in the root directory structure. An object on the root directory structure can set the data authority or the object authority. You can set the data authority to the values listed in the following table. Use the getDataAuthority() method to to display the current values and the setDataAuthority() method to set the data authority. The following table lists and describes the valid data authority values:
Data authority value *none *RWX *RW *RX *WX *R *W *X *EXCLUDE *AUTL Description The user has no authority to the object. The user has read, add, update, delete, and execute authorities. The user has read, add, and delete authorities. The user has read and execute authorities. The user has add, update, delete, and execute authorities. The user has read authority. The user has add, update, and delete authorities. The user has execute authority. The user cannot access the object. The public authorities on this object come from the authorization list.
The object authority can be set to one or more of the following values: alter, existence, management, or reference. You can use the setAlter(), setExistence(), setManagement(), or setReference() methods to set the values on or off. After setting either the data authority or the object authority of an object, it is important that you use the commit() method from the Permissions class to send the changes to the server. For more information about the different authorities, see the Security reference topic. Example This example shows you how to retrieve and print the permissions for a root object.
// Create a system object. AS400 sys = new AS400("MYAS400", "USERID", "PASSWORD"); // Represent the permissions to an object in the root file system. Permission objectInRoot = new Permission(sys, "/fred"); // Print the object pathname and retrieve its permissions. System.out.println("Permissions on "+objectInRoot.getObjectPath()+" are as follows:");
100
Enumeration enum = objectInRoot.getUserPermissions(); while (enum.hasMoreElements()) { // For each of the permissions, print out the user profile name // and that user's authorities to the object. RootPermission rootPerm = (RootPermission)enum.nextElement(); System.out.println(rootPerm.getUserID()+": "+rootPerm.getDataAuthority()); }
Print classes
Print objects include spooled files, output queues, printers, printer files, writer jobs, and Advanced Function Printing (AFP) resources, which include fonts, form definitions, overlays, page definitions, and page segments. The IBM Toolbox for Java classes for print objects are organized on a base class, PrintObject, and on a subclass for each of the six types of print objects. The base class contains the methods and attributes common to all server print objects. The subclasses contain methods and attributes specific to each subtype.
Examples
v Example: Creating spooled files shows how to create a spooled file on a server from an input stream v Example: Creating SCS spooled files shows how to generate a SCS data stream using the SCS3812Writer class, and how to write the stream to a spooled file on the server v Example: Reading spooled files shows how to use PrintObjectInputStream to read an existing server spooled file v Example: Reading and transforming spooled files shows how to use PrintObjectPageInputStream and PrintObjectTransformedInputStream to obtain different transformations when reading spooled file data v Example: Copying a spooled file shows how to copy a spooled file to the same queue that contains the file you want to copy. v Example: Listing spooled files asynchronously (using listeners) shows how to asynchronously list all spooled files on a system and how to use the PrintObjectListListener interface to get feedback as the list is being built v Example: Listing spooled files asynchronously (without using listeners) shows how to asynchronously list all spooled files on a system without using the PrintObjectListListener interface v Example: Listing spooled files synchronously shows how to synchronously list all spooled files on a system Related information PrintObject Javadoc Listing Print objects: You can use the IBM Toolbox for Java PrintObjectList class and its subclasses to work with lists of print objects. Print objects include spooled files, output queues, printers, Advanced Function Printing (AFP) resources, printer files, and writer jobs. Each subclass has methods that allow filtering of the list based on what makes sense for that particular type of print object. For example, SpooledFileList allows you to filter a list of spooled files based on the user who created the spooled files, the output queue that the spooled files are on, the form type, or user data of the spooled files. Only those spooled files that match the filter criteria are listed. If no filters are set, a default for each of the filters are used.
101
To actually retrieve the list of print objects from the server, the openSynchronously() or openAsynchronously() methods are used. The openSynchronously() method does not return until all objects in the list have been retrieved from the server. The openAsynchronously() method returns immediately, and the caller can do other things in the foreground while waiting for the list to build. The asynchronously opened list also allows the caller to start displaying the objects to the user as the objects come back. Because the user can see the objects as they come back, the response time may seem faster to the user. In fact, the response time may actually take longer overall due to the extra processing being done on each object in the list. If the list is opened asynchronously, the caller may get feedback on the building of the list. Methods, such as isCompleted() and size(), indicate whether the list has finished being built or return the current size of the list. Other methods, waitForListToComplete() and waitForItem(), allow the caller to wait for the list to complete or for a particular item. In addition to calling these PrintObjectList methods, the caller may register with the list as a listener. In this situation, the caller is notified of events that happen to the list. To register or unregister for the events, the caller uses PrintObjectListListener(), and then calls addPrintObjectListListener() to register removePrintObjectListListener()or to unregister. The following table shows the events that are delivered from a PrintObjectList.
PrintObjectList event listClosed listCompleted listErrorOccurred listOpened listObjectAdded When event is delivered When the list is closed. When the list completes. If any exception is thrown while the list is being retrieved. When the list is opened. When an object is added to the list.
After the list has been opened and the objects in the list processed, close the list using the close() method. This frees up any resources allocated to the garbage collector during the open. After a list has been closed, its filters can be modified, and the list can be opened again. When print objects are listed, attributes about each print object listed are sent from the server and stored with the print object. These attributes can be updated using the update() method in the PrintObject class. Which attributes are sent back from the server depends on the type of print object being listed. A default list of attributes for each type of print object that can be overridden by using the setAttributesToRetrieve() method in PrintObjectList exists. See the Retrieving PrintObject attributes section for a list of the attributes each type of print object supports. Examples The following examples show different ways to list spooled files. Example: Listing spooled files asynchronously (using listeners) on page 534 shows how to asynchronously list all spooled files on a system and how to use the PrintObjectListListener interface to get feedback as the list is being built Example: Listing spooled files asynchronously (without using listeners) on page 537 shows how to asynchronously list all spooled files on a system without using the PrintObjectListListener interface Example: Listing spooled files synchronously on page 539 shows how to synchronously list all spooled files on a system PrintObjectList Javadoc SpooledFileList Javadoc AFPResource Javadoc
102
Working with Print objects: PrintObject is an abstract class. An abstract class does not allow you to create an instance of the class. Instead, you must create an instance of one of its subclasses to work with print objects. Create objects of the subclasses in any of the following ways: v If you know the system and the identifying attributes of the object, construct the object explicitly by calling its public constructor. v You can use a PrintObjectList subclass to build a list of the objects and then get at the individual objects through the list. v An object may be created and returned to you as a result of a method or set methods being called. For example, the static method start() in the WriterJob class returns a WriterJob object. Use the base class, PrintObjectjavadoc/com/ibm/as400/access/PrintObject.html#NAVBAR_TOP, and its subclasses to work with server print objects: v OutputQueue v Printer v PrinterFile v SpooledFile v WriterJob PrintObject Javadoc PrintObjectList Javadoc OutputQueue Javadoc Printer Javadoc PrinterFile Javadoc SpooledFile Javadoc WriterJob Javadoc Retrieving PrintObject attributes: You can retrieve print object attributes by using the attribute ID and one of several methods from the base PrintObject class. The methods you can use include the following: v Use getIntegerAttribute(int attributeID) to retrieve an integer type attribute. v Use getFloatAttribute(int attributeID) to retrieve a floating point type attribute. v Use getStringAttribute(int attributeID) to retrieve a string type attribute. The attributeID parameter is an integer that identifies which attribute to retrieve. All of the IDs are defined as public constants in the base PrintObject class. The PrintAttributes file contains an entry of each attribute ID. The entry includes a description of the attribute and its type (integer, floating point, or string). For a list of which attributes may be retrieved using these methods, select the following links: v v v v v v AFPResourceAttrs for AFP Resources OutputQueueAttrs for output queues PrinterAttrs for printers PrinterFileAttrs for printer files SpooledFileAttrs for spooled files WriterJobAttrs for writer jobs
103
To achieve acceptable performance, these attributes are copied to the client. These attributes are copied either when the objects are listed, or the first time they are needed if the object was created implicitly. This keeps the object from going to the host every time the application needs to retrieve an attribute. This also makes it possible for the Java print object instance to contain out-of-date information about the object on the server. The user of the object can refresh all of the attributes by calling the update() method on the object. In addition, if the application calls any methods on the object that would cause the object's attributes to change, the attributes are automatically updated. For example, if an output queue has a status attribute of RELEASED (getStringAttribute(ATTR_OUTQSTS); returns a string of "RELEASED"), and the hold() method is called on the output queue, getting the status attribute after that returns HELD. setAttributes method You can use the SpooledFile setAttributes method to change the attributes of spooled files and printer file objects. Select the following links for a list or which attributes may be set: v PrinterFileAttrs file for printer files v SpooledFileAttrs for spooled files The setAttributes method takes a PrintParameterList parameter, which is a class that is used to hold a collection of attributes IDs and their values. The list starts out empty, and the caller can add attributes to the list by using the various setParameter() methods on it. PrintParameterList class You can use the PrintParameterList class to pass a group of attributes to a method that takes any of a number of attributes as parameters. For example, you can send a spooled file using TCP (LPR) by using the SpooledFile method, sendTCP(). The PrintParameterList object contains the required parameters for the send command, such as the remote system and queue, plus any optional parameters desired, such as whether to delete the spooled file after it is sent. In these cases, the method documentation gives a list of required and optional attributes. The PrintParameterList setParameter() method does not check which attributes you are setting and the values that you set them to. The PrintParameterList setParameter() method simply contains the values to pass along to the method. In general, extra attributes in the PrintParameterList are ignored, and illegal values on the attributes that are used are diagnosed on the server. PrintObject Javadoc SpooledFile Javadoc PrintParameterList Javadoc AFP Resource Attributes: This topic lists the attributes that can be retrieved and set for an AFP resource. Retrieve Attributes The following attributes may be retrieved for an AFP resource using the appropriate getIntegerAttribute(), getStringAttribute(), or getFloatAttribute() method: v ATTR_AFP_RESOURCE - AFP resource Integrated File System Path v v v v v ATTR_OBJEXTATTR - Object Extended Attribute ATTR_DESCRIPTION - Text Description ATTR_DATE - Date File Opened ATTR_TIME - Time File Opened ATTR_NUMBYTES - Number of bytes to read/write
104
Set Attributes Attributes are not allowed to be set for an AFP resource. Output queue attributes: This topic lists the attributes available for an output queue. Retrieve attributes The following attributes may be retrieved for an output queue using the appropriate getIntegerAttribute(), getStringAttribute(), or getFloatAttribute() method: v ATTR_AUTHCHCK - Authority to Check v ATTR_DATA_QUEUE - Data Queue Integrated File System Name v ATTR_DISPLAYANY - Display any File v ATTR_JOBSEPRATR - Job Separators v v v v v v v v v v v v v v v v v ATTR_NUMFILES - Number of Files ATTR_NUMWRITERS - Number of Writers Started to Queue ATTR_OPCNTRL - Operator Controlled ATTR_ORDER - Order of Files On Queue ATTR_OUTPUT_QUEUE - Output Queue Integrated File System Name ATTR_OUTQSTS - Output Queue Status ATTR_PRINTER - Printer ATTR_SEPPAGE - Separator page ATTR_DESCRIPTION - Text Description ATTR_USRDEFOPT - User defined option(s) ATTR_USER_DEFINED_OBJECT - User defined object Integrated File System Name ATTR_USER_TRANSFORM_PROG - User transform program Integrated File System Name ATTR_USER_DRIVER_PROG - User driver program Integrated File System Name ATTR_WTRJOBNAME - Writer Job Name ATTR_WTRJOBNUM - Writer Job Number ATTR_WTRJOBSTS - Writer Job Status ATTR_WTRJOBUSER - Writer Job User Name
Set attributes Attributes are not allowed to be set for an output queue. Printer Attributes: The following attributes may be retrieved for a printer using the appropriate getIntegerAttribute(), getStringAttribute(), or getFloatAttribute() method: Retrieve Attributes v ATTR_AFP - Advanced Function Printing v ATTR_ALIGNFORMS - Align Forms v ATTR_ALWDRTPRT - Allow Direct Print v ATTR_BTWNCPYSTS - Between copies status v ATTR_BTWNFILESTS - Between files status
IBM Toolbox for Java
105
v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v
ATTR_CODEPAGE - Code Page ATTR_CHANGES - Changes ATTR_DEVCLASS - Device Class ATTR_DEVMODEL - Device Model ATTR_DEVTYPE - Device Type ATTR_DEVSTATUS - Device Status ATTR_DRWRSEP - Drawer for Separators ATTR_ENDPNDSTS - End pending status ATTR_FILESEP - File Separators ATTR_FONTID - Font Identifier ATTR_FORM_DEFINITION - Form Definition Integrated File System Name ATTR_FORMTYPE - Form Type ATTR_FORMTYPEMSG - Form Type Message ATTR_FORMFEED - Form Feed ATTR_CHAR_ID - Graphic Character Set ATTR_HELDSTS - Held status ATTR_HOLDPNDSTS - Hold pending status ATTR_JOBUSER - Job User ATTR_MFGTYPE - Manufacturer Type and Model ATTR_MESSAGE_QUEUE - Message Queue Integrated File System Name ATTR_ONJOBQSTS - On job queue status ATTR_OUTPUT_QUEUE - Output Queue Integrated File System Name ATTR_OVERALLSTS - Overall Status ATTR_POINTSIZE - Point Size ATTR_PRINTER - Printer ATTR_PRTDEVTYPE - Printer Device Type ATTR_PUBINF_COLOR_SUP - Publishing Info Color Supported ATTR_PUBINF_PPM_COLOR - Publishing Info Pages per Minute (Color) ATTR_PUBINF_PPM - Publishing Info Pages per Minute (Monochrome) ATTR_PUBINF_DUPLEX_SUP - Publishing Info Duplex Support ATTR_PUBINF_LOCATION - Publishing Info Location ATTR_RMTLOCNAME - Remote Location Name ATTR_SPOOLFILE - Spooled File Name ATTR_SPLFNUM - Spooled File Number ATTR_STARTEDBY - Started By User ATTR_DESCRIPTION - Text Description ATTR_USERDATA - User data ATTR_USRDEFOPT - User defined option(s) ATTR_USER_DEFINED_OBJECT - User defined object Integrated File System Name ATTR_USER_TRANSFORM_PROG - User transform program Integrated File System Name ATTR_USER_DRIVER_PROG - User driver program Integrated File System Name ATTR_SCS2ASCII - Transform SCS to ASCII ATTR_WTNGDATASTS - Waiting for data status ATTR_WTNGDEVSTS - Waiting for device status ATTR_WTNGMSGSTS - Waiting for message status
IBM i: Programming IBM Toolbox for Java
106
v v v v v
ATTR_WTRAUTOEND - When to Automatically End Writer ATTR_WTRJOBNAME - Writer Job Name ATTR_WTRJOBSTS - Writer Job Status ATTR_WTRSTRTD - Writer started ATTR_WRTNGSTS - Writing status
Set Attributes Attributes are not allowed to be set for a printer. Printer file attributes: This topic contains a list of printer file attributes for use with IBM Toolbox for Java. Retrieve attributes The following attributes may be retrieved for a printer file using the appropriate getIntegerAttribute(), getStringAttribute(), or getFloatAttribute() method: v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v ATTR_ALIGN - Align Page ATTR_BKMGN_ACR - Back Margin Offset Across ATTR_BKMGN_DWN - Back Margin Offset Down ATTR_BACK_OVERLAY - Back Overlay Integrated File System Name ATTR_BKOVL_DWN - Back Overlay Offset Down ATTR_BKOVL_ACR - Back Overlay offset across ATTR_CPI - Characters per Inch ATTR_CODEDFNTLIB - Coded Font Library Name ATTR_CODEPAGE - Code Page ATTR_CODEDFNT - Code Font Name ATTR_CONTROLCHAR - Control Character ATTR_CONVERT_LINEDATA - Convert Line Data ATTR_COPIES - Copies ATTR_CORNER_STAPLE - Corner staple ATTR_DBCSDATA - User Specified DBCS Data ATTR_DBCSEXTENSN - DBCS Extension Characters ATTR_DBCSROTATE - DBCS Character Rotation ATTR_DBCSCPI - DBCS Characters per Inch ATTR_DBCSSISO - DBCS SO/SI Spacing ATTR_DFR_WRITE - Defer Write ATTR_PAGRTT - Degree of Page Rotation ATTR_EDGESTITCH_NUMSTAPLES - Edge Stitch Number of Staples ATTR_EDGESTITCH_REF - Edge Stitch Reference ATTR_EDGESTITCH_REFOFF - Edge Stitch Reference ATTR_ENDPAGE - Ending Page ATTR_FILESEP - File Separators ATTR_FOLDREC - Fold Records ATTR_FONTID - Font Identifier ATTR_FORM_DEFINITION - Form Definition Integrated File System Name ATTR_FORMFEED - Form Feed
IBM Toolbox for Java
107
v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v
ATTR_FORMTYPE - Form Type ATTR_FTMGN_ACR - Front Margin Offset Across ATTR_FTMGN_DWN - Front Margin Offset Down ATTR_FRONT_OVERLAY - Front overlay Integrated File System Name ATTR_FTOVL_ACR - Front Overlay Offset Across ATTR_FTOVL_DWN - Front Overlay Offset Down ATTR_CHAR_ID - Graphic Character Set ATTR_JUSTIFY - Hardware Justification ATTR_HOLD - Hold Spool File ATTR_LPI - Lines Per Inch ATTR_MAXRCDS - Maximum Spooled Output Records ATTR_OUTPTY - Output Priority ATTR_OUTPUT_QUEUE - Output Queue Integrated File System Name ATTR_OVERFLOW - Overflow Line Number ATTR_PAGE_DEFINITION - Page Definition Integrated File System ATTR_PAGELEN - Length of Page ATTR_MEASMETHOD - Measurement Method ATTR_PAGEWIDTH - Width of Page ATTR_MULTIUP - Pages Per Side ATTR_POINTSIZE - Point Size ATTR_FIDELITY - Print Fidelity ATTR_DUPLEX - Print on Both Sides ATTR_PRTQUALITY - Print Quality ATTR_PRTTEXT - Print Text ATTR_PRINTER - Printer ATTR_PRTDEVTYPE - Printer Device Type ATTR_RPLUNPRT - Replace Unprintable Characters ATTR_RPLCHAR - Replacement Character ATTR_SADDLESTITCH_NUMSTAPLES - Saddle Stitch Number of Staples ATTR_SADDLESTITCH_REF - Saddle Stitch Reference ATTR_SAVE -Save Spooled File ATTR_SRCDRWR - Source Drawer ATTR_SPOOL - Spool the Data ATTR_SCHEDULE - Spooled Output Schedule ATTR_STARTPAGE - Starting Page ATTR_DESCRIPTION - Text Description ATTR_UNITOFMEAS - Unit of Measure ATTR_USERDATA - User Data ATTR_USRDEFDATA - User defined data ATTR_USRDEFOPT - User defined option(s) ATTR_USER_DEFINED_OBJECT - User defined object Integrated File System Name
Set attributes The following attributes may be set for a printer file using the setAttributes() method: v ATTR_ALIGN - Align Page
108
v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v
ATTR_BKMGN_ACR - Back Margin Offset Across ATTR_BKMGN_DWN - Back Margin Offset Down ATTR_BACK_OVERLAY - Back Overlay Integrated File System Name ATTR_BKOVL_DWN - Back Overlay Offset Down ATTR_BKOVL_ACR - Back Overlay offset across ATTR_CPI - Characters per Inch ATTR_CODEDFNTLIB - Coded Font Library Name ATTR_CODEPAGE - Code Page ATTR_CODEDFNT - Code Font Name ATTR_CONTROLCHAR - Control Character ATTR_CONVERT_LINEDATA - Convert Line Data ATTR_COPIES - Copies ATTR_CORNER_STAPLE - Corner staple ATTR_DBCSDATA - User Specified DBCS Data ATTR_DBCSEXTENSN - DBCS Extension Characters ATTR_DBCSROTATE - DBCS Character Rotation ATTR_DBCSCPI - DBCS Characters per Inch ATTR_DBCSSISO - DBCS SO/SI Spacing ATTR_DFR_WRITE - Defer Write ATTR_PAGRTT - Degree of Page Rotation ATTR_EDGESTITCH_NUMSTAPLES - Edge Stitch Number of Staples ATTR_EDGESTITCH_REF - Edge Stitch Reference ATTR_EDGESTITCH_REFOFF - Edge Stitch Reference ATTR_ENDPAGE - Ending Page ATTR_FILESEP - File Separators ATTR_FOLDREC - Fold Records ATTR_FONTID - Font Identifier ATTR_FORM_DEFINITION - Form Definition Integrated File System Name ATTR_FORMFEED - Form Feed ATTR_FORMTYPE - Form Type ATTR_FTMGN_ACR - Front Margin Offset Across ATTR_FTMGN_DWN - Front Margin Offset Down ATTR_FRONT_OVERLAY - Front overlay Integrated File System Name ATTR_FTOVL_ACR - Front Overlay Offset Across ATTR_FTOVL_DWN - Front Overlay Offset Down ATTR_CHAR_ID - Graphic Character Set ATTR_JUSTIFY - Hardware Justification ATTR_HOLD - Hold Spool File ATTR_LPI - Lines Per Inch ATTR_MAXRCDS - Maximum Spooled Output Records ATTR_OUTPTY - Output Priority ATTR_OUTPUT_QUEUE - Output Queue Integrated File System Name ATTR_OVERFLOW - Overflow Line Number ATTR_PAGE_DEFINITION - Page Definition Integrated File System ATTR_PAGELEN - Length of Page
IBM Toolbox for Java
109
v v v v v v v v v v v v v v v v v v v v v v v v v
ATTR_MEASMETHOD - Measurement Method ATTR_PAGEWIDTH - Width of Page ATTR_MULTIUP - Pages Per Side ATTR_POINTSIZE - Point Size ATTR_FIDELITY - Print Fidelity ATTR_DUPLEX - Print on Both Sides ATTR_PRTQUALITY - Print Quality ATTR_PRTTEXT - Print Text ATTR_PRINTER - Printer ATTR_PRTDEVTYPE - Printer Device Type ATTR_RPLUNPRT - Replace Unprintable Characters ATTR_RPLCHAR - Replacement Character ATTR_SADDLESTITCH_NUMSTAPLES - Saddle Stitch Number of Staples ATTR_SADDLESTITCH_REF - Saddle Stitch Reference ATTR_SAVE -Save Spooled File ATTR_SRCDRWR - Source Drawer ATTR_SPOOL - Spool the Data ATTR_SCHEDULE - Spooled Output Schedule ATTR_STARTPAGE - Starting Page ATTR_DESCRIPTION - Text Description ATTR_UNITOFMEAS - Unit of Measure ATTR_USERDATA - User Data ATTR_USRDEFDATA - User defined data ATTR_USRDEFOPT - User defined option(s) ATTR_USER_DEFINED_OBJECT - User defined object Integrated File System Name
Spooled file attributes: This topic lists the attributes that can be retrieved and set for a spooled file. Retrieve attributes The following attributes may be retrieved for a spooled file using the appropriate getIntegerAttribute(), getStringAttribute(), or getFloatAttribute() method: v ATTR_AFP - Advanced Function Printing v v v v v v v v v v v v ATTR_ALIGN - Align Page ATTR_BKMGN_ACR - Back Overlay offset across ATTR_BKMGN_DWN - Back Overlay Offset Down ATTR_BACK_OVERLAY - Back Overlay Integrated File System Name ATTR_BKOVL_DWN - Back Overlay Offset Down ATTR_BKOVL_ACR - Back Overlay offset across ATTR_CPI - Characters per Inch ATTR_CODEDFNTLIB - Coded Font Library Name ATTR_CODEDFNT - Code Font Name ATTR_CODEPAGE - Code Page ATTR_CONTROLCHAR - Control Character ATTR_COPIES - Copies
IBM i: Programming IBM Toolbox for Java
110
v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v
ATTR_COPIESLEFT - Copies left to Produce ATTR_CORNER_STAPLE - Corner staple ATTR_CURPAGE - Current Page ATTR_DATE - Date Object Created ATTR_DATE_WTR_BEGAN_FILE - Date Writer Began Processing Spooled File ATTR_DATE_WTR_CMPL_FILE - Date Writer Completed Processing Spooled File ATTR_DBCSDATA - User Specified DBCS Data ATTR_DBCSEXTENSN - DBCS Extension Characters ATTR_DBCSROTATE - DBCS Character Rotation ATTR_DBCSCPI - DBCS Characters per Inch ATTR_DBCSSISO - DBCS SO/SI Spacing ATTR_PAGRTT - Degree of Page Rotation ATTR_EDGESTITCH_NUMSTAPLES - Edge Stitch Number of Staples ATTR_EDGESTITCH_REF - Edge Stitch Reference ATTR_EDGESTITCH_REFOFF - Edge Stitch Reference Offset ATTR_ENDPAGE - Ending Page ATTR_FILESEP - File Separators ATTR_FOLDREC - Fold Records ATTR_FONTID - Font Identifier ATTR_FORM_DEFINITION - Form definition Integrated File System Name ATTR_FORMFEED - Form Feed ATTR_FORMTYPE - Form Type ATTR_FTMGN_ACR - Front Margin Offset Across ATTR_FTMGN_DWN - Front Margin Offset Down ATTR_FRONTSIDE_OVERLAY - Front overlay Integrated File System Name ATTR_FTOVL_ACR - Front Overlay Offset Across ATTR_FTOVL_DWN - Front Overlay Offset Down ATTR_CHAR_ID - Graphic Character Set ATTR_JUSTIFY - Hardware Justification ATTR_HOLD - Hold Spool File ATTR_IPP_ATTR_CHARSET - IPP Attributes-charset ATTR_IPP_JOB_ID - IPP Job ID ATTR_IPP_JOB_NAME - IPP Job Name ATTR_IPP_JOB_NAME_NL - IPP Job Name NL ATTR_IPP_JOB_ORIGUSER - IPP Job Originating User ATTR_IPP_JOB_ORIGUSER_NL - IPP Job Originating User NL ATTR_IPP_PRINTER_NAME - IPP Printer Name ATTR_JOBNAME - Job Name ATTR_JOBNUMBER - Job Number ATTR_JOBUSER - Job User ATTR_JOB_SYSTEM - Job System ATTR_LASTPAGE - Last Page Printed ATTR_LINESPACING - Line Spacing ATTR_LPI - Lines Per Inch ATTR_MAXRCDS - Maximum Spooled Output Records
IBM Toolbox for Java
111
v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v
ATTR_PAGELEN - Length of Page ATTR_PAGEWIDTH - Width of Page ATTR_MEASMETHOD - Measurement Method ATTR_NETWORK - Network Identifier ATTR_NUMBYTES - Number of bytes to read/write ATTR_OUTPUTBIN - Output Bin ATTR_OUTPTY - Output Priority ATTR_OUTPUT_QUEUE - Output Queue Integrated File System Name ATTR_OVERFLOW - Overflow Line Number ATTR_MULTIUP - Pages Per Side ATTR_POINTSIZE - Point Size ATTR_FIDELITY - Print Fidelity ATTR_DUPLEX - Print on Both Sides ATTR_PRTQUALITY - Print Quality ATTR_PRTTEXT - Print Text ATTR_PRINTER - Printer ATTR_PRTASSIGNED - Printer Assigned ATTR_PRTDEVTYPE - Printer Device Type ATTR_PRINTER_FILE - Printer File Integrated File System Name ATTR_RECLENGTH - Record Length ATTR_REDUCE - Reduce Output ATTR_RPLUNPRT - Replace Unprintable Characters ATTR_RPLCHAR - Replacement Character ATTR_RESTART - Restart Printing ATTR_SADDLESTITCH_NUMSTAPLES - Saddle Stitch Number of Staples ATTR_SADDLESTITCH_REF - Saddle Stitch Reference ATTR_SAVE - Save Spooled File ATTR_SRCDRWR - Source Drawer ATTR_SPOOLFILE - Spooled File Name ATTR_SPLFNUM - Spooled File Number ATTR_SPLFSTATUS - Spooled File Status ATTR_SCHEDULE - Spooled Output Schedule ATTR_STARTPAGE - Starting Page ATTR_SYSTEM - System Where Created ATTR_TIME - Time Object Created ATTR_TIME_WTR_BEGAN_FILE - Time Writer Began Processing Spooled File ATTR_TIME_WTR_CMPL_FILE - Time Writer Completed Processing Spooled File ATTR_PAGES - Total Pages ATTR_UNITOFMEAS - Unit of Measure ATTR_USERCMT - User Comment ATTR_USERDATA - User Data ATTR_USRDEFDATA - User Defined Data ATTR_USRDEFFILE - User Defined File ATTR_USRDEFOPT - User Defined Option(s) ATTR_USER_DEFINED_OBJECT - User Defined Object Integrated File System Name
IBM i: Programming IBM Toolbox for Java
112
Set attributes The following attributes may be set for a spooled file using the setAttributes() method: v v v v v v v v v v v v v v v v v v v v v v v v v v v v ATTR_ALIGN - Align Page ATTR_BACK_OVERLAY - Back Overlay Integrated File System Name ATTR_BKOVL_DWN - Back Overlay Offset Down ATTR_BKOVL_ACR - Back Overlay offset across ATTR_COPIES - Copies ATTR_ENDPAGE - Ending Page ATTR_FILESEP - File Separators ATTR_FORM_DEFINITION - Form definition Integrated File System Name ATTR_FORMFEED - Form Feed ATTR_FORMTYPE - Form Type ATTR_FRONTSIDE_OVERLAY - Front overlay Integrated File System Name ATTR_FTOVL_ACR - Front Overlay Offset Across ATTR_FTOVL_DWN - Front Overlay Offset Down ATTR_OUTPTY - Output Priority ATTR_OUTPUT_QUEUE - Output Queue Integrated File System Name ATTR_MULTIUP - Pages Per Side ATTR_FIDELITY - Print Fidelity ATTR_DUPLEX - Print on Both Sides ATTR_PRTQUALITY - Print Quality ATTR_PRTSEQUENCE - Print Sequence ATTR_PRINTER - Printer ATTR_RESTART - Restart Printing ATTR_SAVE - Save Spooled File ATTR_SCHEDULE - Spooled Output Schedule ATTR_STARTPAGE - Starting Page ATTR_USERDATA - User Data ATTR_USRDEFOPT - User defined option(s) ATTR_USER_DEFINED_OBJECT - User defined object Integrated File System Name
Writer Job Attributes: This topic lists the attributes for writer jobs. Retrieve Attributes The following attributes may be retrieved for a writer job using the appropriate getIntegerAttribute(), getStringAttribute(), or getFloatAttribute() method: v ATTR_WTRJOBNAME - Writer Job Name v ATTR_WTRJOBNUM - Writer Job Number v ATTR_WTRJOBSTS - Writer Job Status v ATTR_WTRJOBUSER - Writer Job User Name Set Attributes Attributes are not allowed to be set for a writer job.
IBM Toolbox for Java
113
Print Object Attributes: This topic lists the attributes available for print objects. v v v v v v v v Advanced Function Printing AFP Resource Align Forms Align Page Allow Direct Print Authority Authority to Check Automatically End Writer
v Auxiliary Storage v Back Margin Offset Across v v v v v Back Margin Offset Down Backside Overlay Back Overlay offset across Back Overlay Offset Down Between Copies Status
v Between Files Status v Changes v Characters per Inch v v v v v v v v Code Page Code Font Name Coded Font Library Name Control Character Convert line data Copies Copies left to Produce Corner staple
v Current Page v Data Format v Data Queue v Date File Opened v Date Spooled File Job Create End v v v v v v v v Date Writer Began Processing Spooled File Date Writer Completed Processing Spooled File User Specified DBCS Data DBCS Extension Characters DBCS Character Rotation DBCS Characters per Inch DBCS SO/SI Spacing Defer Write
114
v v v v v v v v v v v v v v v v v v
Destination Type Device Class Device Model Device Status Device Type Display any File Drawer for Separators Edge Stitch Number of Staples Edge Stitch Reference Edge Stitch Reference Offset End Pending Status Ending Page Envelope Source File Separators Fold Records Font Identifier Form Definition Form Feed
v Form Type v Form Type Message Option v Front Margin Offset Across v v v v v v v v Front Front Front Front Margin Offset Down Overlay Overlay Offset Across Overlay Offset Down
Graphic Character Set Hardware Justification Held Status Hold Spool File
v Hold Pending Status v Image Configuration v Initialize the writer v Internet Address v IPP Attributes-charset v IPP Job ID v v v v v v v IPP Job Name IPP Job Name NL IPP Job Originating User Name IPP Job Originating User Name NL IPP IPP Printer Name Job Name Job Number
115
v v v v v v v v v v v v v v v v v v
Last Page Printed Length of Page Library Name Lines Per Inch Line Spacing Manufacturer Type and Model Max Jobs per Client List Maximum Spooled Output Records Measurement Method Message Help Message ID Message Queue Message Reply Message Text Message Type Message Severity Multi_Item Reply Capability Network Identifier
v Network Print Server Object Attributes v Number of Bytes in Spooled File v Number of Bytes to Read/Write v v v v v v v v v v v v Number of Files Number of Writers Started to Queue Object Extended Attribute On Job Queue Status Open time commands Operator Controlled Order of Files On Queue Output Bin Output Priority Output Queue Output Queue Status Overall Status
v Overflow Line Number v Page At A Time v v v v v v v Page Count Estimated Page Definition Page Number Pages Per Side Paper Source 1 Paper Source 2 Pel Density
116
v v v v v v v v v v v v v v v v v v
Print Quality Print Sequence Print Text Printer Printer Assigned Printer Device Type Printer File Printer Queue Publishing Info Color Supported Publishing Info Pages per Minute (Color) Publishing Info Pages per Minute (Monochrome) Publishing Info Duplex Support Publishing Info Location Remote Location Name Record Length Reduce Output Remote System Replace Unprintable Characters
v Replacement Character v Restart Printing v Saddle Stitch Number of Staples v v v v v v v v v v v v Saddle Stitch Reference Save Spooled File Seek Offset Seek Origin Send Priority Separator page Source Drawer Spool SCS Spool the Data Spooled File Creation Authentication Method Spooled File Creation Security Method Spooled File Name
v Spooled File Number v Spooled File Status v v v v v v v Spooled Output Schedule Started By User Starting Page System Where Created Text Description Time File Opened Time Spooled File Create Job End
v Time Writer Began Processing Spooled File v Time Writer Completed Processing Spooled File v Total Pages
IBM Toolbox for Java
117
v v v v v v v v v v v v v v v v v v
Transform SCS to ASCII Unit of Measure User Comment User Data User Defined Data User User User User User User User Defined File Defined Object Defined Option(s) Driver Program Data Driver Program ID ID Address
User Transform Program Viewing Fidelity VM/MVS Class Waiting for Data Status Waiting for Device Status Waiting for Message Status
v When to Automatically End Writer v When to End Writer v When to Hold File v v v v v v v v Width of Page Workstation Customizing Object Writer Job Name Writer Job Number Writer Writer Writer Writer Job Status Job User Name Started Starting Page
v Writing Status v NPS CCSID v NPS Level Advanced Function Printing ID Type ATTR_AFP String
Description Indicates whether this spooled file uses AFP resources external to the spooled file. Valid values are *YES and *NO. AFP Resource ID Type ATTR_AFP_RESOURCE String
Description The Integrated File System path of the external AFP (Advanced Function Print) resource. The
118
format of the Integrated File System path is "/QSYS.LIB/library.LIB/resource.type" where library is the library that contains the resource, resource is the name of the resource and type is the resource type. Valid values for type include "FNTRSC", "FORMDF", "OVL", "PAGSEG", and "PAGDFN". Align Forms ID Type ATTR_ALIGNFORMS String
Description The time at which a forms alignment message will be sent. Valid values are *WTR, *FILE, *FIRST. Align Page ID Type ATTR_ALIGN String
Description Indicates whether a forms alignment message is sent before printing this spooled file. Valid values are *YES, *NO. Allow Direct Print ID Type ATTR_ALWDRTPRT String
Description Indicates whether the printer writer allows the printer to be allocated to a job that prints directly to a printer. Valid values are *YES, *NO. Authority ID Type ATTR_AUT String
Description Specifies the authority that is given to users who do not have specific authority to the output queue. Valid values are *USE, *ALL, *CHANGE, *EXCLUDE, *LIBCRTAUT. Authority to Check ID Type ATTR_AUTCHK String
Description Indicates what type of authorities to the output queue allow the user to control all the files on the output queue. Valid values are *OWNER, *DTAAUT. Automatically End Writer ID Type ATTR_AUTOEND String
Description Specifies if the writer must be automatically ended. Valid values are *NO, *YES.
119
Description Specifies the number of the auxiliary storage pool (ASP) that the spooled file is stored on. The possible values are: v 1: System ASP v 2-32: One of the user ASPs Back Margin Offset Across ID Type ATTR_BACKMGN_ACR Float
Description For the back side of a piece of paper, it specifies, how far in from the left side of the page printing starts. The special value *FRONTMGN will be encoded as -1. Back Margin Offset Down ID Type ATTR_BACKMGN_DWN Float
Description For the back side of a piece of paper, it specifies, how far down from the top of the page printing starts. The special value *FRONTMGN will be encoded as -1. Back Overlay ID Type ATTR_BACK_OVERLAY String
Description The Integrated File System path of the back overlay or a special value. If the value is an Integrated File System path it will have the format "/QSYS.LIB/library.LIB/overlay.OVL" where library is the library of the resource and overlay is the name of the overlay. Valid special values include *FRONTOVL. Back Overlay offset across ID Type ATTR_BKOVL_ACR Float
Description The offset across from the point of origin where the overlay is printed. Back Overlay Offset Down ID Type ATTR_BKOVL_DWN Float
Description The offset down from the point of origin where the overlay is printed. Between Copies Status ID ATTR_BTWNCPYSTS
IBM i: Programming IBM Toolbox for Java
120
Type
String
Description Whether the writer is between copies of a multiple copy spooled file. Returned values are *YES or *NO. Between Files Status ID Type ATTR_BTWNFILESTS String
Description Whether the writer is between files. Returned values are *YES or *NO. Changes ID Type ATTR_CHANGES String
Description The time at which pending changes take effect. Valid values are *NORDYF, *FILEEND, or blank which implies no changes pending to the writer. Characters per Inch ID Type ATTR_CPI Float
Description The number of characters per horizontal inch. Code Page ID Type ATTR_CODEPAGE String
Description The mapping of graphic characters to code points for this spooled file. If the graphic character set field contains a special value, this field may contain a zero (0). Code Font Name ID Type ATTR_CODEDFNT String
Description The name of the coded font. A coded font is an AFP resource that is composed of a character set and a code page. Special values include *FNTCHRSET. Coded Font Library Name ID Type ATTR_CODEDFNTLIB String
Description The name of the library that contains the coded font. This field may contain blanks if the coded font name field has a special value.
121
Description Whether this file uses the American National Standards printer control character. The possible values are *NONE for no print control characters are passed in the data that is printed or *FCFC which means that the first character of every record is an American National Standards printer control character. Convert Line Data ID Type ATTR_CONVERT_LINEDATA String
Description Whether the line data is converted to AFPDS before it is written to spool. The possible values are *NO and *YES. Copies ID Type ATTR_COPIES Integer
Description The total number of copies to be produced for this spooled file. Copies left to Produce ID Type ATTR_COPIESLEFT Integer
Description The remaining number of copies to be produced for this spooled file. Corner Staple ID Type ATTR_CORNER_STAPLE String
Description The reference corner to be used for a corner staple. A staple is driven into the media at the reference corner. Valid values are *NONE, *DEVD, *BOTRIGHT, *TOPRIGHT, *TOPLEFT, and *BOTLEFT. Current Page ID Type ATTR_CURPAGE Integer
Description Current page that is being written by the writer job. Data Format ID Type ATTR_DATAFORMAT String
122
Description Data format. Valid values are *RCDDATA, *ALLDATA. Data Queue ID Type ATTR_DATA_QUEUE String
Description Specifies the Integrated File System path of the data queue that is associated with the output queue or "*NONE" if no data queue is associated with the the output queue. The format of the Integrated File System path is "/QSYS.LIB/library.LIB/dataqueue.DTAQ" where library is the library that contains the data queue and dataqueue is the name of the data queue. Date File Opened ID Type ATTR_DATE String
Description For spooled files this is the date the spooled file was opened. For AFP resources this is the date the object was last modified. The date is encoded in a character string with the following format, C YY MM DD. Date Spooled File Job Create End ID Type ATTR_DATE_END String
Description The date the job ended that created the spooled file on the system. If the Starting spooled file create date field is set to *ALL, then this field must be set to blanks. If a date has been specified for the Starting spooled file create date field, then this field must be set to a valid date. The date must be in the CYYMMDD format or be one of the following special values: v *LAST: All spooled files with a create date and time equal to or later than the starting spooled file create date are to be returned. v Date: All spooled files with a create date and time equal to or later than the starting spooled file create date and time and less than or equal to the ending spooled file create date and time are to be returned. The date format CYYMMDD is defined as follows: v v v v C is the Century, where 0 indicates years 19xx and 1 indicates years 20xx YY is the Year MM is the Month DD is the Day
Description Indicates the date at which the writer began processing this spooled file. The date is encoded in a character string with the following format, C YY MM DD.
123
Description Indicates the date at which the writer began finished this spooled file. The date is encoded in a character string with the following format, C YY MM DD. User Specified DBCS Data ID Type ATTR_DBCSDATA String
Description Whether the spooled file contains double-byte character set (DBCS) data. Valid values are *NO and *YES. DBCS Extension Characters ID Type ATTR_DBCSEXTENSN String
Description Whether the system is to process the DBCS extension characters. Valid values are *NO and *YES. DBCS Character Rotation ID Type ATTR_DBCAROTATE String
Description Whether the DBCS characters are rotated 90 degrees counterclockwise before printing. Valid values are *NO and *YES. DBCS Characters per Inch ID Type ATTR_DBCSCPI Integer
Description The number of double-byte characters to be printed per inch. Valid values are -1, -2, 5, 6, and 10. The value *CPI is encoded as -1. The value *CONDENSED is encoded as -2. DBCS SO/SI Spacing ID Type ATTR_DBCSSISO String
Description Determines the presentation of shift-out and shift-in characters when printed. Valid values are *NO, *YES, and *RIGHT. Defer Write ID Type ATTR_DFR_WRITE String
124
Description Whether print data is held in system buffers before Degree of Page Rotation ID Type ATTR_PAGRTT Integer
Description The degree of rotation of the text on the page, with respect to the way the form is loaded into the printer. Valid values are -1, -2, -3, 0, 90, 180, 270. The value *AUTO is encoded as -1, the value *DEVD is encoded as -2, and the value *COR is encoded as -3. Delete File After Sending ID Type ATTR_DELETESPLF String
Description Delete the spooled file after sending? Valid values are *NO and *YES. Destination Option ID Type ATTR_DESTOPTION String
Description Destination option. A text string that allows the user to pass options to the receiving system. Destination Type ID Type ATTR_DESTINATION String
Description Destination type. Valid values are *OTHER, *AS400, *PSF2. Device Class ID Type ATTR_DEVCLASS String
Description The model number of the device. Device Status ID Type ATTR_DEVSTATUS Integer
125
Description The status of the printer device. Valid values are 0 (varied off), 10 (vary off pending), 20 (vary on pending), 30 (varied on), 40 (connect pending), 60 (active), 66 (active writer), 70 (held), 75 (powered off), 80 (recovery pending), 90 (recovery canceled), 100 (failed), 106 (failed writer), 110 (being serviced), 111 (damaged), 112 (locked), 113 (unknown). Device Type ID Type ATTR_DEVTYPE String
Description The device type. Display any File ID Type ATTR_DISPLAYANY String
Description Whether users who have authority to read this output queue can display the output data of any output file on this queue or only the data in their own files. Valid values are *YES, *NO, *OWNER. Drawer for Separators ID Type ATTR_DRWRSEP Integer
Description Identifies the drawer from which the job and file separator pages are to be taken. Valid values are -1, -2, 1, 2, 3. The value *FILE is encoded as -1, and the value *DEVD is encoded as -2. Edge Stitch Number of Staples ID Type ATTR_EDGESTITCH_NUMSTAPLES Integer
Description The number of staples that are applied along the finishing operation axis. Edge Stitch Reference ID Type ATTR_EDGESTITCH_REF String
Description Where one or more staples are driven into the media along the finishing operation axis. Valid values are *NONE, *DEVD, *BOTTOM, *RIGHT, *TOP, and *LEFT. Edge Stitch Reference Offset ID Type ATTR_EDGESTITCH_REFOFF Float
Description The offset of the edge stitch from the reference edge toward the center of the media.
126
Description Whether an End Writer (ENDWTR) command has been issued for this writer. Possible values are *NO - no ENDWTR command was issued, *IMMED - the writer ends as soon as its output buffers are empty, *CTRLD - the writer ends after the current copy of the spooled file has printed, *PAGEEND - the writer ends at the end of the page. Ending Page ID Type ATTR_ENDPAGE Integer
Description The page number at which to end printing the spooled file. Valid values are 0 or the ending page number. The value *END is encoded as 0. Envelope Source ID Type ATTR_ENVLP_SOURCE String
Description The size of the envelope in the envelope source. If this field is not specified or the value is not valid, the special value of *MFRTYPMDL is used. Valid values are *NONE - there is no envelope source, *MFRTYPMDL - the envelope size suggested by the manufacturer type and model is used, *MONARCH (3.875 x 7.5 inches), *NUMBER9 (3.875 x 8.875 inches), *NUMBER10 (4.125 x 9.5 inches), *B5 (176mm x 250mm), *C5 (162mm x 229mm), *DL (110mm x 220mm). File Separators ID Type ATTR_FILESEP Integer
Description The number of file separator pages that are placed at the beginning of each copy of the spooled file. Valid values are -1, or the number of separators. The value *FILE is encoded as -1. Fold Records ID Type ATTR_FOLDREC String
Description Whether records that exceed the printer forms width are folded (wrapped) to the next line. Valid values are *YES, *NO. Font Identifier ID Type ATTR_FONTID String
Description The printer font that is used. Valid special values include *CPI and *DEVD.
127
Description The Integrated File System path name of the form definition or a special value. If an Integrated File System path is specified the format is "/QSYS.LIB/library.LIB/formdef.FORMDF" where library is the library of the form definition and formdef is the name of the form definition. Valid special values include *NONE, *INLINE, *INLINED, and *DEVD. Form Feed ID Type ATTR_FORMFEED String
Description The manner in which forms feed to the printer. Valid values are *CONT, *CUT, *AUTOCUT, *DEVD. Form Type ID Type ATTR_FORMTYPE String
Description The type of form to be loaded in the printer to print this spooled file. Form Type Message Option ID Type ATTR_FORMTYPEMSG String
Description Message option for sending a message to the writer's message queue when the current form type is finished. Valid values are *MSG, *NOMSG, *INFOMSG, *INQMSG. Front Margin Offset Across ID Type ATTR_FTMGN_ACR Float
Description For the front side of a piece of paper, it specifies, how far in from the left side of the page printing starts. The special value *DEVD is encoded as -2. Front Margin Offset Down ID Type ATTR_FTMGN_DWN Float
Description For the front side of a piece of paper, it specifies, how far down from the top of the page printing starts. The special value *DEVD is encoded as -2. Front Overlay ID Type ATTR_FRONT_OVERLAY String
IBM i: Programming IBM Toolbox for Java
128
Description The Integrated File System path of the front overlay. The format of the Integrated File System path is "/QSYS.LIB/library.LIB/overlay.OVL" where library is the library of the resource and overlay is the name of the overlay. The string "*NONE" is used to indicate that no front overlay is specified. Front Overlay Offset Across ID Type ATTR_FTOVL_ACR Float
Description The offset across from the point of origin where the overlay is printed. Front Overlay Offset Down ID Type ATTR_FTOVL_DWN Float
Description The offset down from the point of origin where the overlay is printed. Graphic Character Set ID Type ATTR_CHAR_ID String
Description The set of graphic characters to be used when printing this file. Valid special values include *DEVD, *SYSVAL, and *JOBCCSID. Hardware Justification ID Type ATTR_JUSTIFY Integer
Description The percentage that the output is right justified. Valid values are 0, 50, 100. Held Status ID Type ATTR_HELDSTS String
Description Whether the writer is held. Valid values are *YES, *NO. Hold Spool File ID Type ATTR_HOLD String
Description Whether the spooled file is held. Valid values are *YES, *NO. Hold Pending Status ID Type ATTR_HOLDPNDSTS String
IBM Toolbox for Java
129
Description Whether a Hold Writer (HLDWTR) command has been issued for this writer. Possible values are *NO - no HLDWTR command was issued, *IMMED - the writer is held when its output buffers are empty, *CTRLD - writer held after the current copy of the spooled file has printed, *PAGEEND - writer held at the end of the page. Image Configuration ID Type ATTR_IMGCFG String
Description The transform services for a variety of image and print data-stream formats. Initialize the writer ID Type ATTR_WTRINIT String
Description The user can specify when to initialize the printer device. Valid values are *WTR, *FIRST, *ALL. Internet Address ID Type ATTR_INTERNETADDR String
Description The internet address of the receiving system. IPP Attributes-charset ID Type ATTR_IPP_ATTR_CHARSET String
Description Indicates the charset (coded character set and encoding method) of the IPP specified spooled file attributes. IPP Job ID ID Type ATTR_IPP_JOB_ID Integer
Description IPP Job ID relative to the IPP printer that created the job. IPP Job Name ID Type ATTR_IPP_ATR_CHARSET String
Description User friendly name of job. IPP Job Name NL ID Type ATTR_IPP_JOB_NAME_NL String
IBM i: Programming IBM Toolbox for Java
130
Description Natural language of job name. IPP Job Originating User Name ID Type ATTR_IPP_JOB_ORIGUSER String
Description Identifies the end user that submitted this IPP job. IPP Job Originating User Name NL ID Type ATTR_IPP_JOB_ORIGUSER_NL String
Description Identifies the natural language of job-originating user name. IPP Printer Name ID Type ATTR_IPP_PRINTER_NAME String
Description Identifies the IPP printer that created this job. Job Name ID Type ATTR_JOBNAME String
Description The name of the job that created the spooled file. Job Number ID Type ATTR_JOBNUMBER String
Description The number of the job that created the spooled file. Job Separators ID Type ATTR_JOBSEPRATR Integer
Description The number of job separators to be placed at the beginning of the output for each job having spooled files on this output queue. Valid values are -2, 0-9. The value *MSG is encoded as -2. Job separators are specified when the output queue is created. Job System ID Type ATTR_JOBSYSTEM String
131
Description The system job which created spooled file was running. Job User ID Type ATTR_JOBUSER String
Description The name of the user that created the spooled file. Last Page Printed ID Type ATTR_LASTPAGE Integer
Description The number of the last printed page is the file if printing ended before the job completed processing. Length of Page ID Type ATTR_PAGELEN Float
Description The length of a page. Units of measurement are specified in the measurement method attribute. Library Name ID Type ATTR_LIBRARY String
Description The name of the library. Lines Per Inch ID Type ATTR_LPI Float
Description The number of lines per vertical inch in the spooled file. Line Spacing ID Type ATTR_LINESPACING String
Description How a file's line data records are spaced when printed. The information is returned only for *LINE and *AFPDSLINE printer device types files. Valid values are *SINGLE, *DOUBLE, *TRIPLE, or *CTLCHAR. Manufacturer Type and Model ID Type ATTR_MFGTYPE String
132
Description Specifies the manufacturer, type, and model when transforming print data from SCS to ASCII. Maximum Jobs per Client List ID Type ATTR_MAX_JOBS_PER_CLIENT Integer
Description Supplied by the client to indicate the maximum printer queue size of limitation. Maximum Spooled Output Records ID Type ATTR_MAXRECORDS Integer
Description The maximum number of records allowed in this file at the time this file was opened. The value *NOMAX is encoded as 0. Measurement Method ID Type ATTR_MEASMETHOD String
Description The measurement method that is used for the length of page and width of page attributes. Valid values are *ROWCOL, *UOM. Message Help ID Type ATTR_MSGHELP char(*)
Description The message help, which is sometimes known as second-level text, can be returned by a "retrieve message" request. The system limits the length to 3000 characters (English version must be 30% less to allow for translation). Message ID ID Type ATTR_MESSAGEID String
Description The Integrated File System path of the message queue that the writer uses for operational messages. The format of the Integrated File System path is "/QSYS.LIB/library.LIB/ messageque.MSGQ" where library is the library that contains the message queue and messageque is the name of the message queue.
133
Description The message reply. Text string to be provided by the client which answers a message of type "inquiry". In the case of message retrieved, the attribute value is returned by the server and contains the default reply which the client can use. The system limits the length to 132 characters. Must be null-terminated due to variable length. Message Text ID Type ATTR_MSGTEXT String
Description The message text, that is sometimes known as first-level text, can be returned by a "retrieve message" request. The system limits the length to 132 characters. Message Type ID Type ATTR_MSGTYPE String
Description The message type, a 2-digit, EBCDIC encoding. Two types of messages indicate whether one can "answer" a "retrieved" message: '04' Informational messages convey information without asking for a reply (may require a corrective action instead), '05' Inquiry messages convey information and ask for a reply. Message Severity ID Type ATTR_MSGSEV Integer
Description Message severity. Values range from 00 to 99. The higher the value, the more severe or important the condition. Multi-item Reply Capability ID Type ATTR_MULTI_ITEM_REPLY String
Description When this attribute value is set to *YES by the client, the performance of list spooled file operations can be greatly improved. The default value is *NO. Network Identifier ID Type ATTR_NETWORK String
Description The network identifier of the system where the file was created.
134
Description The total number of bytes available in the stream or spooled file. The value indicates the number of bytes BEFORE any transform of the data takes place. In order to accommodate files of sizes greater than 2**31 - 1 bytes, this value is scaled; the user needs to multiply the value by 10K to get the actual number of bytes. This attribute is not valid for spooled files being viewed in page-at-a-time mode. Number of Bytes to Read/Write ID Type ATTR_NUMBYTES Integer
Description The number of bytes to read for a read operation, or the number of bytes to write for a write operation. The object action determines how to interpret this attribute. Number of Files ID Type ATTR_NUMFILES Integer
Description The number of spooled files that exist on the output queue. Number of Writers Started to Queue ID Type ATTR_NUMWRITERS Integer
Description The number of writer jobs started to the output queue. Object Extended Attribute ID Type ATTR_OBJEXTATTR String
Description An "extended" attribute used by some objects like font resources. This value shows up via WRKOBJ and DSPOBJD commands on the server. The title on a server screen may just indicate "Attribute". In the case of object types of font resources, for example, common values are CDEPAG, CDEFNT, and FNTCHRSET. On Job Queue Status ID Type ATTR_ONJOBQSTS String
Description Whether the writer is on a job queue and therefore is not currently running. The possible values are *YES, *NO.
135
Description Specifies whether user wants SCS open time commands to be inserted into datastream before spool file data. Valid values are *YES, *NO. Operator Controlled ID Type ATTR_OPCNTRL String
Description Whether users with job control authority are allowed to manage or control the spooled files on this queue. Valid values are *YES, *NO. Order of Files On Queue ID Type ATTR_ORDER String
Description The order of spooled files on this output queue. Valid values are *FIFO, *JOBNBR. Output Bin ID Type ATTR_OUTPUTBIN Integer
Description The output bin the printer uses for the printed output. Values range from 1 to 65535. The value *DEVD is encoded as 0. Output Priority ID Type ATTR_OUTPTY String
Description The priority of the spooled file. The priority ranges from 1 (highest) to 9 (lowest). Valid values are 0-9, where 0 represents *JOB. Output Queue ID Type ATTR_OUTPUT_QUEUE String
Description The Integrated File System path of the output queue. The format of the Integrated File System path is "/QSYS.LIB/library.LIB/queue.OUTQ" where library is the library that contains the output queue and queue is the name of the output queue. Output Queue Status ID Type ATTR_OUTQSTS String
136
Description The status of the output queue. Valid values are RELEASED, HELD. Overall Status ID Type ATTR_OVERALLSTS Integer
Description The overall status of the "logical printer". "Logical printer" refers to printer device, output queue and writer job. Valid values are 1 (unavailable), 2 (powered off or not yet available), 3 (stopped), 4 (message waiting), 5 (held), 6 (stop pending), 7 (hold pending), 8 (waiting for printer), 9 (waiting to start), 10 (printing), 11 (waiting for output queue), 12 (connect pending), 13 (powered off), 14 (unusable), 15 (being serviced), 999 (unknown). Overflow Line Number ID Type ATTR_OVERFLOW Integer
Description The last line to be printed before the data that is being printed overflows to the next page. Page At A Time ID Type ATTR_PAGE_AT_A_TIME String
Description Specifies whether the spooled file is to be opened in page-at-a-time mode. Valid values are *YES and *NO. Page Count Estimated ID Type ATTR_PAGES_EST String
Description Specifies whether the page count is estimated rather than actual. Valid values are *YES and *NO. Page Definition ID Type ATTR_PAGE_DEFINITION String
Description The Integrated File System path name of the page definition or a special value. If an Integrated File System path is specified the format is "/QSYS.LIB/library.LIB/pagedef.PAGDFN" where library is the library of the page definition and pagedef is the name of the page definition. Valid special values include *NONE. Page Number ID Type ATTR_PAGENUMBER Integer
Description The number of the page to be read from a spooled file opened in page-at-a-time mode.
137
Description The number of logical pages that print on each side of each physical page when the file is printed. Valid values are 1, 2, 4. Paper Source 1 ID Type ATTR_PAPER_SOURCE_1 String
Description The size of the paper in paper source one. If this field is not specified or the value is not valid, the special value of *MFRTYPMDL is used. Valid values are *NONE - there is no paper source one or the paper is manually fed into the printer, *MFRTYPMDL - the paper size suggested by the manufacturer type and model is used, *LETTER (8.5 x 11.0 inches), *LEGAL (8.5 x 14.0 inches), *EXECUTIVE (7.25 x 10.5 inches), *LEDGER (17.0 x 11.0 inches), *A3 (297mm x 420mm), *A4 (210mm x 297mm), *A5 (148mm x 210mm), *B4 (257mm x 364mm), *B5 (182mm x 257mm), *CONT80 (8.0 inches wide with continuous form), *CONT132 (13.2 inches wide with continuous form). Paper Source 2 ID Type ATTR_PAPER_SOURCE_2 String
Description The size of the paper in paper source two. If this field is not specified or the value is not valid, the special value of *MFRTYPMDL is used. Valid values are *NONE - there is no paper source two or the paper is manually fed into the printer, *MFRTYPMDL - the paper size suggested by the manufacturer type and model is used, *LETTER (8.5 x 11.0 inches), *LEGAL (8.5 x 14.0 inches), *EXECUTIVE (7.25 x 10.5 inches), *LEDGER (17.0 x 11.0 inches), *A3 (297mm x 420mm), *A4 (210mm x 297mm), *A5 (148mm x 210mm), *B4 (257mm x 364mm), *B5 (182mm x 257mm), *CONT80 (8.0 inches wide with continuous form), *CONT132 (13.2 inches wide with continuous form). Pel Density ID Type ATTR_PELDENSITY String
Description For font resources only, this value is an encoding of the number of pels ("1" represents a pel size of 240, "2" represents a pel size of 320). Additional values may become meaningful as the server defines them. Point Size ID Type ATTR_POINTSIZE Float
Description The point size in which this spooled file's text is printed. The special value *NONE will be encoded as 0.
138
Description The kind of error handling that is performed when printing. Valid values are *ABSOLUTE, *CONTENT. Print on Both Sides ID Type ATTR_DUPLEX String
Description How the information prints. Valid values are *FORMDF, *NO, *YES, *TUMBLE. Print Quality ID Type ATTR_PRTQUALITY String
Description The print quality that is used when printing this spooled file. Valid values are *STD, *DRAFT, *NLQ, *FASTDRAFT. Print Sequence ID Type ATTR_PRTSEQUENCE String
Description Print sequence. Valid values are *NEXT. Print Text ID Type ATTR_PRTTEXT String
Description The text that is printed at the bottom of each page of printed output and on separator pages. Valid special values include *BLANK and *JOB. Printer ID Type ATTR_PRINTER String
Description The name of the printer device. Printer Assigned ID Type ATTR_PRTASSIGNED String
Description Indicates if the printer is assigned. Valid values are 1 (assigned to a specific printer), 2 (assigned to multiple printers), 3 (not assigned).
IBM Toolbox for Java
139
Description The printer data stream type. Valid values are *SCS, *IPDS, *USERASCII, *AFPDS, *LINE. Printer File ID Type ATTR_PRINTER_FILE String
Description The Integrated File System path of the printer file. The format of the Integrated File System path is "/QSYS.LIB/library.LIB/printerfile.FILE" where library is the library that contains the printer file and printerfile is the name of the printer file. Printer Queue ID Type ATTR_RMTPRTQ String
Description The name of the destination printer queue when sending spooled files via SNDTCPSPLF (LPR). Publishing Info Color Supported ID Type ATTR_PUBINF_COLOR_SUP String
Description Indicates color is supported for this publishing list entry. Publishing Info Pages per Minute (Color) ID Type ATTR_PUBINF_PPM_COLOR Integer
Description The pages per minute supported in color mode for this publishing list entry. Publishing Info Pages per Minute (Monochrome) ID Type ATTR_PUBINF_PPM Integer
Description The pages per minute supported in monochrome for this publishing list entry. Publishing Info Duplex Support ID Type ATTR_PUBINF_DUPLEX_SUP String
Description The duplex supported indicator for this publishing list entry.
140
Description The location description for this publishing list entry. Remote Location Name ID Type ATTR_RMTLOCNAME String
Description The printer device location name. Record Length ID Type ATTR_RECLENGTH Integer
Description The manner in which multiple logical pages print on each side of a physical page. Valid values *TEXT or ????. Remote System ID Type ATTR_RMTSYSTEM String
Description Remote system name. Valid special values include *INTNETADR. Replace Unprintable Characters ID Type ATTR_RPLUNPRT String
Description Whether characters that cannot be printed are to be replaced with another character. Valid values are *YES or *NO. Replacement Character ID Type ATTR_RPLCHAR String
141
Description Restart printing. Valid values are -1, -2, -3, or the page number to restart at. The value *STRPAGE is encoded as -1, the value *ENDPAGE is encoded as -2, and the value *NEXT is encoded as -3. Saddle Stitch Number of Staples ID Type ATTR_SADDLESTITCH_NUMSTAPLES Integer
Description The number of staples that are to be applied along the finishing operation axis. Saddle Stitch Reference ID Type ATTR_SADDLESTITCH_REF String
Description One or more staples are driven into the media along the finishing operation axis, which is positioned at the center of the media parallel to the reference edge. Valid values are *NONE, *DEVD, *TOP, and *LEFT. Save Spooled File ID Type ATTR_SAVESPLF String
Description Whether the spooled file is to be saved after it is written. Valid values are *YES, *NO. Seek Offset ID Type ATTR_SEEKOFF Integer
Description Seek offset. Allows both positive and negative values relative to the seek origin. Seek Origin ID Type ATTR_SEEKORG Integer
Description Valid values include 1 (beginning or top), 2 (current), and 3 (end or bottom). Send Priority ID Type ATTR_SENDPTY String
142
Description Allows a user the option of printing a banner page or not. Valid values are *YES or *NO. Source Drawer ID Type ATTR_SRCDRWR Integer
Description The drawer to be used when the automatic cut sheet feed option is selected. Valid values are -1, -2, 1-255. The value *E1 is encoded as -1, and the value *FORMDF is encoded as -2. Spool SCS ID Type ATTR_SPLSCS Long
Description Determines how SCS data is used during create spool file. Spool the Data ID Type ATTR_SPOOL String
Description Whether the output data for the printer device is spooled. Valid values are *YES, *NO. Spooled File Creation Authentication Method ID Type ATTR_SPLF_AUTH_METHOD Integer
Description Indicates the client authentication method used to create this spooled file. Valid values include x'00'(*NONE), x'01'(*REQUESTER), x'02'(*BASIC), x'03'(*CERTIFICATE), and 'x'04'(*DIGEST). Spooled File Creation Security Method ID Type ATTR_SPLF_SECURITY_METHOD String
Description Indicates the security method used to create this spooled file. Valid values are x'00'(*NONE), x'01'(*SSL3), and x'02'(*TLS). Spooled File Name ID Type ATTR_SPOOLFILE String
143
Description The spooled file number. Special values allowed are -1 and 0. The value *LAST is encoded as -1, the value *ONLY is encoded as 0. Spooled File Status ID Type ATTR_SPLFSTATUS String
Description The status of the spooled file. Valid values are *CLOSED, *HELD, *MESSAGE, *OPEN, *PENDING, *PRINTER, *READY, *SAVED, *WRITING. Spooled Output Schedule ID Type ATTR_SCHEDULE String
Description Specifies, for spooled files only, when the spooled file is available to the writer. Valid values are *IMMED, *FILEEND, *JOBEND. Started By User ID Type ATTR_STARTEDBY String
Description The name of the user who started the writer. Starting Page ID Type ATTR_STARTPAGE Integer
Description The page number at which to start printing the spooled file. Valid values are -1, 0, 1, or the page number. The value *ENDPAGE is encoded as -1. For the value 0, printing starts on page 1. For the value 1, the entire file prints. System Where Created ID Type ATTR_SYSTEM String
Description The name of the system where the spooled file was created. When the name of the system where this spooled file was created cannot be determined, the receiving system name is used. Text Description ID Type ATTR_DESCRIPTION String
144
Description Text to describe an instance of an AS400 object. Time File Opened ID Type ATTR_TIMEOPEN String
Description For spooled files this is the time this spooled file was opened. For AFP resources this is the time the object was last modified. The time is encoded in a character string with the following format, HH MM SS. Time Spooled File Create Job End ID Type ATTR_TIME_END String
Description The time the job that created the spooled file on the system ended. This field must be set to blanks when special value *ALL is used for field Starting spooled file create date or when special value *LAST is used for field Ending spooled file create date. This field must have a value set if a date is specified for field Ending spooled file create date. The time must be in the HHMMSS format, defined as follows: v HH - Hour v MM - Minutes v SS - Seconds Time Writer Began Processing Spooled File ID Type ATTR_TIME_WTR_BEGAN_FILE String
Description Indicates the time at which the writer began processing the spooled file. The time is encoded in a character string with the following format, HH MM SS. Time Writer Completed Processing Spooled File ID Type ATTR_TIME_WTR_CMPL_FILE String
Description Indicates the time at which the writer finished processing the spooled file. The time is encoded in a character string with the following format, HH MM SS. Total Pages ID Type ATTR_PAGES Integer
Description The number of pages that are contained in a spooled file. Transform SCS to ASCII ID Type ATTR_SCS2ASCII String
IBM Toolbox for Java
145
Description Whether the print data is to be transformed from SCS to ASCII. Valid values are *YES, *NO. Unit of Measure ID Type ATTR_UNITOFMEAS String
Description The unit of measure to use for specifying distances. Valid values are *CM, *INCH. User Comment ID Type ATTR_USERCMT String
Description The 100 characters of user-specified comment that describe the spooled file. User Data ID Type ATTR_USERDATA String
Description The 10 characters of user-specified data that describe the spooled file. Valid special values include *SOURCE. User Defined Data ID Type ATTR_USRDFNDTA String
Description User defined data to be utilized by user applications or user specified programs that process spool files. All characters are acceptable. Max size is 255. User Defined File ID Type ATTR_USRDEFFILE String
Description Whether the spooled file was created using an API. Valid values are *YES, or *NO. User Defined Object ID Type ATTR_USER_DEFINED_OBJECT String
Description The Integrated File System path of the user defined object to be utilized by user applications that process spool files. If an Integrated File System path the format of the Integrated File System path is "/QSYS.LIB/library.LIB/object.type" where library is the name of the library that contains the object or one of the special values %LIBL% or %CURLIB%. object is the name of the object and type is the object type. Valid values for type include "DTAARA", "DTAQ", "FILE", "PSFCFG", "USRIDX", "USRQ" and "USRSPC". The string "*NONE" is used to indicate no user defined object is to be used.
146
Description User defined options to be utilized by user applications that process spool files. Up to 4 options may be specifies, each value is length char(10). All characters are acceptable. User Driver Program Data ID Type ATTR_USRDRVPGMDTA String
Description User data to be used with the user driver program. All characters are acceptable. Maximum size is 5000 characters. User Driver Program ID Type ATTR_USER_DRIVER_PROG String
Description The Integrated File System path of the user defined driver program that processes spooled files. The format of the Integrated File System path is "/QSYS.LIB/library.LIB/program.PGM" where library is the name of the library that contains the program and program is the program name. The library may be one of the special values %LIBL% and %CURLIB% or a specific library name. The string "*NONE" is used to indicate that no driver program is defined. User ID ID Type ATTR_TOUSERID String
Description User id to whom the spooled file is sent. User ID Address ID Type ATTR_TOADDRESS String
Description Address of user to whom the spooled file is sent. User Transform Program ID Type ATTR_USER_TRANSFORM_PROG String
Description The Integrated File System path of the user defined transform program that transforms spool file data before it is processed by the driver program. The format of the Integrated File System path is "/QSYS.LIB/library.LIB/program.PGM" where library is the name of the library that contains the program and program is the program name. The library may be one of the special values %LIBL% and %CURLIB% or a specific library name. The string "*NONE" is used to indicate that no transform program is defined.
147
Description The processing to take place when viewing a page of spooled file data (in page-at-a-time mode). Valid values are *ABSOLUTE and *CONTENT(default). To process all non-raster data (commands) prior to the current page, *ABSOLUTE is used. For SCS files, *CONTENT is used to process only open time commands plus the current page. For AFPDS files, *CONTENT is used to process the first page of data plus the current page. VM/MVS Class ID Type ATTR_VMMVSCLASS String
Description VM/MVS class. Valid values are A-Z and 0-9. Waiting for Data Status ID Type ATTR_WTNGDATASTS String
Description Whether the writer has written all the data currently in the spooled file and is waiting for more data. Possible values are *NO - the writer is not waiting for more data, *YES - the writer has written all the data currently in the spooled file and is waiting for more data. This condition occurs when the writer is producing an open spooled file with SCHEDULE(*IMMED) specified. Waiting for Device Status ID Type ATTR_WTNGDEVSTS String
Description Whether the writer is waiting to get the device from a job that is printing directly to the printer. Values are *NO - the writer is not waiting for the device, *YES - the writer is waiting for the device. Waiting for Message Status ID Type ATTR_WTNGMSGSTS String
Description Whether the writer is waiting for a reply to an inquiry message. Values are *NO and *YES. When to Automatically End Writer ID Type ATTR_WTRAUTOEND String
Description When to end the writer if it is to be ended automatically. Valid values are *NORDYF, *FILEEND. Attribute Automatically end writer must be set to *YES.
148
Description When to end the writer. Valid value are *CNTRLD, *IMMED, and *PAGEEND. This is different from when to automatically end the writer. When to Hold File ID Type ATTR_HOLDTYPE String
Description When to hold the spooled file. Valid values are *IMMED, and *PAGEEND. Width of Page ID Type ATTR_PAGEWIDTH Float
Description The width of a page. Units of measurement are specified in the measurement method attribute. Workstation Customizing Object ID Type ATTR_WORKSTATION_CUST_OBJECT String
Description The Integrated File System path of the workstation customizing object. The format of the Integrated File System path is "/QSYS.LIB/library.LIB/custobj.WSCST" where library is the library that contains the customization object and custobj is the name of the workstation customization object. Writer Job Name ID Type ATTR_WRITER String
Description The name of the writer job. Writer Job Number ID Type ATTR_WTRJOBNUM String
Description The writer job number. Writer Job Status ID Type ATTR_WTRJOBSTS String
Description The status of the writer job. Valid values are STR, END, JOBQ, HLD, MSGW.
IBM Toolbox for Java
149
Description The name of the user that started the writer job. Writer Started ID Type ATTR_WTRSTRTD String
Description Indicates whether a writer is started for this printer. Values are 1 - yes a writer is started, 0 - no writer is started. Writer Starting Page ID Type ATTR_WTRSTRPAGE Integer
Description Specifies the page number of the first page to print from the first spooled file when the writer job starts. This is only valid if the spooled file name is also specified when the writer starts. Writing Status ID Type ATTR_WRTNGSTS String
Description Indicates whether the print writer is in writing status. Values are *YES - the writer is in writing status, *NO - the writer is not in writing status, *FILE - the writer is writing the file separators. Network Print Server Object Attributes NPS CCSID ID Type ATTR_NPSCCSID Integer
Description CCSID that the Network Print Server expects that all strings will be encoded in. NPS Level ID ATTR_NPSLEVEL
Description The version, release, and modification level of the Network Print Server. This attribute is a character string encoded as VXRYMY (ie. "V3R1M0") where
X is in (0..9) Y is in (0..9,A..Z)
Copying spooled files: You can use the copy method of the SpooledFile class to create a copy of the spooled file that the SpooledFile object represents.
150
Using SpooledFile.copy() performs the following actions: v Creates the new spooled file on the same output queue and on the same system as the original spooled file v Returns a reference to the new spooled file SpooledFile.copy() is a new method available to you only if you download JTOpen 3.2 or later or apply an IBM i fix. It is recommended that the better solution is to download and use JTOpen. For more information, see the following: v IBM Toolbox for Java and JTOpen: Downloads v IBM Toolbox for Java and JTOpen: Service Packs The copy method uses the Create Spooled File (QSPCRTSP) API within the network print server job to create an exact replica of the spooled file. You need only a unique creation date and time to preserve the identity of the newly created copy of the spooled file. Specifying an output queue as a parameter to the copy method creates the copy of the spooled file to the first position on the specified output queue. Both the output queue and the original spooled file must reside on the same system Example: Copying a spooled file using SpooledFile.copy() Note: Read the Code example disclaimer for important legal information. This example shows how to use SpooledFile.copy() to copy a spooled file to the same queue that contains the file you want to copy. When you want to route the newly copied spooled file to a specific output queue, pass the output queue as a parameter to the copy method:
SpooledFile newSplf = new sourceSpooledFile.copy(<outqname>);
151
+ + + +
// Create the SpooledFile object for the source spooled file. SpooledFile sourceSpooledFile = new SpooledFile(as400, splfTags[i][0], Integer.parseInt(splfTags[i][1]), splfTags[i][2], splfTags[i][3], splfTags[i][5], splfTags[i][6], splfTags[i][7] ); } // Copy the spooled file, which creates a new SpooledFile object. // To route the copy of the spooled file to a specific output queue, // use the following code: // SpooledFile newSplf = new sourceSpooledFile.copy(<outqname>); // where <outqname> is an OutputQueue object. Specify the output // queue in the following way: // OutputQueue outputQueue = // new OutputQueue(as400, "/QSYS.LIB/QUSRSYS.LIB/<outqname>.OUTQ"); try { SpooledFile newSplf = new sourceSpooledFile.copy(); } catch ( Exception e){ }
SpooledFile Javadoc Create Spooled File (QSPCRTSP) API Creating new spooled files: You can use the SpooledFileOutputStream class to create new server spooled files. The class derives from the standard JDK java.io.OutputStream class; after its construction, it can be used anywhere an OutputStream is used. When creating a new SpooledFileOutputStream, the caller may specify the following: v Which printer file to use v Which output queue to put the spooled file on v A PrintParameterList object that may contain parameters to override fields in the printer file These parameters are all optional (the caller may pass null of any or all of them). If a printer file is not specified, the network print server uses the default network print printer file, QPNPSPRTF. The output queue parameter is there as a convenience; it also can be specified in the PrintParameterList. If the output queue parameter is specified in both places, the PrintParameterList field overrides the output queue parameter. See the documentation of the SpooledFileOutputStream constructor in the Javadoc for a complete list of which attributes may be set in the PrintParameterList for creating new spooled files. Use one of the write() methods to write data into the spooled file. The SpooledFileOutputStream object buffers the data and sends it when either the output stream is closed or the buffer is full. Buffering is done for two reasons: v It allows the automatic data typing (see Data stream types in spooled files) to analyze a full-buffer of data to determine the data type v It makes the output stream work faster because not every write request is communicated to the server Use the flush() method to force the data to be written to the server.
152
When the caller is finished writing data to the new spooled file, the close() method is called to close the spooled file. Once the spooled file has been closed, no more data can be written to it. By calling the getSpooledFile() method once the spooled file has been closed, the caller can get a reference to a SpooledFile object that represents the spooled file. Data stream types in spooled files Use the Printer Data Type attribute of the spooled file to set the type of data to be put into the spooled file. If the caller does not specify a printer data type, the default is to use automatic data typing. This method looks at the first few thousand bytes of the spooled file data, determines if it fits either SNA Character Stream (SCS) or Advanced Function Printing data stream (AFPDS) data stream architectures, and then sets the attribute appropriately. If the bytes of spooled file data do not match either of these architectures, the data is tagged as *USERASCII. Automatic data typing works most of the time. The caller generally uses it unless the caller has a specific case in which automatic data typing does not work. In those cases, the caller can set the Printer Data Type attribute to a specific value (for example, *SCS). If the caller wants to use the printer data that is in the printer file, the caller must use the special value *PRTF. If the caller overrides the default data type when creating a spooled file, caution must be used to ensure that the data put into the spooled file matches the data type attribute. Putting non-SCS data into a spooled file that is marked to receive SCS data triggers an error message from the host and the loss of the spooled file. Generally, this attribute can have three values: v *SCS - an EBCDIC, text-based printer data stream. v *AFPDS (Advanced Function Presentation Data Stream) - another data stream supported on the server. *AFPDS can contain text, image, and graphics, and can use external resources such as page overlays and external images in page segments. v *USERASCII - any non-SCS and non-AFPDS printer data that the server handles by just passing it through. Postscript and HP-PCL data streams are examples data streams that are in a *USERASCII spooled file. SpooledFileOutputStream Javadoc Example: Creating spooled files on page 529 This example shows how to create a spooled file on a server from an input stream. Example: Creating SCS spooled files on page 530 This example uses the SCS3812Writer class to generate an SCS data stream and write it to a spooled file on the server. Generating an SCS data stream: To generate spooled files that will print on certain printers attached to the server, an SNA Character Stream (SCS) data stream must be created. SCS is a text-based, EBCDIC data stream that can be printed on SCS printers, IPDS printers, or to PC printers. SCS can be printed by converting it using an emulator or the host print transform on the server. You can use the SCS writer classes to generate such an SCS data stream. The SCS writer classes convert Java Unicode characters and formatting options into an SCS data stream. Five SCS writer classes generate varying levels of SCS data streams. The caller chooses the writer that matches the final printer destination to which the caller or end user will be printing. Use the following SCS writer classes to generate an SCS printer data stream:
153
Description The simplest SCS writer class. Supports text, carriage return, line feed, new line, form feed, absolute horizontal and vertical positioning, relative horizontal and vertical positioning, and set vertical format. Extends the 5256 writer and adds methods to set character per inch (CPI) and lines per inch (LPI). Extends the 5224 writer and adds support for left margin, underline, form type (paper or envelope), form size, print quality, code page, character set, source drawer number, and destination drawer number. Extends the 5219 writer and adds support for character rotation, grid lines, and font scaling. The 5553 is a double-byte character set (DBCS) data stream. Extends the 5219 writer and adds support for bold, duplex, text orientation, and fonts.
SCS5224Writer SCS5219Writer
SCS5553Writer
SCS3812Writer
To construct an SCS writer, the caller needs an output stream and, optionally, an encoding. The data stream is written to the output stream. To create an SCS spooled file, the caller first constructs a SpooledFileOutputStream, and then uses that to construct an SCS writer object. The encoding parameter gives a target EBCDIC coded character set identifier (CCSID) to convert the characters to. Once the writer is constructed, use the write() methods to output text. Use the carriageReturn(), lineFeed(), and newLine() methods to position the write cursor on the page. Use the endPage() method to end the current page and start a new page. When all of the data has been written, use the close() method to end the data stream and close the output stream. Example Example: Creating SCS spooled files on page 530 shows how to generate a SCS data stream using the SCS3812Writer class, and how to write the stream to a spooled file on the server: Reading spooled files and AFP resources: You can use the PrintObjectInputStream class to read the raw contents of a spooled file or Advanced Function Printing (AFP) resource from the server. The class extends the standard JDK java.io.InputStream class so that it can be used anywhere an InputStream is used. Obtain a PrintObjectInputStream object by calling either the getInputStream() method on an instance of the SpooledFile class or the getInputStream() method on an instance of the AFPResource class. Use one of the read() methods for reading from the input stream. These methods all return the number of bytes actually read, or -1 if no bytes were read and the end of file was reached. Use the available() method of PrintObjectInputStream to return the total number of bytes in the spooled file or AFP resource. The PrintObjectInputStream class supports marking the input stream, so PrintObjectInputStream always returns true from the markSupported() method. The caller can use the mark() and reset() methods to move the current read position backward in the input stream. Use the skip() method to move the read position forward in the input stream without reading the data.
154
Example The following example shows how to use PrintObjectInputStream to read an existing server spooled file Example: Reading spooled files PrintObjectInputStream Javadoc Reading spooled files using PrintObjectPageInputStream and PrintObjectTransformedInputStream: You can use the PrintObjectPageInputStream class to read the data out of a server AFP and SCS spooled file one page at a time. You can obtain a PrintObjectPageInputStream object with the getPageInputStream() method. Use one of the read() methods for reading from the input stream. All these methods return the number of bytes actually read, or -1 if no bytes were read and the end of page was reached. Use the available() method of PrintObjectPageInputStream to return the total number of bytes in the current page. The PrintObjectPageInputStream class supports marking the input stream, so PrintObjectPageInputStream always returns true from the markSupported() method. The caller can use the mark() and reset() methods to move the current read position backward in the input stream so that subsequent reads reread the same bytes. The caller can use the skip() method to move the read position forward in the input stream without reading the data. However, when transforming an entire spooled file data stream is desired, use the PrintObjectTransformedInputStream class. Example The following example shows how to use PrintObjectPageInputStream and PrintObjectTransformedInputStream to obtain different transformations when reading spooled file data: Example: Reading and transforming spooled files on page 533 Related information PrintObjectPageInputStream Javadoc PrintObjectTransformedInputStream Javadoc
ProductLicense class
The ProductLicense class enables you to request licenses for products installed on the system. To be compatible with other IBM i license users, the class works through IBM i product license support when requesting or releasing a license. The class does not enforce the license policy but returns enough information such that the application can enforce the policy. When a license is requested the ProductLicense class will return the status of the request -- license granted or denied. If the request is denied the application must disable the behavior that required the license because the IBM Toolbox for Java does not know which function to disable. Use the ProductLicense class with IBM i license support to enforce the license of your application: v The server side of your application registers your product and license terms with IBM i license support. v The client side of your application uses the ProductLicense object to request and release licenses.
155
ProgramCall class
The IBM Toolbox for Java ProgramCall class allows the Java program to call a IBM i program. You can use the ProgramParameter class to specify input, output, and input/output parameters. If the program runs, the output and input/output parameters contain the data that is returned by the IBM i program. If the IBM i program fails to run successfully, the Java program can retrieve any resulting IBM i messages as a list of AS400Message objects. Required parameters are as follows: v The program and parameters to run v The AS400 object that represents the server that has the program. The program name and parameter list can be set on the constructor, through the ProgramCall setProgram() method, or on the run() method The run() method calls the program. Using the ProgramCall class causes the AS400 object to connect to the server. See managing connections for information about managing connections. Example: Using ProgramCall Note: Read the Code example disclaimer for important legal information. The following example shows how to use the ProgramCall class:
// Create an AS400 object. AS400 sys = new AS400("mySystem.myCompany.com"); // Create a program object. I choose // to set the program to run later. ProgramCall pgm = new ProgramCall(sys); // Set the name of the program. // Because the program does not take // any parameters, pass null for the // ProgramParameter[] argument. pgm.setProgram(QSYSObjectPathName.toPath("MYLIB", "MYPROG", "PGM")); // // // // if { Run the program. My program has no parms. If it fails to run, the failure is returned as a set of messages in the message list. (pgm.run() != true) // If you get here, the program
156
// failed to run. Get the list of // messages to determine why the // program didn't run. AS400Message[] messageList = pgm.getMessageList(); // ... Process the message list. } // Disconnect since I am done running programs sys.disconnectService(AS400.COMMAND);
The ProgramCall object requires the integrated file system path name of the program. The default behavior is for IBM i programs to run in a separate server job, even when the Java program and the IBM i program are on the same server. You can override the default behavior and have the IBM i program run in the Java job using the ProgramCall setThreadSafe() method.
157
AS400Bin4 bin4Converter = new AS400Bin4(); // Convert from system type to Java // object. The number starts at the // beginning of the buffer. byte[] data = parmList[1].getOutputData(); int i = bin4Converter.toInt(data); } // Disconnect since I am done running programs sys.disconnectService(AS400.COMMAND);
ProgramCall Javadoc ProgramParameter Javadoc AS400Message Javadoc AS400 Javadoc CommandCall Javadoc ProgramParameter Javadoc
QSYSObjectPathName class
You can use the QSYSObjectPathName class to represent an object in the integrated file system. Use this class to build an integrated file system name or to parse an integrated file system name into its components. Several of the IBM Toolbox for Java classes require an integrated file system path name in order to be used. Use a QSYSObjectPathName object to build the name. Note: Read the Code example disclaimer for important legal information. The following examples show how to use the QSYSObjectPathName class: Example 1: The ProgramCall object requires the integrated file system name of the server program to call. A QSYSObjectPathName object is used to build the name. To call program PRINT_IT in library REPORTS using a QSYSObjectPathName:
// Create an AS400 object. AS400 sys = new AS400("mySystem.myCompany.com"); // Create a program call object. ProgramCall pgm = new ProgramCall(sys); // Create a path name object that // represents program PRINT_IT in library REPORTS. QSYSObjectPathName pgmName = new QSYSObjectPathName("REPORTS","PRINT_IT","PGM"); // Use the path name object to set // the name on the program call object. pgm.setProgram(pgmName.getPath()); // ... run the program, process the // results
Example 2: If the name of the object is used just once, the Java program can use the toPath() method to build the name. This method is more efficient than creating a QSYSObjectPathName object.
// Create an AS400 object. AS400 sys = new AS400("mySystem.myCompany.com"); // Create a program call object. ProgramCall pgm = new ProgramCall(sys); // Use the toPath method to create
158
// the name that represents program // PRINT_IT in library REPORTS. pgm.setProgram(QSYSObjectPathName.toPath("REPORTS", "PRINT_IT", "PGM")); // ... run the program, process the // results
Example 3: In this example, a Java program was given an integrated file system path. The QSYSObjectPathName class can be used to parse this name into its components.
// Create a path name object from // the fully qualified integrated // file system name. QSYSObjectPathName ifsName = new QSYSObjectPathName(pathName); // Use // the String String String the path name object to get library, name and type of server object. library = ifsName.getLibraryName(); name = ifsName.getObjectName(); type = ifsName.getObjectType();
QSYSObjectPathName Javadoc
Record-level access
The record-level access classes create, read, update, and delete IBM i files and members. v Create a IBM i physical file specifying one of the following: The record length An existing data description specifications (DDS) source file A RecordFormat object v Retrieve the record format from a physical or logical file, or the record formats from a IBM i multiple format logical file. Note: The record format of the file is not retrieved in its entirety. The record formats retrieved are meant to be used when setting the record format for an AS400File object. Only enough information is retrieved to describe the contents of a record of the file. Record format information, such as column headings and aliases, is not retrieved. v Access the records in an IBM i file sequentially, by record number, or by key. v Write records to a system file. v Update records in a system file sequentially, by record number, or by key. v Delete records in a system file sequentially, by record number, or by key. v Lock a file for different types of access. v Use commitment control to allow a Java program to do the following: Start commitment control for the connection. Specify different commitment control lock levels for different files. Commit and rollback transactions. v Delete system files. v Delete a member from a system file. Note: The record-level access classes do not support logical join files or null key fields. The following classes perform these functions: v The AS400File class is the abstract base class for the record-level access classes. It provides the methods for sequential record access, creation and deletion of files and members, and commitment control activities.
IBM Toolbox for Java
159
v The KeyedFile class represents a system file that has access by key. v The SequentialFile class represents a system file that has access by record number. v The AS400FileRecordDescription class provides the methods for retrieving the record format of a system file. The record-level access classes require an AS400 object that represents the system that has the database files. Using the record-level access classes causes the AS400 object to connect to the IBM i system. See managing connections for information about managing connections. The record-level access classes require the integrated file system path name of the data base file. See integrated file system path names for more information. The record-level access classes use the following: v The RecordFormat class to describe a record of the database file v The Record class to provide access to the records of the database file v The LineDataRecordWriter class to write a record in line data format These classes are described in the data conversion section. Examples v The sequential access example shows how to access a system file sequentially. v The read file example shows how to use the record-level access classes to read a system file. v The keyed file example shows how to use the record-level access classes to read records by key from a system file. AS400File: The AS400File class provides the methods for several actions. v Creating and deleting server physical files and members v Reading and writing records in server files v Locking files for different types of access v Using record blocking to improve performance v Setting the cursor position within an open server file v Managing commitment control activities Related information AS400File Javadoc KeyedFile: The KeyedFile class gives a Java program keyed access to a file on the server. Keyed access means that the Java program can access the records of a file by specifying a key. Methods exist to position the cursor, read, update, and delete records by key. To position the cursor, use the following methods: v positionCursor(Object[]) - set cursor to the first record with the specified key. v positionCursorAfter(Object[]) - set cursor to the record after the first record with the specified key. v positionCursorBefore(Object[]) - set cursor to the record before the first record with the specified key. To delete a record, use the following method: v deleteRecord(Object[]) - delete the first record with the specified key.
160
The read methods are: v read(Object[]) - read the first record with the specified key. v readAfter(Object[]) - read the record after the first record with the specified key. v readBefore(Object[]) - read the record before the first record with the specified key. v readNextEqual() - read the next record whose key matches the specified key. Searching starts from the record after the current cursor position. v readPreviousEqual() - read the previous record whose key matches the specified key. Searching starts from the record before the current cursor position. To update a record, use the following method: v update(Object[]) - update the record with the specified key. Methods are also provided for specifying a search criteria when positioning, reading, and updating by key. Valid search criteria values are as follows: v Equal - find the first record whose key matches the specified key. v Less than - find the last record whose key comes before the specified key in the key order of the file. v Less than or equal - find the first record whose key matches the specified key. If no record matches the specified key, find the last record whose key comes before the specified key in the key order of the file. v Greater than - find the first record whose key comes after the specified key in the key order of the file. v Greater than or equal - find the first record whose key matches the specified key. If no record matches the specified key, find the first record whose key comes after the specified key in the key order of the file. KeyedFile is a subclass of AS400File; all methods in AS400File are available to KeyedFile. Specifying the key The key for a KeyedFile object is represented by an array of Java Objects whose types and order correspond to the types and order of the key fields as specified by the RecordFormat object for the file. The following example shows how to specify the key for the KeyedFile object.
// Specify the key for a file whose key fields, in order, // are: // CUSTNAME CHAR(10) // CUSTNUM BINARY(9) // CUSTADDR CHAR(100)VARLEN() // Note that the last field is a variable-length field. Object[] theKey = new Object[3]; theKey[0] = "John Doe"; theKey[1] = new Integer(445123); theKey[2] = "2227 John Doe Lane, ANYTOWN, NY 11199";
A KeyedFile object accepts partial keys as well as complete keys. However, the key field values that are specified must be in order. For example:
// Specify a partial key for a file whose key fields, // in order, are: // CUSTNAME CHAR(10) // CUSTNUM BINARY(9) // CUSTADDR CHAR(100)VARLEN() Object[] partialKey = new Object[2]; partialKey[0] = "John Doe"; partialKey[1] = new Integer(445123); // Example of an INVALID partial key
IBM Toolbox for Java
161
Object[] INVALIDPartialKey = new Object[2]; INVALIDPartialKey[0] = new Integer(445123); INVALIDPartialKey[1] = "2227 John Doe Lane, ANYTOWN, NY 11199";
Null keys and null key fields are not supported. The key field values for a record can be obtained from the Record object for a file through the getKeyFields() method. The following example shows how to read from a file by key:
// Create an AS400 object, the file exists on this // server. AS400 sys = new AS400("mySystem.myCompany.com"); // Create a file object that represents the file KeyedFile myFile = new KeyedFile(sys, "/QSYS.LIB/MYLIB.LIB/MYFILE.FILE/%FILE%.MBR"); // Assume that the AS400FileRecordDescription class // was used to generate the code for a subclass of // RecordFormat that represents the record format // of file MYFILE in library MYLIB. The code was // compiled and is available for use by the Java program. RecordFormat recordFormat = new MYKEYEDFILEFormat(); // Set the record format for myFile. This must // be done before invoking open() myFile.setRecordFormat(recordFormat); // Open the file. myFile.open(AS400File.READ_WRITE, 0, AS400File.COMMIT_LOCK_LEVEL_NONE); // The record format for the file contains // four key fields, CUSTNUM, CUSTNAME, PARTNUM // and ORDNUM in that order. // The partialKey will contain 2 key field // values. Because the key field values must be // in order, the partialKey will consist of values for // CUSTNUM and CUSTNAME. Object[] partialKey = new Object[2]; partialKey[0] = new Integer(1); partialKey[1] = "John Doe"; // Read the first record matching partialKey Record keyedRecord = myFile.read(partialKey); // If the record was not found, null is returned. if (keyedRecord != null) { // Found the record for John Doe, print out the info. System.out.println("Information for customer " + (String)partialKey[1] + ":"); System.out.println(keyedRecord); } .... // Close the file since I am done using it myFile.close(); // Disconnect since I am done using record-level access sys.disconnectService(AS400.RECORDACCESS);
162
The SequentialFile class gives a Java program access to a file on the server by record number. Methods exist to position the cursor, read, update, and delete records by record number. To position the cursor, use the following methods: v positionCursor(int) - set cursor to the record with the specified record number. v positionCursorAfter(int) - set cursor to the record after the specified record number. v positionCursorBefore(int) - set cursor to the record before the specified record number. To delete a record, use the following method: v deleteRecord(int) - delete the record with the specified record number. To read a record, use the following methods: v read(int) - read the record with the specified record number. v readAfter(int) - read the record after the specified record number. v readBefore(int) - read the record before the specified record number. To update a record, use the following method: v update(int) - update the record with the specified record number. SequentialFile is a subclass of AS400File; all methods in AS400File are available to SequentialFile. The following example shows how to use the SequentialFile class:
// Create an AS400 object, the file exists on this // server. AS400 sys = new AS400("mySystem.myCompany.com"); // Create a file object that represents the file SequentialFile myFile = new SequentialFile(sys, "/QSYS.LIB/MYLIB.LIB/MYFILE.FILE/%FILE%.MBR"); // Assume that the AS400FileRecordDescription class // was used to generate the code for a subclass of // RecordFormat that represents the record format // of file MYFILE in library MYLIB. The code was // compiled and is available for use by the Java program. RecordFormat recordFormat = new MYFILEFormat(); // Set the record format for myFile. This must // be done before invoking open() myFile.setRecordFormat(recordFormat); // Open the file. myFile.open(AS400File.READ_WRITE, 0, AS400File.COMMIT_LOCK_LEVEL_NONE); // Delete record number 2. myFile.delete(2); // Read record number 5 and update it Record updateRec = myFile.read(5); updateRec.setField("CUSTNAME", newName); // Use the base class' update() method since I am // already positioned on the record. myFile.update(updateRec); // Update record number 7 updateRec.setField("CUSTNAME", nextNewName); updateRec.setField("CUSTNUM", new Integer(7)); myFile.update(7, updateRec); // ....
IBM Toolbox for Java
163
// Close the file since I am done using it myFile.close(); // Disconnect since I am done using record-level access sys.disconnectService(AS400.RECORDACCESS);
Related information SequentialFile Javadoc AS400FileRecordDescription: The IBM Toolbox for Java AS400FileRecordDescription class provides the methods for retrieving the record format of a file on the server. This class provides methods for creating Java source code for subclasses of RecordFormat and for returning RecordFormat objects, which describe the record formats of user-specified physical or logical files on the server. The output of these methods can be used as input to an AS400File object when setting the record format. It is recommended that the AS400FileRecordDescription class always be used to generate the RecordFormat object when the file already exists on the server. Note: The AS400FileRecordDescription class does not retrieve the entire record format of a file. Only enough information is retrieved to describe the contents of the records that make up the file. Information such as column headings, aliases, and reference fields is not retrieved. Therefore, the record formats retrieved cannot necessarily be used to create a file whose record format is identical to the file from which the format was retrieved. Creating Java source code for subclasses of RecordFormat to represent the record format of files on the server The AS400FileRecordDescription createRecordFormatSource() method creates Java source files for subclasses of the RecordFormat class. The files can be compiled and used by an application or applet as input to the AS400File.setRecordFormat() method. The createRecordFormatSource() method should be used as a development time tool to retrieve the record formats of existing files on the server. This method allows the source for the subclass of the RecordFormat class to be created once, modified if necessary, compiled, and then used by many Java programs accessing the same files on the server. Because this method creates files on the local system, it can be used only by Java applications. The output (the Java source code), however, can be compiled and then used by Java applications and applets alike. Note: This method overwrites files with the same names as the Java source files being created. Example 1: The following example shows how to use the createRecordFormatSource() method:
// Create an AS400 object, the file exists on this // server. AS400 sys = new AS400("mySystem.myCompany.com"); // Create an AS400FileRecordDescription object that represents the file AS400FileRecordDescription myFile = new AS400FileRecordDescription(sys, "/QSYS.LIB/MYLIB.LIB/MYFILE.FILE"); // Create the Java source file in the current working directory. // Specify "package com.myCompany.myProduct;" for the // package statement in the source since I will ship the class // as part of my product. myFile.createRecordFormatSource(null, "com.myCompany.myProduct");
164
// // // //
Assuming that the format name for file MYFILE is FILE1, the file FILE1Format.java will be created in the current working directory. It will overwrite any file by the same name. The name of the class will be FILE1Format. The class will extend from RecordFormat.
Example 2: Compile the file you created above, FILE1Format.java, and use it as follows:
// Create an AS400 object, the file exists on this // server. AS400 sys = new AS400("mySystem.myCompany.com"); // Create an AS400File object that represents the file SequentialFile myFile = new SequentialFile(sys, "/QSYS.LIB/MYLIB.LIB/MYFILE.FILE"); // Set the record format // This assumes that import.com.myCompany.myProduct.FILE1Format; // has been done. myFile.setRecordFormat(new FILE1Format()); // Open the file and read from it // .... // Close the file since I am done using it myFile.close(); // Disconnect since I am done using record-level access sys.disconnectService(AS400.RECORDACCESS);
Creating RecordFormat objects to represent the record format of files on the server The AS400FileRecordDescription retrieveRecordFormat() method returns an array of RecordFormat objects that represent the record formats of an existing file on the server. Typically, only one RecordFormat object is returned in the array. When the file for which the record format is being retrieved is a multiple format logical file, more than one RecordFormat object is returned. Use this method to dynamically retrieve the record format of an existing file on the server during runtime. The RecordFormat object then can be used as input to the AS400File.setRecordFormat() method. The following example shows how to use the retrieveRecordFormat() method:
// Create an AS400 object, the file exists on this // server. AS400 sys = new AS400("mySystem.myCompany.com"); // Create an AS400FileRecordDescription object that represents the file AS400FileRecordDescription myFile = new AS400FileRecordDescription(sys, "/QSYS.LIB/MYLIB.LIB/MYFILE.FILE"); // Retrieve the record format for the file RecordFormat[] format = myFile.retrieveRecordFormat(); // Create an AS400File object that represents the file SequentialFile myFile = new SequentialFile(sys, "/QSYS.LIB/MYLIB.LIB/MYFILE.FILE"); // Set the record format myFile.setRecordFormat(format[0]); // Open the file and read from it // .... // Close the file as I am done using it myFile.close(); // Disconnect since I am done using record-level access sys.disconnectService(AS400.RECORDACCESS);
AS400FileRecordDescription Javadoc
IBM Toolbox for Java
165
RecordFormat Javadoc AS400File Javadoc Creating and deleting files and members: Physical files on the server are created by specifying a record length, an existing server data description specifications (DDS) source file, or a RecordFormat object. When you create a file and specify a record length, a data file or a source file can be created. The method sets the record format for the object. Do not call the setRecordFormat() method for the object. A data file has one field. The field name is the name of the file, the field type is of type character, and the field length is the length that is specified on the create method. A source file has three fields: v Field SRCSEQ is ZONED DECIMAL (6,2) v Field SRCDAT is ZONED DECIMAL (6,0) v SRCDTA is a character field with a length that is the length specified on the create method minus 12 The following examples show how to create files and members. Example 1: To create a data file with a 128-byte record:
// Create an AS400 object, the file // will be created on this server. AS400 sys = new AS400("mySystem.myCompany.com"); // Create a file object that represents the file SequentialFile newFile = new SequentialFile(sys, "/QSYS.LIB/MYLIB.LIB/MYFILE.FILE/%FILE%.MBR"); // Create the file newFile.create(128, "*DATA", "Data file with a 128 byte record"); // Open the file for writing only. // Note: The record format for the file // has already been set by create() newFile.open(AS400File.WRITE_ONLY, 0, AS400File.COMMIT_LOCK_LEVEL_NONE); // Write a record to the file. Because the record // format was set on the create(), getRecordFormat() // can be called to get a record properly formatted // for this file. Record writeRec = newFile.getRecordFormat().getNewRecord(); writeRec.setField(0, "Record one"); newFile.write(writeRec); // .... // Close the file since I am done using it newFile.close(); // Disconnect since I am done using record-level access sys.disconnectService(AS400.RECORDACCESS);
Example 2: When creating a file specifying an existing DDS source file, the DDS source file is specified on the create() method. The record format for the file must be set using the setRecordFormat() method before the file can be opened. For example:
// Create an AS400 object, the // file will be created on this server. AS400 sys = new AS400("mySystem.myCompany.com");
166
// Create QSYSObjectPathName // both the new file and the QSYSObjectPathName file = QSYSObjectPathName ddsFile =
objects for DDS file. new QSYSObjectPathName("MYLIB", "MYFILE", "FILE", "MBR"); new QSYSObjectPathName("MYLIB", "DDSFILE", "FILE", "MBR");
// Create a file object that represents the file SequentialFile newFile = new SequentialFile(sys, file); // Create the file newFile.create(ddsFile, "File created using DDSFile description");
// Set the record format for the file // by retrieving it from the server. newFile.setRecordFormat(new AS400FileRecordDescription(sys, newFile.getPath()).retrieveRecordFormat()[0]); // Open the file for writing newFile.open(AS400File.WRITE_ONLY, 0, AS400File.COMMIT_LOCK_LEVEL_NONE); // Write a record to the file. The getRecordFormat() // method followed by the getNewRecord() method is used to get // a default record for the file. Record writeRec = newFile.getRecordFormat().getNewRecord(); newFile.write(writeRec); // .... // Close the file since I am done using it newFile.close(); // Disconnect since I am done using // record-level access sys.disconnectService(AS400.RECORDACCESS);
Example 3: When creating a file specifying a RecordFormat object, the RecordFormat object is specified on the create() method. The method sets the record format for the object. The setRecordFormat() method must not be called for the object.
// Create an AS400 object, the file will be created // on this server. AS400 sys = new AS400("mySystem.myCompany.com"); // Create a file object that represents the file SequentialFile newFile = new SequentialFile(sys, "/QSYS.LIB/MYLIB.LIB/MYFILE.FILE/%FILE%.MBR"); // Retrieve the record format from an existing file RecordFormat recordFormat = new AS400FileRecordDescription(sys, "/QSYS.LIB/MYLIB.LIB/EXISTING.FILE/MBR1.MBR").retrieveRecordFormat()[0]; // Create the file newFile.create(recordFormat, "File created using record format object");
// Open the file for writing only. // Note: The record format for the file // has already been set by create() newFile.open(AS400File.WRITE_ONLY, 0, AS400File.COMMIT_LOCK_LEVEL_NONE); // Write a record to the file. The recordFormat // object is used to get a default record // properly formatted for the file. Record writeRec = recordFormat.getNewRecord(); newFile.write(writeRec); // ....
167
// Close the file since I am done using it newFile.close(); // Disconnect since I am done using // record-level access sys.disconnectService(AS400.RECORDACCESS);
When deleting files and members, use these methods: v Use the delete() method to delete server files and all of their members. v Use the deleteMember()method to delete just one member of a file. Use the addPhysicalFileMember() method to add members to a file. Related information AS400File Javadoc Reading and writing records: You can use the AS400File class to read, write, update, and delete records in files on the server. The record is accessed through the Record class, which is described by a RecordFormat class. The record format must be set through the setRecordFormat() method before the file is opened, unless the file was just created (without an intervening close()) by one of the create() methods, which sets the record format for the object. Use the read() methods to read a record from the file. Methods are provided to do the following: v read() - read the record at the current cursor position v readFirst() - read the first record of the file v readLast() - read the last record of the file v readNext() - read the next record in the file v readPrevious() - read the previous record in the file The following example shows how to use the readNext() method:
// Create an AS400 object, the file exists on this // server. AS400 sys = new AS400("mySystem.myCompany.com"); // Create a file object that represents the file SequentialFile myFile = new SequentialFile(sys, "/QSYS.LIB/MYLIB.LIB/MYFILE.FILE/%FILE%.MBR"); // Assume that the AS400FileRecordDescription class // was used to generate the code for a subclass of // RecordFormat that represents the record format // of file MYFILE in library MYLIB. The code was // compiled and is available for use by the Java // program. RecordFormat recordFormat = new MYFILEFormat(); // Set the record format for myFile. This must // be done before invoking open() myFile.setRecordFormat(recordFormat); // Open the file. myFile.open(AS400File.READ_ONLY, 0, AS400File.COMMIT_LOCK_LEVEL_NONE); // Read each record in the file writing field // CUSTNAME to System.out System.out.println(" CUSTOMER LIST"); System.out.println("____________________________________________"); Record record = myFile.readNext();
168
while(record != null) { System.out.println(record.getField("CUSTNAME")); record = myFile.readNext(); } .... // Close the file since I am done using it myFile.close(); // Disconnect since I am done using // record-level access. sys.disconnectService(AS400.RECORDACCESS);
Use the update() method to update the record at the cursor position. For example:
// Create an AS400 object, the file exists on this // server. AS400 sys = new AS400("mySystem.myCompany.com"); // Create a file object that represents the file SequentialFile myFile = new SequentialFile(sys, "/QSYS.LIB/MYLIB.LIB/MYFILE.FILE/%FILE%.MBR"); // Assume that the AS400FileRecordDescription class // was used to generate the code for a subclass of // RecordFormat that represents the record format // of file MYFILE in library MYLIB. The code was // compiled and is available for use by the Java program. RecordFormat recordFormat = new MYFILEFormat(); // Set the record format for myFile. This must // be done prior to invoking open() myFile.setRecordFormat(recordFormat); // Open the file for updating myFile.open(AS400File.READ_WRITE, 0, AS400File.COMMIT_LOCK_LEVEL_NONE); // Update the first record in the file. Assume // that newName is a String with the new name for // CUSTNAME Record updateRec = myFile.readFirst(); updateRec.setField("CUSTNAME", newName); myFile.update(updateRec); .... // Close the file since I am done using it myFile.close(); // Disconnect since I am done using record-level access sys.disconnectService(AS400.RECORDACCESS);
Use the write() method to append records to the end of a file. A single record or an array of records can be appended to the file. Use the deleteCurrentRecord() method to delete the record at the cursor position. Related information AS400File Javadoc Locking files:
169
The Java program can lock a file to prevent other users from accessing the file while the first Java program is using the file. Lock types are as follows. You can find more information about the lock types in the AS400File Javadoc. v Read/Exclusive Lock - The current Java program reads records, and no other program can access the file. v Read/Allow shared read Lock - The current Java program reads records, and other programs can read records from the file. v Read/Allow shared write Lock - The current Java program reads records, and other programs can change the file. v Write/Exclusive Lock - The current Java program changes the file, and no other program can access the file. v Write/Allow shared read Lock - The current Java program changes the file, and other programs can read records from the file. v Write/Allow shared write Lock - The current Java program changes the file, and other programs can change the file. To give up the locks obtained through the lock() method, the Java program starts the releaseExplicitLocks() method. Related information AS400File Javadoc Using record blocking: The IBM Toolbox for Java AS400File class uses record blocking to improve performance. v If the file is opened for read-only access, a block of records is read when the Java program reads a record. Blocking improves performance because subsequent read requests may be handled without accessing the server. Little performance difference exists between reading a single record and reading several records. Performance improves significantly if records can be served out of the block of records cached on the client. The number of records to read in each block can be set when the file is opened. For example:
// Create an AS400 object, the file exists on this // server. AS400 sys = new AS400("mySystem.myCompany.com"); // Create a file object that represents the file SequentialFile myFile = new SequentialFile(sys, "/QSYS.LIB/MYLIB.LIB/MYFILE.FILE/%FILE%.MBR"); // Assume that the AS400FileRecordDescription class // was used to generate the code for a subclass of // RecordFormat that represents the record format // of file MYFILE in library MYLIB. The code was // compiled and is available for use by the Java // program. RecordFormat recordFormat = new MYFILEFormat(); // Set the record format for myFile. This must // be done before invoking open() myFile.setRecordFormat(recordFormat); // Open the file. Specify a blocking factor of 50. int blockingFactor = 50; myFile.open(AS400File.READ_ONLY, blockingFactor, AS400File.COMMIT_LOCK_LEVEL_NONE); // Read the first record of the file. Because // a blocking factor was specified, 50 records // are retrieved during this read() invocation. Record record = myFile.readFirst();
170
for (int i = 1; i < 50 && record != null; i++) { // The records read in this loop will be served out of the block of // records cached on the client. record = myFile.readNext(); } .... // Close the file since I am done using it myFile.close(); // Disconnect since I am done using // record-level access sys.disconnectService(AS400.RECORDACCESS);
v If the file is opened for write-only access, the blocking factor indicates how many records are written to the file at one time when the write(Record[]) method is invoked. For example:
// Create an AS400 object, the file exists on this // server. AS400 sys = new AS400("mySystem.myCompany.com"); // Create a file object that represents the file SequentialFile myFile = new SequentialFile(sys, "/QSYS.LIB/MYLIB.LIB/MYFILE.FILE/%FILE%.MBR"); // Assume that the AS400FileRecordDescription class // was used to generate the code for a subclass of // RecordFormat that represents the record format // of file MYFILE in library MYLIB. The code was // compiled and is available for use by the Java // program. RecordFormat recordFormat = new MYFILEFormat(); // Set the record format for myFile. This must // be done prior to invoking open() myFile.setRecordFormat(recordFormat); // Open the file. Specify a blocking factor of 50. int blockingFactor = 50; myFile.open(AS400File.WRITE_ONLY, blockingFactor, AS400File.COMMIT_LOCK_LEVEL_NONE); // Create an array of records to write to the file Record[] records = new Record[100]; for (int i = 0; i < 100; i++) { // Assume the file has two fields, // CUSTNAME and CUSTNUM records[i] = recordFormat.getNewRecord(); records[i].setField("CUSTNAME", "Customer " + String.valueOf(i)); records[i].setField("CUSTNUM", new Integer(i)); } // Write the records to the file. Because the // blocking factor is 50, only two trips to the // server are made with each trip writing 50 records myFile.write(records); .... // Close the file since I am done using it myFile.close(); // Disconnect since I am done using // record-level access sys.disconnectService(AS400.RECORDACCESS);
171
v If the file is opened for read-write access, no blocking is done. Any blocking factor specified on open() is ignored. AS400File Javadoc Setting the cursor position: An open file has a cursor. The cursor points to the record to be read, updated, or deleted. When a file is first opened the cursor points to the beginning of the file. The beginning of the file is before the first record. Use the following methods to set the cursor position: v positionCursorAfterLast() - Set cursor to after the last record. This method exists so Java programs can use the readPrevious() method to access records in the file. v positionCursorBeforeFirst() - Set cursor to before the first record. This method exists so Java programs can use the readNext() method to access records in the file. v positionCursorToFirst() - Set the cursor to the first record. v positionCursorToLast() - Set the cursor to the last record. v positionCursorToNext() - Move the cursor to the next record. v positionCursorToPrevious() - Move the cursor to the previous record. The following example shows how to use the positionCursorToFirst() method to position the cursor.
// Create an AS400 object, the file exists on this // server. AS400 sys = new AS400("mySystem.myCompany.com"); // Create a file object that represents the file SequentialFile myFile = new SequentialFile(sys, "/QSYS.LIB/MYLIB.LIB/MYFILE.FILE/%FILE%.MBR"); // Assume that the AS400FileRecordDescription class // was used to generate the code for a subclass of // RecordFormat that represents the record format // of file MYFILE in library MYLIB. The code was // compiled and is available for use by the Java // program. RecordFormat recordFormat = new MYFILEFormat(); // Set the record format for myFile. This must // be done before invoking open() myFile.setRecordFormat(recordFormat); // Open the file. myFile.open(AS400File.READ_WRITE, 1, AS400File.COMMIT_LOCK_LEVEL_NONE); // I want to delete the first record of the file. myFile.positionCursorToFirst(); myFile.deleteCurrentRecord(); .... // Close the file since I am done using it myFile.close(); // Disconnect since I am done using // record-level access sys.disconnectService(AS400.RECORDACCESS);
172
Through commitment control, your Java program has another level of control over changing a file. With commitment control turned on, transactions to a file are pending until they are either committed or rolled back. If committed, all changes are put to the file. If rolled back, all changes are discarded. The transaction can be changing an existing record, adding a record, deleting a record, or even reading a record depending on the commitment control lock level specified on the open(). The levels of commitment control are as follows. To see more details about each level, refer to the AS400File Javadoc. v All - Every record accessed in the file is locked until the transaction is committed or rolled back. v Change - Updated, added, and deleted records in the file are locked until the transaction is committed or rolled back. v Cursor Stability - Updated, added, and deleted records in the file are locked until the transaction is committed or rolled back. Records that are accessed but not changed are locked only until another record is accessed. v None - There is no commitment control on the file. Changes are immediately put to the file and cannot be rolled back. You can use the AS400File startCommitmentControl() method to start commitment control. Commitment control applies to the AS400 connection. Once commitment control is started for a connection, it applies to all files opened under that connection from the time that commitment control was started. Files opened before commitment control is started are not under commitment control. The level of commitment control for individual files is specified on the open() method. Specify COMMIT_LOCK_LEVEL_DEFAULT to use the same level of commitment control as was specified on the startCommitmentControl() method. For example:
// Create an AS400 object, the files exist on this // server. AS400 sys = new AS400("mySystem.myCompany.com"); // Create three file objects SequentialFile myFile = new SequentialFile(sys, "/QSYS.LIB/MYLIB.LIB/MYFILE.FILE/%FILE%.MBR"); SequentialFile yourFile = new SequentialFile(sys, "/QSYS.LIB/YOURLIB.LIB/YOURFILE.FILE/%FILE%.MBR"); SequentialFile ourFile = new SequentialFile(sys, "/QSYS.LIB/OURLIB.LIB/OURFILE.FILE/%FILE%.MBR"); // Open yourFile before starting commitment control // No commitment control applies to this file. The // commit lock level parameter is ignored because // commitment control is not started for the connection. yourFile.setRecordFormat(new YOURFILEFormat()); yourFile.open(AS400File.READ_WRITE, 0, AS400File.COMMIT_LOCK_LEVEL_DEFAULT); // Start commitment control for the connection. // Note: Any of the three files might be used for // this call to startCommitmentControl(). myFile.startCommitmentControl(AS400File.COMMIT_LOCK_LEVEL_CHANGE); // Open myFile and ourFile myFile.setRecordFormat(new MYFILEFormat()); // Use the same commit lock level as specified // when commitment control was started myFile.open(AS400File.WRITE_ONLY, 0, COMMIT_LOCK_LEVEL_DEFAULT); ourFile.setRecordFormat(new OURFILEFormat()); // Specify a different commit lock level than // when commitment control was started ourFile.open(AS400File.READ_WRITE, 0, COMMIT_LOCK_LEVEL_CURSOR_STABILITY); // write and update records in all three files
IBM Toolbox for Java
173
.... // Commit the changes for files myFile and ourFile. // Note that the commit commits all changes for the connection // even though it is invoked on only one AS400File object. myFile.commit(); // Close the files myFile.close(); yourFile.close(); ourFile.close(); // End commitment control // This ends commitment control for the connection. ourFile.endCommitmentControl(); // Disconnect since I am done using record-level access sys.disconnectService(AS400.RECORDACCESS);
The commit() method commits all transactions since the last commit boundary for the connection. The rollback() method discards all transactions since the last commit boundary for the connection. Commitment control for a connection is ended through the endCommitmentControl() method. If a file is closed before invoking the commit() or rollback() method, all uncommitted transactions are rolled back. All files opened under commitment control must be closed before the endCommitmentControl() method is called. The following examples shows how to start commitment control, commit or roll back functions, and then end commitment control:
// ... assume the AS400 object and file have been // instantiated. // Start commitment control for *CHANGE aFile.startCommitmentControl(AS400File.COMMIT_LOCK_LEVEL_CHANGE); // ... open the file and do several changes. // example, update, add or delete records. // Based on a flag either save or discard the // transactions. if (saveChanges) aFile.commit(); else aFile.rollback(); // Close the file aFile.close(); // End commitment control for the connection. aFile.endCommitmentControl(); For
SaveFile class
The SaveFile class represents a save file on a server. Related information SaveFile Javadoc
ServiceProgramCall class
The IBM Toolbox for Java ServiceProgramCall class allows you to call an IBM i service program. ServiceProgramCall is a subclass of the ProgramCall class that you use to call IBM i programs. If you want to call an IBM i program, use the ProgramCall class.
174
The ServiceProgramCall class makes it possible for you to call an IBM i service program, pass data to a service program through input parameters, and access data the service program returns through output parameters. Using ServiceProgramCall causes the AS400 object to connect to the server. See managing connections for information about managing connections. The default behavior is for service programs to run in a separate server job, even when the Java program and the service program are on the same server. You can override the default behavior and have the service program run in the Java job using the setThreadSafe() method, inherited from ProgramCall. Using the ServiceProgramCall class In order to use the ServiceProgramCall class, you must be sure to meet the following requirements: v The service program must be on an server v You can pass no more than seven parameters to the service program v The return value of the service program is void or numeric Working with ProgramParameter objects The ProgramParameter class works with the ServiceProgramCall class to pass parameter data to and from an IBM i service program. You pass input data to the service program with setInputData(). You request the amount of output data you want returned with setOutputDataLength(). You retrieve the output data after the service program is finished running with getOutputData(). In addition to the data itself, ServiceProgramCall needs to know how to pass parameter data to the service program. The setParameterType() method of ProgramParameter is used to supply this information. The type indicates if the parameter is pass by value or pass by reference. In either case, data is sent from the client to the server. Once the data is on the server, the server uses the parameter type to correctly call the service program. All parameters will be in the form of a byte array. Therefore, to convert between IBM i and Java formats, you use the data conversion and description classes. ServiceProgramCall Javadoc ProgramCall Javadoc ProgramParameter Javadoc
Subsystem class
The Subsystem class represents a subsystem on the server. Related information Subsystem Javadoc
SystemStatus classes
The SystemStatus classes allow you to retrieve system status information and to retrieve and change system pool information. The SystemStatus object allows you to retrieve system status information including the following: v getUsersCurrentSignedOn(): Returns the number of users currently signed on the system v getUsersTemporarilySignedOff(): Returns the number of interactive jobs that are disconnected v getDateAndTimeStatusGathered(): Returns the date and time when the system status information was gathered v getJobsInSystem(): Returns the total number of user and system jobs that are currently running v getBatchJobsRunning(): Returns the number of batch jobs currently running on the system v getBatchJobsEnding(): Returns the number of batch jobs that are in the process of ending
IBM Toolbox for Java
175
v getSystemPools(): Returns an enumeration containing a SystemPool object for each system pool In addition to the methods within the SystemStatus class, you also can access SystemPool through SystemStatus. SystemPool allows you to get information about system pools and change system pool information. Example Note: Read the Code example disclaimer for important legal information. This example shows you how to use caching with the SystemStatus class:
AS400 system = new AS400("MyAS400"); SystemStatus status = new SystemStatus(system); // Turn on caching. It is off by default. status.setCaching(true); // This will retrieve the value from the system. // Every subsequent call will use the cached value // instead of retrieving it from the system. int jobs = status.getJobsInSystem(); // ... Perform other operations here ... // This determines if caching is still enabled. if (status.isCaching()) { // This will retrieve the value from the cache. jobs = status.getJobsInSystem(); } // Go to the system next time, regardless if caching is enabled. status.refreshCache(); // This will retrieve the value from the system. jobs = status.getJobsInSystem(); // Turn off caching. Every subsequent call will go to the system. status.setCaching(false); // This will retrieve the value from the system. jobs = status.getJobsInSystem();
SystemStatus Javadoc SystemPool class: The SystemPool class allows you to retrieve and change system pool information. The SystemPool class includes the following methods: v The getPoolSize() method returns the size of the pool, and the setPoolSize() method sets the size of the pool. v The getPoolName() method retrieves the name of the pool, and the setPoolName() method sets the pool's name. v The getReservedSize() method returns the amount of storage in the pool that is reserved for system use. v The getDescription() method returns the description of the system pool. v The getMaximumActiveThreads() method returns the maximum number of threads that can be active in the pool at any one time.
176
v The setMaximumFaults() method sets the maximum faults-per-second guideline to use for this system pool. v The setPriority() method sets the priority of this system pool relative to the priority of the other system pools. Example Note: Read the Code example disclaimer for important legal information.
//Create AS400 object. AS400 as400 = new AS400("system name"); //Construct a system pool object. SystemPool systemPool = new SystemPool(as400,"*SPOOL"); //Get system pool paging option System.out.println("Paging option : "+systemPool.getPagingOption());
System values
The system value classes allow a Java program to retrieve and change system values and network attributes. You can also define your own group to contain the system values you want. A SystemValue object primarily contains the following information: v Name v Description v Release v Value Using the SystemValue class, retrieve a single system value by using the getValue() method and change a system value by using the setValue() method. You can also retrieve group information about a particular system value: v To retrieve the system-defined group to which a system value belongs, use the getGroup() method. v To retrieve the user-defined group to which a SystemValue object belongs (if any), use the getGroupName() and getGroupDescription() methods. Whenever the value of a system value is retrieved for the first time, the value is retrieved from the server and cached. On subsequent retrievals, the cached value is returned. If the current value is what you want instead of the cached value, a clear() must be done to clear the current cache.
177
You can individually add the names of system values to include in the group by using the add() method. You can also remove them by using the remove() method. Once the SystemValueGroup is populated with the required system value names, obtain the real SystemValue objects from the group by calling the getSystemValues() method. In this way, a SystemValueGroup object takes a set of system value names and generates a Vector of SystemValue objects, all having the system, group name, and group description of the SystemValueGroup. To refresh a Vector of SystemValue objects all at once, use the refresh() method.
Examples of using the SystemValueGroup class The following example shows how to build a group of system value names and then manipulate them:
//Create an AS400 object AS400 sys = new AS400("mySystem.myCompany.com"); //Create a system value group initially representing all of the network attributes on the system. String name = "My Group"; String description = "This is one of my system values."; SystemValueGroup svGroup = new SystemValueGroup(sys, name, description, SystemValueList.GROUP_NET); //Add some more system value names to the group and remove some we do not want. svGroup.add("QDATE"); svGroup.add("QTIME"); svGroup.remove("NETSERVER"); svGroup.remove("SYSNAME"); //Obtain the actual SystemValue objects. They are returned inside a Vector. Vector sysvals = svGroup.getSystemValues(); //You will notice that this is one of my system values. SystemValue mySystemValue = (SystemValue)sysvals.elementAt(0); System.out.println(mySystemValue.getName()+" - "+mySystemValue.getGroupDescription()); //We can add another SystemValue object from another system into the group.
178
AS400 sys2 = new AS400("otherSystem.myCompany.com"); SystemValue sv = new SystemValue(sys2, "QDATE"); sysvals.addElement(sv); //Now refresh the entire group of system values all at once. //It does not matter if some system values are from different System i servers. //It does not matter if some system values were generated using SystemValueGroup and some were not. SystemValueGroup.refresh(sysvals); //Disconnect from the systems. sys.disconnectAllServices(); sys2.disconnectAllServices();
Trace class
The Trace class allows the Java program to log trace points and diagnostic messages. This information helps reproduce and diagnose problems. Note: You can also set tracing by using the trace system properties. The Trace class logs the following categories of information:
Information category Conversion Description Logs character set conversions between Unicode and code pages. This category is used only by the IBM Toolbox for Java classes. Logs the data that flows between the system and the Java program. This category is used only by the IBM Toolbox for Java classes. Logs state information. Logs additional errors that cause an exception. Traces the flow through a program. This category is used to determine how PCML interprets the data that is sent to and from the server. This category is used by IBM Toolbox for Java classes to log data flow between the client and the proxy server. Logs information about errors the program was able to recover from. This category is used to enable or disable tracing for all of the above categories at once. Trace information cannot be directly logged to this category.
Datastream
The IBM Toolbox for Java classes also use the trace categories. When a Java program enables logging, IBM Toolbox for Java information is included with the information that is recorded by the application. You can enable the trace for a single category or a set of categories. Once the categories are selected, use the setTraceOn method to turn tracing on and off. Data is written to the log using the log method. You can send trace data for different components to separate logs. Trace data, by default, is written to the default log. Use component tracing to write application-specific trace data to a separate log or standard output. By using component tracing, you can easily separate trace data for a specific application from other data.
IBM Toolbox for Java
179
Excessive logging can impact performance. Use the isTraceOn method to query the current state of the trace. Your Java program can use this method to determine whether it builds the trace record before it calls the log method. Calling the log method when logging is off is not an error, but it takes more time. The default is to write log information to standard out. To redirect the log to a file, call the setFileName() method from your Java application. In general, this works only for Java applications because most browsers do not give applets access to write to the local file system. Logging is off by default. Java programs provide a way for the user to turn on logging so that it is easy to enable logging. For example, the application can parse for a command line parameter that indicates which category of data is logged. The user can set this parameter when log information is needed.
Examples
Note: Read the Code example disclaimer for important legal information. The following examples show how to use the Trace class. Example Using setTraceOn() and writing data to a log by using the log method
// Enable diagnostic, information, and warning logging. Trace.setTraceDiagnosticOn(true); Trace.setTraceInformationOn(true); Trace.setTraceWarningOn(true); // Turn tracing on. Trace.setTraceOn(true); // ... At this point in the Java program, write to the log. Trace.log(Trace.INFORMATION, "Just entered class xxx, method xxx"); // Turning tracing off. Trace.setTraceOn(false);
Example: Using Trace In the following code, Method 2 is the preferable way to use Trace.
// Method 1 - build a trace record // then call the log method and let the trace class determine if the // data should be logged. This will work but will be slower than the // following code. String traceData = new String("Just entered class xxx, data = "); traceData = traceData + data + "state = " + state; Trace.log(Trace.INFORMATION, traceData); // Method 2 - check the log status before building the information to // log. This is faster when tracing is not active. if (Trace.isTraceOn() && Trace.isTraceInformationOn()) { String traceData = new String("just entered class xxx, data = "); traceData = traceData + data + "state = " + state; Trace.log(Trace.INFORMATION, traceData); }
180
// // // //
component log file will only contain trace information specific to that component. If a Trace file is not specified, all trace data will go to standard out with the component specified in front of each trace message.
// Trace.setFileName("c:\\bit.bucket"); // Trace.setFileName(myComponent1, "c:\\Component1.log"); // Trace.setFileName(myComponent2, "c:\\Component2.log"); Trace.setTraceOn(true); // Turn trace on. Trace.setTraceInformationOn(true); // Enable information messages. // Log component specific trace data or general IBM Toolbox for Java // trace data. Trace.setFileName("c:\\bit.bucket"); Trace.setFileName(myComponent1, "c:\\Component1.log");
Retrieving information about users and groups You use a UserList to get a list of the following: v All users and groups v Only groups v All users who are members of groups v All users who are not members of groups
181
The only property of the UserList object that must be set is the AS400 object that represents the system from which the list of users is to be retrieved. By default, all users are returned. Use a combination of UserList methods setUserInfo() and setGroupInfo() to specify exactly which users are returned. User Javadoc UserGroup Javadoc UserList Javadoc AS400 Javadoc Example: Using UserList to list all of the user in a given group on page 552 This source is an example of IBM Toolbox for Java UserList. This program lists all of the users in a given group.
UserSpace class
The UserSpace class represents a user space on the server. Required parameters are the name of the user space and the AS400 object that represents the server that has the user space. Methods exist in user space class to do the following: v Create a user space. v Delete a user space. v Read from a user space. v Write to user space. v Get the attributes of a user space. A Java program can get the initial value, length value, and automatic extendible attributes of a user space. v Set the attributes of a user space. A Java program can set the initial value, length value, and automatic extendible attributes of a user space. The UserSpace object requires the integrated file system path name of the program. See integrated file system path names for more information. Using the UserSpace class causes the AS400 object to connect to the server. See managing connections for information about managing connections. The following example creates a user space, then writes data to it. Note: Read the Code example disclaimer for important legal information.
// Create an AS400 object. AS400 sys = new AS400("mySystem.myCompany.com"); // Create a user space object. UserSpace US = new UserSpace(sys, "/QSYS.LIB/MYLIB.LIB/MYSPACE.USRSPC"); // Use the create method to create the user space on // the server. US.create(10240, // The initial size is 10KB true, // Replace if the user space already exists " ", // No extended attribute (byte) 0x00, // The initial value is a null "Created by a Java program", // The description of the user space "*USE"); // Public has use authority to the user space // Use the write method to write bytes to the user space. US.write("Write this string to the user space.", 0);
UserSpace Javadoc
182
AS400 Javadoc
Commtrace classes
The IBM Toolbox for Java commtrace classes enable your Java programs to work with communications trace data for a specified LAN (Ethernet or token ring) line description. The commtrace package includes a class that you can run as a standalone utility program to format communications trace data. When you dump a communications trace for a server to a stream file, the information is saved in a binary format. The commtrace classes enable you to work with the various components of the stream file. Note: Communications trace files may contain confidential information, for example, unencrypted passwords. When the communications trace file is on server, only users who have *SERVICE special authority can access the trace data. If you move the file to a client, make sure that you protect the file in an appropriate manner. For more information about communications traces, see the links at the bottom of this page. Use the commtrace classes to perform the following tasks: v Format the raw trace data. v Parse any of the data to extract the information you want. You can parse both raw and formatted data, provided that you used the commtrace classes to format the data. Other classes in the com.ibm.as400.commtrace package not listed here are specific to the type of trace data that you want to work with. For more information about communications traces and about all the commtrace classes, see Communications trace.
Commtrace model
The following illustration shows how the commtrace classes correspond to a communications trace file. The graphic also indicates the naming conventions that the commtrace classes use for the components in a communications trace. Figure 1: Commtrace model
183
Each Frame in the trace file contains two initial sections (that provide general information about the contents of the frame) and the packet that the server transmitted between itself and a different point on the network. The very first 24-byte section of data contains general information about the contents of the frame, such as the frame number and data length. Use the Frame class to process this information.
Format class
Use the format class to read both the raw trace data and the trace data that you have already formatted by using the commtrace classes. Note: You cannot use the commtrace classes to read a communications trace that you formatted by using the Print Communications Trace (PRTCMNTRC) control language command. Use the Format class to parse and format the information in a trace, then send that formatted information to a file or a print device. Additionally, you might want to create a graphical front end that displays the information in a standalone application or within a browser. When you want to select only specific data,
184
use the Format class to supply that information to your Java program. For example you could use the Format class to read IP addresses out of a trace and then use that data in your program. The Format constructors accept arguments that represent unformatted data, such as an IFSFileInputStream object, a local file, or the binary trace file. To display a trace that you have already formatted, use the default Format constructor, then use Format.openIFSFile() or Format.openLclFile() to specify the formatted file that you want to display.
Examples
The following examples show how you can display a saved trace or format a binary trace. Note: Read the Code example disclaimer for important legal information. Example: Displaying a saved trace
Format fmt = new Format(); fmt.openLclFile("/path/to/file"); // Read the Prolog System.out.println(fmt.getRecFromFile()); // The total number of records in the trace TCP and non-TCP System.out.println("Total Records:" + fmt.getIntFromFile()); String rec; // Read in records until we reach the end. while((rec = fmt.getRecFromFile())!=null) { System.out.println(rec);
FormatProperties class
Use the FormatProperties class to specify and retrieve the properties for your Format object. In other words, when you use the Format class to send information to a file, use the FormatProperties class to filter the information that you want to send. These properties specify how you want your Format object to handle the information that it encounters in the Frames of the communications trace. The default behavior is for the Format object to ignore properties for which you have not given a specific value.
185
The FormatProperties class provides constants that you use to set properties. Setting properties enables the Format object to verify which filters you want to use. For example, the following code sets a Format object to display a progess dialog and not display broadcast frames:
FormatProperties prop = new FormatProperties(); prop.setProgress(FormatProperties.TRUE); prop.setBroadcast(FormatProperties.NO);
Most of the properties are available to your Format object as filters that you set to explicitly include specific data. Once you set the filters, the Format object displays only data that matches those filters. For example, the following code set a filter to display frames that occurred between a particular start and end time:
FormatProperties prop = new FormatProperties(); // Set the filter to start and end times of 22 July, 2002, // 2:30 p.m. and 2:45 p.m. GMT. // The time is expressed as a Unix(TM) timestamp, which is // based on the standard epoch of 01/01/1970 at 00:00:00 GMT. prop.setStartTime("1027348200"); prop.setEndTime("1027349100");
Example
The following example shows how you can use many of the commtrace classes, including the Format and FormatProperties classes, to display trace information to your monitor: Example: Using the commtrace classes on page 190 Format Javadoc FormatProperties Javadoc Running Format as a standalone program: In addition to using the Format class in your Java programs, you can run it as a standalone, command line utility to format a communications trace. The program connects an IFSFileOutputStream to the specified outfile and writes the data to that file. Running format as a standalone utility enables you to format files by using the processing power and storage space of your server. Running Format from a command line To run the Format utility from a command line prompt, use the following command:
java com.ibm.as400.commtrace.Format [options]
[options] equals one or more of the available options. Options include: system to which you want to connect userID and password for the system communications trace that you want to parse file in which you want to store the results
For a complete list of available options, see the Javadoc reference documentation for the Format class. Running Format remotely To run this class remotely use the JavaApplicationCall class:
// Construct a JavaApplicationCall object. jaCall = new JavaApplicationCall(sys);
186
// Set the Java application you want to run. jaCall.setJavaApplication("com.ibm.as400.util.commtrace.Format"); // Set the classpath environment variable used by the JVM on // the server, so it can find the class to run. jaCall.setClassPath("/QIBM/ProdData/OS400/JT400/lib/JT400Native.jar"); String[] args2 = { "-c", "true", "-t", "/path/to/trace", "-o", "/path/to/trace.extension"}; jaCall.setParameters(args2); if (jaCall.run() != true) { // Call Failed }
Prolog class
The IBM Toolbox for Java Prolog class represents the initial 256-byte section of a communications trace for a LAN line description. The Prolog contains general information about the trace, such as start and end times, number of bytes collected, and so on. Use the Prolog class to retrieve information from this section of trace, which you can then print, display, filter, or process in some other way. The Prolog class provides methods that allow you to perform a variety of actions that include the following: v Retrieve values from the fields of the prolog, such as the trace description, Ethernet Type, data direction, IP address, and so on v Return a formatted String that contains all the fields of the prolog v Test the prolog fields for invalid data
Example
The following example shows how you can use many of the commtrace classes, including the Prolog class, to display trace information to your monitor: Example: Using the commtrace classes on page 190 Related information Prolog Javadoc
Frame class
The Frame class represents all the data in one record, or frame, in a communications trace for a LAN line description. Each Frame contains three main sections of data that appear in the following order: 1. An initial 24-byte section that contains general information about the frame 2. General information about the frame (represented by the LanHeader class) 3. The packet data (represented by subclasses of the IPacket abstract class) Use the Frame class to parse and create a printable representation the data in the frame. The Frame class maintains the packet data in a linked list-like structure that uses specific formats. For specific information about the possible formats for packet data in a frame and for general information about the structure of a frame, see Commtrace model on page 183. The Frame class provides methods that allow you to perform a variety of actions that include the following:
IBM Toolbox for Java
187
v Retrieve the data packet v Retrieve the number, status, and type of the frame v Return specific data from the frame as a formatted String You can use the following process to access the data in a packet: 1. Use Frame.getPacket() to retrieve the packet 2. Access the data in the header by calling Packet.getHeader() 3. After you retrieve the header, call Header.getType() to find the type 4. Use the specific Header subclass to access the data associated with that header (the payload) and any additional headers
Example
The following example shows how you can use many of the commtrace classes, including the Format and FormatProperties classes, to display trace information to your monitor: Example: Using the commtrace classes on page 190
LanHeader class
The LanHeader class retrieves information from the section of data that occurs once, near the beginning of a frame, in the initial 24-byte section. This section typically contains hardware-specific information that includes general information about the frame, such as the frame number, and data length. Use the LanHeader class to parse and print the information in the LanHeader. The kind of information contained by the LanHeader includes: v The byte that identifies the start of the first header in this packet v Medium Access Control (MAC) addresses v Token ring addresses and routing information LanHeader also provides two methods that enable you to return a formatted String that contains the following: v Token ring routing data v Source MAC addresses, destination MAC addresses, frame format, and frame type Related information LanHeader Javadoc
IPPacket class
The IBM Toolbox for Java IPPacket class represents all the data packets that the network transmitted for this frame during the communications trace. IPPacket is an abstract class, so you will use the various concrete subclasses to process the headers and data in the packets. The subclasses of IPPacket include: v ARPPacket v IP4Packet v IP6Packet v UnknownPacket Packet classes enable you to retrieve the type of packet and access the raw data (the header and payload) that the packet contains. All the subclasses use similar constructors and include one additional method that returns a printable version of the packet contents as a String.
188
All the Packet class constructors take a byte array of packet data as an argument, but the ARPPacket also requires an integer that specifies the type of frame. Creating an instance of a Packet class automatically creates the appropriate Header object. The Packet classes provide methods that allow you to perform a variety of actions that include the following: v v v v v Retrieve the name and type of the packet Set the type of the packet Return the top-level Header object associated with the packet Return all the packet data as an unformatted String Return specific data from the packet as a formatted String IPPacket Javadoc ARPPacket Javadoc IP4Packet Javadoc IP6Packet Javadoc UnknownPacket Javadoc
Header class
The Header class is the abstract superclass for creating classes that represent specific kinds of packet headers. Packet headers include the associated data (or payload), which can be other headers and payloads. The subclasses of Header include: v ARPHeader v ExtHeader v v v v v ICMP4Header ICMP6Header IP4Header IP6Header TCPHeader
v UDPHeader v UnknownHeader Header classes enable you to retrieve the data for the header and the payload. One header can encapsulate other headers and their payloads. Creating an instance of a Packet class automatically creates the appropriate Header object. The Header classes provide methods that allow you to perform a variety of actions that include the following: v Return the length, name, and type of the header v Retrieve the data in the header as a byte array v Retrieve the next header in the packet v Retrieve the payload as a byte array, ASCII string, and hexadecimal string v Return all the header data as an unformatted String v Return specific data from the header as a formatted String Header Javadoc ARPHeader Javadoc ExtHeader Javadoc ICMP4Header Javadoc ICMP6Header Javadoc
IBM Toolbox for Java
189
IP4Header Javadoc IP6Header Javadoc TCPHeader Javadoc UDPHeader Javadoc UnknownHeader Javadoc
190
System.out.println(h.getName() + " src:" + ip6.getSrcAddr() + " dst:" + ip6.getDstAddr()); // Print the header as hex System.out.println(ip6.printHexHeader()); // Print a string representation of the header. System.out.println("Complete " + h.getName() + ":\n" + ip6.toString(fmtprop)); // Get the rest of the headers while ((h = h.getNextHeader()) != null) { // If it is a TCP header if (h.getType() == Header.TCP) { // Cast so we can access methods TCPHeader tcp = (TCPHeader) h; System.out.println(h.getName() +" src:" + tcp.getSrcPort() +" dst:" + tcp.getDstPort()); System.out.println("Complete " + h.getName() + ":\n" + tcp.toString(fmtprop)); // If it is a UDP header } else if (h.getType() == Header.UDP) { // Cast so we can access methods UDPHeader udp = (UDPHeader) h; System.out.println(h.getName() +" src:" + udp.getSrcPort() + " dst:" + udp.getDstPort()); System.out.println("Complete " + h.getName() + ":\n" + udp.toString(fmtprop)); } } } } } } } public static void main(String[] args) { CommTraceExample e = new CommTraceExample(); } }
HTML Classes
The IBM Toolbox for Java HTML classes provide representations for many common HTML tag elements. IBM Toolbox for Java HTML classes assist you in: v Setting up forms and tables for HTML pages v Aligning text v Working with a variety of HTML tags v Creating Extensible Stylesheet Language (XSL) formatting object (FO) source data v Altering the language and direction of text v Creating ordered and unordered lists v Creating file lists and HTML hierarchical trees (and the elements within them) v Adding tag attributes not already defined in the HTML classes (for example, bgcolor and style attributes) The HTML classes implement the HTMLTagElement interface. Each class produces an HTML tag for a specific element type. The tag may be retrieved using the getTag() method and can then be embedded into any HTML document. The tags you generate with the HTML classes are consistent with the HTML 3.2 specification. The HTML classes can work with servlet classes to get data from the server. However, they can also be used alone if you supply the table or form data.
191
Additionally, you can use the HTMLDocument class to easily create HTML pages or XSL FO source data. You can convert XSL FO data into Portable Document Format (PDF) documents. Using the PDF format enables your documents to retain the same graphical appearance when you print them as when you view them electronically. Note: The jt400Servlet.jar file includes both the HTML and Servlet classes. You must update your CLASSPATH to point to the jt400Servlet.jar file if you want to use the classes in the com.ibm.as400.util.html package. Related information HTMLTagElement Javadoc DirFilter Javadoc - Use to determine if a File object is a directory HTMLFileFilter Javadoc - Use to determine if a File object is a file URLEncoder Javadoc - Encodes delimiters to use in a URL string URLParser Javadoc - Allows you to parse a URL string for the URI, properties, and reference
BidiOrdering class
The IBM Toolbox for Java BidiOrdering class represents an HTML tag that alters the language and direction of text. An HTML <BDO> string requires two attributes, one for language and the other for the direction of the text. The BidiOrdering class allows you to: v Get and set the language attribute v Get and set the direction of text For more information about using the <BDO> HTML tag, see the W3C Web site.
When you use this tag in an HTML page, browsers that can understand the <BDO> tag display the example like this: .txeT cibarA emoS
192
HTMLAlign class
The IBM Toolbox for Java HTMLAlign class enables you to align sections of your HTML document, instead of just aligning individual items such as paragraphs or headings. The HTMLAlign class represents the <DIV> tag and its associated align attribute. You can use right, left, or center alignment. You can use this class to perform a variety of actions that include the following: v Add or remove items from the list of tags you want to align v v v v Get Get Get Get and set the alignment and set the direction of the text interpretation and set the language of the input element a string representation of the HTMLAlign object
When you use this tag in an HTML page, it looks like this: v Centered unordered list v Another item Related information HTMLAlign Javadoc
HTMLDocument class
The HTMLDocument class enables you to use existing IBM Toolbox for Java HTML classes to create either HTML pages or Portable Document Format (PDF) documents. When you create an HTMLDocument, you specify whether it contains HTML tags or Extensible Stylesheet Language (XSL) Formatting Object (FOs) tags:
193
v When you want to create HTML pages, the HTMLDocument class offers you an easier way to group all the required HTML tags. However, HTML pages do not always look the same when you print them as when you view them in a Web browser. v When you want to create PDF documents, the HTMLDocument class offers you the ability to create XSL FO source that contains all the information you need to produce a PDF document. PDF documents retain the same graphical appearance when you print them as when you view them electronically. To use HTMLDocument, you need to include an XML parser and an XSLT processor in your CLASSPATH environment variable. For more information, see the following pages: v JAR files on page 10 v XML parser and XSLT processor on page 415 You can process the resulting HTML or XSL source data the way you want, for example, by displaying the HTML, saving the XSL to a file, or using the streamed data in another part of your Java program. For more information about creating HTML pages and XSL FO source data, see the following pages: v Using HTMLDocument to create HTML data v Using HTMLDocument to create XSL FO data on page 195 v Examples: Using HTMLDocument on page 197 HTMLDocument Javadoc Using HTMLDocument to create HTML data: An HTMLDocument functions as a wrapper that holds the information necessary to create either HTML or Extensible Stylesheet Language (XSL) Formatting Object (FO) source data. When you want to create HTML pages, the HTMLDocument class offers you an easier way to group all the required HTML tags. Generating HTML source data When creating HTML source, HTMLDocument retrieves HTML tags from the HTML objects you have created. You can use either HTMLDocument.getTag() to stream all the elements you have defined or the getTag() for each individual HTML object. HTMLDocument generates HTML data as you define it in your Java program, so be sure that the resulting HTML is complete and correct. When you call HTMLDocument.getTag(), the HTMLDocument object performs the following actions: v Generates the opening <HTML> tag. At the end of the data, it generates the closing </HTML> tag. v Converts your HTMLHead and HTMLMeta objects into HTML tags. v Generates the opening <BODY> tag immediately after the <HEAD> tag. At the end of the data, just before the closing </HTML> tag, it generates the closing </BODY> tag. Note: If you do not specify a <HEAD> tag, HTMLDocument generates the <BODY> tag after the <HTML> tag. v Converts your remaining HTML objects into HTML tags as your program directs. Note: HTMLDocument streams the HTML tags as your Java program directs, so make sure that you call the tags in the proper order. Examples: Using HTMLDocument The following example shows how to use HTMLDocument to generate HTML source data (and XSL FO source):
194
Example: Using HTMLDocument to generate both HTML source and XSL FO source on page 200 Javadoc reference documentation For more information about the HTMLDocument class, see the following Javadoc reference documentation: HTMLDocument The following disclaimer applies to all of the IBM Toolbox for Java examples: Code example disclaimer IBM grants you a nonexclusive copyright license to use all programming code examples from which you can generate similar function tailored to your own specific needs. All sample code is provided by IBM for illustrative purposes only. These examples have not been thoroughly tested under all conditions. IBM, therefore, cannot guarantee or imply reliability, serviceability, or function of these programs. All programs contained herein are provided to you "AS IS" without any warranties of any kind. The implied warranties of non-infringement, merchantability and fitness for a particular purpose are expressly disclaimed. Using HTMLDocument to create XSL FO data: An HTMLDocument functions as a wrapper that holds the information necessary to create either Extensible Stylesheet Language (XSL) Formatting Object (FO) or HTML source data. Generated XSL FO source follows the XSL FO formatting model. The model uses rectangular elements, called areas, to hold the individual content elements, which can be images, text, other XSL FOs, or nothing. The following list describes the four basic types of areas: v Regions function as the highest level container. v Block areas represent block level elements, for example, paragraphs or list items. v Line areas represent a line of text inside of a block. v Inline areas represent parts of a line, for example, a single character, a footnote, or a mathematical equation. XSL FO tags created by IBM Toolbox for Java adhere to the XSL standards described the W3C recommendation. For more information about XSL, XSL FOs, and the W3C recommendation, see the following: Extensible Stylesheet Language (XSL) Version 1.0 Generating XSL FO source data When creating XSL FO source, HTMLDocument properties represent XSL FO tags that specify page size, orientation, and margins. Additionally, HTMLDocument retrieves from many HTML classes the corresponding XSL FO tags for that content element. After you use HTMLDocument to generate the XSL FO source, you can use an XSL formatter (for example, the XSLReportWriter class) to place the content elements on the pages of a document. HTMLDocument generates XSL FO source data in two major sections:
195
v The first section contains the <fo:root> and <fo:layout-master-set> XSL FO tags that hold general page layout information for page height, page width, and page margins. To specify the values for the layout information, use HTMLDocument set methods to set the values for the associated properties. v The second section contains the XSL FO <fo:page-sequence> tag that holds the individual content elements. To specify individual content elements, which are instances of HTML classes, retrieve the corresponding XSL FO tag from the HTML object. Make sure that for your content elements you use only HTML classes that have the getFoTag() method. Note: Trying to retrieve XSL FO tags from HTML classes that do not have the getFoTag() method results in a comment tag. For more information about the HTML classes that include methods for working with XSL FO tags, see the following Javadoc reference documentation: XSL FO-enabled classes on page 197 After you create an instance of HTMLDocument and set the layout properties, retrieve XSL FO tags from HTML objects by using the setUseFO(), getFoTag(), and getTag() methods. v You can use setUseFO() on either the HTMLDocument or the individual HTML objects. When you use setUseFO(), you can retrieve XSL FO tags by using HTMLDocument.getTag(). v Alternatively, you can use the getFoTag() method on either the HTMLDocument or the individual HTML objects. You might want to use this alternative method when you need to be able to generate both XSL FO and HTML source from the HTMLDocument or the HTML objects. Example: Using HTMLDocument After you create XSL FO source data, you need to convert that XSL FO data to a form that your users can view and print. The following examples show how to generate XSL FO source data (and HTML source) and convert the XSL FO source data to a PDF document by using the XSLReportWriter and Context classes: Example: Using HTMLDocument to generate both HTML source and XSL FO source on page 200 Example: Converting XSL FO source data to a PDF on page 198 Javadoc reference documentation For more information about the HTMLDocument class, see the following Javadoc reference documentation: HTMLDocument The following disclaimer applies to all of the IBM Toolbox for Java examples: Code example disclaimer IBM grants you a nonexclusive copyright license to use all programming code examples from which you can generate similar function tailored to your own specific needs. All sample code is provided by IBM for illustrative purposes only. These examples have not been thoroughly tested under all conditions. IBM, therefore, cannot guarantee or imply reliability, serviceability, or function of these programs.
196
All programs contained herein are provided to you "AS IS" without any warranties of any kind. The implied warranties of non-infringement, merchantability and fitness for a particular purpose are expressly disclaimed. XSL FO-enabled classes: This topic describes the IBM Toolbox for Java classes that are compatible with the HTMLDocument class. Many IBM Toolbox for Java HTML classes feature the following methods, which enable instances of those classes to work with HTMLDocument: v getFoTag() v getTag() v setUseFO() For more information about the HTMLDocument class and about the HTML classes that include methods for working with XSL FOs, see the following Javadoc reference documentation: v v v v v v v v v v v v v HTMLDocument BidiOrdering HTMLAlign HTMLHead HTMLHeading HTMLImage HTMLList HTMLListItem HTMLTable HTMLTableCaption HTMLTableCell HTMLTableHeader HTMLTableRow
v HTMLTagElement v OrderedList v UnorderedList Examples: Using HTMLDocument: The following examples show ways that you can use the HTMLDocument class to generate HTML and Extensible Stylesheet Language (XSL) Formatting Object (FO) source data. Example: Using HTMLDocument to generate both HTML source and XSL FO source The following example shows how to generate both HTML source data and XSL FO source data at the same time: Example: Using HTMLDocument to generate both HTML source and XSL FO source on page 200 Example: Converting XSL FO source data to a PDF After you create XSL FO source data, you need to convert that XSL FO data to a form that your users can view and print. The following example shows how to convert a file that contains XSL FO source data to a PDF document by using the XSLReportWriter and Context classes:
197
Example: Converting XSL FO source data to a PDF The following disclaimer applies to all of the IBM Toolbox for Java examples: Code example disclaimer IBM grants you a nonexclusive copyright license to use all programming code examples from which you can generate similar function tailored to your own specific needs. All sample code is provided by IBM for illustrative purposes only. These examples have not been thoroughly tested under all conditions. IBM, therefore, cannot guarantee or imply reliability, serviceability, or function of these programs. All programs contained herein are provided to you "AS IS" without any warranties of any kind. The implied warranties of non-infringement, merchantability and fitness for a particular purpose are expressly disclaimed. Example: Converting XSL FO source data to a PDF: This example program should not be used as the XSLReportProcessor class is no longer supported. Note: Read the Code example disclaimer for important legal information.
/////////////////////////////////////////////////////////////////////////////// // // Example: Converting XSL FO source to a PDF. // // This program uses the IBM Toolbox for Java ReportWriter classes to convert // XSL FO source data (created by using HTMLDocument) to a PDF. // // This example requires the following.jars to be in the classpath. // // composer.jar // outputwriters.jar // reportwriter.jar // x4j400.jar // xslparser.jar // // These JAR files are part of the IBM ToolBox for Java, and reside in directory // /QIBM/ProdData/HTTP/Public/jt400/lib on your server. // // You will also need the class definition for // org/apache/xerces/dom/NodeContainer, which resides // in directory /QIBM/ProdData/OS400/xml/lib. // // Command syntax: // ProcessXslFo FOfilename PDFfilename // /////////////////////////////////////////////////////////////////////////////// import java.io.FileInputStream; import java.io.FileOutputStream; import java.awt.print.Paper; import java.awt.print.PageFormat; import org.w3c.dom.Document; import com.ibm.xsl.composer.framework.Context; import com.ibm.as400.util.reportwriter.pdfwriter.PDFContext; import com.ibm.as400.util.reportwriter.processor.XSLReportProcessor;
198
public class ProcessXslFo { public static void main(String args[]) { if (args.length != 2) { System.out.println("Usage: java ProcessXslFo <fo file name> <pdf file name>"); System.exit(0); } try { String inName = args[0]; String outName = args[1]; /* Input. File containing XML FO. */ FileInputStream fin = null; /* Output. Which in this example will be PDF. */ FileOutputStream fout = null; try { fin = new FileInputStream(inName); fout = new FileOutputStream(outName); } catch (Exception e) { e.printStackTrace(); System.exit(0); } /* * Setup Page format. */ Paper paper = new Paper(); paper.setSize(612, 792); paper.setImageableArea(0, 0, 756, 936); PageFormat pageFormat = new PageFormat(); pageFormat.setPaper(paper); /* * Create a PDF context. Set output file name. */ PDFContext pdfContext = new PDFContext(fout, pageFormat); /* * Create XSLReportProcessor instance. */ XSLReportProcessor report = new XSLReportProcessor(pdfContext); /* * Open XML FO source. */ try { report.setXSLFOSource(fin); } catch (Exception e) { e.printStackTrace(); System.exit(0); } /* * Process the report.
IBM Toolbox for Java
199
*/ try { report.processReport(); } catch (Exception e) { e.printStackTrace(); System.exit(0); } } catch (Exception e) { e.printStackTrace(); System.exit(0); } /* exit */ System.exit(0); } }
Example: Using HTMLDocument to generate both HTML source and XSL FO source: This example uses the HTMLDocument class to generate HTML and XSL FO source data. Note: Read the Code example disclaimer for important legal information.
/////////////////////////////////////////////////////////////////////////////// // // Example: Using the Toolbox HTMLDocument Class // to generate both HTML and XSL FO source data. // // This program uses the HTMLDocument class to // generate two files: one that has HTML source and // another than has XSL FO source. // // Command syntax: // HTMLDocumentExample // /////////////////////////////////////////////////////////////////////////////// import import import import import com.ibm.as400.util.html.*; java.*; java.io.*; java.lang.*; java.beans.PropertyVetoException;
public class HTMLDocumentExample { public static void main (String[] args) { //Create the HTMLDocument that holds necessary document properties HTMLDocument doc = new HTMLDocument(); //Set page and margin properties. doc.setPageWidth(8.5); doc.setPageHeight(11); doc.setMarginTop(1); doc.setMarginBottom(1); doc.setMarginLeft(1); doc.setMarginRight(1); //Create a header for the page. HTMLHead head = new HTMLHead(); //Set the title for the header Numbers are in inches.
200
head.setTitle("This is the page header."); //Create several HTMLHeading h1 = HTMLHeading h2 = HTMLHeading h3 = HTMLHeading h4 = HTMLHeading h5 = HTMLHeading h6 = headings new HTMLHeading(1, new HTMLHeading(2, new HTMLHeading(3, new HTMLHeading(4, new HTMLHeading(5, new HTMLHeading(6, "Heading "Heading "Heading "Heading "Heading "Heading 1"); 2"); 3"); 4"); 5"); 6");
//Create some text that is printed from right to left. //Create BidiOrdering object and set the direction BidiOrdering bdo = new BidiOrdering(); bdo.setDirection(HTMLConstants.RTL); //Create some text HTMLText text = new HTMLText("This is Arabic text."); //Add the text to the bidi-ordering object bdo.addItem(text); // Create an UnorderedList. UnorderedList uList = new UnorderedList(HTMLConstants.SQUARE); // Create and set the data for UnorderedListItems. UnorderedListItem listItem1 = new UnorderedListItem(); UnorderedListItem listItem2 = new UnorderedListItem(); listItem1.setItemData(new HTMLText("First item")); listItem2.setItemData(new HTMLText("Second item")); // Add the list items to the UnorderedList. uList.addListItem(listItem1); uList.addListItem(listItem2); // Create an OrderedList. OrderedList oList = new OrderedList(HTMLConstants.SMALL_ROMAN); // Create the OrderedListItems. OrderedListItem olistItem1 = new OrderedListItem(); OrderedListItem olistItem2 = new OrderedListItem(); OrderedListItem olistItem3 = new OrderedListItem(); // Set the data in the OrderedListItems. olistItem1.setItemData(new HTMLText("First item")); olistItem2.setItemData(new HTMLText("Second item")); olistItem3.setItemData(new HTMLText("Third item")); // Add the list items to the OrderedList. oList.addListItem(olistItem1); oList.addListItem(olistItem2); // Add (nest) the unordered list to OrderedListItem2 oList.addList(uList); // Add another OrderedListItem to the OrderedList // after the nested UnorderedList. oList.addListItem(olistItem3); // Create a default HTMLTable object. HTMLTable table = new HTMLTable(); try { // Set the table attributes. table.setAlignment(HTMLTable.LEFT); table.setBorderWidth(1); // Create a default HTMLTableCaption object and set the caption text. HTMLTableCaption caption = new HTMLTableCaption(); caption.setElement("Customer Account Balances - January 1, 2000"); // Set the caption. table.setCaption(caption); // Create the table headers and add to the table. HTMLTableHeader account_header = new HTMLTableHeader(new HTMLText("ACCOUNT"));
IBM Toolbox for Java
201
HTMLTableHeader name_header = new HTMLTableHeader(new HTMLText("NAME")); HTMLTableHeader balance_header = new HTMLTableHeader(new HTMLText("BALANCE")); table.addColumnHeader(account_header); table.addColumnHeader(name_header); table.addColumnHeader(balance_header); // Add rows to the table. Each customer record represents a row in the table. int numCols = 3; for (int rowIndex=0; rowIndex< 5; rowIndex++) { HTMLTableRow row = new HTMLTableRow(); row.setHorizontalAlignment(HTMLTableRow.CENTER); HTMLText account = new HTMLText("000" + rowIndex); HTMLText name = new HTMLText("Customer" + rowIndex); HTMLText balance = new HTMLText("" + (rowIndex + 1)*200); row.addColumn(new HTMLTableCell(account)); row.addColumn(new HTMLTableCell(name)); row.addColumn(new HTMLTableCell(balance)); // Add the row to the table. table.addRow(row); } } catch(Exception e) { System.out.println("Problem creating table"); System.exit(0); } //Add the items to the HTMLDocument doc.addElement(head); doc.addElement(h1); doc.addElement(h2); doc.addElement(h3); doc.addElement(h4); doc.addElement(h5); doc.addElement(h6); doc.addElement(oList); doc.addElement(table); doc.addElement(bdo); //Print the fo tags to a file. try { FileOutputStream fout = new FileOutputStream("FOFILE.fo"); PrintStream pout = new PrintStream(fout); pout.println(doc.getFOTag()); } catch (Exception e) { System.out.println("Unable to write fo tags to FOFILE.fo"); } //Print the html tags to a file try { FileOutputStream htmlout = new FileOutputStream("HTMLFILE.html"); PrintStream phtmlout = new PrintStream(htmlout); phtmlout.println(doc.getTag()); } catch (Exception e) { System.out.println("Unable to write html tags to HTMLFILE.html");
202
} } }
203
v v v v v
FileFormInput: Represents a file input type, for an HTML form HiddenFormInput: Represents a hidden input type for an HTML form ImageFormInput: Represents an image input type for an HTML form. ResetFormInput: Represents a reset button input for an HTML form SubmitFormInput: Represents a submit button input for an HTML form
v TextFormInput: Represents a single line of text input for an HTML form where you define the maximum number of characters in a line. For a password input type, you use PasswordFormInput, which extends TextFormInput and represents a password input type for an HTML form v ToggleFormInput: Represents a toggle input type for an HTML form. The user can set or get the text label and specify whether the toggle should be checked or selected. The toggle input type can be one of two: RadioFormInput: Represents a radio button input type for an HTML form. Radio buttons may be placed in groups with the RadioFormInputGroup class; this creates a group of radio buttons where the user selects only one of the choices presented. CheckboxFormInput: Represents a checkbox input type for an HTML form where the user may select more than one from the choices presented, and where the checkbox is initialized as either checked or unchecked. FormInput Javadoc ToggleFormInput Javadoc RadioFormInputGroup Javadoc ButtonFormInput class: The ButtonFormInput class represents a button element for an HTML form. The following example shows you how to create a ButtonFormInput object:
ButtonFormInput button = new ButtonFormInput("button1", "Press Me", "test()"); System.out.println(button.getTag());
Related information ButtonFormInput Javadoc FileFormInput class: The IBM Toolbox for Java FileFormInput class represents a file input type in an HTML form. The following code example shows you how to create a new FileFormInput object
FileFormInput file = new FileFormInput("myFile"); System.out.println(file.getTag());
Related information FileFormInput Javadoc HiddenFormInput class: The IBM Toolbox for Java HiddenFormInput class represents a hidden input type in an HTML form. The following code example shows how to create a HiddenFormInput object:
204
In an HTML page, the HiddenInputType does not display. It sends the information (in this case the account number) back to the server. Related information HiddenFormInput Javadoc ImageFormInput class: The ImageFormInput class represents an image input type in an HTML form. You can retrieve and update many of the attributes for the ImageFormInput class by using the methods provided. v Get or set the source v Get or set the alignment v Get or set the height v Get or set the width Example: Creating an ImageFormInput object The following code example shows you how to create an ImageFormInput object:
ImageFormInput image = new ImageFormInput("myPicture", "myPicture.gif"); image.setAlignment(HTMLConstants.TOP); image.setHeight(81); image.setWidth(100);
Related information ImageFormInput Javadoc ResetFormInput class: The ResetFormInput class represents a reset button input type in an HTML form. The following code example shows you how to create a ResetFormInput object:
ResetFormInput reset = new ResetFormInput(); reset.setValue("Reset"); System.out.println(reset.getTag());
Related information ResetFormInput Javadoc SubmitFormInput class: The SubmitFormInput class represents a submit button input type in an HTML form. The following code example shows you how to create a SubmitFormInput object:
IBM Toolbox for Java
205
Related information SubmitFormInput Javadoc TextFormInput class: The TextFormInput class represents a single line text input type in an HTML form. The TextFormInput class provides methods that let you get and set the maximum number of characters a user can enter in the text field. The following example shows you how to create a new TextFormInput object:
TextFormInput text = new TextFormInput("userID"); text.setSize(40); System.out.println(text.getTag());
Related information TextFormInput Javadoc PasswordFormInput class: The PasswordFormInput class represents a password input field type in an HTML form. The following code example shows you how to create a new PasswordFormInput object:
PasswordFormInput pwd = new PasswordFormInput("password"); pwd.setSize(12); System.out.println(pwd.getTag());
Related information PasswordFormInput Javadoc RadioFormInput class: The RadioFormInput class represents a radio button input type in an HTML form. The radio button may be initialized as selected when constructed. A set of radio buttons with the same control name make a radio button group. The RadioFormInputGroup class creates radio button groups. Only one radio button within the group may be selected at any time. Also, a specific button may be initialized as selected when the group is constructed. The following code example shows you how to create a RadioFormInput object:
RadioFormInput radio = new RadioFormInput("age", "twentysomething", "Age 20 - 29", true); System.out.println(radio.getTag());
RadioFormInput Javadoc
206
RadioFormInputGroup Javadoc CheckboxFormInput class: The IBM Toolbox for Java CheckboxFormInput class represents a checkbox input type in an HTML form. The user may select more than one of the choices presented as checkboxes within a form. The following example shows you how to create a new CheckboxFormInput object:
CheckboxFormInput checkbox = new CheckboxFormInput("uscitizen", "yes", "textLabel", true); System.out.println(checkbox.getTag());
LayoutFormPanel class: The IBM Toolbox for Java LayoutFormPanel class represents a layout of form elements for an HTML form. You can use the methods provided by the LayoutFormPanel to add and remove elements from a panel or get the number of elements in the layout. You may choose to use one of two layouts: v GridLayoutFormPanel: Represents a grid layout of form elements for an HTML form v LineLayoutFormPanel: Represents a line layout of form elements for an HTML form LayoutFormPanel Javadoc GridLayoutFormPanel The GridLayoutFormPanel class represents a grid layout of form elements. You use this layout for an HTML form where you specify the number of columns for the grid. LineLayoutFormPanel class on page 208 The LineLayoutFormPanel class represents a line layout of form elements for an HTML form. The form elements are arranged in a single row within a panel. GridLayoutFormPanel: The GridLayoutFormPanel class represents a grid layout of form elements. You use this layout for an HTML form where you specify the number of columns for the grid. The following example creates a GridLayoutFormPanel object with two columns:
// Create a text form input element for the system. LabelFormElement sysPrompt = new LabelFormElement("System:"); TextFormInput system = new TextFormInput("System"); // Create a text form input element for the userId. LabelFormElement userPrompt = new LabelFormElement("User:"); TextFormInput user = new TextFormInput("User"); // Create a password form input element for the password. LabelFormElement passwordPrompt = new LabelFormElement("Password:"); PasswordFormInput password = new PasswordFormInput("Password"); // Create the GridLayoutFormPanel object with two columns and add the form elements. GridLayoutFormPanel panel = new GridLayoutFormPanel(2); panel.addElement(sysPrompt); panel.addElement(system); panel.addElement(userPrompt); panel.addElement(user); panel.addElement(passwordPrompt); panel.addElement(password);
207
// Create the submit button to the form. SubmitFormInput logonButton = new SubmitFormInput("logon", "Logon"); // Create HTMLForm object and add the panel to it. HTMLForm form = new HTMLForm(servletURI); form.addElement(panel); form.addElement(logonButton);
Related information GridLayoutFormPanel Javadoc LineLayoutFormPanel class: The LineLayoutFormPanel class represents a line layout of form elements for an HTML form. The form elements are arranged in a single row within a panel. Example: Using LineLayoutFormPanel This example creates a LineLayoutFormPanel object and adds two form elements.
CheckboxFormInput privacyCheckbox = new CheckboxFormInput("confidential", "yes", "Confidential", true); CheckboxFormInput mailCheckbox = new CheckboxFormInput("mailingList", "yes", "Join our mailing list", false); LineLayoutFormPanel panel = new LineLayoutFormPanel(); panel.addElement(privacyCheckbox); panel.addElement(mailCheckbox); String tag = panel.getTag();
Related information LineLayoutFormPanel Javadoc TextAreaFormElement class: The TextAreaFormElement class represents a text area element in an HTML form. You specify the size of the text area by setting the number of rows and columns. You can determine the size that a text area element is set for with the getRows() and getColumns() methods. You set the initial text within the text area with the setText() method. You use the getText() method to see what the initial text has been set to.
208
TextAreaFormElement Javadoc LabelFormElement class: The LabelFormElement class represents a label for an HTML form element. You use the LabelFormElement class to label elements of an HTML form such as a text area or password form input. The label is one line of text that you set using the setLabel() method. This text does not respond to user input and is there to make the form easier for the user to understand. Example: Using LabelFormElement The following code example shows you how to create a LabelFormElement object:
LabelFormElement label = new LabelFormElement("Account Balance"); System.out.println(label.getTag());
Related information LabelFormElement Javadoc SelectFormElement class: The SelectFormElement class represents a select input type for an HTML form. You can add and remove various options within the select element. SelectFormElement has methods available that allow you to view and change attributes of the select element: v Use setMultiple() to set whether or not the user can select more than one option v Use getOptionCount() to determine how many elements are in the option layout v Use setSize() to set the number of options visible within the select element and use getSize() to determine the number of visible options. The following example creates a SelectFormElement object with three options. The SelectFormElement object named list, is highlighted. The first two options added specify the option text, name, and select attributes. The third option added is defined by a SelectOption object.
SelectFormElement list = new SelectFormElement("list1"); SelectOption option1 = list.addOption("Option1", "opt1"); SelectOption option2 = list.addOption("Option2", "opt2", false); SelectOption option3 = new SelectOption("Option3", "opt3", true); list.addOption(option3); System.out.println(list.getTag());
209
<select name="list1"> <option value="opt1">Option1</option> <option value="opt2">Option2</option> <option value="opt3" selected="selected">Option3</option> </select>
Related reference SelectOption class The SelectOption class represents an option in an HTML SelectFormElement. You use the option form element in a select form. Related information SelectFormElement Javadoc SelectOption class: The SelectOption class represents an option in an HTML SelectFormElement. You use the option form element in a select form. Methods are provided that you can use to retrieve and set attributes within a SelectOption. For instance, you can set whether the option defaults to being selected. You can also set the input value it will use when the form is submitted. The following example creates three SelectOption objects within a select form. Each of the following SelectOption objects are highlighted. They are named option1, option2 and option3. The option3 object is initially selected.
SelectFormElement list = new SelectFormElement("list1"); SelectOption option1 = list.addOption("Option1", "opt1"); SelectOption option2 = list.addOption("Option2", "opt2", false); SelectOption option3 = new SelectOption("Option3", "opt3", true); list.addOption(option3); System.out.println(list.getTag());
Related reference SelectFormElement class on page 209 The SelectFormElement class represents a select input type for an HTML form. You can add and remove various options within the select element. Related information SelectOption Javadoc RadioFormInputGroup class: The RadioFormInputGroup class represents a group of RadioFormInput objects. A user can select only one of the RadioFormInput objects from a RadioFormInputGroup. The RadioFormInputGroup class methods allow you to work with various attributes of a group of radio buttons. With these methods, you can: v Add a radio button v Remove a radio button v Get or set the name of the radio group
210
HTMLHead class
The IBM Toolbox for Java HTMLHead class represents an HTML head tag. The head section of an HTML page features an opening and closing head tag that typically contains other tags. Typically, the head tag contains a title tag and possibly meta tags. Constructors for HTMLHead enable you to construct a head tag that is empty, that contains a title tag, or that contains a title tag and a meta tag. You can easily add title and meta tags to the empty HTMLHead object. Methods for the HTMLHead class include setting and getting the page title and the meta tags. Define the contents of the meta tags by using the HTMLMeta class. The following code shows one way to create an HTMLHead tag:
// Create an empty HTMLHead. HTMLHead head = new HTMLHead("My Main Page"); // Add the title. head.setTitle("My main page"); // Define your meta information and add it to HTMLHead. HTMLMeta meta = new HTMLMeta("Content-Type", "text/html; charset=iso-8859-1"); head.addMetaInformation(meta);
211
Related reference HTMLMeta class on page 216 The IBM Toolbox for Java HTMLMeta class represents meta-information used within an HTMLHead tag. Attributes in META tags are used when identifying, indexing, and defining information within the HTML document. Related information HTMLHead Javadoc
HTMLHeading class
The IBM Toolbox for Java HTMLHeading class represents an HTML heading. Each heading can have its own alignment and level from 1 (largest font, most importance) to 6. Methods for the HTMLHeading class include: v Get and set the text for the heading v Get and set the level of the heading v Get and set the alignment of the heading v Get and set the direction of the text interpretation v Get and set the language of the input element v Get a String representation of the HTMLHeading object
HTMLHyperlink class
The IBM Toolbox for Java HTMLHyperlink class represents an HTML hyperlink tag. You use the HTMLHyperlink class to create a link within your HTML page. You can get and set many attributes of hyperlinks with this class, including: v Get and set the Uniform Resource Identifier for the link v Get or set the title for the link v Get or set the target frame for the link The HTMLHyperlink class can print the full hyperlink with defined properties so that you can use the output in your HTML page. The following is an example for HTMLHyperlink:
// Create an HTML hyperlink to the IBM Toolbox for Java home page. HTMLHyperlink toolbox = new HTMLHyperlink("http://www.ibm.com/as400/toolbox", "IBM Toolbox for Java home page");
212
HTMLImage class
The HTMLImage class allows you to create image tags for your HTML page. The HTMLImage class provides methods that allow you to get and set image attributes, including the following: v Get or set the height of the image v Get or set the width of the image v Get or set the name of the image v Get or set the alternate text for the image v v v v Get or set the horizontal space around the image Get or set the vertical space around the image Get or set the absolute or relative reference to the image Retrieve a string representation of the HTMLImage object
The print statement produces the following tag on a single line. Text wrapping is for display purposes only.
<img src="http://myWebSite/picture.gif" alt="Alternate text for this graphic" height="94" width="105" />
HTMLList classes
The IBM Toolbox for Java HTMLList classes allow you to easily create lists within your HTML pages. These classes provide methods to get and set various attributes of the lists and the items within the lists. In particular, the parent class HTMLList provides a method to produce a compact list that displays items in as small a vertical space as possible. v Methods for HTMLList include: Compact the list Add and remove items from the list Add and remove lists from the list (making it possible to nest lists) v Methods for HTMLListItem include: Get and set the contents of the item Get and set the direction of the text interpretation
IBM Toolbox for Java
213
Get and set the language of the input element Use the subclasses of HTMLList and HTMLListItem to create your HTML lists: v v OrderedList and OrderedListItem UnorderedList and UnorderedListItem
For coding snippets, see the following examples: v Example: Creating ordered lists v Example: Creating unordered lists v Example: Creating nested lists
214
Example: Creating unordered lists The following example creates an unordered list:
// Create an UnorderedList. UnorderedList uList = new UnorderedList(HTMLConstants.SQUARE); // Create the UnorderedListItems. UnorderedListItem listItem1 = new UnorderedListItem(); UnorderedListItem listItem2 = new UnorderedListItem(); // Set the data in the UnorderedListItems. listItem1.setItemData(new HTMLText("First item")); listItem2.setItemData(new HTMLText("Second item")); // Add the list items to the UnorderedList. uList.addListItem(listItem1); uList.addListItem(listItem2); System.out.println(uList.getTag());
Example: Creating nested lists The following example creates a nested list:
// Create an UnorderedList. UnorderedList uList = new UnorderedList(HTMLConstants.SQUARE); // Create and set the data for UnorderedListItems. UnorderedListItem listItem1 = new UnorderedListItem(); UnorderedListItem listItem2 = new UnorderedListItem(); listItem1.setItemData(new HTMLText("First item")); listItem2.setItemData(new HTMLText("Second item")); // Add the list items to the UnorderedList. uList.addListItem(listItem1); uList.addListItem(listItem2); // Create an OrderedList. OrderedList oList = new OrderedList(HTMLConstants.SMALL_ROMAN); // Create the OrderedListItems. OrderedListItem listItem1 = new OrderedListItem(); OrderedListItem listItem2 = new OrderedListItem(); OrderedListItem listItem3 = new OrderedListItem(); // Set the data in the OrderedListItems. listItem1.setItemData(new HTMLText("First item")); listItem2.setItemData(new HTMLText("Second item")); listItem3.setItemData(new HTMLText("Third item")); // Add the list items to the OrderedList. oList.addListItem(listItem1); oList.addListItem(listItem2); // Add (nest) the unordered list to OrderedListItem2 oList.addList(uList);
215
// Add another OrderedListItem to the OrderedList // after the nested UnorderedList. oList.addListItem(listItem3); System.out.println(oList.getTag());
HTMLMeta class
The IBM Toolbox for Java HTMLMeta class represents meta-information used within an HTMLHead tag. Attributes in META tags are used when identifying, indexing, and defining information within the HTML document. Attributes of the META tag include: v NAME - the name associated with the contents of the META tag v CONTENT - values associated with the NAME attribute v HTTP-EQUIV - information gathered by HTTP servers for response message headers v LANG - the language v URL - used to redirect users from the current page to another URL For example, to help search engines determine the contents of a page, you might use the following META tag:
<META name="keywords" lang="en-us" content="games, cards, bridge">
You can also use HTMLMeta to redirect a user from one page to another. Methods for the HTMLMeta class include: v Get and set the NAME attribute v Get and set the CONTENT attribute v Get and set the HTTP-EQUIV attribute v Get and set the LANG attribute v Get and set the URL attribute
216
<meta name="keywords" content="games, cards, bridge"> <meta http-equiv="Expires" content="Mon, 01 Jun 2000 12:00:00 GMT">
HTMLParameter class
The HTMLParameter class represents the parameters you can use with the HTMLServlet class. Each parameter has its own name and value. Methods for the HTMLParameter class include: v Get and set the name of the parameter v Get and set the value of the parameter Example: Creating HTMLParameter tags The following example creates an HTMLParameter tag:
// Create an HTMLServletParameter. HTMLParameter parm = new HTMLParameter ("age", "21"); System.out.println(parm);
HTMLServlet class
The HTMLServlet class represents a server-side include. The servlet object specifies the name of the servlet and, optionally, its location. You may also choose to use the default location on the local system. The HTMLServlet class works with the HTMLParameter class, which specifies the parameters available to the servlet. Methods for the HTMLServlet class include: v Add and remove HTMLParameters from the servlet tag v Get and set the location of the servlet v Get and set the name of the servlet v Get and set the alternate text of the servlet
217
<servlet name="myServlet" codebase="http://server:port/dir"> <param name="parm1" value="value1"> <param name="parm2" value="value2"> The Web server providing this page does not support the SERVLET tag. </servlet>
HTMLServlet Javadoc HTMLParameter class on page 217 The HTMLParameter class represents the parameters you can use with the HTMLServlet class. Each parameter has its own name and value.
The getTag() method above gives the output of the example: <td align="center"><a href="http://www.ibm.com">IBM Home Page</a></td> HTMLTableCell Javadoc HTMLTagElement Javadoc
218
HTMLTableRow class: The HTMLTableRow class creates a row within a table. This class provides various methods for getting and setting attributes of a row. The methods of the HTMLTableRow class allow you to: v v v v v Add or remove a column from the row Get column data at the specified column Index Get column index for the column with the specified cell. Get the number of columns in a row Set horizontal and vertical alignments
Related information HTMLTableRow Javadoc HTMLTableHeader class: The HTMLTableHeader class inherits from the HTMLTableCell class. It creates a specific type of cell, the header cell, giving you a <th> cell instead of a <td> cell. Like the HTMLTableCell class, you call various methods in order to update or retrieve attributes of the header cell. The following is an example for HTMLTableHeader:
// Create the table headers. HTMLTableHeader account_header = new HTMLTableHeader(new HTMLText("ACCOUNT")); HTMLTableHeader name_header = new HTMLTableHeader(new HTMLText("NAME")); HTMLTableHeader balance_header = new HTMLTableHeader(); HTMLText balance = new HTMLText("BALANCE"); balance_header.setElement(balance); // Add the table headers to an HTMLTable object (assume that the table already exists). table.addColumnHeader(account_header); table.addColumnHeader(name_header); table.addColumnHeader(balance_header);
Related information HTMLTableHeader Javadoc HTMLTableCaption class: The HTMLTableCaption class creates a caption for your HTML table. The class provides methods for updating and retrieving the attributes of the caption. For example, you can use the setAlignment() method to specify to which part of the table the caption should be aligned.
IBM Toolbox for Java
219
When you use this tag in an HTML page, it looks like this: IBM Related information HTMLText Javadoc
HTMLTree classes
The HTMLTree class allows you to easily set up a hierarchical tree of HTML elements that you can use in HTML pages. This class provides methods to get and set various attributes of the tree, in addition to methods allowing you to: v Get and set the HTTP Servlet Request v Add an HTMLTreeElement or FileTreeElement to the tree v Remove an HTMLTreeElement or FileTreeElement from the tree
220
Related information HTMLTree Javadoc Example: Creating a traversable integrated file system tree: The following example is made of three files that, together, show how you can create a traversable integrated file system tree. The example uses frames to display an HTMLTree and FileListElement in a servlet. v FileTreeExample.java - generates the HTML frames and starts the servlet v TreeNav.java - builds and manages the tree v TreeList.java - displays the contents of selections made in the TreeNav.java class HTMLTreeElement class: The HTMLTreeElement class represents an hierarchical element within an HTMLTree or other HTMLTreeElements. Many tree element attributes can be retrieved or updating using methods that are provided in the HTMLTreeElement class. Some of the actions you can do with these methods are: v Get or set the visible text of the tree element v Get or set the URL for the expanded and collapsed icon v Set whether the tree element will be expanded The following example creates an HTMLTreeElement object and displays the tag:
// Create an HTMLTree. HTMLTree tree = new HTMLTree(); // Create parent HTMLTreeElement. HTMLTreeElement parentElement = new HTMLTreeElement(); parentElement.setTextUrl(new HTMLHyperlink("http://myWebPage", "My Web Page")); // Create HTMLTreeElement Child. HTMLTreeElement childElement = new HTMLTreeElement(); childElement.setTextUrl(new HTMLHyperlink("http://anotherWebPage", "Another Web Page")); parentElement.addElement(childElement); // Add the tree element to the tree. tree.addElement(parentElement); System.out.println(tree.getTag());
The getTag() method in the above example generates HTML tags like the following:
<table cellpadding="0" cellspacing="3"> <tr> <td><font color="#0000FF"><u>-</u></font> </td> <td><font color="#0000FF"><u>My Web Page</u></font></td> </tr> <tr> <td> </td> <td> <table cellpadding="0" cellspacing="3"> <tr> <td><font color="#0000FF"><u>-</u></font> </td> <td><font color="#0000FF"><u>Another Web Page</u></font> </td> </tr>
221
Related information HTMLTreeElement Javadoc FileTreeElement class: The IBM Toolbox for Java FileTreeElement class represents the Integrated File System within an HTMLTree view. Many tree element attributes can be retrieved or updating using methods that are provided in the HTMLTreeElement class. You can also get and set the name and path of NetServer shared drives. Some of the actions these methods enable you to perform are: v Get or set the URL for the expanded and collapsed icon (inherited method) v Set whether the tree element will be expanded (inherited method) v Get or set the name of the NetServer shared drive v Get or set the path of the NetServer shared drive Example: Using FileTreeElement The following example creates a FileTreeElement object and displays the tag:
// Create an HTMLTree. HTMLTree tree = new HTMLTree(); // Create a URLParser object. URLParser urlParser = new URLParser(httpServletRequest.getRequestURI()); // Create an AS400 object. AS400 system = new AS400(mySystem, myUserId, myPassword); // Create an IFSJavaFile object. IFSJavaFile root = new IFSJavaFile(system, "/QIBM"); // Create a DirFilter object and get the directories. DirFilter filter = new DirFilter(); File[] dirList = root.listFiles(filter); for (int i=0; i < dirList.length; i++) { // Create a FileTreeElement. FileTreeElement node = new FileTreeElement(dirList[i]); // Set the Icon URL. ServletHyperlink sl = new ServletHyperlink(urlParser.getURI()); sl.setHttpServletResponse(resp); element.setIconUrl(sl); // Add the FileTreeElement to the tree. tree.addElement(element); } System.out.println(tree.getTag());
222
Related information FileTreeElement Javadoc FileListElement class: The IBM Toolbox for Java FileListElement class allows you to create a file list element, which represents the contents of an integrated file system directory. You can use the FileListElement object to represent the contents of a NetServer shared drive by getting and setting the name and path of NetServer shared drives. The FileListElement class provides methods that allow you to: v List and sort the elements of the file list v Get and set the HTTP Servlet Request v Get and set the FileListRenderer v Get and set the HTMLTable with which to display the file list v Get and set the name of a NetServer shared drive v Get and set the path of a NetServer shared drive You can use the FileListElement class with other classes in the html package: v With a FileListRenderer, you can specify how you want to display the list of files v With the FileTreeElement class, you can create a traversable list of integrated file system files or NetServer shared files Example: Using FileListElement to create a traversable integrated file system tree The following example shows how you can use the FileListElement class with HTMLTree classes (FileTreeElement and HTMLTreeElement) to create a traversable integrated file system tree. The example also includes code for setting the path of a NetServer shared drive. Example: Creating a traversable integrated file system tree on page 221 Related information FileListElement Javadoc FileTreeElement Javadoc HTMLTreeElement Javadoc FileListRenderer class: The IBM Toolbox for Java FileListRenderer class renders any field for File objects (directories and files) in a FileListElement. The FileListRenderer class offers methods that allow you to perform the following actions: v Get the name of the directory v Get the name of the file v Get the name of the parent directory v Return the row data that you want to display in the FileListElement This example creates an FileListElement object with a renderer:
// Create a FileListElement. FileListElement fileList = new FileListElement(sys, httpservletrequest);
223
// Set the renderer specific to this servlet, which extends // FileListRenderer and overrides applicable methods. fileList.setRenderer(new myFileListRenderer(request));
If you don't want to use the default renderer, you can extend FileListRenderer and override methods or create new ones. For example, you might want to ensure that you prevent passing the names of specific directories or files with certain extensions to the FileListElement. By extending the class and overriding the appropriate method, you can return null for these files and directories, ensuring that they are not displayed. To fully customize the rows within a FileListElement, use the getRowData() method. An example of customizing row data using getRowData() might be adding a column to the row data or rearranging the columns. When the default behavior of FileListRenderer is satisfactory, you need no additional programming because the FileListElement class creates a default FileListRenderer. Related reference FileListElement class on page 223 The IBM Toolbox for Java FileListElement class allows you to create a file list element, which represents the contents of an integrated file system directory. Related information FileListRenderer Javadoc
ReportWriter classes
The com.ibm.as400.util.reportwriter package provides classes that enable you to easily access and format data from an XML source file or data produced by servlets or JavaServer Pages. The reportwriter package is a convenient way to name three different but related packages: v com.ibm.as400.util.reportwriter.pclwriter v com.ibm.as400.util.reportwriter.pdfwriter v com.ibm.as400.util.reportwriter.processor These packages include a variety of classes that allow you to format XML data streams and generate reports in those formats. Make sure you have the necessary JAR files in your CLASSPATH, including an XML parser and an XSLT processor. For more information, see the following pages: v JAR files Context classes (in the pclwriter and pdfwriter packages) define methods that the ReportProcessor classes need to render XML and JSP data in the chosen format: v Use PCLContext in combination with a ReportWriter class to generate a report in the Hewlett Packard Printer Control Language (PCL) format. v Use PDFContext in combination with a ReportWriter class to generate a report in the Adobe Portable Document Format (PDF). ReportProcessor classes (in the processor package) enable you to generate formatted reports from information your application gathers from Java servlets and JavaServer Pages (JSPs). v Use the JSPReportProcessor class to retrieve data from servlets and JSP pages to produce reports in the available formats (contexts).
Context classes
The IBM Toolbox for Java context classes support specific data formats, that, in combination with the OutputQueue and SpooledFileOutputStream classes, enable the ReportWriter classes to generate reports in that format and put those reports in a spool file.
224
Your application only has to create an instance of the Context class, which the ReportWriter classes then use to generate the reports. Your application never directly calls any of the methods in either Context class. The PCLContext and PDFContext methods are meant to be used internally by the ReportWriter classes. Constructing an instance of the Context class requires an OutputStream (from the java.io package) and a PageFormat (from the java.awt.print package). Example: Using JSPReportProcessor with PDFContext show how you can construct and use the Context classes with other ReportWriter classes to generate reports. OutputQueue Javadoc SpooledFileOutputStream Javadoc ReportWriter classes on page 224 The com.ibm.as400.util.reportwriter package provides classes that enable you to easily access and format data from an XML source file or data produced by servlets or JavaServer Pages. Example: Using XSLReportProcessor with PCLContext on page 631 This example should not be used as the XSLReportProcessor class is no longer supported. Example: Using JSPReportProcessor with PDFContext on page 627 This example uses the JSPReportProcessor and the PDFContext classes to obtain data from a specified URL and convert the data to the PDF format. The data is then streamed to a file as a PDF document.
JSPReportProcessor class
The JSPReportProcessor class enables you to create a document or report from the contents of a JavaServer Page (JSP) or Java servlet. Use this class to obtain a JSP or servlet from a given URL and create a document from the contents. The JSP or servlet must provide the document data, including XSL formatting objects. You must specify the output context and the JSP input data source before you can generate any pages of the document. You can then convert the report data to a specified output data stream format. The JSPReportProcessor class allows you to: v Process the report v Set a URL as the template The following examples show how you can use the JSPReportProcessor and the PDFContext classes to generate a report. The examples include both the Java and the JSP code, which you can view by using the following links. You can also download a ZIP file that contains the example JSP, XML, and XSL source files for the JSPReportProcessor examples: v Example: Using JSPReportProcessor with PDFContext on page 627 v Example: JSPReportProcessor sample JSP file on page 628 Java Server Pages technology
XSLReportProcessor class
The XSLReportProcessor class is no longer supported and should not be used. The XSLReportProcessor class enables you to create a document or report by transforming and formatting your XML source data using an XSL stylesheet. Use this class to create the report by using an XSL stylesheet that contains XSL formatting objects (FOs), which must conform to the XSL specification. You then use a Context class to convert the report data to a specified output data stream format. The XSLReportProcessor class allows you to: v Set the XSL stylesheet v Set the XML data source v Set the XSL FO source
IBM Toolbox for Java
225
v Process a report
Examples
The following examples show how you can use the XSLReportProcessor and the PCLContext classes to generate a report. The examples include the Java, XML, and XSL code, which you can view by using the following links. You can also download a zip file that contains the example XML, XSL, and JSP source files for both the XSLReportProcessor and JSPReportProcessor examples: v Example: Using XSLReportProcessor with PCLContext v Example: XSLReportProcessor sample XML file v Example: XSLReportProcessor sample XSL file For more information about XML and XSL, see the XML Toolkit topic in the Information Center.
Resource classes
The Resource package and its classes have been deprecated. You are advised to use the Access package instead. The com.ibm.as400.resource package provides a generic framework for working with various AS400 objects and lists. This framework provides a consistent programming interface to all such objects and lists. The resource package includes the following classes: v Resource - an object that represents a system resource, such as a user, printer, job, message, or file. Concrete subclasses of resource include: RIFSFile RJavaProgram RJob RPrinter RQueuedMessage RSoftwareResource RUser Note: The NetServer classes in the access package are also concrete subclasses of Resource. v ResourceList - an object that represents a list of system resources, such as a list of users, printers, jobs, messages, or files. Concrete subclasses of resource include: RIFSFileList RJobList RJobLog RMessageQueue RPrinterList RUserList v Presentation - an object that allows you to present information about resource objects, resource lists, attributes, selections, and sorts to end users
226
Resource Resource is an abstract class that provides generic access to the attributes of any resource. Every attribute is identified using an attribute ID, and any given subclass of Resource will normally document the attribute IDs that it supports. Resource provides only read access to the attribute values. IBM Toolbox for Java provides the following resource objects: v RIFSFile - represents a file or directory in the integrated file system v RJavaProgram - represents a Java program on the server v RJob - represents an IBM i job v RPrinter - represents an IBM i printer v RQueuedMessage - represents a message in an IBM i message queue or job log v RSoftwareResource - represents a licensed program on the system v RUser - represents an IBM i user ChangeableResource The ChangeableResource abstract class, a subclass of Resource, adds the ability to change attribute values of a system resource. Attribute changes are cached internally until they are committed or canceled. This allows you to change many attribute values at once. Note: The NetServer classes in the access package are also concrete subclasses of Resource and ChangeableResource.
Examples
The following examples show how you can directly use concrete subclasses of Resource and ChangeableResource, and also how generic code can work with any Resource or ChangeableResource subclass. v Retrieving an attribute value from RUser, a concrete subclass of Resource v Setting attribute values for RJob, a concrete subclass of ChangeableResource v Using generic code to access resources
Resource lists
The Resource package and its classes have been deprecated. You are advised to use the Access package instead. The com.ibm.as400.resource.ResourceList class represents a list of system resources. This is an abstract class which provides generic access to the contents of the list. IBM Toolbox for Java provides the following resource lists: v RIFSFileList - represents a list of files and directories in the integrated file system v RJobList - represents a list of system jobs v RJobLog - represents a list of messages in a system job log v RMessageQueue - represents a list of messages in a system message queue v RPrinterList - represents a list of system printers v RUserList - represents a list of system users
227
A resource list is always either open or closed. The resource list must be open in order to access its contents. In order to provide immediate access to the contents of the list and manage memory efficiently, most resource lists are loaded incrementally. Resource lists allow you to: v Open the list v Close the list v Access a specific Resource from the list v Wait for a particular resource to load v Wait for the complete resource list to load You can also filter resource lists by using selection values. Every selection value is identified using a selection ID. Similarly, resource lists can be sorted using sort values. Every sort value is identified using a sort ID. Any given subclass of ResourceList will normally document the selection IDs and sort IDs that it supports.
Examples
The following examples show various ways of working with resource lists: v Example: Getting and printing the contents of a ResourceList v Example: Using generic code to access a ResourceList v Example: Presenting a resource list in a servlet (HTML table)
Presentation class
The Resource package and its classes have been deprecated. You are advised to use the Access package instead. Every resource object, resource list, and meta data object has an associated com.ibm.as400.resource.Presentation object that provides translated information, such as the name, full name, and icon. Example: Printing a resource list and its sort values using their Presentations You can use the Presentation information to present resource objects, resource lists, attributes, selections, and sorts to end users in text format.
void printCurrentSort(ResourceList resourceList) throws ResourceException { // Get the presentation for the ResourceList and print its full name. Presentation resourceListPresentation = resourceList.getPresentation(); System.out.println(resourceListPresentation.getFullName());
228
// Get the current sort value. Object[] sortIDs = resourceList.getSortValue(); // Print each sort ID. for(int i = 0; i < sortIDs.length; ++i) { ResourceMetaData sortMetaData = resourceList.getSortMetaData(sortIDs[i]); System.out.println("Sorting by " + sortMetaData.getName()); } }
Security classes
You use the IBM Toolbox for Java security classes to provide secured connections to a server, verify a user's identity, and associate a user with the operating system thread when running on the local server. The security services included are: v Communications infrastructure using Java Secure Socket Extension (JSSE) provides secure connections both by encrypting the data exchanged between a client and a server session and by performing server authentication. v Authentication Services provide the ability to: Authenticate a user identity and password against the IBM i user registry. Ability to assign an identity to the current IBM i thread.
229
Setting up IBM i to use SSL: To set up your system to use SSL with IBM Toolbox for Java, complete the following steps. 1. Get and configure the server certificate. 2. Apply the certificate to the following systems that are used by IBM Toolbox for Java: v QIBM_OS400_QZBS_SVR_CENTRAL v QIBM_OS400_QZBS_SVR_DATABASE v QIBM_OS400_QZBS_SVR_DTAQ v QIBM_OS400_QZBS_SVR_NETPRT v QIBM_OS400_QZBS_SVR_RMTCMD v QIBM_OS400_QZBS_SVR_SIGNON v QIBM_OS400_QZBS_SVR_FILE v QIBM_OS400_QRW_SVR_DDM_DRDA Getting and configuring server certificates Before you get and configure your server certificate, you need to install the following products: (5770-DG1) licensed program v IBM HTTP Server v Base operating system option 34 (Digital Certificate Manager) The process you follow to get and configure your server certificate depends on the kind of certificate you use: v If you get a certificate from a trusted authority (such as VeriSign, Inc., or RSA Data Security, Inc.), install the certificate on the system then apply it to the host servers. v If you choose not to use a certificate from a trusted authority, you can build your own certificate to be used on the system. Build the certificate by using Digital Certificate Manager: 1. Create the certificate authority on the system. See the Information Center topic Acting as your own CA. 2. Create a system certificate from the certificate authority that you created. 3. Assign which host servers will use the system certificate that you created.
Authentication services
Classes are provided by the IBM Toolbox for Java that interact with the security services provided by IBM i. Specifically, support is provided to authenticate a user identity, sometimes referred to as a principal, and password against the IBM i user registry. A credential representing the authenticated user can then be established. You can use the credential to alter the identity of the current IBM i thread to perform work under the authorities and permissions of the authenticated user. In effect, this swap of identity results in the thread acting as if a signon was performed by the authenticated user.
230
To use Kerberos tickets, set only the system name (and not the password) into the AS400 object. The user identity is retrieved through the JGSS framework. You can set only one means of authentication in an AS400 object at a time. Setting the password clears any Kerberos ticket or profile token. To use profile tokens, use the getProfileToken() methods to retrieve instances of the ProfileTokenCredential class. Think of profile tokens as a representation of an authenticated user profile and password for a specific server. Profile tokens expire based on time, up to one hour, but can be refreshed in certain cases to provide an extended life span. Note: If you use the ProfileTokenCredential class, make sure to review the information at the bottom of this page that discuss the methods for setting tokens. The following example creates a system object and uses that object to generate a profile token. The example then uses the profile token to create another system object, and uses the second system object to connect to the command service:
AS400 system = new AS400("mySystemName", "MYUSERID", "MYPASSWORD"); ProfileTokenCredential myPT = system.getProfileToken(); AS400 system2 = new AS400("mySystemName", myPT); system2.connectService(AS400.COMMAND);
231
v setToken(String name, int passwordSpecialValue) The ProfileTokenCredential class includes the following static constants for password special value integers: v ProfileTokenCredential.PW_NOPWD: indicates *NOPWD v ProfileTokenCredential.PW_NOPWDCHK: indicates *NOPWDCHK To specify a user profile password as a String, use one of the following methods: v setTokenExtended(AS400Principal principal, String password) v setTokenExtended(String name, String password) The setTokenExended methods do not allow you to pass password special value strings as the password parameter. For example, these methods do not allow a password string of *NOPWD. For more information, see the ProfileTokenCredential Javadoc reference information.
Example
Refer to this code for an example of how to use a profile token credential to swap the IBM i thread identity and perform work on behalf of a specific user. AS400 Javadoc ProfileTokenCredential Javadoc
Servlet classes
The servlet classes that are provided with IBM Toolbox for Java work with the access classes, which are located on the Webserver, to give you access to information located on the server. You decide how to use the servlet classes to assist you with your own servlet projects. The following diagram shows how the servlet classes work between the browser, webserver, and IBM i data. A browser connects to the webserver that is running the servlet. jt400Servlet.jar and jt400.jar files reside on the webserver because the servlet classes use some of the access classes to retrieve the data and the HTML classes to present the data. The webserver is connected to the server where the data is. Figure 1: How servlets work
Long description of Figure 1: How servlets work (rzahh585.gif) on page 233 Note: The jt400Servlet.jar file includes both the HTML and Servlet classes. You must update your CLASSPATH to point to both jt400Servlet.jar and jt400.jar if you want to use classes in the com.ibm.as400.util.html and com.ibm.as400.util.servlet packages. For more information about servlets in general, see the reference section.
232
Description
The figure is composed of the following: v An image on the left of a personal computer, labeled 'Browser,' that represents an instance of a browser running on a personal computer. v An image of an IBM i server on the right, labeled 'System i Data,' that represents the location of the data that you want the servlet to access. v An image of an IBM i server in the middle (between the other two images), labeled 'WebServer,' that represents the Web server. Several labeled shapes on the WebServer image indicate files or functions that reside on the Web server: A green oval labeled Servlet that represents the location of the servlet code. A tan circle labeled jt400Servlet that indicates the location of the jt400Servlet.jar file. A tan circle labeled jt400 that indicates the location of the jt400.jar file. Note: The Web server does not have to be on an IBM i server, but it can be, and can even be the same server as that indicated by the System i Data image. v Lines that connect the images together. A line labeled HTML connects the Browser (the left image) to a Servlet (the green oval) on the Web server (middle image). The line is labeled HTML because servlets most often use HTML to 'serve' data to the browser. The Web server is running two IBM Toolbox for Java JAR files (the tan circles), jt400Servlet.jar and jt400.jar. The classes in jt400Servlet.jar, along with the classes in jt400.jar, enable the Web server to run a servlet that easily connects to servers that contain IBM i data (the right image). The line with arrowheads on both ends that connects the two images indicates this connection.
Authentication classes
Two classes in the servlet package perform authentication for servlets, AuthenticationServlet and AS400Servlet. AuthenticationServlet class AuthenticationServlet is an HttpServlet implementation that performs basic authentication for servlets. Subclasses of AuthenticationServlet override one or more of the following methods: v Override the validateAuthority() method to perform the authentication (required) v Override the bypassAuthentication() method so that the subclass authenticates only certain requests v Override the postValidation() method to allow additional processing of the request after authentication The AuthenticationServlet class provides methods that allow you to: v Initialize the servlet v Get the authenticated user ID v Set a user ID after bypassing authentication v Log exceptions and messages AS400Servlet class
IBM Toolbox for Java
233
The AS400Servlet class is an abstract subclass of AuthenticationServlet that represents an HTML servlet. You can use a connection pool to share connections and manage the number of connections to the server that a servlet user can have. The AS400Servlet class provides methods that allow you to: v Validate user authority (by overriding the validateAuthority() method of the AuthenticationServlet class) v Connect to a system v Get and return connection pool objects to and from the pool v Close a connection pool v Get and set the HTML document head tags v Get and set the HTML document end tags For more information about servlets in general, see the reference section. AuthenticationServlet Javadoc AS400Servlet Javadoc
RowData class
The RowData class is an abstract class that provides a way to describe and access a list of data. The RowData classes allow you to: v Get and set the current position v Get the row data at a given column using the getObject() method v Get the meta data for the row v Get or set the properties for an object at a given column v Get the number of rows in the list using the length() method. RowData position There are several methods that allow you to get and set the current position within a list. The following table lists both the set and get methods for the RowData classes.
Set methods absolute() afterLast() beforeFirst() first() last() next() previous() relative() Get methods getCurrentPosition() isAfterLast() isBeforeFirst() isFirst() isLast()
Related information RowData Javadoc ListRowData class: The IBM Toolbox for Java ListRowData class represents a list of data in table form. In the table, each row contains a finite number of columns determined by the ListMetaData object and each column within a row contains an individual data item. The data can be a directory in the integrated file system, a list of jobs, a list of printers, or a variety of other data. The ListRowData class allows you to do the following: v Add and remove rows to and from the result list.
234
v Get and set the row v Get information about the list's columns with the getMetaData() method v Set column information with the setMetaData() method The ListRowData class represents a list of data. ListRowData can represent many types of information, including the following, through IBM Toolbox for Java access classes: v v v v v v A directory in the integrated file system A list of jobs A list of messages in a message queue A list of users A list of printers A list of spooled files
Example The following example shows how the ListRowData and HTMLTableConverter classes work. The example shows the Java code, HTML code, and HTML look and feel. Example: Using ListRowData on page 650 ListRowData Javadoc RecordListRowData class: The IBM Toolbox for Java RecordListRowData class allows you to do the following: v Add and remove rows to and from the record list. v Get and set the row v Set the record format with the setRecordFormat method v Get the record format The RecordListRowData class represents a list of records. A record can be obtained from the server in different formats, including: v A record to be written to or read from a server file v An entry in a data queue v The parameter data from a program call v Any data returned that needs to be converted between the server format and Java format This example shows you how RecordListRowData and HTMLTableConverter work. It shows the java code, HTML code, and HTML look and feel. Related information RecordListRowData Javadoc ResourceListRowData class: The IBM Toolbox for Java ResourceListRowData class represents a resource list of data. Use ResourceListRowData objects to represent any implementation of the ResourceList interface. Resource lists are formatted into a series of rows, where each row contains a finite number of columns determined by the number of column attribute IDs. Each column within a row contains an individual data item. The ResourceListRowData class offers methods that enable you to perform the following actions:
IBM Toolbox for Java
235
v v v v v
Get and set column attribute IDs Get and set the resource list Retrieve the number of rows in the list Get the column data for the current row Get the property list of the data object
v Get the metadata for the list Example: Presenting a resource list in a servlet Code example disclaimer The following disclaimer applies to all of the IBM Toolbox for Java examples: IBM grants you a nonexclusive copyright license to use all programming code examples from which you can generate similar function tailored to your own specific needs. All sample code is provided by IBM for illustrative purposes only. These examples have not been thoroughly tested under all conditions. IBM, therefore, cannot guarantee or imply reliability, serviceability, or function of these programs. All programs contained herein are provided to you "AS IS" without any warranties of any kind. The implied warranties of non-infringement, merchantability and fitness for a particular purpose are expressly disclaimed. Related reference Resource lists on page 227 The Resource package and its classes have been deprecated. You are advised to use the Access package instead. Related information ResourceListRowData Javadoc SQLResultSetRowData class: The SQLResultSetRowData class represents an SQL result set as a list of data. This data is generated by an SQL statement through JDBC. With methods provided, you can get set the result set metadata. This example shows you how ListRowData and HTMLTableConverter work. It shows the Java code, HTML code, and HTML look and feel. Related reference JDBC classes on page 60 JDBC is an application programming interface (API) included in the Java platform that enables Java programs to connect to a wide range of databases. Related information SQLResultSetRowData Javadoc
RowMetaData classes
The RowMetaData class defines an interface that you use to find out information about the columns of a RowData object. With the RowMetaData classes you can do the following: v Get the number of columns v Get the name, type, or size of the column v Get or set the column label
236
v Get the precision or scale of the column data v Determine if the column data is text data Related information RowMetaData Javadoc ListMetaData class: The IBM Toolbox for Java ListMetaData class lets you get information about and change settings for the columns in a ListRowData class. It uses the setColumns() method to set the number of columns, clearing any previous column information. Alternatively, you can also pass the number of columns when you set the constructor's parameters. Example The following example shows how ListMetaData, ListRowData and HTMLTableConverter work. It shows the Java code, HTML code, and HTML look and feel. Example: Using ListRowData on page 650 ListMetaData Javadoc ListRowData class on page 234 The IBM Toolbox for Java ListRowData class represents a list of data in table form. In the table, each row contains a finite number of columns determined by the ListMetaData object and each column within a row contains an individual data item. The data can be a directory in the integrated file system, a list of jobs, a list of printers, or a variety of other data. RecordFormatMetaData class: The RecordFormatMetaData makes use of the IBM Toolbox for Java RecordFormat class. It allows you to provide the record format when you set the constructor's parameters or use the get set methods to access the record format. The following example shows you how to create a RecordFormatMetaData object:
// Create a RecordFormatMetaData object from a sequential file's record format. RecordFormat recordFormat = sequentialFile.getRecordFormat(); RecordFormatMetaData metadata = new RecordFormatMetaData(recordFormat); // Display the file's column names. int numberOfColumns = metadata.getColumnCount(); for (int column=0; column < numberOfColumns; column++) { System.out.println(metadata.getColumnName(column)); }
Related information RecordFormatMetaData Javadoc RecordFormat Javadoc SQLResultSetMetaData class: The SQLResultSetMetaData class returns information about the columns of an SQLResultSetRowData object. You can either provide the result set when you set the constructor's parameters or use the get and set methods to access the result set meta data. The following example shows you how to create an SQLResultSetMetaData object:
// Create an SQLResultSetMetaData object from the result set's metadata. SQLResultSetRowData rowdata = new SQLResultSetRowData(resultSet); SQLResultSetMetaData sqlMetadata = rowdata.getMetaData();
IBM Toolbox for Java
237
// Display the column precision for non-text columns. String name = null; int numberOfColumns = sqlMetadata.getColumnCount(); for (int column=0; column < numberOfColumns; column++) { name = sqlMetadata.getColumnName(column); if (sqlMetadata.isTextData(column)) { System.out.println("Column: " + name + " contains text data."); } else { System.out.println("Column: " + name + " has a precision of " + sqlMetadata.getPrecision(column)); } }
SQLResultSetMetaData Javadoc SQLResultSetRowData class on page 236 The SQLResultSetRowData class represents an SQL result set as a list of data. This data is generated by an SQL statement through JDBC. With methods provided, you can get set the result set metadata.
Converter classes
You use the IBM Toolbox for Java converter classes to convert row data into formatted string arrays. The result is in HTML format and ready for presentation on your HTML page. The following classes take care of the conversion for you: StringConverter class: The StringConverter class is an abstract class that represents a row data string converter. It provides a convert() method to convert row data. This returns a string array representation of that row's data. Related information StringConverter Javadoc HTMLFormConverter class: The IBM Toolbox for Java HTMLFormConverter classes extend StringConverter by providing an additional convert method called convertToForms(). This method converts row data into an array of single-row HTML tables. You can use these table tags to display the formatted information on a browser. You can tailor the appearance of the HTML form by using the various get and set methods to view or change the attributes of the form. For example, some of the attributes that you can set include: v Alignment v Cell spacing v Header hyper links v Width Example: Using HTMLFormConverter The following example illustrates using HTMLFormConverter. (You can compile and run this example with a webserver running.) Using HTMLFormConverter
238
Related reference StringConverter class on page 238 The StringConverter class is an abstract class that represents a row data string converter. It provides a convert() method to convert row data. This returns a string array representation of that row's data. Related information HTMLFormConverter Javadoc HTMLTableConverter class: The HTMLTableConverter class extends StringConverter by providing a convertToTables() method. This method converts row data into an array of HTML tables that a servlet can use to display the list on a browser. You can use the getTable() and setTable() methods to choose a default table that will be used during conversion. You can set table headers within the HTML table object or you can use the meta data for the header information by setting setUseMetaData() to true. The setMaximumTableSize() method allows you to limit the number of rows in a single table. If the row data does not all fit within the specified size of table, the converter will produce another HTML table object in the output array. This will continue until all row data has been converted. Examples The following examples illustrate how to use the HTMLTableConverter class: v v v v Example: Example: Example: Example: Using ListRowData Using RecordListRowData Using SQLResultSetRowData Presenting ResourceList in a servlet
Code example disclaimer The following disclaimer applies to all of the IBM Toolbox for Java examples: IBM grants you a nonexclusive copyright license to use all programming code examples from which you can generate similar function tailored to your own specific needs. All sample code is provided by IBM for illustrative purposes only. These examples have not been thoroughly tested under all conditions. IBM, therefore, cannot guarantee or imply reliability, serviceability, or function of these programs. All programs contained herein are provided to you "AS IS" without any warranties of any kind. The implied warranties of non-infringement, merchantability and fitness for a particular purpose are expressly disclaimed. HTMLTableConverter Javadoc
Utility classes
The utility classes enable you to do administrative tasks, such as using the AS400JarMaker class. IBM Toolbox for Java offers the following utilities:
239
Because program temporary fixes (PTFs) are applied to this location, Java programs that access these classes directly on the server automatically receive these updates. But, accessing the classes from the server does not always work, specifically for the following situations: v If a low-speed communication link connects server and the client, the performance of loading the classes from the server may be unacceptable. v If Java applications use the CLASSPATH environment variable to access the classes on the client file system, you need IBM i Access for Windows to redirect file system calls to the server. It may not be possible for IBM i Access for Windows to reside on the client. In these cases, installing the classes on the client is a better solution.
AS400ToolboxJarMaker
While the JAR file format was designed to speed up the downloading of Java program files, the AS400ToolboxJarMaker generates an even faster loading IBM Toolbox for Java JAR file through its ability to create a smaller JAR file from a larger one. Also, the AS400ToolboxJarMaker class can unzip a JAR file for you to gain access to the individual content files for basic use.
Flexibility of AS400ToolboxJarMaker
All of the AS400ToolboxJarMaker functions are performed with the JarMaker class and the AS400ToolboxJarMaker subclass: v The generic JarMaker tool operates on any JAR or Zip file; it splits a JAR file or reduces the size of a JAR file by removing classes that are not used. v The AS400ToolboxJarMaker customizes and extends JarMaker functions for easier use with IBM Toolbox for Java JAR files. According to your needs, you can invoke the AS400ToolboxJarMaker methods from within your own Java program or from a command line. Call AS400ToolboxJarMaker from the command line by using the following syntax:
java utilities.JarMaker [options]
where v options = one or more of the available options For a complete set of options available to run at a command line prompt, see the following in the Javadoc: v Options for the JarMaker base class v Extended options for the AS00ToolboxJarMaker subclass
Using AS400ToolboxJarMaker
You can use AS400ToolboxJarMaker to work with JAR files in several ways: v Uncompress one file bundled within a JAR file v Split a large JAR file into smaller JAR files v Exclude any IBM Toolbox for Java files that your application does not need to run Uncompressing a JAR file Suppose you wanted to uncompress just one file bundled within a JAR file. AS400ToolboxJarMaker allows you to expand the file into one of the following: v Current directory (extract(jarFile))
240
v Another directory (extract(jarFile, outputDirectory)) For example, with the following code, you are extracting AS400.class and all of its dependent classes from jt400.jar:
java utilities.AS400ToolboxJarMaker -source jt400.jar -extract outputDir -requiredFile com/ibm/as400/access/AS400.class
Splitting up a single JAR file into multiple, smaller JAR files Suppose you wanted to split up a large JAR file into smaller JAR files, according to your preference for maximum JAR file size. AS400ToolboxJarMaker, accordingly, provides you with the split(jarFile, splitSize) function. In the following code, jt400.jar is split into a set of smaller JAR files, none larger than 300KB:
java utilities.AS400ToolboxJarMaker -split 300
Removing unused files from a JAR file With AS400ToolboxJarMaker, you can exclude any IBM Toolbox for Java files not needed by your application by selecting only the IBM Toolbox for Java components, languages, and CCSIDs that you need to make your application run. AS400ToolboxJarMaker also provides you with the option of including or excluding the JavaBean files associated with the components you select. For example, the following command creates a JAR file that contains only those IBM Toolbox for Java classes needed to make the CommandCall and ProgramCall components of the IBM Toolbox for Java work:
java utilities.AS400ToolboxJarMaker -component CommandCall,ProgramCall
Additionally, if it is unnecessary to convert text strings between Unicode and the double byte character set (DBCS) conversion tables, you can create a 400KB byte smaller JAR file by omitting the unneeded conversion tables with the -ccsid option:
java utilities.AS400ToolboxJarMaker -component CommandCall,ProgramCall -ccsid 61952
Note: Conversion classes are not included with the program call classes. When including program call classes, you must also explicitly include the conversion classes used by your program by using the -ccsid option. JarMaker Javadoc AS400ToolboxJarMaker Javadoc Components supported by IBM Toolbox for Java: Following table lists the component IDs that you can specify when invoking the AS400ToolboxJarMaker tool. v The Component column lists the common name for the component. v The Keyword column lists the keyword that you should specify when using the -component option tag. v The Constant column lists the Integer value that you should specify in setComponents() and getComponents().
Component Server object Command Call Connection Pool Keyword AS400 CommandCall ConnectionPool Constant AS400ToolboxJarMaker.AS400 AS400ToolboxJarMaker.COMMAND_CALL AS400ToolboxJarMaker.CONNECTION_POOL
241
Component Data Areas Data Description and Conversion Data Queues Digital Certificates FTP Integrated File System JAAS Java Application Call JDBC Jobs and Job Queues Messages and Message Queues Numeric Data Types NetServer Network Print Program Call Record Level Access Secure server Service Program Call System Status System Values
Keyword DataArea DataDescription DataQueue DigitalCertificate FTP IntegratedFileSystem JAAS JavaApplicationCall JDBC Job Message NumericDataTypes NetServer Print ProgramCall RecordLevelAccess SecureAS400 ServiceProgramCall SystemStatus SystemValue
Constant AS400ToolboxJarMaker.DATA_AREA AS400ToolboxJarMaker.DATA_DESCRIPTION AS400ToolboxJarMaker.DATA_QUEUE AS400ToolboxJarMaker.DIGITAL_CERTIFICATE AS400ToolboxJarMaker.FTP AS400ToolboxJarMaker.INTEGRATED_FILE_SYSTEM AS400ToolboxJarMaker.JAAS AS400ToolboxJarMaker.JAVA_APPLICATION_CALL AS400ToolboxJarMaker.JDBC AS400ToolboxJarMaker.JOB AS400ToolboxJarMaker.MESSAGE AS400ToolboxJarMaker.NUMERIC_DATA_TYPES AS400ToolboxJarMaker.NETSERVER AS400ToolboxJarMaker.PRINT AS400ToolboxJarMaker.PROGRAM_CALL AS400ToolboxJarMaker.RECORD_LEVEL_ACCESS AS400ToolboxJarMaker.SECURE_AS400 AS400ToolboxJarMaker.SERVICE_PROGRAM_CALL AS400ToolboxJarMaker.SYSTEM_STATUS AS400ToolboxJarMaker.SYSTEM_VALUE AS400ToolboxJarMaker.TRACE AS400ToolboxJarMaker.USER AS400ToolboxJarMaker.USER_SPACE AS400ToolboxJarMaker.AS400_VISUAL AS400ToolboxJarMaker.COMMAND_CALL_VISUAL AS400ToolboxJarMaker.DATA_QUEUE_VISUAL AS400ToolboxJarMaker.INTEGRATED_FILE_SYSTEM_VISUAL AS400ToolboxJarMaker.JAVA_APPLICATION_CALL_VISUAL AS400ToolboxJarMaker.JDBC_VISUAL AS400ToolboxJarMaker.JOB_VISUAL
Trace and Logging Trace Users and Groups User Spaces Visual server object Visual Command Call Visual Data Queues Visual Integrated File System Visual Java Application Call Visual JDBC Visual Jobs and Job Queues User UserSpace AS400Visual CommandCallVisual DataQueueVisual IntegratedFileSystemVisual JavaApplicationCallVisual JDBCVisual JobVisual
242
Component Visual Messages and Message Queues Visual Network Print Visual Program Call Visual Record Level Access Visual Users and Groups
Keyword MessageVisual
Constant AS400ToolboxJarMaker.MESSAGE_VISUAL
CCSID and encoding values supported by IBM Toolbox for Java: IBM Toolbox for Java is shipped with a set of conversion tables, named according to the CCSID. These tables are used internally by IBM Toolbox for Java classes (such as CharConverter) when converting data that is transferred to or from an IBM i system. For example, the conversion table for CCSID 1027 is in file com/ibm/as400/access/ConvTable1027.class. Conversion tables for the following CCSIDs are included in the IBM Toolbox for Java JAR file; other encodings are supported by using the JDK. The central server on the server is no longer used to download tables at runtime. Any specified CCSID for which a conversion table or a JDK encoding cannot be found will cause an exception to be thrown. Some of these tables may be redundant to tables included in your JDK. IBM Toolbox for Java presently supports the following 122 different IBM i CCSIDs. For additional information about CCSIDs, including a complete list of CCSIDs that are recognized on the IBM i platform, see Globalization. Supported CCSIDs in IBM Toolbox for Java
CCSID 37 273 277 278 280 284 285 290 297 300 367 420 423 424 437 500 Format Single-byte EBCDIC Single-byte EBCDIC Single-byte EBCDIC Single-byte EBCDIC Single-byte EBCDIC Single-byte EBCDIC Single-byte EBCDIC Single-byte EBCDIC Single-byte EBCDIC Double-byte EBCDIC ASCII/ISO/Windows Single-byte EBCDIC (bidirectional) Single-byte EBCDIC Single-byte EBCDIC (bidirectional) ASCII/ISO/Windows Single-byte EBCDIC Description United States and others Austria, Germany Denmark, Norway Finland, Sweden Italy Spain, Latin America United Kingdom Japanese Katakana (single-byte only) France Japanese Graphic (subset of 16684) ASCII (ANSI X3.4 standard) Arabic EBCDIC ST4 Greek (for compatibility; see 875) Hebrew EBCDIC ST4 ASCII (USA PC Data) Latin-1 (MNCS)
243
CCSID 720 737 775 813 819 833 834 835 836 837 838 850 851 852 855 857 860 861 862 863 864 865 866 869 870 871 874 875 878 880 912 914 915 916 920 921 922 923 930 933
Format ASCII/ISO/Windows ASCII/ISO/Windows ASCII/ISO/Windows ASCII/ISO/Windows ASCII/ISO/Windows Single-byte EBCDIC Double-byte EBCDIC Double-byte EBCDIC Single-byte EBCDIC Double-byte EBCDIC Single-byte EBCDIC ASCII/ISO/Windows ASCII/ISO/Windows ASCII/ISO/Windows ASCII/ISO/Windows ASCII/ISO/Windows ASCII/ISO/Windows ASCII/ISO/Windows ASCII/ISO/Windows (bidirectional) ASCII/ISO/Windows ASCII/ISO/Windows (bidirectional) ASCII/ISO/Windows ASCII/ISO/Windows ASCII/ISO/Windows Single-byte EBCDIC Single-byte EBCDIC ASCII/ISO/Windows Single-byte EBCDIC ASCII/ISO/Windows Single-byte EBCDIC ASCII/ISO/Windows ASCII/ISO/Windows ASCII/ISO/Windows ASCII/ISO/Windows (bidirectional) ASCII/ISO/Windows ASCII/ISO/Windows ASCII/ISO/Windows ASCII/ISO/Windows Mixed-byte EBCDIC Mixed-byte EBCDIC
Description Arabic (MS-DOS) Greek (MS-DOS) Baltic (MS-DOS) ISO 8859-7 (Greek/Latin) ISO 8859-1 (Latin-1) Korean (single-byte only) Korean Graphic (subset of 4930) Traditional Chinese Graphic Simplified Chinese (single-byte only) Simplified Chinese Graphic Thai Latin-1 Greek Latin-2 Cyrillic Turkish Portuguese Iceland Hebrew ASCII ST4 Canada Arabic ASCII ST5 Denmark/Norway Cyrillic/Russian Greek Latin-2 Iceland Thai (subset of 9066) Greek Russian Cyrillic Multilingual (for compatibility; see 1025) ISO 8859-2 (Latin-2) ISO 8859-4 (Latin-4) ISO 8859-5 (Cyrillic 8-bit) ISO 8859-8 (Hebrew) ST5 ISO 8859-9 (Latin-5) ISO 8859-13 (Baltic 8-bit) Estonia ISO-8 ISO 8859-15 (Latin-9) Japanese (subset of 5026) Korean (subset of 1364)
244
CCSID 935 937 939 1025 1026 1027 1046 1089 1112 1122 1123 1125 1129 1130 1131 1132 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1200 1250 1251 1252 1253 1254 1255 1256 1257 1258 1364 1388 1399 4396
Format Mixed-byte EBCDIC Mixed-byte EBCDIC Mixed-byte EBCDIC Single-byte EBCDIC Single-byte EBCDIC Single-byte EBCDIC ASCII/ISO/Windows (bidirectional) ASCII/ISO/Windows (bidirectional) Single-byte EBCDIC Single-byte EBCDIC Single-byte EBCDIC ASCII/ISO/Windows ASCII/ISO/Windows Single-byte EBCDIC ASCII/ISO/Windows Single-byte EBCDIC Single-byte EBCDIC Single-byte EBCDIC Single-byte EBCDIC Single-byte EBCDIC Single-byte EBCDIC Single-byte EBCDIC Single-byte EBCDIC Single-byte EBCDIC Single-byte EBCDIC Single-byte EBCDIC Unicode ASCII/ISO/Windows ASCII/ISO/Windows ASCII/ISO/Windows ASCII/ISO/Windows ASCII/ISO/Windows ASCII/ISO/Windows (bidirectional) ASCII/ISO/Windows (bidirectional) ASCII/ISO/Windows ASCII/ISO/Windows Mixed-byte EBCDIC Mixed-byte EBCDIC Mixed-byte EBCDIC Double-byte EBCDIC
Description Simplified Chinese (subset of 1388) Traditional Chinese Japanese (subset of 5035) Cyrillic Turkish Japanese Latin (single-byte only) Windows Arabic ST5 ISO 8859-6 (Arabic) ST5 Baltic Multilingual Estonian Ukraine Ukraine Vietnamese Vietnamese Belarus Lao United States and others (Euro support) Austria, Germany (Euro support) Denmark, Norway (Euro support) Finland, Sweden (Euro support) Italy (Euro support) Spain, Latin America (Euro support) United Kingdom (Euro support) France (Euro support) Latin-1 (MNCS) (Euro support) Iceland (Euro support) Unicode UCS-2 (little-endian) Windows Latin-2 Windows Cyrillic Windows Latin-1 Windows Greek Windows Turkey Windows Hebrew ST5 Windows Arabic ST5 Windows Baltic Windows Vietnam Japanese Simplified Chinese Japanese (in V4R5 and higher) Japanese (subset of 300)
IBM Toolbox for Java
245
CCSID 4930 4931 4933 4948 4951 5026 5035 5123 5351 8492 8612 9026 9029 9066 12588 13122 16684 17218 12708 13488 28709 61952 62211 62224 62235 62245
Format Double-byte EBCDIC Double-byte EBCDIC Double-byte EBCDIC ASCII/ISO/Windows ASCII/ISO/Windows Mixed-byte EBCDIC Mixed-byte EBCDIC Single-byte EBCDIC ASCII/ISO/Windows (bidirectional) Double-byte EBCDIC Single-byte EBCDIC Double-byte EBCDIC Double-byte EBCDIC ASCII/ISO/Windows Double-byte EBCDIC Double-byte EBCDIC Double-byte EBCDIC Double-byte EBCDIC Single-byte EBCDIC Unicode Single-byte EBCDIC Unicode Single-byte EBCDIC Single-byte EBCDIC Single-byte EBCDIC Single-byte EBCDIC
Description Korean Traditional Chinese (subset of 835) Simplified Chinese GBK Graphic Latin-2 (subset of 852) Cyrillic (subset of 855) Japanese Japanese Japanese (single-byte only, Euro support) Windows Hebrew (Euro support) ST5 Japanese (subset of 300) Arabic EBCDIC ST5 Korean (subset of 834) Simplified Chinese (subset of 4933) Thai (SBCS extended) Japanese (subset of 300) Korean (subset of 834) Japanese (available in V4R5) Korean (subset of 834) Arabic EBCDIC ST7 Unicode UCS-2 (big-endian) Traditional Chinese (single-byte only) IBM i Unicode (used primarily in the integrated file system) Hebrew EBCDIC ST5 Arabic EBCDIC ST6 Hebrew EBCDIC ST6 Hebrew EBCDIC ST10
CommandHelpRetriever class
The CommandHelpRetriever class retrieves help text for IBM i control language (CL) commands and generates that text either in HTML or User Interface Manager (UIM) format. You can run CommandHelpRetriever from a command line or embed the functionality into your Java program. To use CommandHelpRetriever, your server must have an XML parser and XSL processor in the CLASSPATH environment variable. For more information, see XML parser and XSLT processor on page 415. Additionally, the Generate Command Documentation (GENCMDDOC) CL command uses the CommandHelpRetriever class. So you can simply use the GENCMDDOC command to take advantage of the functionality offered by the CommandHelpRetriever class. For more information, see Generate Command Documentation (GENCMDDOC) in the CL reference topic.
246
CommandPrompter class
The IBM Toolbox for Java CommandPrompter class prompts for the parameter on a given command. The CommandPrompter class offers functionality that is similar to the CL command prompt (pressing F4) and the same as the Management Central command prompt. Using CommandPrompter requires that you have the following JAR files in your CLASSPATH: v v v v jt400.jar jui400.jar util400.jar jhall.jar
You must also have an XML parser in your CLASSPATH. For more information about using a suitable XML parser, see the following page:
IBM Toolbox for Java
247
XML parser and XSLT processor on page 415 All of the JAR files, except for jhall.jar, are included in IBM Toolbox for Java. For more information about IBM Toolbox for Java JAR files, see Jar files. For more information about downloading jhall.jar, see the Sun JavaHelp Web site .
To construct a CommandPrompter object, you pass it parameters for the parent frame that launches the prompter, the AS400 object on which the command will be prompted, and the command string. The command string can be a command name, a full command string, or a partial command name, such as crt*. The CommandPrompter display is a modal dialog that the user must close before returning to the parent frame. The CommandPrompter handles any errors encountered during prompting. For a programming example that shows one way to use the CommandPrompter, see the following page: Example: Using CommandPrompter on page 714
RunJavaApplication
The RunJavaApplication and VRunJavaApplication classes are utilities to run Java programs on the IBM i JVM. Unlike JavaApplicationCall and VJavaApplicationCall classes that you call from your Java program, RunJavaApplication and VRunJavaApplication are complete programs. The RunJavaApplication class is a command line utility. It lets you set the environment (CLASSPATH and properties, for example) for the Java program. You specify the name of the Java program and its parameters, then you start the program. Once started, you can send input to the Java program which it receives via standard input. The Java program writes output to standard output and standard error. The VRunJavaApplication utility has the same capabilities. The difference is VJavaApplicationCall uses a graphical user interface while JavaApplicationCall is a command line interface. RunJavaApplication Javadoc VRunJavaApplication Javadoc JavaApplicationCall class on page 60 The JavaApplicationCall class provides you with the ability to have your client use the server JVM to run a Java program that resides on the server. VJavaApplicationCall class on page 263 The VJavaApplicationCall class allows you to run a Java application on the server from a client by using a graphical user interface (GUI).
JPing
The JPing class is a command line utility that allows you to query your servers to see which services are running and which ports are in service. To query your servers from within a Java application, use the AS400JPing class. See the JPing Javadoc for more information about using JPing from within your Java application. Call JPing from the command line by using the following syntax:
java utilities.JPing System [options]
where: v System = the system that you want to query v [options] = one or more of the available options
248
Options
You can use one or more of the following options. For options that have abbreviations, the abbreviation is listed in parenthesis. -help (-h or -?) Displays the help text. -service i_Service (-s i_Service) Specifies one specific service to ping. The default action is to ping all services. You can use this option to specify one of the following services: as-file, as-netprt, as-rmtcmd, as-dtaq, as-database, as-ddm, as-central, and as-signon. -ssl Specifies whether or not to ping the ssl ports. The default action is not to ping the ssl ports.
-timeout (-t) Specifies the timeout period in milliseconds. The default setting is 20000, or 20 seconds.
Vaccess classes
The Vaccess package and its classes have been deprecated. You are advised to use the Access package in combination with Java Swing instead. IBM Toolbox for Java provides a set of graphical user interface (GUI) classes in the vaccess package. These classes use the access classes to retrieve data and to present the data to the user. Java programs that use the IBM Toolbox for Java vaccess classes require the Swing package, which comes with the Java 2 Platform, Standard Edition (J2SE). For more information about Swing, see the Sun Java Foundation Classes Web site.
For more information about the relationships between theIBM Toolbox for Java GUI classes, the Access classes, and Java Swing, see the Vaccess classes diagram. Note: AS400 panes are used with other vaccess classes (see items marked above with an asterisk) to present and allow manipulation of system resources. When programming with the IBM Toolbox for Java graphical user interface components, use the Error events classes to report and handle error events to the user. See Access classes for more information about accessing system data.
Vaccess classes
The Vaccess package and its classes have been deprecated. You are advised to use the Access package in combination with Java Swing instead. IBM Toolbox for Java provides graphical user interface (GUI) classes in the vaccess package to retrieve, display, and in some cases manipulate, server data. These classes use the Java Swing 1.1 framework. Figure 1 shows the relationship between these classes:
IBM Toolbox for Java
249
Long description of Figure 1: Vaccess classes (rzahh508.gif) Long description of Figure 1: Vaccess classes (rzahh508.gif): found in IBM Toolbox for Java: Vaccess package diagram This figure shows the relationship between the classes in the vaccess package, the access package, and the Java Swing classes. Description The figure is composed of the following: v The topmost image is actually a thick brown border, as of the left and top sides of a rectangle, labeled 'Application,' that represents a Java application. The rectangle delineated by the Java application contains the following irregularly shaped images that fit together like pieces of a puzzle: v A tan polygon that represents the IBM Toolbox for Java vaccess (GUI) classes. This shape contains smaller images that represent the functions contained in the vaccess classes.
250
v A green polygon that represents the Java Swing classes v Below these images is a light blue bar labeled Access Classes, that represents classes in the IBM Toolbox for Java access package. v Below the light blue bar is an identically shaped dark blue bar, labeled 'Sockets/TCP.' v The bottom image is a picture of an IBM i server. v A lightning bolt, which represents a socket connection from the Java application to the server, extends downward from Sockets/TCP (the dark blue bar) and connects to the server (the image of an IBM i server). A Java application (the area delineated by the thick brown border) contains vaccess classes (the tan polygon) and Java Swing classes (the green polygon). The vaccess classes enable the Java application to access the following data and functions on the server (small images in the tan polygon): AS400Panes, CommandCall, DataQueues, integrated file system, JDBC, jobs, messages, print, ProgramCall, record-level input and output, and users and groups The Java application uses IBM Toolbox for Java access classes (the light blue bar) to create one or more socket connections (the dark blue bar). The socket connections enable the Java application to communicate (the lightning bolt) with the server (bottom image of the IBM i server).
AS400Panes
AS400Panes are components in the vaccess package that present and allow manipulation of one or more server resources in a GUI. The behavior of each server resource varies depending on the type of resource. All panes extend the Java Component class. As a result, they can be added to any AWT Frame, Window, or Container. The following AS400Panes are available: v AS400DetailsPane presents a list of server resources in a table where each row displays various details about a single resource. The table allows selection of one or more resources. v AS400ExplorerPane combines an AS400TreePane and AS400DetailsPane so that the resource selected in the tree is presented in the details. v AS400JDBCDataSourcePane presents the property values of an AS400JDBCDataSource object. v AS400ListPane presents a list of server resources and allows selection of one or more resources. v AS400TreePane presents a tree hierarchy of server resources and allows selection of one or more resources. Server resources Server resources are represented in the graphical user interface with an icon and text. Server resources are defined with hierarchical relationships where a resource might have a parent and zero or more children. These are predefined relationships and are used to specify what resources are displayed in an AS400Pane. For example, VJobList is the parent to zero or more VJobs, and this hierarchical relationship is represented graphically in an AS400Pane. The IBM Toolbox for Java provides access to the following server resources: v VIFSDirectory represents a directory in the integrated file system v VJob and VJobList represent a job or a list of jobs v VMessageList and VMessageQueue represent a list of messages returned from a CommandCall or ProgramCall or a message queue v VPrinter, VPrinters, and VPrinterOutput represent a printer, a list of printers, or a list of spooled files v VUserList represents a list of users
IBM Toolbox for Java
251
All resources are implementations of the VNode interface. Setting the root To specify which server resources are presented in an AS400Pane, set the root using the constructor or setRoot() method. The root defines the top level object and is used differently based on the pane: v v v v AS400ListPane presents all of the root's children in its list AS400DetailsPane presents all of the root's children in its table AS400TreePane uses the root as the root of its tree AS400ExplorerPane uses the root as the root of its tree
Any combination of panes and roots is possible. The following example creates an AS400DetailsPane to present the list of users defined on the system:
// Create the server resource // representing a list of users. // Assume that "system" is an AS400 // object created and initialized // elsewhere. VUserList userList = new VUserList (system); // Create the AS400DetailsPane object // and set its root to be the user // list. AS400DetailsPane detailsPane = new AS400DetailsPane (); detailsPane.setRoot (userList); // Add the details pane to a frame. // Assume that "frame" is a JFrame // created elsewhere. frame.getContentPane ().add (detailsPane);
Loading the contents When AS400Pane objects and server resource objects are created, they are initialized to a default state. The relevant information that makes up the contents of the pane is not loaded at creation time. To load the contents, the application must explicitly call the load() method. In most cases, this initiates communication to the server to gather the relevant information. Because it can sometimes take a while to gather this information, the application can control exactly when it happens. For example, you can: v Load the contents before adding the pane to a frame. The frame does not appear until all information is loaded. v Load the contents after adding the pane to a frame and displaying that frame. The frame appears, but it does not contain much information. A "wait cursor" appears and the information is filled in as it is loaded. The following example loads the contents of a details pane before adding it to a frame:
// Load the contents of the details // pane. Assume that the detailsPane // was created and initialized // elsewhere. detailsPane.load (); // Add the details pane to a frame. // Assume that "frame" is a JFrame // created elsewhere. frame.getContentPane ().add (detailsPane);
252
Actions and properties panes At run time, the user can select a pop-up menu on any server resource. The pop-up menu presents a list of relevant actions that are available for the resource. When the user selects an action from the pop-up menu, that action is performed. Each resource has different actions defined. In some cases, the pop-up menu also presents an item that allows the user to view a properties pane. A properties pane shows various details about the resource and may allow the user to change those details. The application can control whether actions and properties panes are available by using the setAllowActions() method on the pane. Models The AS400Panes are implemented using the model-view-controller paradigm, in which the data and the user interface are separated into different classes. The AS400Panes integrate IBM Toolbox for Java models with Java GUI components. The models manage server resources and the vaccess components display them graphically and handle user interaction. The AS400Panes provide enough functionality for most requirements. However, if an application needs more control of the JFC component, then the application can access a server model directly and provide customized integration with a different vaccess component. The following models are available: v AS400ListModel implements the JFC ListModel interface as a list of server resources. This can be used with a JFC JList object. AS400DetailsModel implements the JFC TableModel interface as a table of server resources where each row contains various details about a single resource. This can be used with a JFC JTable object. v AS400TreeModel implements the JFC TreeModel interface as a tree hierarchy of server resources. This can be used with a JFC JTree object. v Examples v Present a list of users on the system using an AS400ListPane with a VUserList object. Figure 1 shows the finished product: Figure 1: Using AS400ListPane with a VUserList object
253
v Present the list of messages generated by a command call using an AS400DetailsPane with a VMessageList object. Figure 2 shows the finished product: Figure 2: Using AS400DetailsPane with a VMessageList object
v Present an integrated file system directory hierarchy using an AS400TreePane with a VIFSDirectory object. Figure 3 shows the finished product: Figure 3: Using AS400TreePane with a VIFSDirectory object
v Present print resources using an AS400ExplorerPane with a VPrinters object. Figure 4 shows the finished product: Figure 4: Using AS400ExplorerPane with a VPrinters object
AS400DetailsPane Javadoc AS400ExplorerPane Javadoc AS400JDBCDataSourcePane Javadoc AS400ListPane Javadoc AS400TreePane Javadoc VNode Javadoc
254
Command Call
The command call vaccess (GUI) components allow a Java program to present a button or menu item that calls a non-interactive server command. A CommandCallButton object represents a button that calls a server command when pressed. The CommandCallButton class extends the Java Foundation Classes (JFC) JButton class so that all buttons have a consistent appearance and behavior. Similarly, a CommandCallMenuItem object represents a menu item that calls a server command when selected. The CommandCallMenuItem class extends the JFC JMenuItem class so that all menu items also have a consistent appearance and behavior. To use a command call graphical user interface component, set both the system and command properties. These properties can be set using a constructor or through the setSystem() and setCommand() methods. The following example creates a CommandCallButton. At run time, when the button is pressed, it creates a library called "FRED":
// Create the CommandCallButton // object. Assume that "system" is // an AS400 object created and // initialized elsewhere. The button // text says "Press Me", and there is // no icon. CommandCallButton button = new CommandCallButton ("Press Me", null, system); // Set the command that the button will run. button.setCommand ("CRTLIB FRED"); // Add the button to a frame. Assume // that "frame" is a JFrame created // elsewhere. frame.getContentPane ().add (button);
When a server command runs, it may return zero or more server messages. To detect when the server command runs, add an ActionCompletedListener to the button or menu item using the addActionCompletedListener() method. When the command runs, it fires an ActionCompletedEvent to all such listeners. A listener can use the getMessageList() method to retrieve any server messages that the command generated. This example adds an ActionCompletedListener that processes all server messages that the command generated:
// Add an ActionCompletedListener that // is implemented using an anonymous // inner class. This is a convenient // way to specify simple event // listeners. button.addActionCompletedListener (new ActionCompletedListener () { public void actionCompleted (ActionCompletedEvent event) { // Cast the source of the event to a // CommandCallButton. CommandCallButton sourceButton = (CommandCallButton) event.getSource (); // Get the list of server messages // that the command generated. AS400Message[] messageList = sourceButton.getMessageList (); // ... Process the message list. } });
IBM Toolbox for Java
255
Examples This example shows how to use a CommandCallMenuItem in an application. Figure 1 shows the CommandCall graphical user interface component: Figure 1: CommandCall GUI component
Data queues
The data queue graphical components allow a Java program to use any Java Foundation Classes (JFC) graphical text component to read or write to a server data queue. The DataQueueDocument and KeyedDataQueueDocument classes are implementations of the JFC Document interface. These classes can be used directly with any JFC graphical text component. Several text components, such as single line fields (JTextField) and multiple line text areas (JTextArea), are available in JFC. Data queue documents associate the contents of a text component with a server data queue. (A text component is a graphical component used to display text that the user can optionally edit.) The Java program can read and write between the text component and data queue at any time. Use DataQueueDocument for sequential data queues and KeyedDataQueueDocument for keyed data queues. To use a DataQueueDocument, set both the system and path properties. These properties can be set using a constructor or through the setSystem() and setPath() methods. The DataQueueDocument object is then "plugged" into the text component, usually using the text component's constructor or setDocument() method. KeyedDataQueueDocuments work the same way. The following example creates a DataQueueDocument whose contents are associated with a data queue:
// Create the DataQueueDocument // object. Assume that "system" is // an AS400 object created and // initialized elsewhere. DataQueueDocument dqDocument = new DataQueueDocument (system, "/QSYS.LIB/MYLIB.LIB/MYQUEUE.DTAQ");
256
// Create a text area to present the // document. JTextArea textArea = new JTextArea (dqDocument); // Add the text area to a frame. // Assume that "frame" is a JFrame // created elsewhere. frame.getContentPane ().add (textArea);
Initially, the contents of the text component are empty. Use read() or peek() to fill the contents with the next entry on the queue. Use write() to write the contents of the text component to the data queue. Note that these documents only work with String data queue entries. Examples Example of using a DataQueueDocument in an application. Figure 1 shows the DataQueueDocument graphical user interface component being used in a JTextField. A button has been added to provide a GUI interface for the user to write the contents of the test field to the data queue. Figure 1: DataQueueDocument GUI component
Error events
In most cases, the IBM Toolbox for Java GUI components fire error events instead of throw exceptions. An error event is a wrapper around an exception that is thrown by an internal component. You can provide an error listener that handles all error events that are fired by a particular graphical user interface component. Whenever an exception is thrown, the listener is called, and it can provide appropriate error reporting. By default, no action takes place when error events are fired. The IBM Toolbox for Java provides a graphical user interface component called ErrorDialogAdapter, which automatically displays a dialog to the user whenever an error event is fired.
Examples
The following examples show how you can handle errors and define a simple error listener. Example: Handling error events by displaying a dialog The following example shows how you can handle error events by displaying a dialog:
// All the setup work to lay out a graphical user interface component // is done. Now add an ErrorDialogAdapter as a listener to the component. // This will report all error events fired by that component through
257
Example: Defining an error listener You can write a custom error listener to handle errors in a different way. Use the ErrorListener interface to accomplish this. The following example shows how to define an simple error listener that only prints errors to System.out:
class MyErrorHandler implements ErrorListener { // This method is invoked whenever an error event is fired. public void errorOccurred(ErrorEvent event) { Exception e = event.getException (); System.out.println ("Error: " + e.getMessage ()); } }
Example: Handling error events by using an error listener The following example shows how to handle error events for a graphical user interface component using this customized handler:
MyErrorHandler errorHandler = new MyErrorHandler (); component.addErrorListener (errorHandler);
Related reference Vaccess classes on page 249 The Vaccess package and its classes have been deprecated. You are advised to use the Access package in combination with Java Swing instead. Exceptions on page 47 The IBM Toolbox for Java access classes throw exceptions when device errors, physical limitations, programming errors, or user input errors occur. The exception classes are based upon the type of error that occurs instead of the location where the error originates. Related information ErrorDialogAdapter Javadoc
258
The IFSFileSystemView provides a gateway to the IBM i integrated file system, for use when constructing javax.swing.JFileChooser objects. JFileChooser is a standard Java way to build dialogs for navigating and choosing files, and is the recommended replacement for IFSFileDialog. Example: Using IFSFileSystemView The following example demonstrates the use of IFSFileSystemView.
import import import import import com.ibm.as400.access.AS400; com.ibm.as400.access.IFSJavaFile; com.ibm.as400.vaccess.IFSFileSystemView; javax.swing.JFileChooser; java.awt.Frame;
// Work with directory /Dir on the system myAS400. AS400 system = new AS400("myAS400"); IFSJavaFile dir = new IFSJavaFile(system, "/Dir"); JFileChooser chooser = new JFileChooser(dir, new IFSFileSystemView(system)); Frame parent = new Frame(); int returnVal = chooser.showOpenDialog(parent); if (returnVal == JFileChooser.APPROVE_OPTION) { IFSJavaFile chosenFile = (IFSJavaFile)(chooser.getSelectedFile()); System.out.println("You selected the file named " + chosenFile.getName()); }
Related information IFSFileSystemView Javadoc File dialogs: The IFSFileDialog class is a dialog that allows the user to traverse the directories of the integrated file system on the server and select a file. The caller can set the text on the buttons on the dialog. In addition, the caller can use FileFilter objects, which allow the user to limit the choices to certain files. If the user selects a file in the dialog, use the getFileName() method to get the name of the selected file. Use the getAbsolutePath() method to get the full path name of the selected file. The following example sets up an integrated file system file dialog with two file filters:
// Create a IFSFileDialog object // setting the text of the title bar. // Assume that "system" is an AS400 // object and "frame" is a JFrame // created and initialized elsewhere. IFSFileDialog dialog = new IFSFileDialog (frame, "Select a file", system); // Set a list of filters for the dialog. // The first filter will be used // when the dialog is first displayed. FileFilter[] filterList = {new FileFilter ("All files (*.*)", "*.*"), new FileFilter ("HTML files (*.HTML", "*.HTM")}; // Then, set the filters in the dialog. dialog.setFileFilter (filterList, 0); // Set the text on the buttons. dialog.setOkButtonText ("Open"); dialog.setCancelButtonText ("Cancel"); // Show the dialog. If the user // selected a file by pressing the // "Open" button, then print the path
IBM Toolbox for Java
259
Example Present an IFSFileDialog and print the selection, if any. Figure 1 shows the IFSFileDialog graphical user interface component: Figure 1: IFSFileDialog GUI component
IFSFileDialog Javadoc FileFilter Javadoc Directories in AS400Panes: AS400Panes are GUI components that present and allow manipulation of one or more server resources. A VIFSDirectory object is a resource that represents a directory in the integrated file system for use in AS400Panes. AS400Pane and VIFSDirectory objects can be used together to present many views of the integrated file system, and to allow the user to navigate, manipulate, and select directories and files. To use a VIFSDirectory, set both the system and path properties. You set these properties using a constructor or through the setSystem() and setPath() methods. You then plug the VIFSDirectory object into the AS400Pane as the root, using the constructor or setRoot() method of the AS400Pane. VIFSDirectory has some other useful properties for defining the set of directories and files that are presented in AS400Panes. Use setInclude() to specify whether directories, files, or both appear. Use setPattern() to set a filter on the items that are shown by specifying a pattern that the file name must match. You can use wildcard characters, such as "*" and "?", in the patterns. Similarly, use setFilter() to set a filter with an IFSFileFilter object.
260
When AS400Pane objects and VIFSDirectory objects are created, they are initialized to a default state. The subdirectories and the files that make up the contents of the root directory have not been loaded. To load the contents, the caller must explicitly call the load() method on either object to initiate communication to the server to gather the contents of the directory. At run-time, a user can perform actions on any directory or file by right-clicking it to display the context menu. The directory context menu can include the following items: v Create file - creates a file in the directory. This will give the file a default name v Create directory - creates a subdirectory with a default name v Rename - renames a directory v Delete - deletes a directory v Properties - displays properties such as the location, number of files and subdirectories, and modification date The file context menu can include the following items: v Edit - edits a text file in a different window v View - views a text file in a different window v Rename - renames a file v Delete - deletes a file v Properties - displays properties such as the location, size, modification date, and attributes Users can only read or write directories and files to which they are authorized. In addition, the caller can prevent the user from performing actions by using the setAllowActions() method on the pane. The following example creates a VIFSDirectory and presents it in an AS400ExplorerPane:
// Create the VIFSDirectory object. // Assume that "system" in an AS400 // object created and initialized // elsewhere. VIFSDirectory root = new VIFSDirectory (system, "/DirectoryA/DirectoryB"); // Create and load an AS400ExplorerPane object. AS400ExplorerPane explorerPane = new AS400ExplorerPane (root); explorerPane.load (); // Add the explorer pane to a frame. // Assume that "frame" is a JFrame // created elsewhere. frame.getContentPane ().add (explorerPane);
Example Present an integrated file system directory hierarchy using an AS400TreePane with a VIFSDirectory object. Figure 1 shows the VIFSDirectory graphical user interface component: Figure 1: VIFSDirectory GUI component
261
AS400Panes on page 251 AS400Panes are components in the vaccess package that present and allow manipulation of one or more server resources in a GUI. The behavior of each server resource varies depending on the type of resource. VIFSDirectory Javadoc IFSFileFilter Javadoc IFSTextFileDocument: Text file documents allow a Java program to use any Java Foundation Classes (JFC) graphical text component to edit or view text files in the integrated file system on a server. (A text component is a graphical component used to display text that the user can optionally edit.) The IFSTextFileDocument class is an implementation of the JFC Document interface. It can be used directly with any JFC graphical text component. Several text components, such as single line fields (JTextField) and multiple line text areas (JTextArea), are available in JFC. Text file documents associate the contents of a text component with a text file. The Java program can load and save between the text component and the text file at any time. To use an IFSTextFileDocument, set both the system and path properties. These properties can be set using a constructor or through the setSystem() and setPath() methods. The IFSTextFileDocument object is then "plugged" into the text component, typically using the text component's constructor or setDocument() method. Initially, the contents of the text component are empty. Use load() to load the contents from the text file. Use save() to save the contents of the text component to the text file. The following example creates and loads an IFSTextFileDocument:
262
// Create and load the // IFSTextFileDocument object. Assume // that "system" is an AS400 object // created and initialized elsewhere. IFSTextFileDocument ifsDocument = new IFSTextFileDocument (system, "/DirectoryA/MyFile.txt"); ifsDocument.load (); // Create a text area to present the // document. JTextArea textArea = new JTextArea (ifsDocument); // Add the text area to a frame. // Assume that "frame" is a JFrame // created elsewhere. frame.getContentPane ().add (textArea);
Example Present an IFSTextFileDocument in a JTextPane. Figure 1 shows the IFSTextFileDocument graphical user interface component: Figure 1: IFSTextFileDocument example
IFSTextFileDocument Javadoc
VJavaApplicationCall class
The VJavaApplicationCall class allows you to run a Java application on the server from a client by using a graphical user interface (GUI). The GUI is a panel with two sections. The top section is an output window that displays output that the Java program writes to standard output and standard error. The bottom section is an input field where the user enters the Java environment, the Java program to run with parameters and input the Java program receives via standard input. Refer to the Java command options for more information. For example, this code might create the following GUI for your Java program. VJavaApplicationCall is a class that you call from your Java program. However, the IBM Toolbox for Java also provides a utility that is a complete Java application that can be used to call your Java program from a workstation. Refer to the RunJavaApplication class for more information. Related information VJavaApplicationCall Javadoc
JDBC classes
The JDBC graphical user interface components allow a Java program to present various views and controls for accessing a database using SQL (Structured Query Language) statements and queries. The following components are available:
IBM Toolbox for Java
263
v SQLStatementButton and SQLStatementMenuItem are either a button or a menu item that issues an SQL statement when clicked or selected. v SQLStatementDocument is a document that can be used with any Java Foundation Classes (JFC) graphical text component to issue an SQL statement. v SQLResultSetFormPane presents the results of an SQL query in a form. v SQLResultSetTablePane presents the results of an SQL query in a table. v SQLResultSetTableModel manages the results of an SQL query in a table. v SQLQueryBuilderPane presents an interactive tool for dynamically building SQL queries. All JDBC graphical user interface components communicate with the database using a JDBC driver. The JDBC driver must be registered with the JDBC driver manager in order for any of these components to work. The following example registers the IBM Toolbox for Java JDBC driver:
// Register the JDBC driver. DriverManager.registerDriver (new com.ibm.as400.access.AS400JDBCDriver ());
SQL connections
An SQLConnection object represents a connection to a database using JDBC. The SQLConnection object is used with all of the JDBC graphical user interface components. To use an SQLConnection, set the URL property using the constructor or setURL(). This identifies the database to which the connection is made. Other optional properties can be set: v Use setProperties() to specify a set of JDBC connection properties. v Use setUserName() to specify the user name for the connection. v Use setPassword() to specify the password for the connection. The actual connection to the database is not made when the SQLConnection object is created. Instead, it is made when getConnection() is called. This method is normally called automatically by the JDBC graphical user interface components, but it can be called at any time in order to control when the connection is made. The following example creates and initializes an SQLConnection object:
// Create an SQLConnection object. SQLConnection connection = new SQLConnection (); // Set the URL and user name properties of the connection. connection.setURL ("jdbc:as400://MySystem"); connection.setUserName ("Lisa");
An SQLConnection object can be used for more than one JDBC graphical user interface component. All such components will use the same connection, which can improve performance and resource usage. Alternately, each JDBC graphical user interface component can use a different SQL object. It is sometimes necessary to use separate connections, so that SQL statements are issued in different transactions. When the connection is no longer needed, close the SQLConnection object using close(). This frees up JDBC resources on both the client and server. SQLConnection Javadoc Buttons and menu items: An SQLStatementButton object represents a button that issues an SQL (Structured Query Language) statement when pressed. The SQLStatementButton class extends the Java Foundation Classes (JFC) JButton class so that all buttons have a consistent appearance and behavior.
264
Similarly, an SQLStatementMenuItem object represents a menu item that issues an SQL statement when selected. The SQLStatementMenuItem class extends the JFC JMenuItem class so that all menu items have a consistent appearance and behavior. To use either of these classes, set both the connection and the SQLStatement properties. These properties can be set using a constructor or the setConnection() and setSQLStatement() methods. The following example creates an SQLStatementButton. When the button is pressed at run time, it deletes all records in a table:
// Create an SQLStatementButton object. // The button text says "Delete All", // and there is no icon. SQLStatementButton button = new SQLStatementButton ("Delete All"); // Set the connection and SQLStatement // properties. Assume that "connection" // is an SQLConnection object that is // created and initialized elsewhere. button.setConnection (connection); button.setSQLStatement ("DELETE FROM MYTABLE"); // Add the button to a frame. Assume // that "frame" is a JFrame created // elsewhere. frame.getContentPane ().add (button);
After the SQL statement is issued, use getResultSet(), getMoreResults(), getUpdateCount(), or getWarnings() to retrieve the results. SQLStatementButton Javadoc SQLStatementMenuItem Javadoc SQLStatementDocument class: The SQLStatementDocument class is an implementation of the Java Foundation Classes (JFC) Document interface. It can be used directly with any JFC graphical text component. Several text components, such as single line fields (JTextField) and multiple line text areas (JTextArea), are available in JFC. SQLStatementDocument objects associate the contents of text components with SQLConnection objects. The Java program can run the SQL statement contained in the document contents at any time and then process the results, if any. To use an SQLStatementDocument, you must set the connection property. Set this property by using the constructor or the setConnection() method. The SQLStatementDocument object is then "plugged" into the text component, typically using the text component's constructor or setDocument() method. Use the execute() method at any time to run the SQL statement contained in the document. The following example creates an SQLStatementDocument in a JTextField:
// Create an SQLStatementDocument // object. Assume that "connection" // is an SQLConnection object that is // created and initialized elsewhere. // The text of the document is // initialized to a generic query. SQLStatementDocument document = new SQLStatementDocument (connection, "SELECT * FROM QIWS.QCUSTCDT"); // Create a text field to present the // document. JTextField textField = new JTextField (); textField.setDocument (document);
265
// Add the text field to a frame. // Assume that "frame" is a JFrame // created elsewhere. frame.getContentPane ().add (textField); // Run the SQL statement that is in // the text field. document.execute ();
After the SQL statement is issued, use getResultSet(), getMoreResults(), getUpdateCount(), or getWarnings() to retrieve the results. Related information SQLStatementDocument Javadoc SQLResultSetFormPane class: An SQLResultSetFormPane presents the results of an SQL (Structured Query Language) query in a form. The form displays one record at a time and provides buttons that allow the user to scroll forward, backward, to the first or last record, or refresh the view of the results. To use an SQLResultSetFormPane, set the connection and query properties. Set these properties by using the constructor or the setConnection() and setQuery() methods. Use load() to execute the query and present the first record in the result set. When the results are no longer needed, call close() to ensure that the result set is closed. The following example creates an SQLResultSetFormPane object and adds it to a frame:
// Create an SQLResultSetFormPane // object. Assume that "connection" // is an SQLConnection object that is // created and initialized elsewhere. SQLResultSetFormPane formPane = new SQLResultSetFormPane (connection, " SELECT * FROM QIWS.QCUSTCDT"); // Load the results. formPane.load (); // Add the form pane to a frame. // Assume that "frame" is a JFrame // created elsewhere. frame.getContentPane ().add (formPane);
Related information SQLResultSetFormPane Javadoc SQLResultSetTablePane class: An SQLResultSetTablePane presents the results of an SQL (Structured Query Language) query in a table. Each row in the table displays a record from the result set and each column displays a field. To use an SQLResultSetTablePane, set the connection and query properties. Set properties by using the constructor or the setConnection() and setQuery() methods. Use load() to execute the query and present the results in the table. When the results are no longer needed, call close() to ensure that the result set is closed. The following example creates an SQLResultSetTablePane object and adds it to a frame:
// Create an SQLResultSetTablePane // object. Assume that "connection" // is an SQLConnection object that is // created and initialized elsewhere. SQLResultSetTablePane tablePane = new SQLResultSetTablePane (connection, "SELECT * FROM QIWS.QCUSTCDT");
266
// Load the results. tablePane.load (); // Add the table pane to a frame. // Assume that "frame" is a JFrame // created elsewhere. frame.getContentPane ().add (tablePane);
Example Present an SQLResultSetTablePane that displays the contents of a table. This example uses an SQLStatementDocument (denoted in the following image by the text, "Enter a SQL statement here") that allows the user to type in any SQL statement, and an SQLStatementButton (denoted by the text, "Delete all rows") that allows the user to delete all rows from the table. Figure 1 shows the SQLResultSetTablePane graphical user interface component: Figure 1: SQLResultSetTablePane GUI component
Related information SQLResultSetTablePane Javadoc SQLResultSetTableModel class: SQLResultSetTablePane is implemented using the model-view-controller paradigm, in which the data and the user interface are separated into different classes. The implementation integrates SQLResultSetTableModel with the Java Foundation Classes' (JFC) JTable. The SQLResultSetTableModel class manages the results of the query and JTable displays the results graphically and handles user interaction. SQLResultSetTablePane provides enough functionality for most requirements. However, if a caller needs more control of the JFC component, then the caller can use SQLResultSetTableModel directly and provide customized integration with a different graphical user interface component. To use an SQLResultSetTableModel, set theconnection and query properties. Set these properties by using the constructor or the setConnection() and setQuery() methods. Use load() to execute the query and load the results. When the results are no longer needed, call close() to ensure that the result set is closed. The following example creates an SQLResultSetTableModel object and presents it with a JTable:
// Create an SQLResultSetTableModel // object. Assume that "connection" // is an SQLConnection object that is // created and initialized elsewhere. SQLResultSetTableModel tableModel = new SQLResultSetTableModel (connection,
IBM Toolbox for Java
267
"SELECT * FROM QIWS.QCUSTCDT"); // Load the results. tableModel.load (); // Create a JTable for the model. JTable table = new JTable (tableModel); // Add the table to a frame. Assume // that "frame" is a JFrame created // elsewhere. frame.getContentPane ().add (table);
Related information SQLResultSetTableModel Javadoc SQL query builders: An SQLQueryBuilderPane presents an interactive tool for dynamically building SQL queries. To use an SQLQueryPane, set the connection property. This property can be set using the constructor or the setConnection() method. Use load() to load data needed for the query builder graphical user interface. Use getQuery() to get the SQL query that the user has built. The following example creates an SQLQueryBuilderPane object and adds it to a frame:
// Create an SQLQueryBuilderPane // object. Assume that "connection" // is an SQLConnection object that is // created and initialized elsewhere. SQLQueryBuilderPane queryBuilder = new SQLQueryBuilderPane (connection); // Load the data needed for the query // builder. queryBuilder.load (); // Add the query builder pane to a // frame. Assume that "frame" is a // JFrame created elsewhere. frame.getContentPane ().add (queryBuilder);
Example Present an SQLQueryBuilderPane and a button. When the button is clicked, present the results of the query in an SQLResultSetFormPane in another frame. Figure 1 shows the SQLQueryBuilderPane graphical user interface component: Figure 1: SQLQueryBuilderPane GUI component
268
Jobs
The jobs vaccess (GUI) components allow a Java program to present lists of server jobs and job log messages in a GUI. The following components are available: v A VJobList object is a resource that represents a list of server jobs for use in AS400Panes. v A VJob object is a resource that represents the list of messages in a job log for use in AS400Panes. You can use AS400Panes, VJobList objects, and VJob objects together to present many views of a job list or job log. To use a VJobList, set the system, name, number, and user properties. Set these properties by using a constructor or through the setSystem(), setName(), setNumber(), and setUser() properties. To use a VJob, set the system property. Set this property by using a constructor or through the setSystem() method.
269
Either the VJobList or VJob object is then "plugged" into the AS400Pane as the root, using the pane's constructor or setRoot() method. VJobList has some other useful properties for defining the set of jobs that are presented in AS400Panes. Use setName() to specify that only jobs with a certain name appear. Use setNumber() to specify that only jobs with a certain number appear. Similarly, use setUser() to specify that only jobs for a certain user appear. When AS400Pane, VJobList, and VJob objects are created, they are initialized to a default state. The list of jobs or job log messages are not loaded at creation time. To load the contents, the caller must explicitly call the load() method on either object. This will initiate communication to the server to gather the contents of the list. At run-time, right-click a job, job list, or job log message to display the shortcut menu. Select Properties from the shortcut menu to perform actions on the selected object: v Job - Work with properties, such as the type and status. You can also change the value of some of the properties. v Job list - Work with the properties, such as name, number, and user properties. You can also change the contents of the list. v Job log message - Display properties, such as the full text, severity, and time sent. Users can only access jobs to which they are authorized. In addition, the Java program can prevent the user from performing actions by using the setAllowActions() method on the pane. The following example creates a VJobList and presents it in an AS400ExplorerPane:
// Create the VJobList object. Assume // that "system" is an AS400 object // created and initialized elsewhere. VJobList root = new VJobList (system); // Create and load an // AS400ExplorerPane object. AS400ExplorerPane explorerPane = new AS400ExplorerPane (root); explorerPane.load (); // Add the explorer pane to a frame. // Assume that "frame" is a JFrame // created elsewhere. frame.getContentPane ().add (explorerPane);
Examples This VJobList example presents an AS400ExplorerPane filled with a list of jobs. The list shows jobs on the system that have the same job name. The following image shows the VJobList graphical user interface component:
270
VJobList Javadoc AS400Panes on page 251 AS400Panes are components in the vaccess package that present and allow manipulation of one or more server resources in a GUI. The behavior of each server resource varies depending on the type of resource. VJob Javadoc
271
To use a VMessageList, set the messageList property. Set this property by using a constructor or through the setMessageList() method. The VMessageList object is then "plugged" into the AS400Pane as the root, using the constructor or setRoot() method of the AS400Pane. When AS400Pane and VMessageList objects are created, they are initialized to a default state. The list of messages is not loaded at creation time. To load the contents, the caller must explicitly call the load() method on either object. At run-time, a user can perform actions on a message by right-clicking it to display the context menu. The message context menu can include an item called Properties that displays properties such as the severity, type, and date. The caller can prevent the user from performing actions by using the setAllowActions() method on the pane. The following example creates a VMessageList for the messages generated by a command call and presents it in an AS400DetailsPane:
// Create the VMessageList object. // Assume that "command" is a // CommandCall object created and run // elsewhere. VMessageList root = new VMessageList (command.getMessageList ()); // Create and load an AS400DetailsPane // object. AS400DetailsPane detailsPane = new AS400DetailsPane (root); detailsPane.load (); // // // frame.getContentPane Add the details pane to a frame. Assume that "frame" is a JFrame created elsewhere. ().add (detailsPane);
Example Present the list of messages generated by a command call using an AS400DetailsPane with a VMessageList object. Figure 1 shows the VMessageList graphical user interface component: Figure 1: VMessageList GUI component
Related reference AS400Panes on page 251 AS400Panes are components in the vaccess package that present and allow manipulation of one or more server resources in a GUI. The behavior of each server resource varies depending on the type of resource. Related information VMessageList Javadoc VMessageQueue class:
272
A VMessageQueue object is a resource that represents the messages in a server message queue for use in AS400Panes. To use a VMessageQueue, set the system and path properties. These properties can be set using a constructor or through the setSystem() and setPath() methods. The VMessageQueue object is then "plugged" into the AS400Pane as the root by using the constructor or setRoot() method of the AS400Pane. VMessageQueue has some other useful properties for defining the set of messages that are presented in AS400Panes. Use setSeverity() to specify the severity of messages that appear. Use setSelection() to specify the type of messages that appear. When AS400Pane and VMessageQueue objects are created, they are initialized to a default state. The list of messages is not loaded at creation time. To load the contents, the caller must explicitly call the load() method on either object. This will initiate communication to the server to gather the contents of the list. At run-time, a user can perform actions on a message or message queue by right-clicking it to display the context menu. The context menu for message queues can include the following items: v Clear - clears the message queue v Properties - allows the user to set the severity and selection properties. This may be used to change the contents of the list The following action is available for messages on a message queue: v Remove - removes the message from the message queue v Reply - replies to an inquiry message v Properties - displays properties such as the severity, type, and date Of course, users can only access message queues to which they are authorized. In addition, the caller can prevent the user from performing actions by using the setAllowActions() method on the pane. The following example creates a VMessageQueue and presents it in an AS400ExplorerPane:
// // // // VMessageQueue root = Create the VMessageQueue object. Assume that "system" is an AS400 object created and initialized elsewhere. new VMessageQueue (system, "/QSYS.LIB/MYLIB.LIB/MYMSGQ.MSGQ");
// Create and load an // AS400ExplorerPane object. AS400ExplorerPane explorerPane = new AS400ExplorerPane (root); explorerPane.load (); // // // frame.getContentPane Add the explorer pane to a frame. Assume that "frame" is a JFrame created elsewhere. ().add (explorerPane);
Example Present the list of messages in a message queue using an AS400ExplorerPane with a VMessageQueue object. Figure 1 shows the VMessageQueue graphical user interface component: Figure 1: VMessageQueue GUI component
273
Permission classes
The Permission classes information can be used in a graphical user interface (GUI) through the VIFSFile and VIFSDirectory classes. Permission has been added as an action in each of these classes. The following example shows how to use Permission with the VIFSDirectory class:
// Create AS400 object AS400 as400 = new AS400(); // Create an IFSDirectory using the system name // and the full path of a QSYS object VIFSDirectory directory = new VIFSDirectory(as400, "/QSYS.LID/testlib1.lib"); // Create as explorer Pane AS400ExplorerPane pane = new AS400ExplorerPane((VNode)directory); // Load the information pane.load();
AS400Panes are GUI components that present and allow manipulation of one or more server resources. VPrinters, VPrinter, and VPrinterOutput objects are resources that represent lists of server print resources in AS400Panes. You can use AS400Pane, VPrinters, VPrinter, and VPrinterOutput objects together to present many views of print resources and to allow the user to select and perform operations on them. VPrinters class: A VPrinters object is a resource that represents a list of printers for use in AS400Panes. To use a VPrinters object, set the system property. Set this property by using a constructor or through the setSystem() method. The VPrinters object is then "plugged" into the AS400Pane as the root, using the pane's constructor or setRoot() method. A VPrinters object has another useful property for defining the set of printers that is presented in AS400Panes. Use setPrinterFilter() to specify a filter that defines which printers should appear.
274
When AS400Pane and VPrinters objects are created, they are initialized to a default state. The list of printers has not been loaded. To load the contents, the caller must explicitly call the load() method on either object. At run-time, a user can perform actions on any printer list or printer by right-clicking it to display the context menu. The printer list context menu can include an item called Properties that allows the user to set the printer filter property, which can change the contents of the list. The printer context menu can include the following items: v Hold - holds the printer v Release - releases the printer v Start - starts the printer v Stop - stops the printer v Make available - makes the printer available v Make unavailable - makes the printer unavailable v Properties - displays properties of the printer and allows the user to set filters Users can only access printers to which they are authorized. In addition, the caller can prevent the user from performing actions by using the setAllowActions() method on the pane. The following example creates a VPrinters object and presents it in an AS400TreePane
// // // // VPrinters root = new Create the VPrinters object. Assume that "system" is an AS400 object created and initialized elsewhere. VPrinters (system);
// Create and load an AS400TreePane // object. AS400TreePane treePane = new AS400TreePane (root); treePane.load (); // // // frame.getContentPane Add the tree pane to a frame. Assume that "frame" is a JFrame created elsewhere. ().add (treePane);
Example Present print resources using an AS400ExplorerPane with a VPrinters object. Figure 1 shows the VPrinters graphical user interface component: Figure 1: VPrinters GUI component
275
Related information VPrinters Javadoc VPrinter class: A VPrinter object is a resource that represents a server printer and its spooled files for use in AS400Panes. To use a VPrinter, set the printer property. Set this property by using a constructor or through the setPrinter() method. The VPrinter object is then "plugged" into the AS400Pane as the root, using the pane's constructor or setRoot() method. When AS400Pane and VPrinter objects are created, they are initialized to a default state. The printer's attributes and list of spooled files are not loaded at creation time. To load the contents, the caller must explicitly call the load() method on either object. This will initiate communication to the server to gather the contents of the list. At run-time, a user can perform actions on any printer or spooled file by right-clicking it to display the context menu. The context menu for message queues can include the following items: v Hold - holds the printer v v v v v Release - releases the printer Start - starts the printer Stop - stops the printer Make available - makes the printer available Make unavailable - makes the printer unavailable
v Properties - displays properties of the printer and allows the user to set filters The context menu for spooled files listed for a printer can include the following items: v Reply - replies to the spooled file v Hold - holds the spooled file v Release - releases the spooled file v Print next - prints the next spooled file v Send - sends the spooled file v Move - moves the spooled file v Delete - deletes the spooled file v Properties - displays many properties of the spooled file and allows the user to change some of them Users can only access printers and spooled files to which they are authorized. In addition, the caller can prevent the user from performing actions by using the setAllowActions() method on the pane. The following example creates a VPrinter and presents it in an AS400ExplorerPane:
// Create the VPrinter object. // Assume that "system" is an AS400 // object created and initialized // elsewhere. VPrinter root = new VPrinter (new Printer (system, "MYPRINTER")); // Create and load an // AS400ExplorerPane object. AS400ExplorerPane explorerPane = new AS400ExplorerPane (root); explorerPane.load ();
276
// // // frame.getContentPane
Add the explorer pane to a frame. Assume that "frame" is a JFrame created elsewhere. ().add (explorerPane);
Example Present print resources using an AS400ExplorerPane with a VPrinter object. Figure 1 shows the VPrinter graphical user interface component: Figure 1: VPrinter GUI component
Related information VPrinter Javadoc VPrinterOutput class: A VPrinterOutput object is a resource that represents a list of spooled files on a server for use in AS400Panes. To use a VPrinterOutput object, set the system property. This property can be set using a constructor or through the setSystem() method. The VPrinterOutput object is then "plugged" into the AS400Pane as the root, using the constructor or setRoot() method of the AS400Pane. A VPrinterOutput object has other useful properties for defining the set of spooled files that is presented in AS400Panes. Use setFormTypeFilter() to specify which types of forms should appear. Use setUserDataFilter() to specify which user data should appear. Finally, use setUserFilter() to specify which users spooled files should appear. When AS400Pane and VPrinterOutput objects are created, they are initialized to a default state. The list of spooled files is not loaded at creation time. To load the contents, the caller must explicitly call the load() method on either object. This will initiate communication to the server to gather the contents of the list. At run-time, a user can perform actions on any spooled file or spooled file list by right-clicking it to display the context menu. The spooled file list context menu can include an item called Properties that allows the user to set the filter properties, which can change the contents of the list. The spooled file context menu can include the following items: v Reply - replies to the spooled file v Hold - holds the spooled file v Release - releases the spooled file v Print next - prints the next spooled file v Send - sends the spooled file v Move - moves the spooled file
IBM Toolbox for Java
277
v Delete - deletes the spooled file v Properties - displays many properties of the spooled file and allows the user to change some of them Of course, users can only access spooled files to which they are authorized. In addition, the caller can prevent the user from performing actions by using the setAllowActions() method on the pane. The following example creates a VPrinterOutput and presents it in an AS400ListPane:
// Create the VPrinterOutput object. // Assume that "system" is an AS400 // object created and initialized // elsewhere. VPrinterOutput root = new VPrinterOutput (system); // Create and load an AS400ListPane // object. AS400ListPane listPane = new AS400ListPane (root); listPane.load (); // // // frame.getContentPane Add the list pane to a frame. Assume that "frame" is a JFrame created elsewhere. ().add (listPane);
Example Present a list of spooled files by using the print resource, VPrinterOutput object. Figure 1 shows the VPrinterOutput graphical user interface component: Figure 1: VPrinterOutput GUI component
Related information VPrinterOutput Javadoc SpooledFileViewer class: The IBM Toolbox for Java SpooledFileViewer class creates a window for viewing Advanced Function Printing (AFP) and Systems Network Architecture character string (SCS) files that have been spooled for printing. The class essentially adds a "print preview" function to your spooled files, common to most word processing programs, as illustrated in Figure 1.
278
The spooled file viewer is especially helpful when viewing the accuracy of the layout of the files is more important than printing the files, or when viewing the data is more economical than printing, or when a printer is not available. Note: SS1 Option 8 (AFP Compatibility Fonts) must be installed on the host server. Using the SpooledFileViewer class Three constructor methods are available to create an instance of the SpooledFileViewer class. The SpooledFileViewer() constructor can be used to create a viewer without a spooled file associated with it. If this constructor is used, a spooled file will need to be set later using setSpooledFile(SpooledFile). The SpooledFileViewer(SpooledFile) constructor can be used to create a viewer for the given spooled file, with page one as the initial view. Finally, the SpooledFileViewer(spooledFile, int) constructor can be used to create a viewer for the given spooled file with the specified page as the initial view. No matter which constructor is used, once a viewer is created, a call to load() must be performed in order to actually retrieve the spooled file data. Then, your program can traverse the individual pages of the spooled file by using the following methods: v v v v load FlashPage() load Page() pageBack() pageForward()
If, however, you need to examine particular sections of the document more closely, you can magnify or reduce the image of a page of the document by altering the ratio proportions of each page with the following: v fitHeight() v fitPage() v fitWidth() v actualSize() Your program concludes with calling the close() method that closes the input stream and releases any resource associations with the stream. Using the SpooledFileViewer An instance of the SpooledFileViewer class is actually a graphical representation of a viewer capable of displaying and navigating through an AFP or SCS spooled file. For example, the following code creates the spooled file viewer in Figure 1 to display a spooled file previously created on the server. Note: You can either select a button on the image in Figure 1 for an explanation of its function, or (if your browser is not JavaScript enabled) see the toolbar description.
// Assume splf is the spooled file. // Create the spooled file viewer SpooledFileViewer splfv = new SpooledFileViewer(splf, 1); splfv.load(); // Add the spooled file viewer to a frame JFrame frame = new JFrame("My Window"); frame.getContentPane().add(splfv); frame.pack(); frame.show();
Figure 1: SpooledFileViewer
279
The actual size button returns the spooled file page image to its original size by using the actualSize() method.
The fit width button stretches the spooled file page image to the left and right edges of the viewer's frame by using the fitWidth() method.
The fit page button stretches the spooled file page image vertically and horizontally to fit within the spooled file viewer's frame by using the fitPage() method.
The zoom button allows you to increase or decrease the size of the spooled file page image by selecting one of the preset percentages or entering your own percent in a text field that appears in a dialog box after selecting the zoom button.
The go to page button allows you to go to a specific page within the spooled file when selected.
The first page button takes you to the first page of the spooled file when selected and indicates that you are on the first page when deactivated.
280
The previous page button takes you to the page immediately before the page you are viewing when selected.
The next page button advances you to the page immediately after the page you are viewing when selected.
The last page button advances you to the last page of the spooled file when selected and indicates that you are on the last page when deactivated.
The load flash page button loads the previously viewed page by using the loadFlashPage() method when selected.
The set paper size button allows you to set the paper size when selected.
The set viewing fidelity button allows you to set the viewing fidelity when selected. SpooledFileViewer Javadoc
281
// represents program MYPROG in // library MYLIB QSYSObjectPathName programName = new QSYSObjectPathName("MYLIB", "MYPROG", "PGM"); // Set the name of the program. menuItem.setProgram (programName.getPath()); // Add the menu item to a menu. // Assume that the menu was created // elsewhere. menu.add (menuItem);
When a server program runs, it may return zero or more server messages. To detect when the server program runs, add an ActionCompletedListener to the button or menu item using the addActionCompletedListener() method. When the program runs, it fires an ActionCompletedEvent to all such listeners. A listener can use the getMessageList() method to retrieve any server messages that the program generated. This example adds an ActionCompletedListener that processes all server messages that the program generated:
// Add an ActionCompletedListener // that is implemented by using an // anonymous inner class. This is a // convenient way to specify simple // event listeners. menuItem.addActionCompletedListener (new ActionCompletedListener () { public void actionCompleted (ActionCompletedEvent event) { // Cast the source of the event to a // ProgramCallMenuItem. ProgramCallMenuItem sourceMenuItem = (ProgramCallMenuItem) event.getSource (); // Get the list of server messages // that the program generated. AS400Message[] messageList = sourceMenuItem.getMessageList (); // ... Process the message list. } });
Parameters ProgramParameter objects are used to pass parameter data between the Java program and the server program. Input data is set with the setInputData() method. After the program is run, output data is retrieved with the getOutputData() method. Each parameter is a byte array. It is up to the Java program to convert the byte array between Java and server formats. The data conversion classes provide methods for converting data. You can add parameters to a program call graphical user interface component one at a time using the addParameter() method or all at once using the setParameterList() method. For more information about using ProgramParameter objects, see the ProgramCall access class. The following example adds two parameters:
// // // // // The first parameter is a String name of up to 100 characters. This is an input parameter. Assume that "name" is a String created and initialized elsewhere.
282
AS400Text parm1Converter = new AS400Text (100, system.getCcsid (), system); ProgramParameter parm1 = new ProgramParameter (parm1Converter.toBytes (name)); menuItem.addParameter (parm1); // The second parameter is an Integer // output parameter. AS400Bin4 parm2Converter = new AS400Bin4 (); ProgramParameter parm2 = new ProgramParameter (parm2Converter.getByteLength ()); menuItem.addParameter (parm2); // ... after the program is called, // get the value returned as the // second parameter. int result = parm2Converter.toInt (parm2.getOutputData ());
Examples Example of using a ProgramCallButton in an application. Figure 1 shows how the ProgramCallButton looks: Figure 1: Using ProgramCallButton in an application
ProgramParameter Javadoc ProgramCallButton Javadoc ProgramCallMenuItem Javadoc ActionCompletedListener Javadoc ActionCompletedEvent Javadoc
283
By default, only records whose keys are equal to the specified key are displayed. To change this, specify the searchType property using the constructor or setSearchType() method. Possible choices are as follows: v KEY_EQ - Display records whose keys are equal to the specified key. v KEY_GE - Display records whose keys are greater than or equal to the specified key. v KEY_GT - Display records whose keys are greater than the specified key. v KEY_LE - Display records whose keys are less than or equal to the specified key. v KEY_LT - Display records whose keys are less than the specified key. The following example creates a RecordListTablePane object to display all records less than or equal to a key.
// Create a key that contains a // single element, the Integer 5. Object[] key = new Object[1]; key[0] = new Integer (5); // Create a RecordListTablePane // object. Assume that "system" is an // AS400 object that is created and // initialized elsewhere. Specify // the key and search type. RecordListTablePane tablePane = new RecordListTablePane (system, "/QSYS.LIB/QGPL.LIB/PARTS.FILE", key, RecordListTablePane.KEY_LE); // Load the file contents. tablePane.load (); // // // frame.getContentPane Add the table pane to a frame. Assume that "frame" is a JFrame created elsewhere. ().add (tablePane);
RecordListFormPane class: A RecordListFormPane presents the contents of a server file in a form. The form displays one record at a time and provides buttons that allow the user to scroll forward, backward, to the first or last record, or refresh the view of the file contents. To use a RecordListFormPane, set the system and fileName properties. Set these properties by using the constructor or the setSystem() and setFileName() methods. Use load() to retrieve the file contents and present the first record. When the file contents are no longer needed, call close() to ensure that the file is closed. The following example creates a RecordListFormPane object and adds it to a frame:
// Create a RecordListFormPane // object. Assume that "system" is // an AS400 object that is created // and initialized elsewhere. RecordListFormPane formPane = new RecordListFormPane (system, "/QSYS.LIB/QIWS.LIB/QCUSTCDT.FILE"); // Load the file contents. formPane.load (); // // // frame.getContentPane Add the form pane to a frame. Assume that "frame" is a JFrame created elsewhere. ().add (formPane);
Example
284
Present an RecordListFormPane which displays the contents of a file. Figure 1 shows the RecordListFormPane graphical user interface component: Figure 1: RecordListFormPane GUI component
Related information RecordListFormPane Javadoc RecordListTablePane class: A RecordListTablePane presents the contents of a server file in a table. Each row in the table displays a record from the file and each column displays a field. To use a RecordListTablePane, set the system and fileName properties. Set these properties by using the constructor or the setSystem() and setFileName() methods. Use load() to retrieve the file contents and present the records in the table. When the file contents are no longer needed, call close() to ensure that the file is closed. The following example creates a RecordListTablePane object and adds it to a frame:
IBM Toolbox for Java
285
// Create an RecordListTablePane // object. Assume that "system" is // an AS400 object that is created // and initialized elsewhere. RecordListTablePane tablePane = new RecordListTablePane (system, "/QSYS.LIB/QIWS.LIB/QCUSTCDT.FILE"); // Load the file contents. tablePane.load (); // // // frame.getContentPane Add the table pane to a frame. Assume that "frame" is a JFrame created elsewhere. ().add (tablePane);
Related information RecordListTablePane Javadoc RecordListTablePane and RecordListTableModel classes: RecordListTablePane is implemented using the model-view-controller paradigm, in which the data and the user interface are separated into different classes. The implementation integrates RecordListTableModel with Java Foundation Classes' (JFC) JTable. The RecordListTableModel class retrieves and manages the contents of the file and JTable displays the file contents graphically and handles user interaction. RecordListTablePane provides enough functionality for most requirements. However, if a caller needs more control of the JFC component, then the caller can use RecordListTableModel directly and provide customized integration with a different graphical user interface component. To use a RecordListTableModel, set the system and fileName properties. Set these properties by using the constructor or the setSystem() and setFileName() methods. Use load() to retrieve the file contents. When the file contents are no longer needed, call close() to ensure that the file is closed. The following example creates a RecordListTableModel object and presents it with a JTable:
// // // // RecordListTableModel
Create a RecordListTableModel object. Assume that "system" is an AS400 object that is created and initialized elsewhere. tableModel = new RecordListTableModel (system, "/QSYS.LIB/QIWS.LIB/QCUSTCDT.FILE");
// Load the file contents. tableModel.load (); // Create a JTable for the model. JTable table = new JTable (tableModel); // // // frame.getContentPane Add the table to a frame. Assume that "frame" is a JFrame created elsewhere. ().add (table);
RecordListTableModel Javadoc
286
The table columns for a ResourceListDetailsPane are specified as an array of column attribute IDs. The table contains a column for each element of the array and a row for each resource object. Pop-up menus are enabled by default for both ResourceListPane and ResourceListDetailsPane. Most errors are reported as com.ibm.as400.vaccess.ErrorEvents rather than thrown exceptions. Listen for ErrorEvents in order to diagnose and recover from error conditions. Example: Displaying a resource list in a GUI This example creates a ResourceList of all users on a system and displays it in a GUI (details pane):
// Create the resource list. AS400 system = new AS400("MYSYSTEM", "MYUSERID", "MYPASSWORD"); RUserList userList = new RUserList(system); // Create the ResourceListDetailsPane. In this example, // there are two columns in the table. The first column // contains the icons and names for each user. The // second column contains the text description for each // user. Object[] columnAttributeIDs = new Object[] { null, RUser.TEXT_DESCRIPTION }; ResourceListDetailsPane detailsPane = new ResourceListDetailsPane(); detailsPane.setResourceList(userList); detailsPane.setColumnAttributeIDs(columnAttributeIDs); // Add the ResourceListDetailsPane to a JFrame and show it. JFrame frame = new JFrame("My Window"); frame.getContentPane().add(detailsPane); frame.pack(); frame.show(); // The ResourceListDetailsPane will appear empty until // we load it. This gives us control of when the list // of users is retrieved from the server. detailsPane.load();
287
VSystemStatus Javadoc VSystemStatusPane Javadoc VSystemPool class: The VSystemPool class allows you to retrieve and set system pool information from a server using a GUI design. VSystemPool works with various panes in the vaccess package including the VSystemStatusPane. The following list is some of the methods that are available to use in VSystemPool: v The getActions() method returns a list of actions that you can perform v The getSystem() method returns the server where the system pool information is found v The setSystemPool() method sets the system pool object Related information VSystemPool Javadoc VSystemStatusPane VSystemStatusPane class: The VSystemStatusPane class allows a Java program to display system status and system pool information. VSystemStatusPane includes the following methods: v getVSystemStatus(): Returns the VSystemStatus information in a VSystemStatusPane. v setAllowModifyAllPools(): Sets the value to determine if system pool information can be modified. The following example shows you how to use the VSystemStatusPane class:
// Create an as400 object. AS400 mySystem = new AS400("mySystem.myCompany.com"); // Create a VSystemStatusPane VSystemStatusPane myPane = new VSystemStatusPane(mySystem); // Set the value to allow pools to be modified myPane.setAllowModifyAllPools(true); //Load the information myPane.load();
VSystemStatusPane Javadoc
288
289
// AS400DetailsPane object. AS400DetailsPane detailsPane = new AS400DetailsPane (root); detailsPane.load (); // Add the details pane to a frame. // Assume that "frame" is a JFrame // created elsewhere. frame.getContentPane ().add (detailsPane);
Other Examples Present a list of users on the system using an AS400ListPane with a VUserList object. The following image shows the VUserList graphical user interface component:
290
The GUI Builder is a WYSIWYG visual editor for creating Java dialogs, property sheets and wizards. With the GUI Builder you can add, arrange, or edit user interface controls on a panel, and then preview the panel to verify the layout behaves the way you expected. The panel definitions you create can be used in dialogs, inserted within property sheets and wizards, or arranged into splitter, deck, and tabbed panes. The GUI Builder also allows you to build menu bars, toolbars, and context menu definitions. You can also incorporate JavaHelp in your panels, including context sensitive help. The Resource Script Converter converts Windows resource scripts into an XML representation that is usable by Java programs. With the Resource Script Converter you can process Windows resource scripts (RC files) from your existing Windows dialogs and menus. These converted files can then be edited with the GUI Builder. Property sheets and wizards can be made from RC files using the resource script converter along with the GUI Builder. Underlying these two tools is a new technology called the Panel Definition Markup Language, or PDML. PDML is based on the Extensible Markup Language (XML) and defines a platform-independent language for describing the layout of user interface elements. Once your panels are defined in PDML, you can use the runtime API provided by the Graphical Toolbox to display them. The API displays your panels by interpreting the PDML and rendering your user interface using the Java Foundation Classes. Note: Using PDML requires that you run version 1.4 or later of the Java Runtime Environment.
291
or you can use the Resource Script Converter to convert existing Windows-based panels to Java. The converted files can then be edited with GUI Builder. Both tools support internationalization.
GUI Builder
Two windows are displayed when you invoke the GUI Builder for the first time, as shown in Figure 1: Figure 1: GUI Builder windows
Use the File Builder window to create and edit your PDML files. Figure 2: File Builder window
Use the Properties window to view or change the properties of the currently selected control. Figure 3: Properties window
292
Use the Panel Builder window to create and edit your graphical user interface components. Select the desired component from the toolbar and click on the panel to place it where ever you want. The toolbar also facilities for aligning groups of controls, for previewing the panel, and for requesting online help for a GUI Builder function. See GUI Builder Panel Builder toolbar for a description of what each icon does. Figure 4: Panel Builder window
The panel being edited is displayed in the Panel Builder window. Figure 5 shows how the windows work together: Figure 5: Example of how GUI Builder windows work together
293
294
After the conversion has run successfully, you can use the View pane to view the contents of your newly-created PDML file, and preview your new Java panels. You can use the GUI Builder to make minor adjustments to a panel if needed. The Converter always checks for an existing PDML file before performing a conversion, and attempts to preserve any changes in case you need to run the conversion again later. Figure 7: Resource Script Converter View pane
295
296
You also need to add an XML parser to your CLASSPATH. For more information, see the following page: XML parser and XSLT processor on page 415 If you have installed the Graphical Toolbox using IBM i Access for Windows, the JAR files (except jhall.jar) will all reside in the directory \Program Files\Ibm\Client Access\jt400\lib on the drive where you have installed IBM i Access for Windows. IBM i Access for Windows installs jhall.jar in the \Program Files\Ibm\Client Access\jre\lib directory. The path names in your classpath reflect this.
297
If you did not set your CLASSPATH environment variable to contain the Graphical Toolbox JAR files, then you will need to specify them on the command line using the classpath option. See Setting Up the Graphical Toolbox. Options -plaf look and feel The platform look and feel that you want. This option lets you override the default look and feel that is set based on the platform you are developing on, so you can preview your panels to see how they will look on different operating system platforms. The following look and feel values are accepted: v Windows v Metal v Motif Currently, additional look and feel attributes that Swing 1.1 may support are not supported by the GUI Builder
Menu A popup window containing one or more selectable actions, each represented by a text string ("Cut", "Copy" and "Paste" are examples). You can define mnemonics and accelerator keys for each action, insert separators and cascading submenus, or define special checked or radio button menu items. A menu resource may be used as a stand-alone context menu, as a drop-down menu in a menu bar, or it may itself define the menu bar associated with a panel resource. Toolbar A window consisting of a series of push buttons, each representing a possible user action. Each button may contain text, an icon or both. You can define the toolbar as floatable, which lets the user drag the toolbar out of a panel and into a stand-alone window. Property Sheet A stand-alone window or dialog consisting of a tabbed panels and OK, Cancel, and Help buttons. Panel resources define the layout of each tabbed window. Wizard A stand-alone window or dialog consisting of a series of panels that are displayed to the user in a predefined sequence, with Back, Next, Cancel, Finish, and Help buttons. The wizard window may also display a list of tasks to the left of the panels which track the user's progress through the wizard. Split Pane A subpane consisting of two panels separated by a splitter bar. The panels may be arranged horizontally or vertically.
298
Tabbed Pane A subpane that forms a tabbed control. This tabbed control can be placed inside of another panel, split pane, or deck pane. Deck Pane A subpane consisting of a collection of panels. Of these, only one panel can be displayed at a time. For example, at runtime the deck pane might change the panel which is displayed depending on a given user action. String Table A collection of string resources and their associated resource identifiers.
Generated files
The translatable strings for a panel are not stored in the PDML file itself, but in a separate Java resource bundle. The tools let you specify how the resource bundle is defined, either as a Java PROPERTIES file or as a ListResourceBundle subclass. A ListResourceBundle subclass is a compiled version of the translatable resources, which enhances the performance of your Java application. However, it will slow down the GUI Builder's saving process, because the ListResourceBundle will be compiled in each save operation. Therefore it's best to start with a PROPERTIES file (the default setting) until you're satisfied with the design of your user interface. You can use the tools to generate HTML skeletons for each panel in the PDML file. At runtime, the correct help topic is displayed when the user clicks on the panel's Help button or presses F1 while the focus is on one of the panel's controls. You must insert your help content at the appropriate points in the HTML, within the scope of the <!-- HELPDOC:SEGMENTBEGIN --> and <!-- HELPDOC:SEGMENTEND --> tags. For more specific help information see Editing Help Documents generated by GUI builder. You can generate source code skeletons for the JavaBeans that will supply the data for a panel. Use the Properties window of the GUI Builder to fill in the DATACLASS and ATTRIBUTE properties for the controls which will contain data. The DATACLASS property identifies the class name of the bean, and the ATTRIBUTE property specifies the name of the gettor/settor methods that the bean class implements. Once you've added this information to the PDML file, you can use the GUI Builder to generate Java source code skeletons and compile them. At runtime, the appropriate gettor/settor methods will be called to fill in the data for the panel. Note: The number and type of gettor/settor methods is dependent on the type of UI control with which the methods are associated. The method protocols for each control are documented in the class description for the DataBean class.
Finally, you can serialize the contents of your PDML file. Serialization produces a compact binary representation of all of the UI resources in the file. This greatly improves the performance of your user interface, because the PDML file must not be interpreted in order to display your panels. To summarize: If you have created a PDML file named MyPanels.pdml, the following files will also be produced based on the options you have selected on the tools: v MyPanels.properties if you have defined the resource bundle as a PROPERTIES file v MyPanels.java and MyPanels.class if you have defined the resource bundle as a ListResourceBundle subclass v <panel name>.html for each panel in the PDML file, if you have elected to generate online help skeletons v <dataclass name>.java and <dataclass name>.class for each unique bean class that you have specified on your DATACLASS properties, if you have elected to generate source code skeletons for your JavaBeans v <resource name>.pdml.ser for each UI resource defined in the PDML file, if you've elected to serialize its contents.
IBM Toolbox for Java
299
Note: The conditional behavior functions (SELECTED/DESELECTED) will not work if the panel name is the same as the one in which the conditional behavior function is being attached. For instance, if PANEL1 in FILE1 has a conditional behavior reference attached to a field that references a field in PANEL1 in FILE2, the conditional behavior event will not work. To fix this, rename PANEL1 in FILE2 and then update the conditional behavior event in FILE1 to reflect this change.
If you did not set your CLASSPATH environment variable to contain the Graphical Toolbox JAR files, then you will need to specify them on the command line using the classpath option. See Setting Up the Graphical Toolbox. You can also run the Resource Script Converter in batch mode using the following command:
java com.ibm.as400.ui.tools.RC2XML file [options]
Where file is the name of the resource script (RC file) to be processed. Options -x name The name of the generated PDML file. Defaults to the name of the RC file to be processed. -p name The name of the generated PROPERTIES file. Defaults to the name of the PDML file. -r name The name of the generated ListResourceBundle subclass. Defaults to the name of the PDML file. -package name The name of the package to which the generated resources will be assigned. If not specified, no package statements will be generated. -l locale The locale in which to produce the generated resources. If a locale is specified, the appropriate 2-character ISO language and country or region codes are suffixed to the name of the generated resource bundle. -h -d -s Generate HTML skeletons for online help. Generate source code skeletons for JavaBeans. Serialize all resources.
300
where <class name> is the fully-qualified name of the bean class that you want to designate as the DATACLASS property of the control, and <attribute> is the name of the bean property that you want to designate as the ATTRIBUTE property of the control. For example, a Windows text field with the resource ID IDCB_com_MyCompany_MyPackage_MyBean_SampleAttribute produces a DATACLASS property of com.MyCompany.MyPackage.MyBean and an ATTRIBUTE property of SampleAttribute. If you elect to generate JavaBeans when you run the conversion, the Java source file MyBean.java is produced, containing the package statement package com.MyCompany.MyPackage, and gettor and settor methods for the SampleAttribute property.
301
Examples
Assume that the panel MyPanel is defined in the file TestPanels.pdml, and that a properties file TestPanels.properties is associated with the panel definition. Both files reside in the directory com/ourCompany/ourPackage, which is accessible either from a directory defined in the classpath or from a ZIP or JAR file defined in the classpath. Note: Read the Code example disclaimer for important legal information. Example: Creating and displaying a panel The following code creates and displays the panel:
import com.ibm.as400.ui.framework.java.*; // // // // Create the panel manager. Parameters: 1. Resource name of the panel definition 2. Name of panel 3. List of DataBeans omitted
PanelManager pm = null; try { pm = new PanelManager("com.ourCompany.ourPackage.TestPanels", "MyPanel", null); } catch (DisplayManagerException e) { e.displayUserMessage(null); System.exit(-1); } // Display the panel pm.setVisible(true);
302
Example: Creating a dialog Once the DataBeans that supply data to the panel have been implemented and the attributes have been identified in the PDML, the following code may be used to construct a fully-functioning dialog:
import com.ibm.as400.ui.framework.java.*; import java.awt.Frame; // Instantiate the objects which supply data to the panel TestDataBean1 db1 = new TestDataBean1(); TestDataBean2 db2 = new TestDataBean2(); // Initialize the objects db1.load(); db2.load(); // Set up to pass the objects to the UI framework DataBean[] dataBeans = { db1, db2 }; // // // // // Create the panel manager. Parameters: 1. Resource name of the panel definition 2. Name of panel 3. List of DataBeans 4. Owner frame window
Frame owner; ... PanelManager pm = null; try { pm = new PanelManager("com.ourCompany.ourPackage.TestPanels", "MyPanel", dataBeans, owner); } catch (DisplayManagerException e) { e.displayUserMessage(null); System.exit(-1); } // Display the panel pm.setVisible(true);
Example: Using the dynamic panel manager A new service has been added to the existing panel manager. The dynamic panel manager dynamically sizes the panel at runtime. Let's look at the MyPanel example again, using the dynamic panel manager:
import com.ibm.as400.ui.framework.java.*; // // // // Create the dynamic panel manager. Parameters: 1. Resource name of the panel definition 2. Name of panel 3. List of DataBeans omitted
DynamicPanelManager dpm = null; try { pm = new DynamicPanelManager("com.ourCompany.ourPackage.TestPanels", "MyPanel", null); } catch (DisplayManagerException e) { e.displayUserMessage(null); System.exit(-1); } // Display the panel pm.setVisible(true);
303
When you instantiate this panel application you can see the dynamic sizing feature of the panels. Move your cursor to the edge of the GUI's display and, when you see the sizing arrows, you can change the size of the panel. Related information Package com.ibm.as400.ui.framework.java summary
Description
The figure is composed of several boxes of differing shapes, sizes, and colors that are connected to each other by lines terminated by arrowheads at one or both ends. In order to visualize the figure, it is useful to divide it into three columns and four rows, numbering the areas in sequence from top left to bottom right. fo example, The first row contains areas 1, 2, and 3; the second row contains areas 4, 5, and 6; and so on: v The image of a dialog box that occupies areas 2 and 5 represents the GUI interface for your Java program. The dialog box features a variety of options, like check boxes, text fields, and so on. v Two tan cylinders at the top of area 1 are labeled PDML Source and Resource Bundle. These cylinders represent PDML source and Java resource files that reside on a storage medium. v One tan cylinder in area 10 labeled PDML Serialized represents one or more serialized PDML files that reside on a storage medium. v Five blue rectangles that surround the bottom portion of the dialog box represent components of the Graphical Toolbox. Starting at the leftmost rectangle and moving counter-clockwise, they are labeled: XML Parser (Pure Java) in area 4, which represents the IBM XML Parser. Runtime Managers (Pure Java) in area 7. Your Java program is a client of one or more of the objects contained in Runtime Managers: Panels, Property sheets, Wizards, and Layout. Common Data Exchanger (Pure Java) in area 8. Common Formatters (Pure Java) in area 9. Common Handlers (Pure Java) in area 6. v Three green rectangles represent code provided by the application programmer and are labeled: Custom Handlers (Java Application) in area 3 Custom Formatters (Java Application) in are 12 User Interface Data Beans (Pure Java) in area 11 v Lines connect many of the shapes: A line that has a single arrowhead (on one end) indicates an action. Single arrowhead lines point toward a function or component that uses the object from which the line originates. In the following description, the word "use" means that a line with a single arrowhead points toward an object from the component that acts upon it. A line that has a double arrowhead (one at each end) indicates an interaction. These lines connect objects that share a two-way exchange of information. In the following description, the word "interact" means that the components are connected by a line with a double arrowhead. The GUI interface for your Java program (the image of the dialog in areas 2 and 5) interacts with the Runtime Managers for the Graphical Toolbox (the blue rectangle in area 7).
304
The Runtime Managers, which are pure Java, contain panels, property sheets, wizards, and the GUI layouts. To generate the GUI, the Runtime Managers use a Java resource bundle (one of two tan cylinders in area 1) and PDML data. Runtime Managers can process PDML data in one of two ways: v Using serialized PDML files (the tan cylinder in area 10) v Using the IBM XML Parser (the blue rectangle in area 4), which in turn uses (parses) the PDML source files (one of two tan cylinders in area 1) Your GUI-enabled Java program operates on data in one of the following ways: v Having the GUI interface interact with custom handlers (the green rectangle in area 3) and common handlers (the blue rectangle in area 6) v Having the common data exchanger (the blue rectangle in area 8) use the GUI interface to obtain information The custom handlers, common handlers, and the common data exchanger all interact with the user interface data beans (the green rectangle in area 11), passing information back and forth. The common data exchanger interacts with common formatters (the blue rectangle in area 9) and custom formatters (the green rectangle in area 12) to convert the data into appropriate formats for the user interface data beans.
In addition, you can add additional topic sections before the footer to provide additional information or common information. Topic sections have only the html body until they are split, when a header and footer are created. When the Help Document is split up, the processor adds a header and footer to the topic section to make a complete HTML file. The header and footer from the Help Document are used as default header and footer. However, you can override the default header with your own.
If you want to override the default header for all of the individual topics when they are split, use the HEADER keyword and provide the name of an html fragment to include. For example:
<!-- HELPDOC:HEADEREND HEADER="defaultheader.html" -->
305
and
<!-- HELPDOC:SEGMENTEND -->
Immediately following the SEGMENTBEGIN tag is an anchor tag which names the segment. It also provides the file name of the HTML document that is created when the Help Document is split. The name of the segment combines the panel identifier, control identifier, and future file extension (html). For example: "MY_PANEL.MY_CONTROL.html" Segments for panels have only the panel identifier and future file extension. The help generator will place text in the document indicating where you place your help information:
<!-- HELPDOC:SEGMENTBEGIN PDMLSYNCH="YES" --><A NAME="MY_PANEL.MY_CONTROL.html"></A> <H2>My favorite control</H2> Insert help for "My favorite control" here. <P><!-- HELPDOC:SEGMENTEND -->
You can add additional HTML 2.0 tags as needed after the anchor tag and before the SEGMENTEND tag. The PDMLSYNCH tag controls how closely a segment is tied to the controls defined in PDML. If PDMLSYCH is "YES", the Help Document segment will be removed if the control of the same name is removed in the PDML. PDMLSYNCH="NO" indicates the topic must be kept in the Help Document regardless of whether a corresponding control exists in the PDML. This is used, for example, when you create additional topics for depth or a common topic. The help generated for a panel has links to each control enabled for help on the panel. These links are generated with a local anchor reference, so that you can test them as internal links in a standard browser. When the Help Document is split, the processor removes the "#" on these internal links making them external links in the resulting single topic HTML files. Because you may want to have internal links within a topic, the processor only removes any preceding "#" when the reference has ".html" embedded in it. If you want to override the default header for any particular topic, use the HEADER keyword and provide the name of an html fragment to include. For example:
<!-- HELPDOC:SEGMENTBEGIN PDMLSYNCH="YES" HEADER="specialheader.html" -->
Footer The footer in the Help Document begins with the following tag:
<!-- HELPDOC:FOOTERBEGIN -->
Adding links
You can add links to any external or internal URL as well as any other segment. However, you must follow some conventions: v External URLs are used in the standard manner. This includes internal links to external URLs v Internal links within the same topic are written in the standard way, but must not have ".html" as part of the tag name. This is because the Help Document processor assumes that any link with .html will need to be an external link when the topics are separate. Therefore, it removes the preceding "#". v Links to other topic segments must be written with a preceding "#" as though they are an internal anchor reference. v Internal links to other topic segments may also be created. Only the leading "#" is removed during processing. Note:
306
v At run-time, the PanelManager class looks for help files in a subdirectory with the same name as the PDML file. When the processor splits the Help Document, it creates this subdirectory by default and places the resulting HTML files in it. v The processor does not make any adjustments for external URL references that are relative links. When you link from an individual topic file, any relative links will be searching from the new subdirectory. Therefore, you will need to place copies of resources such as images where they can be found or use "../" in the path in order to search from the panel directory.
307
public class SampleApplet extends JApplet { // The following are needed to maintain the panel's size private PanelManager m_pm; private Dimension m_panelSize;
308
// Define an exception to throw in case something goes wrong class SampleAppletException extends RuntimeException {} public void init() { System.out.println("In init!"); // Trace applet parameters System.out.println("SampleApplet code base=" + getCodeBase()); System.out.println("SampleApplet document base=" + getDocumentBase()); // Do a check to make sure we're running a Java virtual machine that's compatible with Swing 1.1 if (System.getProperty("java.version").compareTo("1.1.5") < 0) throw new IllegalStateException("SampleApplet cannot run on Java VM version " + System.getProperty("java.version") + " - requires 1.1.5 or higher"); // Instantiate the bean object that supplies data to the panel SampleBean bean = new SampleBean(); // Initialize the object bean.load(); // Set up to pass the bean to the panel manager DataBean[] beans = { bean }; // Update the status bar showStatus("Loading the panel definition..."); // // // // // Create the panel manager. Parameters: 1. PDML file as a resource name 2. Name of panel to display 3. List of data objects that supply panel data 4. The content pane of the applet
try { m_pm = new PanelManager("MyGUI", "PANEL_1", beans, getContentPane()); } catch (DisplayManagerException e) { // Something didn't work, so display a message and exit e.displayUserMessage(null); throw new SampleAppletException(); } // Identify the directory where the online help resides m_pm.setHelpPath("http://MyDomain/MyDirectory/"); // Display the panel m_pm.setVisible(true); } public void start() { System.out.println("In start!"); // Size the panel to its predefined size m_panelSize = m_pm.getPreferredSize(); if (m_panelSize != null) { System.out.println("Resizing to " + m_panelSize); resize(m_panelSize); } else System.err.println("Error: getPreferredSize returned null"); } public void stop() {
IBM Toolbox for Java
309
System.out.println("In stop!"); } public void destroy() { System.out.println("In destroy!"); } public void paint(Graphics g) { // Call the parent first super.paint(g); // Preserve the panel's predefined size on a repaint if (m_panelSize != null) resize(m_panelSize); } }
The applet's content pane is passed to the Graphical Toolbox as the container to be laid out. In the start method, the applet pane is set to its correct size, and then override the paint method in order to preserve the panel's size when the browser window is resized. When running the Graphical Toolbox in a browser, the HTML files for your panel's online help cannot be accessed from a JAR file. They must reside as separate files in the directory where your applet resides. The call to PanelManager.setHelpPath identifies this directory to the Graphical Toolbox, so that your help files can be located.
HTML tags
Because it is recommended to use Sun's Java Plug-in to provide the correct level of the Java runtime environment, the HTML for identifying a Graphical Toolbox applet is not as straightforward as preferred. Fortunately, the same HTML template may be reused, with only slight changes, for other applets. The markup is designed to be interpreted in both Netscape Navigator and Internet Explorer, and it generates a prompt for downloading the Java Plug-in from Sun's Web site if it's not already installed on the user's machine. For detailed information on the workings of the Java Plug-in see the Java Plug-in HTML Specification. Here is the HTML for the sample applet, in the file MyGUI.html:
<html> <head> <title>Graphical Toolbox Demo</title> </head> <body> <h1>Graphical Toolbox Demo Using Java(TM) Plug-in</h1> <p> <!-- BEGIN JAVA(TM) PLUG-IN APPLET TAGS --> <!-- The following tags use a special syntax which allows both Netscape and Internet Explorer to load --> <!-- the Java Plug-in and run the applet in the Plug-in's JRE. Do not modify this syntax. --> <!-- For more information see http://java.sun.com/products/jfc/tsc/swingdoc-current/java_plug_in.html.--> <OBJECT classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93" width="400" height="200" align="left" codebase="http://java.sun.com/products/plugin/1.1.3/jinstall-113-win32.cab#Version=1,1,3,0"> <PARAM name="code" value="SampleApplet"> <PARAM name="codebase" value="http://www.mycompany.com/~auser/applets/">
310
<PARAM name="archive" value="MyGUI.jar,jui400.jar,util400.jar,x4j400.jar"> <PARAM name="type" value="application/x-java-applet;version=1.1"> <COMMENT> <EMBED type="application/x-java-applet;version=1.1" width="400" height=200" align="left" code="SampleApplet" codebase="http://www.mycompany.com/~auser/applets/" archive="MyGUI.jar,jui400.jar,util400.jar,x4j400.jar" pluginspage="http://java.sun.com/products/plugin/1.1.3/plugin-install.html"> <NOEMBED> </COMMENT> No support for JDK 1.1 applets found! </NOEMBED> </EMBED> </OBJECT> <!-- END JAVA(TM) PLUG-IN APPLET TAGS --> <p> </body> </html>
It is important that the version information be set for 1.1.3. Note: In this example, the XML parser JAR file, x4j400.jar, is stored on the Web server. You can use other XML parsers. For more information, see XML parser and XSLT processor on page 415. This is required only when you include your PDML file as part of your applet's installation. For performance reasons, you would normally serialize your panel definitions so that the Graphical Toolbox does not have to interpret the PDML at runtime. This greatly improves the performance of your user interface by creating compact binary representations of your panels. For more information see the description of files generated by the tools.
311
Click Pointer to move and resize a component on a panel. Click Label to insert a static label on a panel. Click Text to insert a text box on a panel. Click Button to insert a button on a panel. Click Combo Box to insert a drop down list box on a panel. Click List Box to insert a list box on a panel.
312
Click Radio Button to insert a radio button on a panel. Click Checkbox to insert a check box on a panel. Click Spinner to insert a spinner on a panel. Click Image to insert an image on a panel. Click Menu Bar to insert a menu bar on a panel. Click Group Box to insert a labeled group box on a panel. Click Tree to insert an hierarchical tree on a panel. Click Table to insert a table on a panel. Click Slider to insert an adjustable slider on a panel. Click Progress Bar to insert a progress bar on a panel. Click Deck Pane to insert a deck pane on a panel. A deck pane contains a stack of panels. The user can select any of the panels, but only the selected panel is fully visible. Click Split Pane to insert a split pane on a panel. A split pane is one pane divided into two horizontal or vertical panes. Click Tabbed Pane to insert a tabbed pane on a panel. A tabbed pane contains a collection of panels with tabs at the top. The user clicks a tab to display the contents of a panel. The title of the panel is used as the text for a tab. Click Custom to insert a custom-defined user interface component on a panel. Click Toolbar to insert a toolbar on a panel. Click Toggle Grid to enable a grid on a panel. Click Align Top to align multiple components on a panel with the top edge of a specific, or primary, component. Click Align Bottom to align multiple components on a panel with the bottom edge of a specific, or primary, component.
313
Click Equalize Height to equalize the height of multiple components with the height of a specific, or primary, component. Click Center Vertically to center a selected component vertically relative to the panel. Click Toggle Margins to view the margins of the panel. Click Align Left to align multiple components on a panel with the left edge of a specific, or primary, component. Click Align Right to align multiple components on a panel with the left edge of a specific, or primary, component. Click Equalize Width to equalize the width of multiple components with the width of a specific, or primary, component. Click Center Horizontally to center a selected component horizontally relative to the panel. Click Cut to cut panel components. Click Copy button to copy panel components. Click Paste to paste panel components between different panels or files. Click Undo to undo the last action. Click Redo to redo the last action. Click Tab Order to control the selection order of each panel component when the user presses TAB to navigate through the panel. Click Preview to display a preview of what a panel will look like. Click Help to get more specific information about the Graphical Toolbox.
314
Many IBM Toolbox for Java public classes are also JavaBeans. These classes were built to Javasoft JavaBean standards; they function as reuseable components. The properties and methods for an IBM Toolbox for Java bean are the same as the properties and methods of the class. JavaBeans can be used within an application program or they can be visually manipulated in builder tools, such as the IBM VisualAge for Java product.
Examples
The following examples show how to use JavaBeans in your program and how to create a program from JavaBeans by using a visual bean builder: Example: IBM Toolbox for Java bean code on page 554 Example: Creating beans with a visual bean builder on page 555
JDBC
JDBC is an application programming interface (API) included in the Java platform that enables Java programs to connect to a wide range of databases. The IBM Toolbox for Java JDBC driver allows you to use JDBC API interfaces to issue structured query language (SQL) statements to and process results from databases on the server. You can also use IBM Developer Kit for Java JDBC driver, called the 'native' JDBC driver: v Use the IBM Toolbox JDBC driver when the Java program is on one system and the database files are on another system, as in a client/server environment v Use the native JDBC driver when both the Java program and database files are on the same server
Enhancements to IBM Toolbox for Java JDBC support for IBM i 7.1
Many additions were made to JDBC support in IBM i 7.1. The enhancements to IBM Toolbox for Java JDBC support are detailed in the following sections: v XML data type support on page 316 v v v v Database metadata updates on page 317 Currently committed support on page 317 Array type support on page 317 Long schema name support on page 318
315
| XML data type support | The JDBC 4.0 interface specification adds new methods and classes for XML data type support. IBM | Toolbox for Java implements XML support in its JDBC 4.0 driver. This allows JDBC clients easy access to | IBM i 7.1 XML support. | You can set the data in the JDBC SQLXML object by passing in various data types such as Java String. As | is done for all other text column data types, IBM Toolbox for Java or the Database Management System | (DBMS) does the necessary conversions of XML data to match column CCSID for the XML column. | The DBMS reads and writes XML data using SQL locators. | | | | | | | XML being sent as input to the DBMS has to be handled with a few special rules in order for correct CCSID conversion. Input XML data which has an XML declaration with encoding specified must correctly encode the XML data with that specified encoding. For example XML encoded in UTF-16 (Java String), but having a UTF-8 specified in its encoding in the XML declaration is incorrect. If the XML input data has no declaration, then the DBMS expects the data stream to be sent in UTF-8. In this case IBM Toolbox for Java first converts the XML data to UTF-8 before sending the data to the DBMS for processing.
| Note: XML columns in the database are stored without the XML declaration. When the XML data is retrieved, the XML declaration is dynamically generated, which can lead to the XML data not | being identical to the XML data that was sent as input. | | | | | | | | | | | | | | | The DBMS may optimize XML data when appropriate. For example an empty tag, "<tag><tag/>", becomes "</tag>". Generally if input XML data that is not in UTF-16 and has an XML declaration along with an encoding specified, it should not be passed into JDBC through PreparedStatement.setString. This is because the data in Strings is UTF-16 and it does not match the specified encoding. There are some rules that govern how XML declarations are returned from a query. JDBC handles the declaration visibility depending on which type ResultSet getter method called. Methods that return characters, such as getString() and getClob(), do not return the XML declaration with the data. Methods that return binary data, such as getBytes() and getBlob(), will return the XML declaration. This is due to the difference in XML declaration encoding and the CCSID of the actual XML column on the table. Note that calling getString() will return a Unicode String, which could be different from the CCSID specified in the XML declaration encoding. Because of this anomaly, the declaration is simply discarded unless accessed with binary getter methods. The retrieval of XML tags with methods such as getString will allow XML data to be easily concatenated with other XML data since it will have its declaration removed already.
| XML JDBC support is implemented in the following IBM Toolbox for Java JDBC methods: | v AS400JDBCConnection.createSQLXML() | v AS400JDBCSQLXML - all methods in this new class | v AS400JDBCPreparedStatement.setSQLXML(int parameterIndex, SQLXML xmlObject) | | | | v v v v | v | v | v | v | v AS400JDBCCallableStatement.setSQLXML(String parameterName, SQLXML xmlObject) AS400JDBCCallableStatement.getSQLXML(int parameterIndex) AS400JDBCCallableStatement.getSQLXML(String parameterName) AS400JDBCResultSet.getSQLXML(int columnIndex) AS400JDBCResultSet.getSQLXML(String columnLabel) AS400JDBCResultSet.updateSQLXML(int columnIndex, SQLXML xmlObject) AS400JDBCResultSet.updateSQLXML(String columnLabel, SQLXML xmlObject) AS400JDBCRowSet.setSQLXML(int parameterIndex, SQLXML xmlObject) AS400JDBCRowSet.setSQLXML(String parameterName, SQLXML xmlObject)
IBM i: Programming IBM Toolbox for Java
316
| | | | | | | | | |
| In order to provide backwards compatibility of the metadata functionality, a new connection property, | "metadata source", can be used to force IBM Toolbox for Java JDBC to use the old method of retrieval of | database metadata. | | | | | |
| Under the new currently committed semantics, if currently committed is enabled then only committed data | is returned, as was the case previously, but now readers do not wait for writers to release row locks. | Instead, the data returned to readers is based on the currently committed version; that is, data prior to | the start of the write operation. | This feature also implements a way to direct the database manager to wait for the outcome when | encountering data in the process of being updated. | | | | | | IBM Toolbox for Java JDBC has added support for currently committed semantics on data sources and connections. This support is added with the following class updates: v AS400JDBCDataSource.CONCURRENTACCESS_NOT_SET v AS400JDBCDataSource.CONCURRENTACCESS_USE_CURRENTLY_COMMITTED v AS400JDBCDataSource.CONCURRENTACCESS_WAIT_FOR_OUTCOME v AS400JDBCDataSource.CONCURRENTACCESS_SKIP_LOCKS
| v AS400JDBCDataSource.setConcurrentAccessResolution (int) | v AS400JDBCDataSource.getConcurrentAccessResolution () | v AS400JDBCConnection.setConcurrentAccessResolution (int) | v AS400JDBCConnection.getConcurrentAccessResolution () | Note: Setting concurrent access resolution on the connection only affects new statements created on the connections following the change. Existing statements continue to use the value that was in effect | when the statement was created. A corresponding connection property "concurrent access | resolution" is also available for setting this information. | | | |
317
| IBM Toolbox for Java JDBC adds support for arrays as IN, OUT, and INOUT parameters to stored | procedures. However, ResultSets returned from stored procedures or other queries containing arrays is | not supported. | JDBC supports the calling of stored procedures in the java.sql.CallableStatement class, which IBM Toolbox | for Java implements in AS400JDBCCallableStatement. | | | | | | | | | | | The JDBC specification from Sun says that JDBC drivers support arrays by implementing java.sql.Array interface. The IBM Toolbox for Java implementation exists in the class com.ibm.as400.access.AS400JDBCArray. Below are new interfaces and methods which IBM Toolbox for Java has implemented to support arrays: v AS400JDBC.PreparedStatement.setArray (int parameterIndex, Array x) v AS400JDBCCallableStatement.getArray() v AS400JDBCArray.getResultSet() v v v v AS400JDBCArray.getBaseType() AS400JDBCArray.getBaseTypeName() AS400JDBCArrayResultSet - all methods in this new class AS400JDBConnection.createArrayOf(String typeName, Object[] elements)
| Note: An AS400JDBCArrayResultSet is a local copy of the array data in a ResultSet interface object. | Long schema name support | IBM i 7.1 DBMS has added support for 128 byte schema names. IBM Toolbox for Java JDBC is also | adding support for long schema names. | | | | | | | IBM Toolbox for Java converts schemas from Java Strings to the system CCSID prior to sending the data to the host DBMS. IBM Toolbox for Java does allow a long schema name as the default-schema. However, long schema names in the library list is not supported. If a long schema name is specified in the "libraries" property, a warning back from host and trace that the library was not added will be issued. If a long schema name is specified as the first name in the "libraries" property, then IBM Toolbox for Java still sets the name as the default schema, but does not add it to the library list. Clients which need to use long schema names in the library list have to make use of the DB2 SET PATH command.
| Database metadata also supports long schema names for parameters and ResultSets returned. | The following metadata methods provide support for long schema names: | v AS400JDBCDatabaseMetadata.getMaxSchemaNameLength() | v AS400JDBCDatabaseMetadata.getProcedures(String catalog, String schemaPattern, String procedureNamePattern) | | v AS400JDBCDatabaseMetadata.getProcedureColumns(String catalog, String schemaPattern, String procedureNamePattern, String columnNamePattern) | | v AS400JDBCDatabaseMetadata.getTables(String catalog, String schemaPattern, String tableNamePattern, String types[]) | | v AS400JDBCDatabaseMetadata.getSchemas() | v AS400JDBCDatabaseMetadata.getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) | | v AS400JDBCDatabaseMetadata.getColumnPrivileges(String catalog, String schema, String table, String columnNamePattern) | | v AS400JDBCDatabaseMetadata.getTablePrivileges(String catalog, String schemaPattern, String tableNamePattern) |
318
| | | | | | | | | | | | | | | | | | | | | | |
v AS400JDBCDatabaseMetadata.getBestRowIdentifier(String catalog, String schema, String table, int scope, boolean nullable) v AS400JDBCDatabaseMetadata.getVersionColumns(String catalog, String schema, String table) v AS400JDBCDatabaseMetadata.getPrimaryKeys(String catalog, String schema, String table) v AS400JDBCDatabaseMetadata.getImportedKeys(String catalog, String schema, String table) v AS400JDBCDatabaseMetadata.getCrossReference( String parentCatalog, String parentSchema, String parentTable, String foreignCatalog, String foreignSchema, String foreignTable) v AS400JDBCDatabaseMetadata.getIndexInfo(String catalog, String schema, String table, boolean unique, boolean approximate) v AS400JDBCDatabaseMetadata.getUDTs(String catalog, String schemaPattern, String typeNamePattern, int[] types) v AS400JDBCDatabaseMetadata.getSuperTypes(String catalog, String schemaPattern, String typeNamePattern) v AS400JDBCDatabaseMetadata.getSuperTables(String catalog, String schemaPattern, String tableNamePattern) v AS400JDBCDatabaseMetadata.getAttributes(String catalog, String schemaPattern, String typeNamePattern, String attributeNamePattern) v AS400JDBCDatabaseMetadata.getSchemas(String catalog, String schemaPattern) v AS400JDBCDatabaseMetadata.getFunctions(String catalog, String schemaPattern, String functionNamePattern) v AS400JDBCDatabaseMetadata.getFunctionColumns(String catalog, String schemaPattern, String functionNamePattern, String columnNamePattern)
Enhancements to IBM Toolbox for Java JDBC support for IBM i 6.1
Many additions were made to JDBC support in IBM i 6.1. The enhancements to IBM Toolbox for Java JDBC support are detailed in the following sections: v Support for JDBC 4.0 v Query storage limit v v v v v v v Decimal float (DECFLOAT) data type on page 320 Passing the client type and application name to the server on page 321 Maximum length of cursor names extended on page 322 Generated key support on page 322 Improved default value support on page 322 Increased maximum in GROUP BY clause on page 322 Batch update support on page 322
319
Beginning in V6R1, the IBM Toolbox for Java JDBC driver will add the following methods to the AS400JDBCDataSource class: setQueryStorageLimit() public void setQueryStorageLimit(int limit); Specifies the query storage limit value to be used when statements in a connection are executed. Valid values are -1 to 2 147 352 578. The default is value -1, indicating a special value of *NOMAX. getQueryStorageLimit() public int getQueryStorageLimit() Returns the query storage limit value used when statements in a connection are executed. The default value is -1, indicating a special value of *NOMAX. Systems that run a release of IBM i prior to V6R1 will ignore the getQueryStorageLimit property.
half down Round to the nearest digit. If equidistant between two digits, round down. The numeric value of this constant is 5. up Round to nearest higher digit. The numeric value of this constant is 6.
320
ClientAccounting ClientHostname
255 255
"" ""
ClientProgramID ClientUser
255 255
"" ""
321
Enhancements to IBM Toolbox for Java JDBC support for IBM i 5.4
Several JDBC functions were enhanced for IBM i 5.4. The enhancements to IBM Toolbox for Java JDBC support are detailed in the following sections: v 2 MB statement size on page 323 v 128 byte column name support on page 323
322
v Database host server trace support v eWLM Correlator support For information about enhanced JDBC functions for previous releases, see Enhancements to JDBC support for Version 5 Release 3 on page 324 and Enhanced JDBC functions for i5/OS Version 5 Release 2 on page 325.
2 MB statement size
Prior to V5R4, the limit on SQL statement size was 65 535 bytes. This corresponds to 65 535 characters when the statement text is represented using a single-byte CCSID, and 32 767 characters when the statement text is represented using a double-byte CCSID. Some customers, particularly those using applications that automatically generate SQL statements, were affected by this limit. In V5R4, the IBM i statement size limit has been increased to two megabytes, or 2 097 152 bytes. The IBM Toolbox for Java JDBC driver always sends statement text in two byte Unicode. Therefore, the maximum statement length in characters will be one megabyte or 1 048 576 characters.
Sets the eWLM Correlator. It is assumed a valid correlator value is used. If the value is null, all ARM/eWLM implementation will be turned off. eWLM correlators require i5/OS V5R3 or later servers. This request is ignored when running to V5R2 or earlier servers. Parameters: v bytes: The eWLM correlator value v SQLException: See the Class SQLException information at the Sun Microsystems, Inc. Web site.
323
For information about enhanced JDBC functions for previous releases, see Enhancements to JDBC support for Version 5 Release 3 and Enhanced JDBC functions for i5/OS Version 5 Release 2 on page 325.
For information about enhanced JDBC functions for previous releases, see V5R2 enhancements to IBM Toolbox for Java JDBC support. UTF-8 and UTF-16 support UTF-8 data is stored in a character field with a CCSID of 1208. A UTF-8 character is a variable number of bytes (one, two, three, or four) for a non-combining character, and any number of bytes for a combining character. The length specified for a character field is the maximum number of bytes the field can contain. You can tag the following data types with a UTF-8 1208 CCSID: v Fixed length character (CHAR) v Variable length character (VARCHAR) v Character LOB (CLOB) UTF-16 data is stored in a graphic field with a CCSID of 1200. A UTF-16 character can be either two or four bytes (that is, Surrogate) in length for a non-combining character and any number of bytes for a combining character. The length specified for a graphic data field is the maximum number of two bytes characters the field can contain. You can tag the following data types with a UTF-16 1200 CCSID: v Fixed length graphic (GRAPHIC) v Variable length graphic (VARGRAPHIC) v Double-byte character LOB (DBCLOB) Binary and Varbinary support The BINARY and VARBINARY data types are similar to the CHAR and VARCHAR data types, but contain binary data rather than character data. BINARY fields have a fixed length. VARBINARY fields are of varying length. The BINARY and VARBINARY data types have the following characteristics: v The coded character set identifier (CCSID) for binary types is 65535 v In assignments and comparisons, binary data types are compatible only with other binary data types (BINARY, VARBINARY, and BLOB) v The pad character for binary data types is x'00' instead of the blank character v In situations requiring trailing characters to be stripped to prevent truncation errors, x'00' characters are stripped instead of trailing blanks v When comparing binary data types, for two fields to be equal both the data and the lengths must be the same. Trailing zeros are not ignored in comparisons
324
v When comparing binary data types, if two fields have different lengths, the shorter field is considered less than the longer field if the fields are the same up to the length of the shorter field Increased Decimal Precision support Decimal precision now supports up to 63 digits. Three properties were added, "minimum divide scale", "maximum precision", and "maximum scale" and six methods added to AS400JDBCDataSource, setMinimumDivideScale(int divideScale), getMinimumDivideScale(), setMaximumPrecision(int precision), getMaximumPrecision(), setMaximumScale(int scale), and getMaximumScale(). Minimum divide scale specifies the minimum scale value for the result of decimal division and is set to any number between 0 and 9. Maximum precision specifies the maximum decimal precision the database uses and is set to either 31 or 63. Maximum scale specifies the maximum scale the database uses and is set to any number between 0 and 63. 2 GB large object (LOB) support Enhancements for IBM Toolbox for Java JDBC now allow the use of up to 2 GB LOBs support. Insensitive cursor support Cursor support now supports insensitive cursors. When using a ResultSet with TYPE_SCROLL_INSENSITIVE, an insensitive cursor is used. The ResultSet does not show changes to the underlying database while it is open. Materialized Query Table support Returns "MATERIALIZED QUERY TABLE" as the TABLE_TYPE in a call to DatabaseMetaData.getTables().
Removal of the 'FOR UPDATE' restriction You no longer need to specify FOR UPDATE on your SELECT statements in order to guarantee an updatable cursor. When connecting to V5R1 and later versions of i5/OS, IBM Toolbox for Java honors whatever concurrency you pass in when you create statements. The default continues to be a read-only cursor if you do not specify a concurrency. Data truncation throws exceptions only when truncated character data is written to the database Data truncation rules for IBM Toolbox for Java now are the same as those for the IBM Developer Kit for Java JDBC driver. For more information, see IBM Toolbox for Java JDBC properties. Get and modify columns and parameters by name New methods allow you to get and update information by column name in ResultSet and to get and set information by parameter name in CallableStatement. For example, in ResultSet, where you previously used the following:
ResultSet rs = statement.executeQuery( SELECT * FROM MYCOLLECTION/MYTABLE ); rs.getString(1);
325
Be aware that accessing parameters by their index results in better performance than accessing them by their name. You can also specify parameter names to set in CallableStatement. Where you might have used the following in CallableStatement:
CallableStatement cs = connection.prepareCall( CALL MYPGM (?) ); cs.setString( 1 );
To use these new methods, you need JDBC 3.0 or later and the Java 2 Platform, version 1.4 (either the Standard or the Enterprise Edition). Retrieve auto-generated keys The getGeneratedKeys() method on AS400JDBCStatement retrieves any auto-generated keys created as a result of executing that Statement object. When the Statement object does not generate any keys, an empty ResultSet object is returned. Currently the server supports returning only one auto-generated key (the key for the last inserted row). The following example shows how you might insert a value into a table then get the auto-generated key:
Statement s = statement.executeQuery("INSERT INTO MYSCHOOL/MYSTUDENTS (FIRSTNAME) VALUES ('JOHN'"); ResultSet rs = s.getGeneratedKeys(); // Currently the server supports returning only one auto-generated // key -- the key for the last inserted row. rs.next(); String autoGeneratedKey = rs.getString(1); // Use the auto-generated key, for example, as the primary key in another table
To retrieve auto-generated keys, you need JDBC 3.0 or later, and the Java 2 Platform, version 1.4 (either the Standard or the Enterprise Edition). Retrieving auto-generated keys also requires connecting to a V5R2 or later version of i5/OS. Improved performance when running SQL insert statements in a batch Performance of running SQL insert statements in a batch has been improved. Run SQL statements in a batch by using the different addBatch() methods available in AS400JDBCStatement, AS400JDBCPreparedStatement, and AS400JDBCCallableStatement. Enhanced batch support affects only insert requests. For example, using batch support to process several inserts involves only one pass to the server. However, using batch support to process an insert, and update, and a delete sends each request individually. To use batch support, you need JDBC 2.0 or later and the Java 2 Platform, version 1.2 (either the Standard or the Enterprise Edition). Enhanced support for ResultSet.getRow() Previously, the IBM Toolbox for Java JDBC driver was limited in its support for the getRow() method in ResultSet. Specifically, using ResultSet.last(), ResultSet.afterLast(), and ResultSet.absolute() with a negative value made the current row number not available. The previous restrictions are lifted, making this method fully functional. Using mixed case in column names IBM Toolbox for Java methods must match either column names provided by the user or column names provided by the application with the names that are on the database table. In either case, when a column name is not enclosed in quotes, IBM Toolbox for Java changes the name to
326
uppercase characters before matching it against the names on the server. When the column name is enclosed in quotes, it must exactly match the name on the server or IBM Toolbox for Java throws an exception. Specify holdability in created Statements, CallableStatements, and PreparedStatements New methods in AS400JDBCConnection allow you to specify the holdability for Statements, CallableStatements, and PreparedStatements that you create. Holdability determines whether cursors are held open or closed when committing the transaction. You can now have a statement that has a different holdability than its connection object. Also, connection objects can have multiple open statement objects, each with a different specified holdability. Calling commit causes each statement to be handled according to the holdability specified for that statement. Holdability is derived in the following order of precedence: 1. Holdability specified on statement creation by using the Connection class methods createStatement(), prepareCall(), or prepareStatement(). 2. Holdability specified by using Connection.setHoldability(int). 3. Holdability specified by the IBM Toolbox for Java JDBC cursor hold property (when methods in 1. or 2. are not used) To use these methods, you need JDBC 3.0 or later, and the Java 2 Platform, version 1.4 (either the Standard or the Enterprise Edition). Also, servers running a V5R1 or earlier version of i5/OS are able to use only the holdability specified by the JDBC cursor hold property. Enhanced transaction isolation support The IBM Toolbox for Java JDBC driver now features support for switching to a transaction isolation level of *NONE after a connection is made. Before V5R2, the IBM Toolbox for Java JDBC driver threw an exception when switching to *NONE after making a connection.
General properties
General properties are system attributes that specify the user, password, and whether a prompt is necessary to connect to the server.
Property "password" Description Specifies the password for connecting to the server. If none is specified, then the user will be prompted, unless the "prompt" property is set to "false", in which case an attempt to connect will fail. Required no Choices system password Default (user will be prompted)
327
Property "prompt"
Description Specifies whether the user is prompted if a user name or password is needed to connect to the server. If a connection cannot be made without prompting the user, and this property is set to "false", then an attempt to connect will fail. Specifies the user name for connecting to the server. If none is specified, then the user will be prompted, unless the "prompt" property is set to "false", in which case an attempt to connect will fail.
Required no
Default "true"
"user"
no
server user
Server properties
Server properties specify attributes that govern transactions, libraries, and databases.
Property Description Specifies whether auto-commit mode is the default connection mode for new connections. Calling AS400JDBCConnection.setAutoCommit() will override this property on a per-connection basis. Note: In order to use transaction isolation levels other than *NONE when using auto-commit mode, the property "true autocommit" needs to be set to true. Required Choices no "true" "false" Default "true"
| | | | | | | | | | | | | | | | | | | |
"auto commit"
"concurrent Specifies whether "currently committed" access resolution" access is used on the connection. A value of 1 indicates that "currently committed" will be used. A value of 2 indicates that "wait for outcome" will be used. A value of 3 indicates that "skip locks" will be used. "cursor hold" Specifies whether to hold the cursor across transactions. If this property is set to "true", cursors are not closed when a transaction is committed or rolled back. All resources acquired during the unit of work are held, but locks on specific rows and objects implicitly acquired during the unit of work are released. Specifies the cursor sensitivity to request from the database. The behavior depends on the resultSetType: v ResultSet.TYPE_FORWARD_ONLY or ResultSet.TYPE_SCROLL_SENSITIVE means that the value of this property controls what cursor sensitivity the Java program requests from the database. v ResultSet.TYPE_SCROLL_INSENSITIVE causes this property to be ignored.
no
(system default)
no
"true" "false"
"true"
"cursor sensitivity"
no
"asensitive"
328
Property
Description Specifies the database to use for the connection to an independent auxiliary storage pool (ASP). This property applies only when connecting to an IBM i server. When you specify a database name, the name must exist in the relational database directory on the server and correspond to either an independent ASP or the system default database. The following criteria determine which database is accessed: v When this property is used to specify a database which corresponds to an independent ASP, the connection is made to the independent ASP. When the specified database does not exist, the connection fails. v When this property is used to specify *SYSBAS as the database name, the system default database is used. v When this property is omitted, the initial ASP group specified in the job description for the user profile is used. When the job description does not specify an initial ASP group, the system default database is used.
Default The database name specified in the job description for the user profile is used. When the job description does not specify a database name, the system default database is used.
| | | | | | | | | | | | | | | | | | | | | | | | |
"database name"
Specifies the rounding mode to use when working with the decfloat data type. This property is ignored when connecting to systems running IBM i 5.4 and earlier.
no
"half even" "half up" "down" "ceiling" "floor" "half down" "up"
"half even"
329
Property
Description Specifies one or more libraries that you want to add to or replace the library list of the server job, and optionally sets the default SQL schema (default library). Note that libraries cannot be longer than 10 characters in length. You must use the SET PATH SQL statement if you have libraries longer than 10 characters. Library list The server uses specified libraries to resolve unqualified stored procedure names, and stored procedures use them to resolve unqualified names. To specify multiple libraries, use commas or spaces to separate individual entries. You can use *LIBL as a placeholder for the current library list of the server job v When the first entry is *LIBL, the specified libraries are added to the current library list of the server job v When you do not use *LIBL, the specified libraries replace the current library list of the server job For more information about library list properties, see JDBC LibraryList property. Default SQL schema The server uses the default SQL schema to resolve unqualified names in SQL statements. For example, in the statement "SELECT * FROM MYTABLE", the server looks only in the default SQL schema for MYTABLE. You can specify the default SQL schema on the connection URL. When you do not specify the default SQL schema on the connection URL, the following conditions apply, depending on the SQL naming convention that is used: v If SQL Naming is being used: The first entry (unless it is *LIBL) becomes the default SQL schema When the first entry is *LIBL, the second entry becomes the default SQL schema When you do not set this property or when it contains only *LIBL, the user profile becomes the default SQL schema v If System Naming is being used: No default SQL schema is set, and the server uses the specified libraries to search for unqualified names When you do not set this property or when it contains only *LIBL, the server uses the current library list of the server job to search for unqualified names
Required Choices no
Default
| | | | | | | |
"libraries"
330
Description Specifies the maximum decimal precision the database might use. Specifies the maximum scale the database might use.
Required Choices no "31" "63" no no "0"-"63" "0" "1" "2" "3" "4" "5" "6" "7" "8" "9"
Default "31"
"31" "0"
"minimum divide Specifies the minimum scale value for the scale" result of decimal division.
"package ccsid"
Specifies the character encoding to use for the SQL package and any statements sent to the server. Specifies the default transaction isolation.
no
"13488"
"transaction isolation"
no
"read uncommitted"
"translate hex"
no
"character" (Interpret hexadecimal literals as character data) "binary" (Interpret hexadecimal literals as binary data)
"character"
"true autocommit"
Specifies whether the connection should use true auto commit support. True autocommit means that autocommit is on and is running under a isolation level other than *NONE. By default, the driver handles autocommit by running under the server isolation level of *NONE. Specifies whether lock sharing is allowed for loosely coupled transaction branches. Note: This setting is ignored when running to IBM i 5.3 or earlier.
no
"true" (Use true "false" autocommit.) "false" (Do not use true autocommit.)
no
"0"
331
Format properties
Format properties specify date and time formats, date and decimal separators, and table naming conventions used within SQL statements.
Property "date format" Description Specifies the date format used in date literals within SQL statements. Required no Choices "mdy" "dmy" "ymd" "usa" "iso" "eur" "jis" "julian" "date separator" Specifies the date separator used in date literals within SQL statements. This property has no effect unless the "date format" property is set to "julian", "mdy", "dmy" or "ymd". Specifies the decimal separator used in numeric literals within SQL statements. Specifies the naming convention used when referring to tables. no "/" (slash) "-" (dash) "." (period) "," (comma) "b" (space) "decimal separator" "naming" no "." (period) "," (comma) no "sql" (as in schema.table) "system" (as in schema/table) "hms" "usa" "iso" "eur" "jis" "time separator" Specifies the time separator used in time literals within SQL statements. This property has no effect unless the "time format" property is set to "hms". no ":" (colon) "." (period) "," (comma) "b" (space) (server job) "sql" (server job) (server job) Default (server job)
"time format"
Specifies the time format used in time literals within SQL statements.
no
(server job)
Performance properties
Performance properties are attributes that include caching, data conversion, data compression, and prefetching that affect performance.
332
Description Specifies whether an intermediate java.math.BigDecimal object is used for packed and zoned decimal conversions. If this property is set to "true", an intermediate java.math.BigDecimal object is used for packed and zoned decimal conversions as described by the JDBC specification. If this property is set to "false", no intermediate objects are used for packed and zoned decimal conversions. Instead, such values are converted directly to and from Java double values. Such conversions will be faster but may not follow all conversion and data truncation rules documented by the JDBC specification. Specifies the criteria for retrieving data from the server in blocks of records. Specifying a non-zero value for this property will reduce the frequency of communication to the server, and therefore improve performance. Ensure that record blocking is off if the cursor is going to be used for subsequent UPDATEs, or else the row that is updated will not necessarily be the current row.
Required no
Default "true"
"block criteria"
no
"0" (no record blocking) "1" (block if FOR FETCH ONLY is specified) "2" (block unless FOR UPDATE is specified)
"2"
"block size"
Specifies the block size (in kilobytes) to retrieve from the server and cache on the client. This property has no effect unless the "block criteria" property is non-zero. Larger block sizes reduce the frequency of communication to the server, and therefore may improve performance.
no
"32"
"data compression"
Specifies whether result set data is compressed. If this property is set to "true", then result set data is compressed. If this property is set to "false", then result set data is not compressed. Data compression may improve performance when retrieving large result sets.
no
"true" "false"
"true"
333
Description Specifies whether to use extended dynamic support. Extended dynamic support provides a mechanism for caching dynamic SQL statements on the server. The first time a particular SQL statement is prepared, it is stored in a SQL package on the server. If the package does not exist, it is automatically created. On subsequent prepares of the same SQL statement, the server can skip a significant part of the processing by using information stored in the SQL package. If this is set to "true", then a package name must be set using the "package" property. Specifies whether to delay closing cursors until subsequent requests. This will improve overall performance by reducing the total number of requests. Specifies the maximum LOB (large object) size (in bytes) that can be retrieved as part of a result set. LOBs that are larger than this threshold will be retrieved in pieces using extra communication to the server. Larger LOB thresholds will reduce the frequency of communication to the server, but will download more LOB data, even if it is not used. Smaller LOB thresholds may increase frequency of communication to the server, but will only download LOB data as it is needed. Specifies the base name of the SQL package. Note that only the first seven characters are used to generate the name of the SQL package on the server. This property has no effect unless the "extended dynamic" property is set to "true". In addition, this property must be set if the "extended dynamic" property is set to "true". Specifies whether to add newly prepared statements to the SQL package specified on the "package" property. This property has no effect unless the "extended dynamic" property is set to "true". Specifies whether to cache a subset of the SQL package information in client memory. Caching SQL packages locally reduces the amount of communication to the server for prepares and describes. This property has no effect unless the "extended dynamic" property is set to "true".
Required no
Default "false"
"lazy close"
no
"true" "false"
"false"
"lob threshold"
no
"0" - "16777216"
"32768"
"package"
no
SQL package
""
"package add"
no
"true" "false"
"true"
"package cache"
no
"true" "false"
"false"
334
Description Specifies the type of SQL statements to be stored in the SQL package. This can be useful to improve the performance of complex join conditions. This property has no effect unless the "extended dynamic" property is set to "true".
Required no
Choices
Default
"default" (only "default" store SQL statements with parameter markers in the package) "select" (store all SQL SELECT statements in the package)
"package error"
Specifies the action to take when SQL package errors occur. When a SQL package error occurs, the driver will optionally throw a SQLException or post a notice to the Connection, based on the value of this property. This property has no effect unless the "extended dynamic" property is set to "true". Specifies the library for the SQL package. This property has no effect unless the "extended dynamic" property is set to "true". Specifies whether to prefetch data upon executing a SELECT statement. This will improve performance when accessing the initial rows in the ResultSet. Specifies a QAQQINI library name. Used to specify the library that contains the qaqqini file to use. A qaqqini file contains all of the attributes that can potentially impact the performance of the DB2 for i database engine.
no
"warning"
"package library"
no
"QGPL"
"prefetch"
no
"true" "false"
"true"
"qaqqinilib"
no
(server default)
335
Property
Description
Required no
Choices
Default
"query optimize goal" Specifies the goal the server should use with optimization of queries. This setting corresponds to the server's QAQQINI option called OPTIMIZATION_GOAL. Note: This property is ignored when connecting to systems running to IBM i 5.3 and earlier.
"0" "0" = Optimize query for first block of data (*FIRSTIO) when extended dynamic packages are used; Optimize query for entire result set (*ALLIO) when packages are not used "1" = Optimize query for first block of data (*FIRSTIO) "2" = Optimize query for entire result set (*ALLIO)
Limits the storage used by a query. This property compares the storage limit you specify to the estimated storage usage of the query. If the estimated storage usage exceeds the specified storage limit, the query is not allowed to execute. Specifies the buffer size used to receive data through the socket connection between the front-end driver and the system. Note: This does not specify the actual receive buffer size. It is only used as a hint by the underlying socket code. Specifies the buffer size used to send data through the socket connection between the front-end driver and the system. Note: This does not specify the actual send buffer size. It is only used as a hint by the underlying socket code. Specifies whether variable-length fields should be compressed.
no
no
(platform dependent)
no
(platform dependent)
no
"true" "false"
"true"
336
Sort properties
Sort properties specify how the server performs stores and performs sorts.
Sort property "sort" Description Specifies how the server sorts records before sending them to the client. Required no Choices "hex" (base the sort on hexadecimal values) "language" (base the sort on the language set in the "sort language" property) "table" (base the sort on the sort sequence table set in the "sort table" property) "sort language" Specifies a 3-character language id to use for selection of a sort sequence. This property has no effect unless the "sort" property is set to "language". Specifies the library and file name of a sort sequence table stored on the server. This property has no effect unless the "sort" property is set to "table". Specifies how the server treats case while sorting records. This property has no effect unless the "sort" property is set to "language." no Language id ENU Default "hex"
"sort table"
no
""
"sort weight"
no
"shared" (upperand lowercase characters sort as the same character) "unique" (upperand lowercase characters sort as different characters)
"shared"
Other properties
Other properties are those properties not easily categorized. These properties determine which JDBC driver is used, and specify options related to level of database access, bidirectional string type, data truncation and so on.
Other property "access" Description Specifies the level of database access for the connection. Required no Choices "all" (all SQL statements allowed) "read call" (SELECT and CALL statements allowed) "read only" (SELECT statements only) Default "all"
| | | |
"autocommit Specifies whether to throw an SQLException exception" when Connection.commit() or Connection.rollback() is called if autocommit is enabled.
no
"true" "false"
"false"
337
Description Specifies the output string type of bidirectional data. See BidiStringType for more information.
Required no
Choices
Default
"" (use the CCSID to "" determine bidirectional string type) "0" (the default string type for nonbidirectional data (LTR)) "4" "5" "6" "7" "8" "9" "10" "11"
Specifies if bidi implicit LTR-RTL reordering should be used. Specifies if the numeric ordering round trip feature should be used. Specifies whether truncation of character data generates attention notices and exceptions. When this property is "true", the following apply: v Writing truncated character data to the database throws an exception v Using truncated character data in a query posts an attention notice. When this property is "false", writing truncated data to the database or using such data in a query generates no exception or attention notice. The default value is "true". This property does not affect numeric data. Writing truncated numeric data to the database always throws an error and using truncated numeric data in a query always posts attention notices.
no
"true" "false"
"true"
no
"true" "false"
"false"
no
"true" "false"
"true"
338
Description Specifies the JDBC driver implementation. The IBM Toolbox for Java JDBC driver can use different JDBC driver implementations based on the environment. If the environment is an IBM i JVM on the same server as the database to which the program is connecting, the native IBM Developer Kit for Java JDBC driver can be used. In any other environment, the IBM Toolbox for Java JDBC driver is used. This property has no effect if the "secondary URL" property is set. Specifies the amount of detail to be returned in the message for errors that occur on the server. Specifies whether the driver requests extended metadata from the server. Setting this property to true increases the accuracy of the information returned from the following ResultSetMetaData methods: v getColumnLabel(int) v isReadOnly(int) v isSearchable(int) v isWriteable(int)
Required no
Choices "toolbox" (use only the IBM Toolbox for Java JDBC driver) "native" (use the IBM Developer Kit for Java JDBC driver if running on the server, otherwise use the IBM Toolbox for Java JDBC driver)
Default "toolbox"
"errors"
no
"basic" "full"
"basic"
"extended metadata"
no
"true" "false"
"false"
| | | | |
Additionally, setting this property to true enables support for the ResultSetMetaData.getSchemaName(int) and ResultSetMetaData.isAutoIncrement(int) methods. Note: Setting this property to true may degrade performance because it requires retrieving more information from the server. Leave the property as the default (false) unless you need more specific information from the listed methods. For example, when this property is off (false), ResultSetMetaData.isSearchable(int) always returns "true" because the driver does not have enough information from the server to make a judgment. Turning on this property (true) forces the driver to get the correct data from the server. "full open" Specifies whether the server fully opens a file for each query. By default the server optimizes open requests. This optimization improves performance but may fail if a database monitor is active when a query is run more than once. Set the property to true only when identical queries are issued when monitors are active. Specifies whether input locators should be allocated as type hold locators or not hold locators. If the locators are of type hold, they will not be released when a commit is done. no "true" "false" "false"
no
"true"
339
Description Specifies if statements should remain open until a transaction boundary when autocommit is off and they are associated with a LOB locator. By default, all the resources associated with a statement are released when the statement is closed. Set this property to true only when access to a LOB locator is needed after a statement has been closed. Specifies a list of SQL states for which the driver should not create warning objects. By default, the IBM Toolbox for Java JDBC driver will internally create a java.sql.SQLWarning object for each warning returned by the database. For example, a warning with the SQLSTATE 0100C is created every time a result set is returned from a stored procedure. This warning can be safely ignored to improve the performance of applications that call stored procedures. Specifies whether socket connection is to be periodically checked for operational status. Specifies the key ring class name used for SSL connections with the server. This property has no effect unless "secure" is set to true and a key ring password is set using the "key ring password" property. Specifies the password for the key ring class used for SSL communications with the server. This property has no effect unless "secure" is set to true and a key ring name is set using the "key ring name" property. Specifies how to retrieve DatabaseMetaData. If set to "0," database metadata will be retrieved through the Retrieve Object Information (ROI) data flow. If set to "1," database metadata will be retrieved by calling system stored procedures.
Required no
Default "false"
| | | | | | | | | | |
"ignore warnings"
no
"keep alive"
no
no
no
""
| | | | | |
"metadata source"
no
"0" for IBM i 6.1 and older releases, "1" for all other releases
"proxy server"
Specifies the host name and port of the middle-tier machine where the proxy server is running. The format for this is hostname[:port], where the port is optional. If this is not set, then the hostname and port are retrieved from the com.ibm.as400.access.AS400.proxyServer property. The default port is 3470 (if the connection uses SSL, the default port is 3471). The ProxyServer must be running on the middle-tier machine. The name of the middle-tier machine is ignored in a two-tier environment.
no
Proxy server host name (value of and port the proxyServer property, or none if not set)
340
Description Specifies the source of the text for REMARKS columns in ResultSets returned by DatabaseMetaData methods. This property is only used if the "metadata source" property is set to "0". Specifies the URL to be used for a connection on the middle-tier's DriverManager in a multiple tier environment, if it is different than already specified. This property allows you to use this driver to connect to other databases. Use a backslash as an escape character before backslashes and semicolons in the URL. Specifies whether a Secure Sockets Layer (SSL) connection is used to communicate with the server.
Required no
Default "system"
"secondary URL"
no
JDBC URL
"secure"
no
"true" (encrypt all client/server communication) "false" (encrypt only the password)
"false"
"server trace"
Specifies the level of tracing of the JDBC server job. When tracing is enabled, tracing starts when the client connects to the server and ends when the connection is disconnected. You must start tracing before connecting to the server, because the client enables server tracing only at connect time.
no
"0" (trace is not active) "2" (start the database monitor on the JDBC server job) "4" (start debug on the JDBC server job) "8" (save the job log when the JDBC server job ends) "16" (start job trace on the JDBC server job) "32" (save SQL information) "64" (supports the activation of database host server tracing) Multiple types of trace can be started by adding these values together. For example, "6" starts the database monitor and starts debug.
"0"
"thread used"
Specifies whether threads are used in communication with the host servers.
no
"true" "false"
"true"
341
Description Specifies what category of an IBM Toolbox for Java trace to log. Trace messages are useful for debugging programs that call JDBC. However, there is a performance penalty associated with logging trace messages, so this property is only set for debugging. Trace messages are logged to System.out.
Required no
Choices "" "none" "datastream" (log data flow between the local host and the remote system) "diagnostic" (log object state information) "error" (log errors that cause an exception) "information" (used to track the flow of control through the code) "warning" (log errors that are recoverable) "conversion" (log character set conversions between Unicode and native code pages) "proxy" (log data flow between the client and the proxy server) "pcml" (used to determine how PCML interprets the data that is sent to and from the server) "jdbc" (log jdbc information) "all" (log all categories) "thread" (log thread information)
Default ""
"trace"
Specifies whether trace messages are logged. Trace messages are useful for debugging programs that call JDBC. However, there is a performance penalty associated with logging trace messages, so this property only set to "true" for debugging. Trace messages are logged to System.out. Specifies whether binary data is translated. If this property is set to "true", then BINARY and VARBINARY fields are treated as CHAR and VARCHAR fields.
no
"true" "false"
"false"
"translate binary"
no
"true" "false"
"false"
342
Description Specifies how Boolean objects are interpreted when setting the value for a character field/parameter using the PreparedStatement.setObject(), CallableStatement.setObject() or ResultSet.updateObject() methods. Setting the property to "true" would store the Boolean object in the character field as either "true" or "false." Setting the property to "false" would store the Boolean object in the character field as either "1" or "0."
Required no
Default "true"
Related reference Registering the JDBC driver on page 78 Before using JDBC to access data in a server database file, you need to register the IBM Toolbox for Java JDBC driver with the DriverManager.
The job's library list is updated with the libraries on the libraries property. If a If a default SQL schema is specified on the URL, it is used. It becomes the default library. default SQL schema is specified on the URL then that becomes the default v If no default SQL schema is specified on the library. URL, the first library in the "libraries" property is used. It becomes the default library. v If no default SQL schema is specified on URL and if no "libraries" property is specified, the library with the same name as the signed-on user profile is used.
The job's library list is updated with the libraries in the libraries property. This may affect the behavior of some triggers and stored procedures. It does not affect unqualified names in statements. 1. No default SQL Default SQL schema is the user profile name. schema specified on URL and "libraries" property is not specified 2. Default SQL schema specified on URL and "libraries" property not specified Default SQL schema is what is specified in the URL. No default SQL schema. Job's library list is searched.
Default SQL schema is what is specified in the URL. Library list is not searched to resolve unqualified name in SQL statements.
343
Scenario 3. Default SQL schema not specified on URL and "libraries" property is specified 4. Default SQL schema specified on URL and "libraries" property specified 5. No default SQL schema specified on URL, the "libraries" property is specified and a library in the list is not valid 6. No default SQL schema specified on URL, "libraries" property specified, file found in second library in list
System Naming No default SQL schema. All libraries specified in property are searched.
Default SQL schema is what is specified in the URL. Library list is not searched to resolve unqualified name in SQL statements. No default SQL schema. The library list can not be changed because one of the libraries in the list is not found so the job's library list is used.
Default SQL schema is first library specified in property, rest of libraries ignored.
If all libraries exist , then no default SQL schema, all libraries on list searched, list replaces job's library list. If one of the libraries on the list does not exist, the job's library list is not changed. No default SQL schema, all libraries on list searched, list replaces job's library list.
Default SQL schema is user profile. 7. No default SQL schema specified on URL, the "libraries" property is specified, list starts with a comma 8. No default SQL schema specified on URL, "libraries" property specified, list starts with a *LIBL 9. No default SQL schema specified on URL, "libraries" property specified, list ends with a *LIBL 10. Default SQL schema specified on URL not valid Default SQL schema is user profile.
No default SQL schema, all libraries on list searched, libraries specified added to end of list
Default SQL schema is first library specified in property, rest of libraries ignored.
No default SQL schema, all libraries on list searched, libraries specified added to beginning of job's library list
Note: When a default SQL schema is specified on the URL and the libraries property is not used, the default SQL schema is appended before the current library list
344
Proxy Support
IBM Toolbox for Java includes proxy support for some classes. Proxy support is the processing that IBM Toolbox for Java needs to carry out a task on a Java virtual machine (JVM) when the application is on a different JVM. The proxy classes reside in jt400Proxy.jar, which ships with the rest of the IBM Toolbox for Java. The proxy classes, like the other classes in the IBM Toolbox for Java, comprise a set of platform independent Java classes that can run on any computer with a Java virtual machine. The proxy classes dispatch all method calls to a server application, or proxy server. The full IBM Toolbox for Java classes are on the proxy server. When a client uses a proxy class, the request is transferred to the proxy server which creates and administers the real IBM Toolbox for Java objects. Figure 1 shows how the standard and proxy client connect to the server. The proxy server can be the IBM i server that contains the data. Figure 1: How a standard client and a proxy client connect to a server
An application that uses proxy support performs more slowly than if it uses standard IBM Toolbox for Java classes due to the extra communication needed to support the smaller proxy classes. Applications that make fewer method calls have less performance degradation. Before proxy support, the classes containing the public interface, all the classes needed to process a request, and the application itself ran on the same JVM. When using proxy support, the public interface must be with the application, but classes for processing requests can run on a different JVM. Proxy support does not change the public interface. The same program can run with either the proxy version of IBM Toolbox for Java or the standard version.
345
An additional benefit is that proxy support requires you to have fewer ports open through a firewall. With standard IBM Toolbox for Java, you must have multiple ports open. This is because each IBM Toolbox for Java service uses a different port to communicate with the server. For example, Command call uses a different port than JDBC, which uses a different port than print, and so on. You must allow each of these ports through the firewall. However, when using proxy support, all the data flows through the same port.
346
v Standard proxy is where the proxy client and proxy server communicate by using a socket over a port. The default port is 3470. Change the default port by using the setPort() method on the ProxyServer class, or by using the -port option when starting the proxy server. For example:
java com.ibm.as400.access.ProxyServer -port 1234
v HTTP tunneling is where the proxy client and proxy server communicate by way of the HTTP server. The IBM Toolbox for Java provides a servlet that handles the proxy request. The proxy client calls the servlet by way of the HTTP server. The advantage of tunneling is that you are not required to open an additional port through the firewalls, because communication is by way of the HTTP port. The disadvantage of tunneling is that it is slower than standard proxy. IBM Toolbox for Java uses the proxy server name to determine if standard proxy or tunneling proxy is being used: v For standard proxy, just use the server name. For example:
com.ibm.as400.access.AS400.proxyServer=myServer
v For tunneling, use a URL to force the proxy client to use tunneling. For example:
com.ibm.as400.access.AS400.proxyServer=http://myServer
When running standard proxy, a socket connection exists between the client and server. If that connection fails, the server cleans up resources associated with that client. When using HTTP tunneling, using the HTTP protocol makes proxy connectionless. That is, a new connection is made for each data flow. Because the protocol is connectionless, the server does not know if the client application is no longer active. Consequently, the server does not know when to clean up resources. The tunneling server solves this problem by using a thread to clean up resources at a predetermined interval (which is based on a timeout value). At the end of the predetermined interval, the thread runs and cleans up resources that have not been used lately. Two system properties govern the thread: v com.ibm.as400.access.TunnelProxyServer. clientCleanupInterval is how often, in seconds, the cleanup thread runs. The default is every two hours. v com.ibm.as400.access.TunnelProxyServer. clientLifetime is how long, in seconds, a resource can be idle before it is cleaned up. The default is 30 minutes.
v For tunneling proxy, configure your HTTP server to use the proxy servlet. The servlet class name is com.ibm.as400.access.TunnelProxyServer and it is contained in jt400.jar. 6. On the client, set a system property to identify the proxy server. IBM Toolbox for Java uses this system property to determine if standard proxy or tunneling proxy is being used.
IBM Toolbox for Java
347
v For standard proxy, the property value is the name of the machine that runs the proxy server. For example:
com.ibm.as400.access.AS400.proxyServer=myServer
v For tunneling proxy, use a URL to force the proxy client to use tunneling. For example:
com.ibm.as400.access.AS400.proxyServer=http://myServer
7. Run the client program. When you want to work with both the proxy classes and classes not in jt400Proxy.jar, you can refer to jt400.jar instead of jt400Proxy.jar. jt400Proxy.jar is a subset of the jt400.jar and, therefore, all of the proxy classes are contained in the jt400.jar file.
v Data area v AS400 class v SecureAS400 class Other classes are not supported at this time by jt400Proxy. Also, integrated file system permissions are not functional using only the proxy JAR file. However, you can use the JarMaker class to include these classes from the jt400.jar file.
348
4. Set the value of the com.ibm.as400.access.AS400.proxyServer system property to be the name of your proxy server, and run the application. An easy way to do this is by using the -D option on most Java Virtual Machine invocations: java -Dcom.ibm.as400.access.AS400.proxyServer=psMachineName YourApplication 5. As your application runs, you see (if you set verbose in step 2) the application make at least one connection to the proxy server.
4. The applet must set the value of the com.ibm.as400.access.AS400.proxyServer system property to be the name of your proxy server. A convenient way to do this for applets is using a compiled Properties class (Example). Compile this class and place the generated Properties.class file in the com/ibm/as400/access directory (the same path your html file is coming from). For example, if the html file is /mystuff/HelloWorld.html, then Properties.class is in /mystuff/com/ibm/as400/access. 5. Put the jt400ProxySmall.jar in the same directory as the html file (/mystuff/ in step 4). 6. Refer to the applet like this in your HTML file:
<APPLET archive="jt400Proxy.jar, Properties.class" code="YourApplet.class" width=300 height=100> </APPLET>
Note: The proxy client code creates the correct servlet URL by concatenating "servlet" and the servlet name to the server name. In this example, it converts http://psMachineName to http://psMachineName/servlet/TunnelProxyServer
349
JSSE provides the ability to perform server authentication, enable secure communications, and encrypt data. Using JSSE, you can provide for secure data exchange between clients and servers that run any application protocol (for example, HTTP and FTP) over TCP/IP. If you have previously used sslight, you should migrate to JSSE. As of IBM i 5.4, JSSE is the only package supported, and sslight is no longer shipped.
ToolboxME requirements
Your workstation, wireless device, and server must meet certain requirements (listed below) for developing and running IBM Toolbox for Java 2 Micro Edition applications. Although Toolbox ME is considered a part of IBM Toolbox for Java, it is not included in the licensed product. ToolboxME (jt400Micro.jar) is included in the open source version of Toolbox for Java, called JTOpen. You must separately download and set up ToolboxME, which is contained in JTOpen.
Requirements
To use ToolboxME, your workstation, Tier0 wireless device, and server must meet the following requirements. Workstation requirements Workstation requirements for developing ToolboxME applications: v A supported version of Java Standard Edition v Java virtual machine for wireless devices v Wireless device simulator or emulator Wireless device requirements The only requirement for running ToolboxME applications on your Tier0 device is using a Java virtual machine for wireless devices. Server requirements Server requirements for using ToolboxME applications: v MEServer class, which is included in IBM Toolbox for Java or the latest version of JTOpen v IBM i requirements for IBM Toolbox for Java
350
How you set up ToolboxME is different for the Tier0 device, the development workstation, and the server: v Build an application for your wireless device (using jt400Micro.jar) and install the application as documented by the device manufacturer. v Make sure that the IBM i Host Servers are started on the server that contains the target data. v Make sure that the system that you want to run the MEServer has access to jt400.jar. For more information, see the following pages: Installing IBM Toolbox for Java on your workstation on page 9 Installing IBM Toolbox for Java on your system on page 8
Tier0 devices
Wireless devices, such as PDAs and cell phones, that use wireless technology to connect to computers and networks are referred to as Tier0 devices. This name is based on the common 3-tier application model. The 3-tier model describes a distributed program that is organized into three major parts, each of which resides on a different computer or network: v The third tier is the database and related programs that reside on a server, often a different server than the second tier. This tier provides the information and the access to that information that the other tiers use to perform work. v The second tier is the business logic, which typically resides on a different computer, typically a server, shared on a network. v The first tier is generally the part of the application that resides on a workstation, including the user interface. Tier0 devices are often small, portable, resource-constrained devices, like PDAs and cell phones. Tier0 devices substitute for or complement the functionality of devices on the first tier.
351
Related information
You can use any one of a number of development tools created to help you build wireless Java applications. For a brief list of such tools, see Related information for IBM Toolbox for Java. To learn more about and to download wireless device simulators and emulators, consult the Web site for the device or operating system on which you want your application to run.
ToolboxME classes
The com.ibm.as400.micro package provides the classes necessary to write applications that enable your Tier0 devices to access server data and resources. Note: To use IBM Toolbox for Java 2 Micro Edition classes, you must separately download and set up the ToolboxME component. ToolboxME provides the following classes: com.ibm.as400.micro package Tier0 devices on page 351
MEServer class
Use the IBM Toolbox for Java MEServer class to fulfill requests from your Tier0 client application that uses the IBM Toolbox for Java 2 Micro Edition JAR file. The MEServer creates IBM Toolbox for Java objects and invokes methods on them on behalf of the client application. Note: To use ToolboxMe classes, you must separately download and set up the ToolboxME component. For more information, see Downloading and setting up ToolboxME. Use the following command to start an MEServer:
java com.ibm.as400.micro.MEServer [options]
352
-pcml pcml_doc1 [;pcml_doc2;...] Specifies the PCML document to preload and parse. You can abbreviate this option by using -pc. For important information about using this option, see the MEServer Javadoc. -port port Specifies the port to use for accepting connections from clients. The default port is 3470. You can abbreviate this option by using -po. -verbose [true|false] Specifies whether to print status and connection information to System.out. You can abbreviate this option by using -v. -help Prints usage information to System.out. You can abbreviate this option by using -h or -?. The default is not to print usage information.
MEServer will not start if another server is already active on the specified port. Related information MEServer Javadoc Tier0 devices on page 351
AS400 class
The AS400 class in the micro package (com.ibm.as400.micro.AS400) provides a modified subset of the functions available in the AS400 class in the access package (com.ibm.as400.access.AS400). Use the IBM Toolbox for Java 2 Micro Edition AS400 class to sign on the system from a Tier0 device. Note: To use ToolboxME classes, you must separately download and set up the ToolboxME component. For more information, see Downloading and setting up ToolboxME. The AS400 class provides the following functions: v Connect to the MEServer v Disconnect from the MEServer The connection to the MEServer is made implicitly. For example, after you create an AS400 object, you can use the run() method in CommandCall to automatically perform connect(). In other words, you do not explicitly call the connect() method unless you want to control when the connection is established.
AS400 Javadoc AS400 class on page 22 The IBM Toolbox for Java AS400 class manages a set of socket connections to the server jobs on server and sign-on behavior for the server, including prompting the user for sign-on information, password caching, and default user management. Tier0 devices on page 351
IBM Toolbox for Java
353
CommandCall class - Micro package The CommandCall class in the micro package (com.ibm.as400.micro.CommandCall) provides a modified subset of the functions available in the CommandCall class in the access package (com.ibm.as400.access.CommandCall). Use the CommandCall class to call an IBM i command from a Tier0 device.
Related reference CommandCall class on page 29 The CommandCall class allows a Java program to call a non-interactive IBM i command. Related information Micro package CommandCall Javadoc Tier0 devices on page 351
354
Note: To use IBM Toolbox for Java 2 Micro Edition classes, you must separately download and set up the ToolboxME component. The DataQueue class includes the following methods: v Read or write an entry as a String v Read or write an entry as an array of bytes To read or write entries, you need to supply the name of the server where the data queue resides and the fully qualified integrated file system path name of the data queue. When no entries are available, reading an entry returns a null value.
Related reference Data queues on page 42 The DataQueue classes allow the Java program to interact with server data queues. Concepts important for using ToolboxME on page 351 Before you begin developing IBM Toolbox for Java 2 Micro Edition Java applications, you need to understand the following concepts and standards that govern such development. Related information DataQueue Javadoc Tier0 devices on page 351
355
v The string array that contains the name of any parameters to be returned after the program executes ProgramCall uses PCML to describe the input and output parameters for the program. The PCML file must be on the same machine as the MEServer, and you must have an entry for the directory that contains the PCML file in the CLASSPATH of that machine. You must register each PCML document with the MEServer. Registering a PCML document is telling the MEServer which PCML-defined program you want to run. Register the PCML document either during runtime or when you start the MEServer. For more information about the hashtable that contains program parameters or how to register a PCML document, see the ToolboxME ProgramCall Javadoc. For more information about PCML, see Program Call Markup Language on page 378.
356
ProgramCall Javadoc (micro package) ProgramCall class on page 156 The IBM Toolbox for Java ProgramCall class allows the Java program to call a IBM i program. You can use the ProgramParameter class to specify input, output, and input/output parameters. If the program runs, the output and input/output parameters contain the data that is returned by the IBM i program. If the IBM i program fails to run successfully, the Java program can retrieve any resulting IBM i messages as a list of AS400Message objects. Tier0 devices on page 351
JdbcMe classes
The IBM Toolbox for Java 2 Micro Edition classes provide JDBC support, including support for the java.sql package. The classes are meant to be used in a program that runs on a Tier 0 device. The following sections discuss accessing and using data and describe what is in JdbcMe.
What is in JdbcMe
By definition, a driver of any kind for a Tier0 device must be very small. The JDBC API, however, is very large. The JdbcMe classes had to be extremely small but still support enough of the JDBC interfaces so that Tier0 devices might use it to perform meaningful work. JdbcMe classes offer the following JDBC functionality: v The ability to insert or update data v Transaction control and the ability to modify transaction isolation levels v Result sets that are both scrollable and updatable v SQL support for calls to stored procedures and drive triggers In addition, JdbcMe classes include some unique features: v A universal driver that enables the majority of the configuration details to be consolidated at a single point on the server side v A standard mechanism for persisting data to offline storage
357
ToolboxME provides a java.sql package that follows the JDBC specification but contains only the smallest set of useful classes and methods. Providing a minimal set of sql function allows the JdbcMe classes to be small in size yet useful enough to perform common JDBC tasks. Tier0 devices on page 351 Using ToolboxME to connect to a database on the host server: The JdbcMeConnection class provides a subset of functions available in the IBM Toolbox for Java AS400JDBCConnection class. Use JdbcMeConnection to enable your Tier0 device to access DB2 Universal Database (UDB) databases on the host server. Note: To use IBM Toolbox for Java 2 Micro Edition classes, you must separately download and set up the ToolboxME component. For more information, see ToolboxME requirements and installation. Use JdbcMeDriver.getConnection() to connect to the server database. The getConnection() method takes a uniform resource locator (URL) string as an argument, the user ID, and password. The JDBC driver manager on the host server attempts to locate a driver that can connect to the database that is represented by the URL. JdbcMeDriver uses the following syntax for the URL:
jdbc:as400://server-name/default-schema;meserver=<server>[:port];[other properties];
Note: The previous syntax example is on two lines so you can easily see and print it. Normally, the URL appears on one line with no breaks or extra spaces. You must specify a server name, or JdbcMeDriver throws an exception. The default SQL schema is optional. If you do not specify a port, the JdbcMeDriver uses port 3470. Also, you can set a variety of JDBC properties within the URL. To set properties, use the following syntax:
name1=value1;name2=value2;...
See JDBC properties for a complete list of properties supported by JdbcMeDriver. Examples: Using the JdbcMeDriver to connect to a server Example: Connecting to the server database without specifying a default SQL schema, a port, or JDBC properties The examples specifies user ID and password as parameters on the method:
// Connect to system 'mysystem'. No default SQL schema, port or // properties are specified. Connection c = JdbcMeDriver.getConnection("jdbc:as400://mysystem.helloworld.com;meserver=myMeServer;" "auser", "apassword");
Example: Connecting to the server database when specifying the default SQL schema and JDBC properties The example specifies user ID and password as parameters on the method:
// Connect to system 'mysystem'. Specify a default SQL schema and // two JDBC properties. Do not specify a port. Connection c2 = JdbcMeDriver.getConnection( "jdbc:as400://mysystem.helloworld.com/mySchema;meserver=myMeServer;naming=system;errors=full;" "auser", "apassword");
Example: Connecting to the server database The example specifies properties (including user ID and password) by using a uniform resource locator (URL):
358
// Connect using properties. The properties are set on the URL // instead of through a properties object. Connection c = DriverManager.getConnection( "jdbc:as400://mySystem;meserver=myMeServer;naming=sql;errors=full;user=auser;password=apassword");
Example: Disconnecting from the database The example uses the close() method on the connecting object to disconnect from the server:
c.close();
JdbcMeConnection Javadoc AS400JDBCConnection Javadoc Tier0 devices on page 351 JdbcMeDriver class: Use JdbcMeDriver in your Tier0 client application to run simple SQL statements that have no parameters and obtain ResultSets that the statements produce. The JdbcMeDriver class provides a subset of functions available in the IBM Toolbox for Java AS400JDBCStatement class. Note: To use IBM Toolbox for Java 2 Micro Edition classes, you must separately download and set up the ToolboxME component. For more information, see Downloading and setting up ToolboxME on page 351. You don't explicitly register the JdbcMeDriver; instead the driver property you specify on the URL in the JdbcMeConnection.getConnection() method determines the driver. For example, to load the IBM Developer Kit for Java JDBC driver (called the 'native' driver), use code similar to the following:
Connection c = JdbcMeDriver.getConnection( "jdbc:as400://mysystem.myworld.com;meserver=myMeSrvr;driver=native;user=auser;password=apassword");
The IBM Toolbox for Java JDBC driver does not require an AS400 object as an input parameter like the other IBM Toolbox for Java classes that get data from a server. However, an AS400 object is used internally and you must explicitly provide a user ID and password. Provide the user ID and password either in the URL or by way of the parameters on the getConnection() method. For examples of using getConnection(), see JDBCMeConnection. Related reference Result sets The IBM Toolbox for Java 2 Micro Edition result set classes are JdbcMeLiveResultSet, JdbcMeOfflineResultSet, JdbcMeResultSetMetaData. Related information JdbcMeDriver Javadoc Tier0 devices on page 351 Result sets: The IBM Toolbox for Java 2 Micro Edition result set classes are JdbcMeLiveResultSet, JdbcMeOfflineResultSet, JdbcMeResultSetMetaData. JdbcMeLiveResultSet and JdbcMeOfflineResultSet contain the same functionality, except that: v JdbcMeLiveResultSet retrieves data by making a call to the database on the server v JdbcMeOfflineResultSet retrieves data from the database on the local device Note: To use ToolboxME classes, you must separately download and set up the ToolboxME component. For more information, see Downloading and setting up ToolboxME.
IBM Toolbox for Java
359
JdbcMeLiveResultSet The JdbcMeLiveResultSet class provides a subset of functions available in the IBM Toolbox for Java AS400JDBCResultSet class. Use JdbcMeLiveResultSet in your Tier0 client application to access a table of data that is generated by running a query. JdbcMeLiveResultSet retrieves the table rows in sequence. Within a row, you can access column values in any order. JdbcMeLiveResultSet includes methods that enable you to perform the following actions: v Retrieve data of various types that are stored in the result set v Move the cursor to the row you specify (previous row, current row, next row, and so on) v Insert, update, and delete rows v Update columns (using String and int values) v Retrieve the ResultSetMetaData object that describes the columns in the result set A cursor, which is an internal pointer, is used by a result set to point the row in the result set that is being accessed by the Java program. JDBC 2.0 provides additional methods for accessing specific positions within a database. These are the available scrollable cursor positions: v absolute v first v last v moveToCurrentRow v moveToInsertRow v previous v relative Scrolling capabilities If a result set is created by executing a statement, you can move (scroll) backward (last-to-first) or forward (first-to-last) through the rows in a table. A result set that supports this movement is called a scrollable result set. Scrollable result sets also support relative and absolute positioning. Relative positioning allows you to move to a row in the result set by specifying a position that is relative to the current row. Absolute positioning allows you to move directly to a row by specifying its position in the result set. With JDBC 2.0, you have two additional scrolling capabilities available to use when working with the ResultSet class: scroll-insensitive and scroll-sensitive result sets. A scroll-insensitive result set is not typically sensitive to changes that are made while it is open, while the scroll-sensitive result set is sensitive to changes. The IBM Toolbox for Java JDBC driver does not support scroll-insensitive result sets. Updatable result sets In your application, you can use result sets that use either read-only concurrency (no updates can be made to the data) or updatable concurrency (allows updates to the data and may use database write locks to control access to the same data item by different transactions). In an updatable result set, rows can be updated, inserted, and deleted. See the method summary in the Javadoc for a complete listing of the update methods available in JdbcMeResultSet. Example: Updatable result sets
360
The following example shows how to use a result set that allows updates to the data (update concurrency) and allows changes to be made to the result set while it is open (scroll sensitive).
// Connect to the server. Connection c = JdbcMeDriver.getConnection( "jdbc:as400://mySystem;meserver=myMeServer;user=auser;password=apassword"); // Create a Statement object. Set the result set // concurrency to updatable. Statement s = c.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); // Run a query. The result is placed // in a ResultSet object. ResultSet rs = s.executeQuery ("SELECT NAME,ID FROM MYLIBRARY.MYTABLE FOR UPDATE"); // Iterate through the rows of the ResultSet. As we read // the row, we will update it with a new ID. int newId = 0; while (rs.next ()) { // Get the values from the ResultSet. The first value // is a string, and the second value is an integer. String name = rs.getString("NAME"); int id = rs.getInt("ID"); System.out.println("Name = " + name); System.out.println("Old id = " + id); // Update the id with a new integer. rs.updateInt("ID", ++newId); // Send the updates to the server. rs.updateRow (); System.out.println("New id = " + newId); } // Close the Statement and the Connection. s.close(); c.close();
JdbcMeOfflineResultSet class The JdbcMeOfflineResultSet class provides a subset of functions available in the IBM Toolbox for Java AS400JDBCResultSet class. Use JdbcMeOfflineResultSet in in your Tier0 client application to access a table of data that is generated by running a query. Use the JdbcMeOfflineResultSet class to work with data that resides on your Tier0 device. The data that resides on the device might already reside there or you might have put it there by calling JdbcMeStatement.executeToOfflineData() method. the executeToOfflineData() method downloads and stores to the device all of the data that satisfies the query. You can then use JdbcMeOfflineResultSet class to access the stored data. JdbcMeOfflineResultSet includes methods that enable you to perform the following actions: v Retrieve data of various types that are stored in the result set v Move the cursor to the row you specify (previous row, current row, next row, and so on) v Insert, update, and delete rows v Update columns (using String and int values) v Retrieve the ResultSetMetaData object that describes the columns in the result set
361
You can provide the ability to synchronize the local device database with the database on the server by using the functions present in the JdbcMe classes. JdbcMeResultSetMetaData class The JdbcMeResultSetMetaData class provides a subset of functions available in the IBM Toolbox for Java AS400JDBCResultSetMetaData class. Use JdbcMeResultSetMetaData in your Tier0 client application to determine the types and properties of the columns in a JdbcMeLiveResultSet or JdbcMeOfflineResultSet. The following example shows how to use the JdbcMeResultSetMetaData class:
// Connect to the server. Connection c = JdbcMeDriver.getConnection( "jdbc:as400://mySystem;meserver=myMeServer;user=auser;password=apassword"); // Create a Statement object. Statement s = c.createStatement(); // Run a query. The result is placed in a ResultSet object. JdbcMeLiveResultSet rs = s.executeQuery ("SELECT NAME,ID FROM MYLIBRARY.MYTABLE"); // Iterate through the rows of the ResultSet. while (rs.next ()) { // Get the values from the ResultSet. The first value is // a string, and the second value is an integer. String name = rs.getString("NAME"); int id = rs.getInt("ID"); System.out.println("Name = " + name); System.out.println("ID = " + id); } // Close the Statement and the Connection. s.close(); c.close();
Related information JDBCMeLiveResultSet Javadoc AS400JDBCResultSet Javadoc JDBCMeResultSetMetaData Javadoc AS400JDBCResultSetMetaData Javadoc JDBCMeOfflineResultSet Javadoc JdbcMeOfflineData class: The JdbcMeOfflineData class is an offline data repository meant to be used on a Tier0 device. The repository is generic, regardless of the profile and Java virtual machine that you are using. Note: To use IBM Toolbox for Java 2 Micro Edition classes, you must separately download and set up the ToolboxME component. For more information, see Downloading and setting up ToolboxME. The JdbcMeOfflineData class provides methods that enable you to perform the following functions: v Create an offline data repository v v v v Open an existing repository Get the number of records in the repository Get and delete individual records Update records
IBM i: Programming IBM Toolbox for Java
362
v Add a record to the end of the repository v Close the repository For an example of using the JdbcMeOfflineData class, see the following example: Example: Using ToolboxME, MIDP, and IBM Toolbox for Java on page 702 Related reference Concepts important for using ToolboxME on page 351 Before you begin developing IBM Toolbox for Java 2 Micro Edition Java applications, you need to understand the following concepts and standards that govern such development. Related information JdbcMeOfflineData Javadoc JdbcMeStatement class: Use JdbcMeStatement in your Tier0 client application to run simple SQL statements that have no parameters and obtain ResultSets that the statements produce. The JdbcMeStatement class provides a subset of functions available in the IBM Toolbox for Java AS400JDBCStatement class. Note: To use IBM Toolbox for Java 2 Micro Edition classes, you must separately download and set up the ToolboxME component. For more information, see Downloading and setting up ToolboxME. Use JdbcMeConnection.createStatement() to create new Statement objects. The following example shows how to use a JdbcMeStatement object:
// Connect to the server. JdbcMeConnection c = JdbcMeDriver.getConnection( "jdbc:as400://mysystem.helloworld.com/mylibrary;naming=system;errors=full;meserver=myMeServer;" + "user=auser;password=apassword"); // Create a Statement object. JdbcMeStatement s = c.createStatement(); // Run an SQL statement that creates a table in the database. s.executeUpdate("CREATE TABLE MYLIBRARY.MYTABLE (NAME VARCHAR(20), ID INTEGER)"); // Run an SQL statement that inserts a record into the table. s.executeUpdate("INSERT INTO MYLIBRARY.MYTABLE (NAME, ID) VALUES ('DAVE', 123)"); // Run an SQL statement that inserts a record into the table. s.executeUpdate("INSERT INTO MYLIBRARY.MYTABLE (NAME, ID) VALUES ('CINDY', 456)"); // Run an SQL query on the table. JdbcMeLiveResultSet rs = s.executeQuery("SELECT * FROM MYLIBRARY.MYTABLE"); // Close the Statement and the Connection. s.close(); c.close();
363
You can also use this information as a general guide for creating, testing, and running the ToolboxME working examples and your own ToolboxME applications. The example program uses the K Virtual Machine (KVM) and allows the user to perform any JDBC query. The user can then perform JDBC actions (next, previous, close, commit, and rollback) against the result of the query. Before you begin creating any of the ToolboxME examples, make sure that your environment meets the ToolboxME requirements. Creating the ToolboxME example To create the ToolboxME example program for your Tier0 device, complete the following steps: 1. Copy the Java code for the ToolboxME example, called JdbcDemo.java. 2. In your chosen text or Java editor, change the portions of the code as indicated in the program comments and save the file with the name JdbcDemo.java. Note: Consider using a wireless application development tool, which makes it easier to complete the remaining steps. Some wireless application development tools may compile, preverify, and build your program in a single step, then automatically run it in an emulator. 3. Compile JdbcDemo.java, making sure you point to the JAR file that contains the KVM classes. 4. Preverify the executable file, either by using your wireless application development tool or by using the Java preverify command. 5. Build the appropriate type of executable file for the operating system of your Tier0 device. For example, for the Palm OS, you build a file called JdbcDemo.prc. 6. Test the program. If you have installed an emulator, you can test the program and see what it will look like by running it in the emulator. Note: If you test the program on your wireless device and you do not use a wireless application development tool, make sure that you preinstall your chosen Java virtual machine or MIDP on the device. See ToolboxME concepts for related information about concepts, wireless application development tools, and emulators. Running the ToolboxME example To run the ToolboxME example program on your Tier0 device, complete the following tasks: v Load the executable file to the device, using the instructions provided by your Tier0 device manufacturer. v Start the MEServer v Run the JdbcDemo program on your Tier0 device by clicking the JdbcDemo icon.
364
////////////////////////////////////////////////////////////////////////////////// // // ToolboxME example. This program demonstrates how your wireless // device can connect to the server and use JDBC to perform work on a // remote database. // ////////////////////////////////////////////////////////////////////////////////// import import import import import import import java.sql.*; // SQL Interfaces provided by JdbcMe com.ibm.as400.micro.*; // JdbcMe implementation java.awt.*; java.awt.event.*; java.io.*; javax.microedition.io.*; // Part of the CLDC specification de.kawt.*; // Part of the CLDC specification
class DemoConstants { // These constants are actually used mainly by the demo // for the JDBC driver. The Jdbc and JDBC application // creator IDs ( http://www.palmos.com/dev ) // are reserved at palm computing. public static final int demoAppID = 0x4a444243; // JDBC // Make the dbCreator something else so that the // user can actually see the Palm DB seperately from // the JdbcDemo application. public static final int dbCreator = 0x4a444231; // JDB1 public static final int dbType = 0x4a444231; // JDB1 } /** * Little configuration dialog box to display the * current connections/statements, the * URL being used, user id and password */ class ConfigurationDialog extends Dialog implements ActionListener { TextField data; ConfigurationDialog(Frame w) { super(w, "Configuration"); // Show/Modify current URL connection data = new TextField(JdbcDemo.mainFrame.jdbcPanel.url); add("Center", data); // Ok button. Panel panel = new Panel(); Button button = new Button("Ok"); button.addActionListener(this); panel.add(button); add("South", panel); pack(); } public void actionPerformed(ActionEvent e) { JdbcDemo.mainFrame.jdbcPanel.url = data.getText(); data = null; setVisible(false); } } /** * Little configuration dialog box to display the * current connections/statements, the * URL being used, user id and password
IBM Toolbox for Java
365
*/ class MultiChoiceDialog extends Dialog implements ActionListener { Choice task; ActionListener theListener; MultiChoiceDialog(Frame w, String title, String prompt, String choices[], ActionListener it) { super(w, title); theListener = it; // Show/Modify current URL connection Label txt = new Label(prompt); add("West", txt); task = new Choice(); for (int i=0; i<choices.length; ++i) { task.add(choices[i]); } task.select(0); add("Center", task); // Ok button. Panel panel = new Panel(); Button button = new Button("Ok"); button.addActionListener(this); panel.add(button); button = new Button("Cancel"); button.addActionListener(this); panel.add(button); add("South", panel); pack(); } /** * Determine the action performed. **/ public void actionPerformed(ActionEvent e) { int choice = task.getSelectedIndex(); setVisible(false); if (e.getActionCommand().equals("Ok")) { if (theListener != null) { ActionEvent ev = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, task.getItem(choice)); theListener.actionPerformed(ev); } task = null; } else { // No-op } } } /** * The JdbcPanel is the main panel of the application. * It displays the current connection and statement * at the top. * A text field for entering SQL statements next. * A Results field for displaying each column of data * or results. * An task list and a 'go' button so that different * tasks can be tried.
366
*/ class JdbcPanel extends { public final static public final static public final static public final static public final static public final static public final static public final static public final static public final static public final static public final static public final static
Panel implements ActionListener int int int int int int int int int int int int int TASK_EXIT = TASK_NEW = TASK_CLOSE = TASK_EXECUTE = TASK_PREV = TASK_NEXT = TASK_CONFIG = TASK_TOPALMDB = TASK_FROMPALMDB = TASK_SETAUTOCOMMIT= TASK_SETISOLATION = TASK_COMMIT = TASK_ROLLBACK = 0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12;
// JDBC objects. java.sql.Connection connObject = null; Statement stmtObject = null; ResultSet rs = null; ResultSetMetaData rsmd = null; String String Label Label TextField List final Choice lastErr url connection statement sql data task; = = = = = = null; null; null; null; null; null;
/** * Build the GUI. */ public JdbcPanel() { // The JDBC URL // Make sure to edit the following line so that it correctly specifies the // the MEServer and the server to which you want to connect. url = "jdbc:as400://mySystem;user=myUidl;password=myPwd;meserver=myMEServer;"; Panel p1left = new Panel(); p1left.setLayout(new BorderLayout()); connection = new Label("None"); p1left.add("West", new Label("Conn:")); p1left.add("Center", connection); Panel p1right = new Panel(); p1right.setLayout(new BorderLayout()); statement = new Label("None"); p1right.add("West", new Label("Stmt:")); p1right.add("Center", statement); Panel p1 = new Panel(); p1.setLayout(new GridLayout(1,2)); p1.add(p1left); p1.add(p1right); Panel p2 = new Panel(); p2.setLayout(new BorderLayout()); p2.add("North", new Label("Sql:")); sql = new TextField(25); sql.setText("select * from QIWS.QCUSTCDT"); // Default query p2.add("Center", sql); Panel p3 = new Panel();
IBM Toolbox for Java
367
p3.setLayout(new BorderLayout()); data = new List(); data.add("No Results"); p3.add("North", new Label("Results:")); p3.add("Center", data); Panel p4 = new Panel(); // // // // // // // // // // // // // // TASK_EXIT TASK_NEW TASK_CLOSE TASK_EXECUTE TASK_PREV TASK_NEXT TASK_CONFIGURE TASK_TOPALMDB TASK_FROMPALMDB TASK_SETAUTOCOMMIT TASK_SETISOLATION TASK_COMMIT TASK_ROLLBACK Start off here.
task = new Choice(); task.add("Exit"); task.add("New"); task.add("Close"); task.add("Execute"); task.add("Prev"); task.add("Next"); task.add("Config"); task.add("RS to PalmDB"); task.add("Query PalmDB"); task.add("Set AutoCommit"); task.add("Set Isolation"); task.add("Commit"); task.add("Rollback"); task.select(TASK_EXECUTE); p4.add("West", task); Button b = new Button("Go"); b.addActionListener(this); p4.add("East", b);
Panel prest = new Panel(); prest.setLayout(new BorderLayout()); prest.add("North", p2); prest.add("Center", p3); Panel pall = new Panel(); pall.setLayout(new BorderLayout()); pall.add("North", p1); pall.add("Center", prest); setLayout(new BorderLayout()); add("Center", pall); add("South", p4); } /** * Do a task based on whichever task is * currently selected in the task list. */ public void actionPerformed(ActionEvent e) { if (e.getSource() instanceof MultiChoiceDialog) { String cmd = e.getActionCommand(); processExtendedCommand(cmd); return; } switch (task.getSelectedIndex()) { case TASK_EXIT: System.exit(0); break; case TASK_NEW: JdbcPanel.this.goNewItems(); break; case TASK_PREV: JdbcPanel.this.goPrevRow(); break;
368
case TASK_NEXT: JdbcPanel.this.goNextRow(); break; case TASK_EXECUTE: if (connObject == null || stmtObject == null) JdbcPanel.this.goNewItems(); JdbcPanel.this.goExecute(); break; case TASK_CONFIG: JdbcPanel.this.goConfigure(); break; case TASK_CLOSE: JdbcPanel.this.goClose(); break; case TASK_TOPALMDB: if (connObject == null || stmtObject == null) JdbcPanel.this.goNewItems(); JdbcPanel.this.goResultsToPalmDB(); break; case TASK_FROMPALMDB: JdbcPanel.this.goQueryFromPalmDB(); break; case TASK_SETAUTOCOMMIT: JdbcPanel.this.goSetAutocommit(); break; case TASK_SETISOLATION: JdbcPanel.this.goSetIsolation(); break; case TASK_COMMIT: JdbcPanel.this.goTransact(true); break; case TASK_ROLLBACK: JdbcPanel.this.goTransact(false); break; default : { Dialog dialog = new FeedbackDialog(JdbcDemo.mainFrame, "Error", "Task not implemented"); dialog.show(); dialog = null; } } } public void processExtendedCommand(String cmd) { try { if (cmd.equals("true")) { connObject.setAutoCommit(true); return; } if (cmd.equals("false")) { connObject.setAutoCommit(false); return; } if (cmd.equals("read uncommitted")) { connObject.setTransactionIsolation(java.sql.Connection.TRANSACTION_READ_UNCOMMITTED); return; } if (cmd.equals("read committed")) {
IBM Toolbox for Java
369
connObject.setTransactionIsolation(java.sql.Connection.TRANSACTION_READ_COMMITTED); return; } if (cmd.equals("repeatable read")) { connObject.setTransactionIsolation(java.sql.Connection.TRANSACTION_REPEATABLE_READ); return; } if (cmd.equals("serializable")) { connObject.setTransactionIsolation(java.sql.Connection.TRANSACTION_SERIALIZABLE); return; } throw new IllegalArgumentException("Invalid command: " + cmd); } catch (Exception e) { JdbcDemo.mainFrame.exceptionFeedback(e); return; } } /** * Perform commit or rollback processing. */ public void goTransact(boolean commit) { if (connObject == null) { FeedbackDialog dialog = new FeedbackDialog(JdbcDemo.mainFrame, "Skip", "Connection not allocated"); dialog.show(); dialog = null; return; } try { if (commit) connObject.commit(); else connObject.rollback(); } catch (Exception e) { JdbcDemo.mainFrame.exceptionFeedback(e); } } /** * Prompt the user for setting the autocommit value * Real work handled by the actionPerformed method * calling processExtendedCommand(). */ public void goSetAutocommit() { if (connObject == null) { FeedbackDialog dialog = new FeedbackDialog(JdbcDemo.mainFrame, "Skip", "Connection not allocated"); dialog.show(); dialog = null; return; } try {
370
String currentValue; if (connObject.getAutoCommit()) currentValue = "Now: true"; else currentValue = "Now: false"; Dialog dialog = new MultiChoiceDialog(JdbcDemo.mainFrame, "Set Autocommit", currentValue, new String[]{ "true", "false"}, this); dialog.show(); dialog = null; } catch (Exception e) { JdbcDemo.mainFrame.exceptionFeedback(e); } } /** * Prompt the user for setting the isolation level, * real work handled by the actionPerformed() method * calling processExtendedCommand(). */ public void goSetIsolation() { if (connObject == null) { FeedbackDialog dialog = new FeedbackDialog(JdbcDemo.mainFrame, "Skip", "Connection not allocated"); dialog.show(); dialog = null; return; } try { int level = connObject.getTransactionIsolation(); String currentLevel; switch (level) { case java.sql.Connection.TRANSACTION_READ_UNCOMMITTED: currentLevel = "Now: read uncommitted"; break; case java.sql.Connection.TRANSACTION_READ_COMMITTED: currentLevel = "Now: read committed"; break; case java.sql.Connection.TRANSACTION_REPEATABLE_READ: currentLevel = "Now: repeatable read"; break; case java.sql.Connection.TRANSACTION_SERIALIZABLE: currentLevel = "Now: serializable"; break; default : { currentLevel = "error"; } } Dialog dialog = new MultiChoiceDialog(JdbcDemo.mainFrame, "Set Isolation Level", currentLevel, new String[]{ "read uncommitted", "read committed", "repeatable read", "serializable"}, this); dialog.show();
IBM Toolbox for Java
371
dialog = null; } catch (Exception e) { JdbcDemo.mainFrame.exceptionFeedback(e); } } /** * Create a new connection or statement. * Only one connection and statement is currently * supported. */ public void goNewItems() { if (connObject != null || stmtObject != null) { FeedbackDialog dialog = new FeedbackDialog(JdbcDemo.mainFrame, "Skip", "Conn/Stmt already allocated"); dialog.show(); dialog = null; } if (connObject == null) { try { connObject = DriverManager.getConnection(url); //connection.setText(Integer.toString(((JdbcMeConnection)connObject).getId())); connection.repaint(); } catch (Exception e) { JdbcDemo.mainFrame.exceptionFeedback(e); return; } } if (stmtObject == null) { try { try { stmtObject = connObject.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY); } catch (Exception e) { // Try again... DB2 NT version 6.1 doesn't support // Scollable result sets, so we'll assume other // JDBC 2.0 databases don't either. We'll attempt // to create another. try { stmtObject = connObject.createStatement(); } catch (Exception ex) { // If the second try failed, rethrow the // first exception. Its probably // a more meaninful error. throw e; } FeedbackDialog dialog = new FeedbackDialog(JdbcDemo.mainFrame, "2nd try worked", "Non-scrollable result set"); dialog.show();
372
dialog = null; } statement.repaint(); } catch (Exception e) { JdbcDemo.mainFrame.exceptionFeedback(e); return; } } } /** * Close the statement and connection. **/ public void goClose() { // Close the statement. if (stmtObject != null) { if (rs != null) { try { rs.close(); } catch (Exception e) { } rs = null; rsmd = null; } try { stmtObject.close(); } catch (Exception e) { } stmtObject = null; statement.setText("None"); statement.repaint(); } // Clost the connection. if (connObject != null) { try { connObject.close(); } catch (Exception e) { } connObject = null; connection.setText("None"); connection.repaint(); } data.removeAll(); data.add("No Results"); data.repaint(); sql.repaint(); return; }
373
/** * display the configuration dialog. **/ public void goConfigure() { // Note there is no model dialog support in KAWT, this only // works because the data to be changed (url) is set before // this dialog is used, and the user cannot access the // main frame while this is up on the palm (i.e. all dialogs // in Kawt are modal). ConfigurationDialog dialog = new ConfigurationDialog(JdbcDemo.mainFrame); dialog.show(); dialog = null; } /** * Execute the specified query. **/ public void goExecute() { // Get the currently selected statement. try { if (rs != null) rs.close(); rs = null; rsmd = null; boolean results = stmtObject.execute(sql.getText()); if (results) { rs = stmtObject.getResultSet(); rsmd = rs.getMetaData(); // Show the first row goNextRow(); } else { data.removeAll(); data.add(stmtObject.getUpdateCount() + " rows updated"); data.repaint(); } } catch (Exception e) { JdbcDemo.mainFrame.exceptionFeedback(e); } } /** * Move to the next row in the result set. **/ public void goNextRow() { try { if (rs == null || rsmd == null) return; int count = rsmd.getColumnCount(); int i; data.removeAll(); if (!rs.next()) data.add("End of data"); else {
374
for (i=1; i>=count; ++i) { data.add(rs.getString(i)); } } data.repaint(); } catch (Exception e) { JdbcDemo.mainFrame.exceptionFeedback(e); } } /** * Move to the previous row in the result set. **/ public void goPrevRow() { try { if (rs == null || rsmd == null) return; int count = rsmd.getColumnCount(); int i; data.removeAll(); if (!rs.previous()) data.add("Start of data"); else { for (i=1; i<=count; ++i) { data.add(rs.getString(i)); } } data.repaint(); } catch (Exception e) { JdbcDemo.mainFrame.exceptionFeedback(e); } } /** * Perform a query and store the results in the local devices database **/ public void goResultsToPalmDB() { try { if (stmtObject == null) { FeedbackDialog dialog = new FeedbackDialog(JdbcDemo.mainFrame, "Skip", "No Statement"); dialog.show(); dialog = null; return; } boolean results = ((JdbcMeStatement)stmtObject).executeToOfflineData(sql.getText(), "JdbcResultSet", DemoConstants.dbCreator, DemoConstants.dbType); if (!results) { FeedbackDialog dialog = new FeedbackDialog(JdbcDemo.mainFrame, "No Data", "Not a query");
IBM Toolbox for Java
375
dialog.show(); dialog = null; return; } data.removeAll(); data.add("Updated Palm DB 'JdbcResultSet'"); data.repaint(); } catch (Exception e) { JdbcDemo.mainFrame.exceptionFeedback(e); } } /** * Perform a query from the database that resides on the palm device. **/ public void goQueryFromPalmDB() { try { if (rs != null) { rs.close(); rs = null; } rs = new JdbcMeOfflineResultSet ("JdbcResultSet", DemoConstants.dbCreator, DemoConstants.dbType); rsmd = rs.getMetaData(); // If we want to debug some output, this // method can be used to dump the contents // of the PalmDB represented by the result set // (Uses System.out so its mostly useful in // the Palm emulator when debugging your // applications. // ((JdbcMeOfflineResultSet)rs).dumpDB(true); // show the first row. goNextRow(); } catch (SQLException e) { JdbcDemo.mainFrame.exceptionFeedback(e); } } } public class JdbcDemo extends Frame { /** An ActionListener that ends the application. Only * one is required, and can be reused */ private static ActionListener exitActionListener = null; /** * The main application in this process. */ static JdbcDemo mainFrame = null; JdbcPanel jdbcPanel = null;
376
{ public void actionPerformed(ActionEvent e) { System.exit(0); } }; } return exitActionListener; } /** * Demo Constructor **/ public JdbcDemo() { super("Jdbc Demo"); setLayout(new BorderLayout()); jdbcPanel = new JdbcPanel(); add("Center", jdbcPanel); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); setSize(200,300); pack(); } public void exceptionFeedback(Exception e) { Dialog dialog = new FeedbackDialog(JdbcDemo.mainFrame, e); dialog.show(); dialog = null; } /** * Main method. **/ public static void main(String args[]) { try { mainFrame = new JdbcDemo(); mainFrame.show(); mainFrame.jdbcPanel.goConfigure(); } catch (Exception e) { System.exit(1); } } }
377
Example: Using ToolboxME, MIDP, and IBM Toolbox for Java on page 702 Downloading the ToolboxME examples For more information about how to build a ToolboxME application, see Creating and running a ToolboxME program on page 363. For more information about MIDP, see Mobile Information Device Profile (MIDP) on page 352.
Before you begin compiling the source and building the executable files for your Tier0 device, see the following for more information: v ToolboxME requirements on page 6 v Downloading and setting up ToolboxME on page 351
378
Although PCML was designed to support distributed program calls to server program objects from a client Java platform, you can also use PCML to make calls to a server program from within the server environment.
379
When your application constructs the ProgramCallDocument object, the XML parser reads and parses the PCML source file. For more information about using an XML parser with IBM Toolbox for Java, see XML parser and XSLT processor. After the ProgramCallDocument class has been created, the application program uses the ProgramCallDocument class's methods to retrieve the necessary information from the server through the IBM i distributed program call (DPC) server. To improve run-time performance, the ProgramCallDocument class can be serialized during your product build time. The ProgramCallDocument is then constructed using the serialized file. In this case, the XML parser is not used at run-time. Refer to Using serialized PCML files.
The ProgramCallDocument object will look for your PCML source in a file called myPcmlDoc.pcml. Notice that the .pcml extension is not specified on the constructor. If you are developing a Java application in a Java package, you can package-qualify the name of the PCML resource:
380
This method is helpful for having batch processes to build your application. v From within a Java program:
ProgramCallDocument pcmlDoc; // Initialized elsewhere pcmlDoc.serialize();
If your PCML is in a source file named myDoc.pcml, the result of serialization is a file named myDoc.pcml.ser.
The ProgramCallDocument constructor will first try to find a serialized PCML file named myPcmlDoc.pcml.ser in the com.mycompany.mypackage package in the Java CLASSPATH. If a serialized PCML file does not exist, the constructor will then try to find a PCML source file named myPcmlDoc.pcml in the com.mycompany.mypackage package in the Java CLASSPATH. If a PCML source file does not exist, an exception is thrown.
Qualified names
Your Java application uses ProgramCallDocument.setValue() to set input values for the IBM i program being called. Likewise, your application uses ProgramCallDocument.getValue() to retrieve output values from the IBM i program. When accessing values from the ProgramCallDocument class, you must specify the fully qualified name of the document element or <data> tag. The qualified name is a concatenation of the names of all the containing tags with each name separated by a period. For example, given the following PCML source, the qualified name for the "nbrPolygons" item is "polytest.parm1.nbrPolygons". The qualified name for accessing the "x" value for one of the points in one of the polygons is "polytest.parm1.polygon.point.x". If any one of the elements needed to make the qualified name is unnamed, all descendants of that element do not have a qualified name. Any elements that do not have a qualified name cannot be accessed from your Java program.
<pcml version="1.0"> <program name="polytest" path="/QSYS.lib/MYLIB.lib/POLYTEST.pgm"> <!-- Parameter 1 contains a count of polygons along with an array of polygons --> <struct name="parm1" usage="inputoutput">
IBM Toolbox for Java
381
<data name="nbrPolygons" type="int" length="4" init="5" /> <!-- Each polygon contains a count of the number of points along with an array of points --> <struct name="polygon" count="nbrPolygons"> <data name="nbrPoints" type="int" length="4" init="3" /> <struct name="point" count="nbrPoints" > <data name="x" type="int" length="4" init="100" /> <data name="y" type="int" length="4" init="200" /> </struct> </struct> </struct> </program> </pcml>
Debugging
When you use PCML to call programs with complex data structures, it is easy to have errors in your PCML that result in exceptions from the ProgramCallDocument class. If the errors are related to incorrectly describing offsets and lengths of data, the exceptions can be difficult to debug. Use the following method from the Trace class to turn on PCML tracing:
Trace.setTraceOn(true); // Turn on tracing function. Trace.setTracePCMLOn(true); // Turn on PCML tracing.
Note: All public methods in the PcmlMessageLog class, including tracing, were deprecated in V5R2. The Trace setFileName() method enables you to send the following types of information to specific log files or, by default, to System.out:
382
v A dump of the hexadecimal data being transferred between the Java application and the IBM i program. This shows the program input parameters after character data is converted to EBCDIC and integers are converted to big-endian. It also shows the output parameters before they are converted to the Java environment. The data is shown in a typical hexadecimal dump format with hexadecimal digits on the left and a character interpretation on the right. The following is an example of this dump format. (The following example was altered to allow for width restrictions)
qgyolobj[6] Offset : 0....... 4....... 8....... C....... 0....... 4....... 8....... C....... 0...4...8...C...0...4...8...C... 0 : 5CE4E2D9 D7D9C640 4040 **USRPRF *
In the above example, the dump shows the seventh parameter has 10 bytes of data set to "*USRPRF ". v For output parameters, following the hexadecimal dump is a description of how the data has been interpreted for the document. (The following example was altered to allow for width restrictions)
/QSYS.lib/QGY.lib/QGYOLOBJ.pgm[2] Offset : 0....... 4....... 8....... C....... 0....... 4....... 8....... C....... 0...4...8...C...0...4...8...C... 0 : 0000000A 0000000A 00000001 00000068 D7F0F9F9 F0F1F1F5 F1F4F2F6 F2F5F400 *................P09901151426254.* 20 : 00000410 00000001 00000000 00000000 00000000 00000000 00000000 00000000 *................................* 40 : 00000000 00000000 00000000 00000000 *................ * Reading data -- Offset: 0 Length: 4 Name: "qgyolobj.listInfo.totalRcds" Byte data: 0000000A Reading data -- Offset: 4 Length: 4 Name: "qgyolobj.listInfo.rcdsReturned" Byte data: 0000000A Reading data -- Offset: 8 Length: 4 Name: "qgyolobj.listInfo.rqsHandle" Byte data: 00000001 Reading data -- Offset: c Length: 4 Name: "qgyolobj.listInfo.rcdLength" Byte data: 00000068 Reading data -- Offset: 10 Length: 1 Name: "qgyolobj.listInfo.infoComplete" Byte data: D7 Reading data -- Offset: 11 Length: 7 Name: "qgyolobj.listInfo.dateCreated" Byte data: F0F9F9F0F1F1F5 Reading data -- Offset: 18 Length: 6 Name: "qgyolobj.listInfo.timeCreated" Byte data: F1F4F2F6F2F5 Reading data -- Offset: 1e Length: 1 Name: "qgyolobj.listInfo.listStatus" Byte data: F4 Reading data -- Offset: 1f Length: 1 Name: "qgyolobj.listInfo.[8]" Byte data: 00 Reading data -- Offset: 20 Length: 4 Name: "qgyolobj.listInfo.lengthOfInfo" Byte data: 00000410 Reading data -- Offset: 24 Length: 4 Name: "qgyolobj.listInfo.firstRecord" Byte data: 00000001 Reading data -- Offset: 28 Length: 40 Name: "qgyolobj.listInfo.[11]" Byte data: 00000000000000000000000000000000000000000000000000000000000000000000000000000000
The above messages can be very helpful in diagnosing cases where the output data coming from the IBM i program does not match the PCML source. This can easily occur when you are using dynamic lengths and offsets.
PCML syntax
PCML consists of the following tags, each of which has its own attribute tags. v The program tag begins and ends code that describes one program v The struct tag defines a named structure which can be specified as an argument to a program or as a field within another named structure. A structure tag contains a data or a structure tag for each field in the structure.
IBM Toolbox for Java
383
v The data tag defines a field within a program or structure. In the following example the PCML syntax describes one program with one category of data and some isolated data.
<program> <struct> <data> </data> </struct> <data> </data> </program>
PCML program tag: The PCML program tag can be expanded with the following elements.
<program name="name" [ entrypoint="entry-point-name" ] [ epccsid="ccsid" ] [ path="path-name" ] [ parseorder="name-list" ] [ returnvalue="{ void | integer }" ] [ threadsafe="{ true | false }" ]> </program>
The following table lists the program tag attributes. Each entry includes the attribute name, the possible valid values, and a description of the attribute.
Attribute entrypoint= Value entry-point-name Description Specifies the name of the entry point within a service program object that is the target of this program call. Specifies the CCSID of the entry point within a service program. For more information, see the service program entry notes in the ServiceProgramCall javadoc. Specifies the name of the program.
epccsid=
ccsid
name=
name
384
Attribute path=
Value path-name
Description Specifies the path to the program object. The default value is to assume the program is in the QSYS library. The path must be a valid integrated file system path name to a *PGM or *SRVPGM object. If a *SRVPGM object is called, the entrypoint attribute must be specified to indicate the name of the entrypoint to be called. If the entrypoint attribute is not specified, the default value for this attribute is assumed to be a *PGM object from the QSYS library. If the entrypoint attribute is specified, the default value for this attribute is assumed to be a *SRVPGM object in the QSYS library. The path name must be specified as all uppercase characters. Do not use the path attribute when the application needs to set the path at run time, for example, when a user specifies what library is used for the install. In this case, use the ProgramCallDocument.setPath() method.
parseorder=
name-list
Specifies the order in which output parameters will be processed. The value specified is a blank separated list of parameter names in the order in which the parameters are to be processed. The names in the list must be identical to the names specified on the name attribute of tags belonging to the <program>. The default value is to process output parameters in the order the tags appear in the document. Some programs return information in one parameter that describes information in a previous parameter. For example, assume a program returns an array of structures in the first parameter and the number of entries in the array in the second parameter. In this case, the second parameter must be processed in order for the ProgramCallDocument to determine the number of structures to process in the first parameter.
385
Attribute returnvalue=
Value void The program does not return a value. integer The program returns a 4-byte signed integer.
Description Specifies the type of value, if any, that is returned from a service program call. This attribute is not allowed for *PGM object calls. When you call a Java program and an IBM i program that are on the same server, use this property to specify whether you want to call the IBM i program in the same job and on the same thread as the Java program. If you know your program is thread-safe, setting the property to true results in better performance. To keep the environment safe, the default is to call programs in separate server jobs. The default value is false.
threadsafe=
true The program is considered to be thread-safe. false The program is not thread-safe.
PCML struct tag: The PCML struct tag can be expanded with the following elements.
<struct name="name" [ count="{number | data-name }"] [ maxvrm="version-string" ] [ minvrm="version-string" ] [ offset="{number | data-name }" ] [ offsetfrom="{number | data-name | struct-name }" ] [ outputsize="{number | data-name }" ] [ usage="{ inherit | input | output | inputoutput }" ]> </struct>
The following table lists the struct tag attributes. Each entry includes the attribute name, the possible valid values, and a description of the attribute.
Attribute name= count= Value name number where number defines a fixed, never-changing sized array. data-name where data-name defines the name of a <data> element within the PCML document that will contain, at runtime, the number of elements in the array. The data-name specified can be a fully qualified name or a name that is relative to the current element. In either case, the name must reference a <data> element that is defined with type="int". See Resolving Relative Names for more information about how relative names are resolved. Description Specifies the name of the <struct> element Specifies that the element is an array and identifies the number of entries in the array. If this attribute is omitted, the element is not defined as an array, although it may be contained within another element that is defined as an array.
386
Attribute maxvrm=
Value version-string
Description Specifies the highest version of IBM i on which the element exists. If the version of IBM i is greater than the version specified on the attribute, the element and its children, if any exist, will not be processed during a call to a program. The maxvrm element is helpful for defining program interfaces which differ between releases ofIBM i. The syntax of the version string must be "VvRrMm," where the capitals letters "V," "R," and "M" are literal characters and "v," "r," and "m" are one or more digits representing the version, release and modification level. The value for "v" must be from 1 to 255 inclusively. The value for "r" and "m" must be from 0 to 255, inclusively.
minvrm=
version-string
Specifies the lowest version of IBM i on which this element exists. If the version of IBM i is less than the version specified on this attribute, this element and its children, if any exist, will not be processed during a call to a program. This attribute is helpful for defining program interfaces which differ between releases of IBM i. The syntax of the version string must be "VvRrMm," where the capitals letters "V," "R," and "M" are literal characters and "v," "r," and "m" are one or more digits representing the version, release and modification level. The value for "v" must be from 1 to 255, inclusively. The value for "r" and "m" must be from 0 to 255, inclusively.
387
Attribute offset=
Value number where number defines a fixed, never-changing offset. data-name where data-name defines the name of a <data> element within the PCML document that will contain, at runtime, the offset to the element. The data-name specified can be a fully qualified name or a name that is relative to the current element. In either case, the name must reference a <data> element that is defined with type="int". See Resolving Relative Names for more information about how relative names are resolved.
Description Specifies the offset to the <struct> element within an output parameter. Some programs return information with a fixed structure followed by one or more variable length fields or structures. In this case, the location of a variable length element is typically specified as an offset or displacement within the parameter. The offset attribute is used to describe the offset to this <struct> element. Offset is used in conjunction with the offsetfrom attribute. If the offsetfrom attribute is not specified, the base location for the offset specified on the offset attribute is the parent of the element. See Specifying Offsets for more information about how to use the offset and offsetfrom attributes. The offset and offsetfrom attributes are only used to process output data from a program. These attributes do not control the offset or displacement of input data. If the attribute is omitted, the location of the data for the element is immediately following the preceding element in the parameter, if any.
388
Attribute offsetfrom=
Value number where number defines a fixed, never-changing base location. A number attribute is most typically used to specify number="0" indicating that the offset is an absolute offset from the beginning of the parameter.
Description Specifies the base location from which the offset attribute is relative.
If the offsetfrom attribute is not specified, the base location for the offset specified on the offset attribute is the parent of this element. See Specifying Offsets for more data-name where data-name defines the information about how to use the name of a <data> element to be used offset and offsetfrom attributes. as a base location for the offset. The The offset and offsetfrom attributes element name specified must be the parent or an ancestor of this element. are only used to process output data from a program. These attributes do The value from the offset attribute will be relative to the location of the not control the offset or displacement of input data. element specified on this attribute. The data-name specified can be a fully qualified name or a name that is relative to the current element. In either case, the name must reference an ancestor of this element. See Resolving Relative Names for more information about how relative names are resolved. struct-name where struct-name defines the name of a <struct> element to be used as a base location for the offset. The element name specified must be the parent or an ancestor of this element. The value from the offset attribute will be relative to the location of the element specified on this attribute. The struct-name specified can be a fully qualified name or a name that is relative to the current element. In either case, the name must reference an ancestor of this element. See Resolving Relative Names for more information about how relative names are resolved.
389
Attribute outputsize=
Value
Description
Specifies the number of bytes to number where number defines a fixed,never-changing number of bytes reserve for output data for the element. For output parameters to reserve. which are variable in length, the data-name where data-name defines the outputsize attribute is needed to name of a <data> element within the specify how many bytes must be PCML document that will contain, at reserved for data to be returned from runtime, the number of bytes to the server program. Outputsize can reserve for output data. The be specified on all variable length data-name specified can be a fully fields and variable sized arrays, or it qualified name or a name that is can be specified for an entire relative to the current element. In parameter that contains one or more either case, the name must reference variable length fields. a <data> element that is defined with Outputsize is not necessary and type="int". See Resolving Relative must not be specified for fixed-size Names for more information about output parameters. how relative names are resolved. The value specified on the attribute is used as the total size for the element including all children of the element. Therefore, the outputsize attribute is ignored on any children or descendants of the element. If the attribute is omitted, the number of bytes to reserve for output data is determined at runtime by adding the number of bytes to reserve for all of the children of the <struct> element.
usage=
inherit
Usage is inherited from the parent element. If the structure does not have a parent, usage is assumed to be inputoutput. The structure is an input value to the host program. For character and numeric types, the appropriate conversion is performed. The structure is an output value from the host program. For character and numeric types, the appropriate conversion is performed. The structure is both and input and an output value.
input
output
inputoutput
Specifying offsets Some programs return information with a fixed structure followed by one or more variable length fields or structures. In this case, the location of a variable length element is typically specified as an offset or displacement within the parameter. An offset is the distance in bytes from a the beginning of the parameters to the beginning of a field or structure. A displacement is the distance in bytes from the beginning of one structure to the beginning of another structure.
390
For offsets, since the distance is from the beginning of the parameter, specify offsetfrom="0". The following is an example of an offset from the beginning of the parameter:
<pcml version="1.0"> <program name="myprog" path="/QSYS.lib/MYLIB.lib/MYPROG.pgm"> <!-- receiver variable contains a path --> <struct name="receiver" usage="output" outputsize="2048"> <data name="pathType" type="int" length="4" /> <data name="offsetToPathName" type="int" length="4" /> <data name="lengthOfPathName" type="int" length="4" /> <data name="pathName" type="char" length="lengthOfPathName" offset="offsetToPathName" offsetfrom="0"/> </struct> </program> </pcml>
For displacements, since the distance is from the beginning of another structure, you specify the name of the structure to which the offset is relative. The following is an example of an displacement from the beginning of a named structure:
<pcml ="1.0"> <program name="myprog" path="/QSYS.lib/MYLIB.lib/MYPROG.pgm"> <!-- receiver variable contains an object --> <struct name="receiver" usage="output" > <data name="objectName" type="char" length="10" /> <data name="libraryName" type="char" length="10" /> <data name="objectType" type="char" length="10" /> <struct name="pathInfo" usage="output" outputsize="2048" > <data name="pathType" type="int" length="4" /> <data name="offsetToPathName" type="int" length="4" /> <data name="lengthOfPathName" type="int" length="4" /> <data name="pathName" type="char" length="lengthOfPathName" offset="offsetToPathName" offsetfrom="pathInfo"/> </struct> </struct> </program> </pcml>
PCML data tag: The PCML data tag can have the following attributes. Attributes enclosed in brackets, [], indicate that the attribute is optional. If you specify an optional attribute, do not include the brackets in your source. Some attribute values are shown as a list of choices enclosed in braces, {}, with possible choices separated by vertical bars, |. When you specify one of these attributes, do not include the braces in your source and only specify one of the choices shown.
<data type="{ char | int | packed | zoned | float | byte | struct }" [ bidistringtype="{ ST4 | ST5 | ST6 | ST7 | ST8 | ST9 | ST10 | ST11 | DEFAULT }"] [ ccsid="{ number | data-name }" ] [ chartype="{ onebyte | twobyte }"] [ count="{ number | data-name }" ] [ init="string" ] [ length="{ number | data-name }" ] [ maxvrm="version-string" ] [ minvrm="version-string" ] [ name="name" ] [ offset="{ number | data-name }" ] [ offsetfrom="{ number | data-name | struct-name }" ] [ outputsize="{ number | data-name | struct-name }" ] [ passby= "{ reference | value }" ] [ precision="number" ] [ struct="struct-name" ] [ trim="{ right | left | both | none }" ] [ usage="{ inherit | input | output | inputoutput }" ]> </data>
IBM Toolbox for Java
391
The following table lists the data tag attributes. Each entry includes the attribute name, the possible valid values, and a description of the attribute.
Attribute type= Value char where char indicates a character value. A char data value is returned as a java.lang.String. For more information, see the char values for length. int where int is an integer value. An int data value is returned as a java.lang.Long. For more information, see the int values for length and precision. packed where packed is a packed decimal value. A packed data value is returned as a java.math.BigDecimal. For more information, see the packed values for length and precision. zoned where zoned is a zoned decimal value. A zoned data value is returned as a java.math.BigDecimal. For more information, see the zoned values for length and precision. float where float is a floating point value. The length attribute specifies the number of bytes, "4" or "8". A 4-byte integer is returned as a java.lang.Float. An 8-byte integer is returned as a java.lang.Double. For more information, see the float values for length. byte where byte is a byte value. No conversion is performed on the data. A byte data value is returned as an array of byte values (byte[]). For more information, see the byte values for length. struct where struct specifies the name of the <struct> element. A struct allows you to define a structure once and reuse it multiple times within the document. When you type="struct", it is as if the structure specified appeared at this location in the document. A struct does not allow for a length value and has no value for precision. Description Indicates the type of data being used (character, integer, packed, zoned, floating point, byte, or struct). Values for the length and precision attributes are different for different data types. For more information, see the Values for length and precision.
392
Attribute bidistringtype=
Value DEFAULT where DEFAULT is the default string type for non-bidirectional data (LTR). ST4 where ST4 is String Type 4. ST5 where ST5 is String Type 5. ST6 where ST6 is String Type 6. ST7 where ST7 is String Type 7. ST8 where ST8 is String Type 8. ST9 where ST9 is String Type 9. ST10 where ST10 is String Type 10. ST11 where ST11 is String Type 11.
Description Specifies the bidirectional string type for <data> elements with type="char". If this attribute is omitted, string type for this element is implied by the CCSID (whether explicitly specified or the default CCSID of the host environment). String types are defined in the javadoc for the BidiStringType class.
ccsid=
number where number defines a fixed, Specifies the host Coded Character Set ID (CCSID) for character data for never-changing CCSID. the <data> element. The ccsid data-name where data-name defines the attribute can be specified only for name that will contain, at runtime, <data> elements with type="char". the CCSID of the character data. The If this attribute is omitted, character data-name specified can be a fully data for this element is assumed to qualified name or a name that is be in the default CCSID of the host relative to the current element. In either case, the name must reference environment. a <data> element that is defined with type="int". See Resolving Relative Names for more information about how relative names are resolved. onebyte where onebyte specifies the size of each character. twobyte where twobyte specifies the size of each character. When using chartype, the length="number" attribute specifies the number of characters, not the number of bytes. Specifies the size of each character.
chartype=
count=
number where number defines a fixed, Specifies that the element is an array and identifies the number of entries never-changing number of elements in the array. in a sized array. data-name where data-name defines the name of a <data> element within the PCML document that will contain, at runtime, the number of elements in the array. The data-name specified can be a fully qualified name or a name that is relative to the current element. In either case, the name must reference a <data> element that is defined with type="int". See Resolving Relative Names for more information about how relative names are resolved. If the count attribute is omitted, the element is not defined as an array, although it may be contained within another element that is defined as an array.
393
Attribute init=
Value string
Description Specifies an initial value for the <data> element. The init value is used if an initial value is not explicitly set by the application program when <data> elements with usage="input" or usage="inputoutput" are used. The initial value specified is used to initialize scalar values. If the element is defined as an array or is contained within a structure defined as an array, the initial value specified is used as an initial value for all entries in the array.
length=
number where number defines the number of bytes that the data requires. However, when using the chartype attribute, number specifies the number of characters, not the number of bytes. data-name where data-name defines the name of a <data> element within the PCML document that will contain, at runtime, the length. A data-name can be specified only for <data> elements with type="char" or type="byte". The data-name specified can be a fully qualified name or a name that is relative to the current element. In either case, the name must reference a <data> element that is defined with type="int". See Resolving Relative Names for more information about how relative names are resolved.
Specifies the length of the data element. Usage of this attribute varies depending on the data type. For more information, see the Values for length and precision.
maxvrm=
version-string
Specifies the highest version of IBM i on which this element exists. If the IBM i version is greater than the version specified on this attribute, this element and its children, if any exist, will not be processed during a call to a program. This attribute is helpful for defining program interfaces which differ between releases of IBM i. The syntax of the version string must be "VvRrMm", where the capitals letters "V," "R," and "M" are literal characters and "v," "r," and "m" are one or more digits representing the version, release and modification level. The value for "v" must be from 1 to 255 inclusively. The value for "r" and "m" must be from 0 to 255, inclusively.
394
Attribute minvrm=
Value version-string
Description Specifies the lowest version of IBM i on which this element exists. If the IBM i version is less than the version specified on this attribute, this element and its children, if any exist, will not be processed during a call to a program. This attribute is helpful for defining program interfaces which differ between releases of IBM i. The syntax of the version string must be "VvRrMm," where the capitals letters "V," "R," and "M" are literal characters and "v," "r," and "m" are one or more digits representing the version, release and modification level. The value for "v" must be from 1 to 255 inclusively. The value for "r" and "m" must be from 0 to 255, inclusively.
name= offset=
name
number where number defines a fixed, Specifies the offset to the <data> element within an output parameter. never-changing offset. data-name where data-name defines the name of a <data> element within the PCML document that will contain, at runtime, the offset to this element. The data-name specified can be a fully qualified name or a name that is relative to the current element. In either case, the name must reference a <data> element that is defined with type="int". See Resolving Relative Names for more information about how relative names are resolved. Some programs return information with a fixed structure followed by one or more variable length fields or structures. In this case, the location of a variable length element is typically specified as an offset or displacement within the parameter. An offset attribute is used in conjunction with the offsetfrom attribute. If the offsetfrom attribute is not specified, the base location for the offset specified on the offset attribute is the parent of this element. See Specifying Offsets for more information on how to use the offset and offsetfrom attributes. The offset and offsetfrom attributes are only used to process output data from a program. These attributes do not control the offset or displacement of input data. If this attribute is omitted, the location of the data for this element is immediately following the preceding element in the parameter, if any.
395
Attribute offsetfrom=
Value number where number defines a fixed, never-changing base location. Number is most typically used to specify number="0" indicating that the offset is an absolute offset from the beginning of the parameter.
Description Specifies the base location from which the offset attribute is relative.
If the offsetfrom attribute is not specified, the base location for the offset specified on the offset attribute is the parent of this element. See data-name where data-name defines the Specifying Offsets for more name of a <data> element used as a information about how to use the offset and offsetfrom attributes. base location for the offset. The element name specified must be the parent or an ancestor of this element. The offset and offsetfrom attributes are only used to process output data The value from the offset attribute will be relative to the location of the from a program. These attributes do not control the offset or displacement element specified on this attribute. The data-name specified can be a fully of input data. qualified name or a name that is relative to the current element. In either case, the name must reference an ancestor of this element. See Resolving Relative Names for more information about how relative names are resolved. struct-name where struct-name defines the name of a <struct> element used as a base location for the offset. The element name specified must be the parent or an ancestor of this element. The value from the offset attribute will be relative to the location of the element specified on this attribute. The struct-name specified can be a fully qualified name or a name that is relative to the current element. In either case, the name must reference an ancestor of this element. See Resolving Relative Names for more information about how relative names are resolved.
396
Attribute outputsize=
Value number where a number defines a fixed, never-changing number of bytes to reserve.
Description
Specifies the number of bytes to reserve for output data for the element. For output parameters which are variable in length, the data-name where data-name defines the outputsize attribute is needed to name of a <data> element within the specify how many bytes must be PCML document that will contain, at reserved for data to be returned from runtime, the number of bytes to the IBM i program. An outputsize reserve for output data. The attribute can be specified on all data-name specified can be a fully variable length fields and variable qualified name or a name that is sized arrays, or it can be specified for relative to the current element. In an entire parameter that contains one either case, the name must reference or more variable length fields. a <data> element that is defined with Outputsize is not necessary and type="int". See Resolving Relative must not be specified for fixed-size Names for more information about output parameters. how relative names are resolved. The value specified on this attribute is used as the total size for the element including all the children of the element. Therefore, the outputsize attribute is ignored on any children or descendants of the element. If outputsize is omitted, the number of bytes to reserve for output data is determined at runtime by adding the number of bytes to reserve for all of the children of the <struct> element.
passby=
reference where reference indicates that the parameter will be passed by reference. When the program is called, the program will be passed a pointer to the parameter value. value where value indicates an integer value. This value is allowed only when type= "int" and length="4" is specified.
Specifies whether the parameter is passed by reference or passed by value. This attribute is allowed only when this element is a child of a <program> element defining a service program call.
precision=
number
Specifies the number of bytes of precision for some numeric data types. For more information, see the Values for length and precision. Specifies the name of a <struct> element for the <data> element. A struct attribute can be specified only for <data> elements with type="struct".
struct=
name
397
Attribute trim=
Value right where right is the default behavior that means to trim trailing white spaces. left where left means to trim preceding white spaces. both where both means to trim both preceding and trailing white spaces. none where none means that white spaces are not trimmed.
usage=
inherit
Usage is inherited from the parent element. If the structure does not have a parent, usage is assumed to be inputoutput. Defines an input value to the host program. For character and numeric types, the appropriate conversion is performed. Defines an output value from the host program. For character and numeric types, the appropriate conversion is performed. Defines both and input and an output value.
input
output
inputoutput
Specifying offsets Some programs return information with a fixed structure followed by one or more variable length fields or structures. In this case, the location of a variable length element is typically specified as an offset or displacement within the parameter. An offset is the distance in bytes from the beginning of the parameters to the beginnings of a field or structure. A displacement is the distance in bytes from the beginning of one structure to the beginning of another structure. For offsets, since the distance is from the beginning of the parameter, you must specify offsetfrom="0". The following is an example of an offset from the beginning of the parameter:
<pcml version="1.0"> <program name="myprog" path="/QSYS.lib/MYLIB.lib/MYPROG.pgm"> <!-- receiver variable contains a path --> <struct name="receiver" usage="output" outputsize="2048"> <data name="pathType" type="int" length="4" /> <data name="offsetToPathName" type="int" length="4" /> <data name="lengthOfPathName" type="int" length="4" /> <data name="pathName" type="char" length="lengthOfPathName" offset="offsetToPathName" offsetfrom="0"/> </struct> </program> </pcml>
For displacements, since the distance is from the beginning of another structure, you specify the name of the structure to which the offset is relative. The following is an example of an displacement from the beginning of a named structure:
398
<pcml version="1.0"> <program name="myprog" path="/QSYS.lib/MYLIB.lib/MYPROG.pgm"> <!-- receiver variable contains an object --> <struct name="receiver" usage="output" > <data name="objectName" type="char" length="10" /> <data name="libraryName" type="char" length="10" /> <data name="objectType" type="char" length="10" /> <struct name="pathInfo" usage="output" outputsize="2048" > <data name="pathType" type="int" length="4" /> <data name="offsetToPathName" type="int" length="4" /> <data name="lengthOfPathName" type="int" length="4" /> <data name="pathName" type="char" length="lengthOfPathName" offset="offsetToPathName" offsetfrom="pathInfo"/> </struct> </struct> </program> </pcml>
Values for length and precision: Values for the length and precision attributes are different for different data types. The following table lists each data type with a description of the possible values for length and precision.
Data type type="char" Length The number of bytes of data for this element, which is not necessarily the number of characters. You must specify either a literal number or a data-name. The number of bytes of data for this element: 2, 4, or 8. You must specify a literal number. Precision Not applicable
type="int"
Indicates the number of bits of precision and whether the integer is signed or unsigned: v For length="2" Use precision="15" for a signed 2-byte integer. This is the default value Use precision="16" for an unsigned 2-byte integer v For length="4" Use precision="31" for a signed 4-byte integer Use precision="32" for an unsigned 4-byte integer v For length="8" use precision="63" for a signed 8-byte integer
type="packed" or "zoned"
The number of numeric digits of data The number of decimal digits for the for this element. You must specify a element. This number must be literal number. greater than or equal to zero and less than or equal to the total number of digits specified on the length attribute. The number of bytes, 4 or 8, of data for this element. You must specify a literal number. The number of bytes of data for this element. You must specify either a literal number or data-name. Not applicable
type="float"
type="byte"
Not applicable
399
Resolving relative names Several attributes allow you to specify the name of another element, or tag, within the document as the attribute value. The name specified can be a name that is relative to the current tag. Names are resolved by seeing if the name can be resolved as a child or descendent of the tag containing the current tag. If the name cannot be resolved at this level, the search continues with the next highest containing tag. This resolution must eventually result in a match of a tag that is contained by either the <pcml> tag or the <rfml> tag, in which case the name is considered to be an absolute name, not a relative name. Here is an example using PCML:
<pcml version="1.0"> <program name="polytest" path="/QSYS.lib/MYLIB.lib/POLYTEST.pgm"> <!-- Parameter 1 contains a count of polygons along with an array of polygons --> <struct name="parm1" usage="inputoutput"> <data name="nbrPolygons" type="int" length="4" init="5" /> <!-- Each polygon contains a count of the number of points along with an array of points --> <struct name="polygon" count="nbrPolygons"> <data name="nbrPoints" type="int" length="4" init="3" /> <struct name="point" count="nbrPoints" > <data name="x" type="int" length="4" init="100" /> <data name="y" type="int" length="4" init="200" /> </struct> </struct> </struct> </program> </pcml>
400
the panel to verify the layout behaves the way you expected. The panel definitions you create can be used in dialogs, inserted within property sheets and wizards, or arranged into splitter, deck, and tabbed panes. The GUI Builder also allows you to build menu bars, toolbars, and context menu definitions. You can also incorporate JavaHelp in your panels, including context sensitive help. The Resource Script Converter converts Windows resource scripts into an XML representation that is usable by Java programs. With the Resource Script Converter you can process Windows resource scripts (RC files) from your existing Windows dialogs and menus. These converted files can then be edited with the GUI Builder. Property sheets and wizards can be made from RC files using the resource script converter along with the GUI Builder. Underlying these two tools is a new technology called the Panel Definition Markup Language, or PDML. PDML is based on the Extensible Markup Language (XML) and defines a platform-independent language for describing the layout of user interface elements. Once your panels are defined in PDML, you can use the runtime API provided by the Graphical Toolbox to display them. The API displays your panels by interpreting the PDML and rendering your user interface using the Java Foundation Classes. Note: Using PDML requires that you run version 1.4 or later of the Java Runtime Environment.
401
GUI Builder
Two windows are displayed when you invoke the GUI Builder for the first time, as shown in Figure 1: Figure 1: GUI Builder windows
Use the File Builder window to create and edit your PDML files. Figure 2: File Builder window
Use the Properties window to view or change the properties of the currently selected control. Figure 3: Properties window
402
Use the Panel Builder window to create and edit your graphical user interface components. Select the desired component from the toolbar and click on the panel to place it where ever you want. The toolbar also facilities for aligning groups of controls, for previewing the panel, and for requesting online help for a GUI Builder function. See GUI Builder Panel Builder toolbar for a description of what each icon does. Figure 4: Panel Builder window
The panel being edited is displayed in the Panel Builder window. Figure 5 shows how the windows work together: Figure 5: Example of how GUI Builder windows work together
403
404
After the conversion has run successfully, you can use the View pane to view the contents of your newly-created PDML file, and preview your new Java panels. You can use the GUI Builder to make minor adjustments to a panel if needed. The Converter always checks for an existing PDML file before performing a conversion, and attempts to preserve any changes in case you need to run the conversion again later. Figure 7: Resource Script Converter View pane
405
406
Example: Using RFML compared to using IBM Toolbox for Java Record classes
This example illustrates the differences between using RFML and using the IBM Toolbox for Java Record classes. Using the traditional Record classes, you interweave the data format specifications with the business logic of your application. Adding, changing, or deleting a field means that you must edit and recompile your Java code. However, using RFML isolates the data format specifications into RFML source files that are entirely separate from the business logic. Accommodating field changes means modifying the RFML file, often without having to change or recompile your Java application. The example assumes that your application deals with customer records, which you have defined in an RFML source file and named qcustcdt.rfml. The source file represents the fields that compose each customer record. The listing below shows how a Java application might interpret a customer record using the IBM Toolbox for Java Record, RecordFormat, and FieldDescription classes:
// Buffer containing the binary representation of one record of information. byte[] bytes; // ... Read the record data into the buffer ... // Set up a RecordFormat object to represent one customer record. RecordFormat recFmt1 = new RecordFormat("cusrec"); recFmt1.addFieldDescription(new ZonedDecimalFieldDescription(new AS400ZonedDecimal(6, 0), "cusnum")); recFmt1.addFieldDescription(new CharacterFieldDescription(new AS400Text(8, 37), "lstnam")); recFmt1.addFieldDescription(new CharacterFieldDescription(new AS400Text(3, 37), "init")); recFmt1.addFieldDescription(new CharacterFieldDescription(new AS400Text(13, 37), "street")); recFmt1.addFieldDescription(new CharacterFieldDescription(new AS400Text(6, 37), "city")); recFmt1.addFieldDescription(new CharacterFieldDescription(new AS400Text(2, 37), "state")); recFmt1.addFieldDescription(new ZonedDecimalFieldDescription(new AS400ZonedDecimal(5, 0), "zipcod")); recFmt1.addFieldDescription(new ZonedDecimalFieldDescription(new AS400ZonedDecimal(4, 0), "cdtlmt")); recFmt1.addFieldDescription(new ZonedDecimalFieldDescription(new AS400ZonedDecimal(1, 0), "chgcod")); recFmt1.addFieldDescription(new ZonedDecimalFieldDescription(new AS400ZonedDecimal(6, 2), "baldue")); recFmt1.addFieldDescription(new ZonedDecimalFieldDescription(new AS400ZonedDecimal(6, 2), "cdtdue")); // Read the byte buffer into the RecordFormatDocument object. Record rec1 = new Record(recFmt1, bytes); // Get the field values. System.out.println("cusnum: " + rec1.getField("cusnum")); System.out.println("lstnam: " + rec1.getField("lstnam"));
IBM Toolbox for Java
407
+ + + + + + + + +
By comparison, here is how the same record might be interpreted using RFML. The Java code to interpret the contents of the customer data record using RFML might look like this: // Buffer containing the binary representation of one record of information. byte[] bytes; // ... Read the record data into the buffer ... // Parse the RFML file into a RecordFormatDocument object. // The RFML source file is called qcustcdt.rfml. RecordFormatDocument rfml1 = new RecordFormatDocument("qcustcdt"); // Read the byte buffer into the RecordFormatDocument object. rfml1.setValues("cusrec", bytes); // Get the field values. System.out.println("cusnum: System.out.println("lstnam: System.out.println("init: System.out.println("street: System.out.println("city: System.out.println("state: System.out.println("zipcod: System.out.println("cdtlmt: System.out.println("chgcod: System.out.println("baldue: System.out.println("cdtdue:
" " " " " " " " " " "
+ + + + + + + + + + +
rfml1.getValue("cusrec.cusnum")); rfml1.getValue("cusrec.lstnam")); rfml1.getValue("cusrec.init")); rfml1.getValue("cusrec.street")); rfml1.getValue("cusrec.city")); rfml1.getValue("cusrec.state")); rfml1.getValue("cusrec.zipcod")); rfml1.getValue("cusrec.cdtlmt")); rfml1.getValue("cusrec.chgcod")); rfml1.getValue("cusrec.baldue")); rfml1.getValue("cusrec.cdtdue"));
RecordFormatDocument class
The RecordFormatDocument class enables your Java programs to convert between RFML representations of data and Record and RecordFormat objects for use with other IBM Toolbox for Java components. RecordFormatDocument class The RecordFormatDocument class represents an RFML source file, and it provides methods that allow your Java program to perform the following actions: v Compose RFML source files from Record objects, RecordFormat objects, and byte arrays v Generate Record objects, RecordFormat objects, and byte arrays that represent the information that the RecordFormatDocument object contains v Get and set the values of different objects and data types v Generate XML (RFML) that represents the data that the RecordFormatDocument object contains v Serialize the RFML source file that the RecordFormatDocument object represents For more information about the available methods, see the Javadoc method summary for the RecordFormatDocument class.
408
Using the RecordFormatDocument class with other IBM Toolbox for Java classes Use the RecordFormatDocument class with the following IBM Toolbox for Java classes: v Record-oriented classes, which include the record-level access file classes (AS400File, SequentialFile, and KeyedFile) that read, manipulate, and write Record objects. This category also includes the LineDataRecordWriter class. v Byte-oriented classes, which include certain DataQueue, UserSpace, and IFSFile classes that read and write a byte-array of data at a time. Do not use RecordFormatDocument class with the following IBM Toolbox for Java classes, which read and write data in forms that RecordFormatDocument does not handle: v The DataArea classes because the read and write methods deal only with String, boolean, and BigDecimal data types. v IFSTextFileInputStream and IFSTextFileOutputStream because these read and write methods deal only with String. v JDBC classes because RFML focuses only on data described by the IBM i data description specification (DDS). Related information RecordFormatDocument Javadoc
The RFML DTD resides in the jt400.jar file (com/ibm/as400/data/rfml.dtd). RFML syntax The RFML DTD defines tags, each of which has its own attribute tags. You use the RFML tags to declare and define the elements in your RFML files. In the following example, RFML syntax describes one record format and one structure:
<rfml> <recordformat> <data> </data> </recordformat> <struct>
409
RFML document type definition (DTD): This is the RFML DTD. Note that the version is 4.0. The RFML DTD resides in the jt400.jar file (com/ibm/as400/data/rfml.dtd).
<!-Record Format Markup Language (RFML) Document Type Definition. RFML is an XML language. Typical usage: <?xml version="1.0"?> <!DOCTYPE rfml SYSTEM "rfml.dtd"> <rfml version="4.0"> ... </rfml> (C) Copyright IBM Corporation, 2001,2002 All rights reserved. Licensed Materials Property of IBM US Government Users Restricted Rights Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp. --> <!-- Convenience entities --> <!ENTITY % string "CDATA"> <!-- a string of length 0 or greater --> <!ENTITY % nonNegativeInteger "CDATA"> <!-- a non-negative integer --> <!ENTITY % binary2 "CDATA"> <!-- an integer in range 0-65535 --> <!ENTITY % boolean "(true|false)"> <!ENTITY % datatype "(char | int | packed | zoned | float | byte | struct)"> <!ENTITY % biditype "(ST4 | ST5 | ST6 | ST7 | ST8 | ST9 | ST10 | ST11 | DEFAULT)"> <!-- The document root element --> <!ELEMENT rfml (struct | recordformat)+> <!ATTLIST rfml version %string; #FIXED "4.0" ccsid %binary2; #IMPLIED > <!-- Note: The ccsid is the default value that will be used for --> <!-- any contained <data type="char"> elements that do not specify a ccsid. --> <!-- Note: RFML does not support nested struct declarations. --> <!-- All struct elements are direct children of the root node. --> <!ELEMENT struct (data)+> <!ATTLIST struct name ID #REQUIRED > <!-- <!ELEMENT recordformat (data | struct)*> --> <!ELEMENT recordformat (data)*> <!ATTLIST recordformat name ID #REQUIRED description %string; #IMPLIED > <!-- Note: On the server, the Record "text description" field is limited to 50 bytes. --> <!ELEMENT data EMPTY> <!ATTLIST data name
%string;
#REQUIRED
410
The 'name' attribute must be unique within a given recordformat. --> On the server, the length of Record field names is limited to 10 bytes. --> The 'length' attribute is required, except when type="struct". --> If type="struct", then the 'struct' attribute is required. --> The 'ccsid' and 'bidistringtype' attributes are valid only when type="char". --> The 'precision' attribute is valid only for types "int", "packed", and "zoned". -->
<!-- The <!ENTITY <!ENTITY <!ENTITY <!ENTITY <!ENTITY <!ENTITY <!ENTITY <!ENTITY <!ENTITY <!ENTITY
standard predefined character entities --> quot """> <!-- quotation mark --> amp "&#38;"> <!-- ampersand --> apos "'"> <!-- apostrophe --> lt "&#60;"> <!-- less than --> gt ">"> <!-- greater than --> nbsp " "> <!-- non-breaking space --> shy "­"> <!-- soft hyphen (discretionary hyphen) --> mdash "&#x2014;"> ldquo "&#x201C;"> rdquo "&#x201D;">
The RFML data tag: The RFML data tag defines a field within a record format or structure. Listed below are the attributes for the data tag. Attributes enclosed in brackets, [], indicate that the attribute is optional. If you specify an optional attribute, do not include the brackets in your source. Some attribute values are shown as a list of choices enclosed in braces, {}, with possible choices separated by vertical bars, |. When you specify one of these attributes, do not include the braces in your source and only specify one of the choices shown.
<data type="{ char | int | packed | zoned | float | byte | struct }" ] [ bidistringtype="{ ST4 | ST5 | ST6 | ST7 | ST8 | ST9 | ST10 | ST11 | DEFAULT }"] [ ccsid="{ number | data-name }" ] [ count="{ number | data-name }" ] [ init="string" ] [ length="{ number | data-name }" ] [ name="name" ] [ precision="number" ] [ struct="struct-name" ]> </data>
The following table lists the data tag attributes. Each entry includes the attribute name, the possible valid values, and a description of the attribute.
411
Attribute type=
Value char A character value. A char data value is returned as a java.lang.String. For more information, see the char values for length. int An integer value. An int data value is returned as a java.lang.Long. For more information, see the int values for length and precision. packed A packed decimal value. A packed data value is returned as a java.math.BigDecimal. For more information, see the packed values for length and precision. zoned A zoned decimal value. A zoned data value is returned as a java.math.BigDecimal. For more information, see the zoned values for length and precision. float A floating point value. The length attribute specifies the number of bytes: either 4 or 8. A 4-byte integer is returned as a java.lang.Float. An 8-byte integer is returned as a java.lang.Double. For more information, see the float values for length. byte A byte value. No conversion is performed on the data. A byte data value is returned as an array of byte values (byte[]). For more information, see the byte values for length. struct The name of the <struct> element. A struct allows you to define a structure once and reuse it multiple times within the document. When you use type="struct", it is as if the structure specified appears at this location in the document. A struct does not allow for a length value and has no value for precision.
Description Indicates the type of data being used (character, integer, packed, zoned, floating point, byte, or struct). Values for the length and precision attributes are different for different data types. For more information, see the Values for length and precision.
412
Attribute bidistringtype=
Value DEFAULT where DEFAULT is the default string type for non-bidirectional data (LTR). ST4 where ST4 is String Type 4. ST5 where ST5 is String Type 5. ST6 where ST6 is String Type 6. ST7 where ST7 is String Type 7. ST8 where ST8 is String Type 8. ST9 where ST9 is String Type 9. ST10 where ST10 is String Type 10. ST11 where ST11 is String Type 11.
Description Specifies the bidirectional string type for <data> elements with type="char". If this attribute is omitted, string type for this element is implied by the CCSID (whether explicitly specified or the default CCSID of the host environment). String types are defined in the Javadoc for the BidiStringType class.
ccsid=
data-name where data-name defines the name that will contain, at runtime, the CCSID of the If this attribute is omitted, character data character data. The data-name for this element is assumed to be in the specified can be a fully qualified name or a name that is relative to default CCSID of the host environment. the current element. In either case, the name must reference a <data> element that is defined with type="int". See Resolving Relative Names for more information about how relative names are resolved. count= number where number defines a fixed, never-changing number of elements in a sized array. data-name where data-name defines the name of a <data> element within the RFML document that will contain, at runtime, the number of elements in the array. The data-name specified can be a fully qualified name or a name that is relative to the current element. In either case, the name must reference a <data> element that is defined with type="int". See Resolving Relative Names for more information about how relative names are resolved.
Specifies the host coded character set identifier (CCSID) for character data for the <data> element. The ccsid attribute can be specified only for <data> elements with type="char".
Specifies that the element is an array and identifies the number of entries in the array. If the count attribute is omitted, the element is not defined as an array, although it may be contained within another element that is defined as an array.
413
Attribute init=
Value string
Description Specifies an initial value for the <data> element. The initial value specified is used to initialize scalar values. If the element is defined as an array or is contained within a structure defined as an array, the initial value specified is used as an initial value for all entries in the array.
length=
number where number defines a fixed, never-changing length. data-name where data-name defines the name of a <data> element within the RFML document that will contain, at runtime, the length. A data-name can be specified only for <data> elements with type="char" or type="byte". The data-name specified can be a fully qualified name or a name that is relative to the current element. In either case, the name must reference a <data> element that is defined with type="int". See Resolving Relative Names for more information about how relative names are resolved.
Specifies the length of the data element. Usage of this attribute varies depending on the data type. For more information, see the Values for length and precision.
name= precision=
name number
Specifies the name of the <data> element. Specifies the number of bytes of precision for some numeric data types. For more information, see the Values for length and precision. Specifies the name of a <struct> element for the <data> element. A struct attribute can be specified only for <data> elements with type="struct".
struct=
name
Related information BidiStringType Javadoc The RFML rfml tag: The rfml tag begins and ends the RFML source file that describes the data format. Listed below are the attributes for the rfml tag. Attributes enclosed in brackets, [], indicate that the attribute is optional. If you specify an optional attribute, do not include the brackets in your source.
<rfml version="version-string" [ ccsid="number" ]> </rfml>
The following table lists the rfml tag attributes. Each entry includes the attribute name, the possible valid values, and a description of the attribute.
414
Attribute version=
Value version-string A fixed version of the RFML DTD. For V5R3, 4.0 is the only valid value. number A fixed, never-changing coded character set identifier (CCSID).
Description Specifies the version of the RFML DTD, which you can use to verify the correct value. Specifies the host CCSID, which applies to all enclosed <data type="char"> elements that do not specify a CCSID. For more information, see the RFML <data> tag. When you omit this attribute, the default CCSID of the host environment is used.
ccsid=
The RFML recordformat tag: The RFML recordformat tag defines a record format, which contains either data elements or references to structure elements. Listed below are the attributes for the recordformat tag. Attributes enclosed in brackets, [], indicate that the attribute is optional. If you specify an optional attribute, do not include the brackets in your source.
<recordformat name="name" [ description="description" ]> </recordformat>
The following table lists the recordformat tag attributes. Each entry includes the attribute name, the possible valid values, and a description of the attribute.
Attribute name= description= Value name description Description Specifies the name of the recordformat. Specifies the description of the recordformat.
The RFML struct tag: The RFML struct tag defines a named structure that you can reuse within the RFML source file. The structure contains a data tag for each field in the structure. Listed below are the attributes for the struct tag. Attributes enclosed in brackets, [], indicate that the attribute is optional. If you specify an optional attribute, do not include the brackets in your source.
<struct name="name"> </struct>
The following table lists the struct tag attributes. Each entry includes the attribute name, the possible valid values, and a description of the attribute.
Attribute name= Value name Description Specifies the name of the <struct> element.
415
Refer to the following information to determine which parser and processor you want to use. For more information about which IBM Toolbox for Java packages and functions require an XML parser or XSLT processor, see the following page: JAR files on page 10
XML parser
If the package or function requires an XML parser, you must include an XML parser in the CLASSPATH at run-time. The XML parser must meet the following requirements: v Be JAXP-compliant v Extend class org.apache.xerces.parsers.SAXParser v Support full schema validation Note: The parser only needs to support full schema validation if use intend to use XPCML. If you are only using PCML, full schema validation is not necessary. The Java 2 Software Developer Kit (J2SDK), version 1.4, includes a suitable XML parser. If you use a previous version of J2SDK, use any of the following methods to access a suitable XML parser: v Use x4j400.jar (an IBM version of the Xerces XML parser from Apache) v Download the Xerces XML parser from the Apache Web site v Use any compatible XML parser in the /QIBM/ProdData/OS400/xml/lib directory on your system Note: Consider using the latest versions of the parsers that reside in /QIBM/ProdData/OS400/xml/lib. For example, xmlapis11.jar and xerces411.jar are both fully validating parsers. You can use these parsers on your server or copy them to a workstation. Note: Any XML parser that meets the requirements for running XPCML can run PCML and RFML. Keep in mind that XPCML does not support serialization.
XSLT processor
If the package or function requires an XSLT processor, you must include an XSLT processor in the CLASSPATH at run-time. The XSLT processor must meet the following requirements: v Be JAXP-compliant v Contain the class javax.xml.transform.Transformer The Java 2 Software Developer Kit (J2SDK), version 1.4, includes a suitable XSLT processor. If you use a previous version of J2SDK, use any of the following methods to access a suitable XSLT processor: v Use xslparser.jar (an IBM version of the Xalan XSLT processor from Apache) v Download the Xalan XSLT processor from the Apache Web site v Use any compatible XSLT processor in the /QIBM/ProdData/OS400/xml/lib directory on your system You can use these processors on your system or copy them to a workstation.
416
However, XPCML offers several valuable enhancements when compared to PCML: v Specify and pass values for program parameters v Retrieve the results of a program call to your server in XPCML v Transform an existing PCML document into the equivalent XPCML document v Extend and customize the XPCML schema to define new simple and complex elements and attributes For more information about XPCML, see the following pages: Related reference Extensible Markup Language components on page 378 IBM Toolbox for Java includes several Extensible Markup Language (XML) components, including an XML parser. Related information XML Toolkit W3C Architecture domain: XML Schema
417
Note: If you do not run the previous command from the directory that contains jt400.jar, you can specify a fully qualified path to jt400.jar. You can place the default schema file (or any schema file) in any directory. The only requirement is that you specify the location of the schema file by using the xsi:noNamespaceSchemaLocation attribute in the <xpcml> tag. You can specify the location of the schema as a file path or as a URL. Note: Although the following examples use xpcml.xsd as the schema file, you can specify any schema that extends xpcml.xsd. v To specify the same directory as the XPCML file, use xsi:noNamespaceSchemaLocation='xpcml.xsd' v To specify a fully qualified path: xsi:noNamespaceSchemaLocation='c:\myDir\xpcml.xsd' v To specify a URL: xsi:noNamespaceSchemaLocation='http://myServer/xpcml.xsd' To see an HTML version of the xpcml.xsd file, see the following page: Schema xpcml.xsd file on page 420
418
Because XPCML uses XML schemas instead of a document type definition (DTD), you can use XPCML in ways that you cannot use PCML: v Pass values for input parameters to your program as XML elements v Receive values for output parameters from your program as XML elements v Have the XML parser automatically validate the values passed to your program v Extend the schema to define new simple and complex elements For more information about the XPCML schema and syntax, see the following pages: Comparison of XPCML source to PCML source: XPCML differs from PCML in several ways, but one major difference is that XPCML allows you to specify the values of input parameters within the XPCML source file. PCML allows you to use the init attribute of the <data> tag to specify the initial value for a data element in the PCML source. However, using PCML to specify values has the following limitations: v You cannot use the init attribute to set array values v Validation of the init value occurs only after parsing the PCML document To specify array values in PCML, you must first read in and parse the PCML document, then perform a series of calls to ProgramCallDocument.setValue(). Using XPCML makes it easier to specify values of single elements and arrays: v Specify values for both scalar and array elements in the XPCML source file v Validate the specified array values at parse time The following simple comparisons indicate ways in which XPCML differs from PCML. Each example defines a program call for an IBM i program. Example: Calling an IBM i program The following examples call an IBM i program called prog1. XPCML source code
<?xml version="1.0" encoding="UTF-8"?> <xpcml xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation='xpcml.xsd' version="4.0"> <program name="prog1" path="/QSYS.LIB/W95LIB.LIB/PROG1.PGM"> <parameterList> <stringParm name="parm1" passDirection="in" length="10">Parm1</stringParm> <intParm name="parm2" passDirection="in">5</intParm> <shortParm name="parm3" passDirection="in">3</shortParm> </parameterList> </program> </xpcml>
419
Example: Calling an IBM i program using an array of string parameters The following examples call an IBM i program called prog2 and define parm1 as an array of string parameters. Note the functionality of XPCML: v Initializes the value of each element in the array v Specifies the input values as element content that a fully validating XML parser can verify You can take advantage of this XPCML functionality without writing any Java code. PCML cannot match the XPCML performance. PCML cannot initialize the value of each element in the array. PCML cannot validate the init values at parse time. To match the functionality of XPCML, you would have to read in and parse the PCML document, then code your Java application to set the value for each array element. You would also have to write code to validate the parameters. XPCML source code
<?xml version="1.0" encoding="UTF-8"?> <xpcml xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="xpcml.xsd" version="4.0"> <program name="prog2" path="/QSYS.LIB/W95LIB.LIB/PROG2.PGM"> <parameterList> <arrayOfStringParm name="parm1" passDirection="in" length="10" count="3"> <i>Parm1-First value</i> <i>Parm1-Second value</i> <i>Parm1-Third value</i> </arrayOfStringParm> <longParm name="parm2" passDirection="in">5</longParm> <zonedDecimalParm name="parm3" passDirection="in" totalDigits="5" fractionDigits="2">32.56</zonedDecimalParm> </parameterList> </program> </xpcml>
Schema xpcml.xsd file: To make it easier to display and print, some lines of this HTML version of xpcml.xsd wrap to a second line. The same lines in the source xsd file appear on a single line. For more information about using the xpcml.xsd file, see Requirements for using XPCML. Note: Read the Code example disclaimer for important legal information.
<?xml version="1.0" encoding="UTF-8"?> <!--/////////////////////////////////////////////////////////////////////////// // // JTOpen (IBM Toolbox for Java - OSS version) // // Filename: xpcml.xsd // // The source code contained herein is licensed under the IBM Public License
420
// Version 1.0, which has been approved by the Open Source Initiative. // Copyright (C) 1997-2008 International Business Machines Corporation and // others. All rights reserved. // ////////////////////////////////////////////////////////////////////////////--> <xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'> <xs:annotation> <xs:documentation> Schema for xpcml (eXtended Program Call Markup Language). </xs:documentation> </xs:annotation> <xs:element name="xpcml"> <xs:complexType> <xs:sequence> <xs:element ref="structOrProgram" minOccurs="1" maxOccurs="unbounded" /> </xs:sequence> <xs:attribute name="version" use="required"> <xs:simpleType> <xs:restriction base="xs:string"> <xs:enumeration value="4.0"/> </xs:restriction> </xs:simpleType> </xs:attribute> </xs:complexType> <!-- Define key/keyref link between the name of a struct <!-- and the struct attribute of a parameter field. <xs:key name="StructKey"> <xs:selector xpath="struct"/> <xs:field xpath="@name"/> </xs:key> <xs:keyref name="spRef" refer="StructKey"> <xs:selector xpath="structParm" /> <xs:field xpath="@struct" /> </xs:keyref> </xs:element> --> -->
<!-- Program tag and attributes --> <xs:element name="program" substitutionGroup="structOrProgram"> <xs:complexType> <xs:sequence> <xs:element ref="parameterList" minOccurs="1" maxOccurs="1"/> <!-- Used as a wrapper tag around the parameter list for the program. --> </xs:sequence> <!-- Name of the program to call. --> <xs:attribute name="name" type="string50" use="required" /> <!-- Path to the program object. Default is to assume in library QSYS. --> <xs:attribute name="path" type="xs:string"/> <!-- Specifies the order in which parameters should be parsed. --> <!-- Value is a blank-separated list of parameter names. --> <xs:attribute name="parseOrder" type="xs:string"/> <!-- The entry point name within a service program. --> <xs:attribute name="entryPoint" type="xs:string"/> <!-- The type of value, if any, returned from a service program call. --> <xs:attribute name="returnValue" type="returnValueType"/> <!-- When calling a Java program and System i --> <!-- program is on same server --> <!-- and is thread-safe, set to true to call the <!-- System i program in same job --> <!-- and on same thread as the Java program. --> <xs:attribute name="threadSafe" type="xs:boolean" /> <!-- The CCSID of the entry point name within a service program. --> <xs:attribute name="epccsid" type="ccsidType"/> </xs:complexType>
IBM Toolbox for Java
421
</xs:element> <!-- A parameter list is made up of one or more parameters. --> <xs:element name="parameterList"> <xs:complexType> <xs:group ref="programParameter" minOccurs="1" maxOccurs="unbounded"/> </xs:complexType> </xs:element> <!-- All the different kinds of program parameters that we understand. --> <xs:group name="programParameter"> <xs:choice> <xs:element ref="stringParmGroup"/> <xs:element ref="stringParmArrayGroup"/> <xs:element ref="intParmGroup"/> <xs:element ref="intParmArrayGroup"/> <xs:element ref="unsignedIntParmGroup"/> <xs:element ref="unsignedIntParmArrayGroup"/> <xs:element ref="shortParmGroup"/> <xs:element ref="shortParmArrayGroup"/> <xs:element ref="unsignedShortParmGroup"/> <xs:element ref="unsignedShortParmArrayGroup"/> <xs:element ref="longParmGroup"/> <xs:element ref="longParmArrayGroup"/> <xs:element ref="zonedDecimalParmGroup"/> <xs:element ref="zonedDecimalParmArrayGroup"/> <xs:element ref="packedDecimalParmGroup"/> <xs:element ref="packedDecimalParmArrayGroup"/> <xs:element ref="floatParmGroup"/> <xs:element ref="floatParmArrayGroup"/> <xs:element ref="doubleParmGroup"/> <xs:element ref="doubleParmArrayGroup"/> <xs:element ref="hexBinaryParmGroup"/> <xs:element ref="hexBinaryParmArrayGroup"/> <xs:element ref="structParmGroup"/> <xs:element ref="structParmArrayGroup"/> <xs:element ref="structArrayGroup"/> <xs:element ref="struct"/> </xs:choice> </xs:group> <!-- Abstract type for all data parameter types. --> <xs:element name="stringParmGroup" type="stringParmType" abstract="true" /> <xs:element name="stringParmArrayGroup" type="stringParmArrayType" abstract="true" /> <xs:element name="intParmGroup" type="intParmType" abstract="true" /> <xs:element name="intParmArrayGroup" type="intParmArrayType" abstract="true" /> <xs:element name="unsignedIntParmGroup" type="unsignedIntParmType" abstract="true" /> <xs:element name="unsignedIntParmArrayGroup" type="unsignedIntParmArrayType" abstract="true" /> <xs:element name="shortParmGroup" type="shortParmType" abstract="true" /> <xs:element name="shortParmArrayGroup" type="shortParmArrayType" abstract="true" /> <xs:element name="unsignedShortParmGroup" type="unsignedShortParmType" abstract="true" /> <xs:element name="unsignedShortParmArrayGroup" type="unsignedShortParmArrayType" abstract="true" /> <xs:element name="longParmGroup" type="longParmType" abstract="true" /> <xs:element name="longParmArrayGroup" type="longParmArrayType" abstract="true" /> <xs:element name="zonedDecimalParmGroup" type="zonedDecimalParmType" abstract="true" /> <xs:element name="zonedDecimalParmArrayGroup" type="zonedDecimalParmArrayType" abstract="true" /> <xs:element name="packedDecimalParmGroup" type="packedDecimalParmType" abstract="true" /> <xs:element name="packedDecimalParmArrayGroup" type="packedDecimalParmArrayType" abstract="true" /> <xs:element name="floatParmGroup" type="floatParmType" abstract="true" /> <xs:element name="floatParmArrayGroup" type="floatParmArrayType" abstract="true" /> <xs:element name="doubleParmGroup" type="doubleParmType" abstract="true" /> <xs:element name="doubleParmArrayGroup" type="doubleParmArrayType" abstract="true" /> <xs:element name="hexBinaryParmGroup" type="hexBinaryParmType" abstract="true" /> <xs:element name="hexBinaryParmArrayGroup" type="hexBinaryParmArrayType" abstract="true" /> <xs:element name="structParmGroup" type="structParmType" abstract="true" /> <xs:element name="structParmArrayGroup" type="structParmArrayType" abstract="true" />
422
<xs:element name="structArrayGroup" type="structArrayType" abstract="true" substitutionGroup="structOrProgram" /> <!-- String parameter --> <xs:element name="stringParm" type="stringParmType" substitutionGroup="stringParmGroup" nillable="true"/> <xs:complexType name="stringParmType"> <xs:simpleContent> <xs:extension base="stringFieldType"> <xs:attributeGroup ref="commonParmAttrs"/> </xs:extension> </xs:simpleContent> </xs:complexType> <!-- Array of string parameters --> <xs:element name="arrayOfStringParm" type="stringParmArrayType" substitutionGroup="stringParmArrayGroup" nillable="true" /> <xs:complexType name="stringParmArrayType"> <xs:sequence> <xs:element name="i" type="stringElementType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:attributeGroup ref="commonParmAttrs"/> <xs:attributeGroup ref="commonFieldAttrs"/> <!-- The number of elements in the array. --> <!-- 'count' is required if you want to input and/or output array data as XPCML. --> <xs:attribute name="count" type="xs:string" /> <!-- The number of characters in each string. --> <xs:attribute name="length" type="xs:string"/> <!-- The host CCSID for each string. --> <xs:attribute name="ccsid" type="xs:string"/> <!-- Specifies how to trim whitespace (left, right, both, none). --> <xs:attribute name="trim" type="trimType" /> <!-- The size of each character ('chartype' in PCML). --> <xs:attribute name="bytesPerChar" type="charType" /> <!-- The bidirectional string type. --> <xs:attribute name="bidiStringType" type="bidiStringTypeType" /> </xs:complexType> <xs:complexType name="stringElementType"> <xs:simpleContent> <xs:extension base="xs:string"> <!-- The index into the array. --> <xs:attribute name="index" type="xs:nonNegativeInteger" </xs:extension> </xs:simpleContent> </xs:complexType>
/>
<!-- Integer parameter (4 bytes on server) --> <xs:element name="intParm" type="intParmType" nillable="true" substitutionGroup="intParmGroup" <xs:complexType name="intParmType" > <xs:simpleContent> <xs:extension base="intFieldType"> <xs:attributeGroup ref="commonParmAttrs"/> </xs:extension> </xs:simpleContent> </xs:complexType> <!-- intParm array type --> <xs:element name="arrayOfIntParm" type="intParmArrayType" substitutionGroup="intParmArrayGroup" nillable="true" /> <xs:complexType name="intParmArrayType"> <xs:sequence> <!-- 'i' is the tag used for non-struct array elements. --> <xs:element name="i" type="intElementType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <!-- 'count' is required if you want to input and/or output array data as XPCML. -->
IBM Toolbox for Java
/>
423
<xs:attribute name="count" type="xs:string" /> <xs:attributeGroup ref="commonParmAttrs"/> <xs:attributeGroup ref="commonFieldAttrs"/> </xs:complexType> <xs:complexType name="intElementType"> <xs:simpleContent> <xs:extension base="xs:int"> <xs:attribute name="index" type="xs:nonNegativeInteger" </xs:extension> </xs:simpleContent> </xs:complexType>
/>
<!-- Unsigned Integer parameter (4 bytes on server) --> <xs:element name="unsignedIntParm" type="unsignedIntParmType" nillable="true" substitutionGroup="unsignedIntParmGroup" /> <xs:complexType name="unsignedIntParmType"> <xs:simpleContent> <xs:extension base="unsignedIntFieldType"> <xs:attributeGroup ref="commonParmAttrs"/> </xs:extension> </xs:simpleContent> </xs:complexType> <!-- unsigned intParm array type --> <xs:element name="arrayOfUnsignedIntParm" type="unsignedIntParmArrayType" substitutionGroup="unsignedIntParmArrayGroup" nillable="true" /> <xs:complexType name="unsignedIntParmArrayType"> <xs:sequence> <xs:element name="i" type="unsignedIntElementType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <!-- 'count' is required if you want to input and/or output array data as XPCML. --> <xs:attribute name="count" type="xs:string" /> <xs:attributeGroup ref="commonParmAttrs"/> <xs:attributeGroup ref="commonFieldAttrs"/> </xs:complexType> <xs:complexType name="unsignedIntElementType"> <xs:simpleContent> <xs:extension base="xs:unsignedInt"> <xs:attribute name="index" type="xs:nonNegativeInteger" </xs:extension> </xs:simpleContent> </xs:complexType>
/>
<!-- Short integer parameter (2 bytes on server) --> <xs:element name="shortParm" type="shortParmType" nillable="true" substitutionGroup="shortParmGroup"/> <xs:complexType name="shortParmType"> <xs:simpleContent> <xs:extension base="shortFieldType"> <xs:attributeGroup ref="commonParmAttrs"/> </xs:extension> </xs:simpleContent> </xs:complexType> <!-- shortParm array type --> <xs:element name="arrayOfShortParm" type="shortParmArrayType" substitutionGroup="shortParmArrayGroup" nillable="true" /> <xs:complexType name="shortParmArrayType"> <xs:sequence> <xs:element name="i" type="shortElementType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <!-- 'count' is required if you want to input and/or output array data as XPCML. --> <xs:attribute name="count" type="xs:string" /> <xs:attributeGroup ref="commonParmAttrs"/>
424
<xs:attributeGroup ref="commonFieldAttrs"/> </xs:complexType> <xs:complexType name="shortElementType"> <xs:simpleContent> <xs:extension base="xs:short"> <xs:attribute name="index" type="xs:nonNegativeInteger" </xs:extension> </xs:simpleContent> </xs:complexType>
/>
<!-- Unsigned Short integer parameter (2 bytes on server) --> <xs:element name="unsignedShortParm" type="unsignedShortParmType" nillable="true" substitutionGroup="unsignedShortParmGroup" /> <xs:complexType name="unsignedShortParmType"> <xs:simpleContent> <xs:extension base="unsignedShortFieldType"> <xs:attributeGroup ref="commonParmAttrs"/> </xs:extension> </xs:simpleContent> </xs:complexType> <!-- unsignedShortParm array type --> <xs:element name="arrayOfUnsignedShortParm" type="unsignedShortParmArrayType" substitutionGroup="unsignedShortParmArrayGroup" nillable="true" /> <xs:complexType name="unsignedShortParmArrayType"> <xs:sequence> <xs:element name="i" type="unsignedShortElementType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <!-- 'count' is required if you want to input and/or output array data as XPCML. --> <xs:attribute name="count" type="xs:string" /> <xs:attributeGroup ref="commonParmAttrs"/> <xs:attributeGroup ref="commonFieldAttrs"/> </xs:complexType> <xs:complexType name="unsignedShortElementType"> <xs:simpleContent> <xs:extension base="xs:unsignedShort"> <xs:attribute name="index" type="xs:nonNegativeInteger" </xs:extension> </xs:simpleContent> </xs:complexType>
/>
<!-- Long integer parameter (8 bytes on server) --> <xs:element name="longParm" type="longParmType" nillable="true" substitutionGroup="longParmGroup" <xs:complexType name="longParmType"> <xs:simpleContent> <xs:extension base="longFieldType"> <xs:attributeGroup ref="commonParmAttrs"/> </xs:extension> </xs:simpleContent> </xs:complexType> <!-- longParm array type --> <xs:element name="arrayOfLongParm" type="longParmArrayType" substitutionGroup="longParmArrayGroup" nillable="true" /> <xs:complexType name="longParmArrayType"> <xs:sequence> <xs:element name="i" type="longElementType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <!-- 'count' is required if you want to input and/or output array data as XPCML. --> <xs:attribute name="count" type="xs:string" /> <xs:attributeGroup ref="commonParmAttrs"/> <xs:attributeGroup ref="commonFieldAttrs"/> </xs:complexType>
IBM Toolbox for Java
/>
425
<xs:complexType name="longElementType"> <xs:simpleContent> <xs:extension base="xs:long"> <xs:attribute name="index" type="xs:nonNegativeInteger" </xs:extension> </xs:simpleContent> </xs:complexType>
/>
<!-- ZonedDecimal parameter --> <xs:element name="zonedDecimalParm" type="zonedDecimalParmType" nillable="true" substitutionGroup="zonedDecimalParmGroup" /> <xs:complexType name="zonedDecimalParmType"> <xs:simpleContent> <xs:extension base="zonedDecimalFieldType"> <xs:attributeGroup ref="commonParmAttrs"/> </xs:extension> </xs:simpleContent> </xs:complexType> <!-- zonedDecimalParm array type --> <xs:element name="arrayOfZonedDecimalParm" type="zonedDecimalParmArrayType" substitutionGroup="zonedDecimalParmArrayGroup" nillable="true" /> <xs:complexType name="zonedDecimalParmArrayType"> <xs:sequence> <xs:element name="i" type="zonedDecimalElementType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:attributeGroup ref="commonParmAttrs"/> <xs:attributeGroup ref="commonFieldAttrs"/> <!-- 'count' is required if you want to input and/or output array data as XPCML. --> <xs:attribute name="count" type="xs:string" /> <!-- The total number of digits in the field ('length' in PCML). --> <xs:attribute name="totalDigits" type="xs:positiveInteger"/> <!-- The number of fractional digits ('precision' in PCML). --> <xs:attribute name="fractionDigits" type="xs:nonNegativeInteger"/> </xs:complexType> <xs:complexType name="zonedDecimalElementType"> <xs:simpleContent> <xs:extension base="xs:decimal"> <xs:attribute name="index" type="xs:nonNegativeInteger" </xs:extension> </xs:simpleContent> </xs:complexType>
/>
<!-- packedDecimal parameter --> <xs:element name="packedDecimalParm" type="packedDecimalParmType" nillable="true" substitutionGroup="packedDecimalParmGroup" /> <xs:complexType name="packedDecimalParmType"> <xs:simpleContent> <xs:extension base="packedDecimalFieldType"> <xs:attributeGroup ref="commonParmAttrs"/> </xs:extension> </xs:simpleContent> </xs:complexType> <!-- packedDecimalParm array type --> <xs:element name="arrayOfPackedDecimalParm" type="packedDecimalParmArrayType" substitutionGroup="packedDecimalParmArrayGroup" nillable="true" /> <xs:complexType name="packedDecimalParmArrayType"> <xs:sequence> <xs:element name="i" type="packedDecimalElementType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:attributeGroup ref="commonParmAttrs"/> <xs:attributeGroup ref="commonFieldAttrs"/> <!-- 'count' is required if you want to input and/or output array data as XPCML. -->
426
<xs:attribute name="count" type="xs:string" /> <xs:attribute name="totalDigits" type="xs:positiveInteger"/> <xs:attribute name="fractionDigits" type="xs:nonNegativeInteger"/> </xs:complexType> <xs:complexType name="packedDecimalElementType"> <xs:simpleContent> <xs:extension base="xs:decimal"> <xs:attribute name="index" type="xs:nonNegativeInteger" </xs:extension> </xs:simpleContent> </xs:complexType>
/>
<!-- Float parameter (4 bytes on server) --> <xs:element name="floatParm" type="floatParmType" nillable="true" substitutionGroup="floatParmGroup"/> <xs:complexType name="floatParmType"> <xs:simpleContent> <xs:extension base="floatFieldType"> <xs:attributeGroup ref="commonParmAttrs"/> </xs:extension> </xs:simpleContent> </xs:complexType> <!-- floatParm array type --> <xs:element name="arrayOfFloatParm" type="floatParmArrayType" substitutionGroup="floatParmArrayGroup" nillable="true" /> <xs:complexType name="floatParmArrayType"> <xs:sequence> <xs:element name="i" type="floatElementType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <!-- 'count' is required if you want to input and/or output array data as XPCML. --> <xs:attribute name="count" type="xs:string" /> <xs:attributeGroup ref="commonParmAttrs"/> <xs:attributeGroup ref="commonFieldAttrs"/> </xs:complexType> <xs:complexType name="floatElementType"> <xs:simpleContent> <xs:extension base="xs:float"> <xs:attribute name="index" type="xs:nonNegativeInteger" </xs:extension> </xs:simpleContent> </xs:complexType>
/>
<!-- Double parameter (8 bytes on server) --> <xs:element name="doubleParm" type="doubleParmType" nillable="true" substitutionGroup="doubleParmGroup" /> <xs:complexType name="doubleParmType"> <xs:simpleContent> <xs:extension base="doubleFieldType"> <xs:attributeGroup ref="commonParmAttrs"/> </xs:extension> </xs:simpleContent> </xs:complexType> <!-- doubleParm array type --> <xs:element name="arrayOfDoubleParm" type="doubleParmArrayType" substitutionGroup="doubleParmArrayGroup" nillable="true" /> <xs:complexType name="doubleParmArrayType"> <xs:sequence> <xs:element name="i" type="doubleElementType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <!-- 'count' is required if you want to input and/or output array data as XPCML. --> <xs:attribute name="count" type="xs:string" /> <xs:attributeGroup ref="commonParmAttrs"/> <xs:attributeGroup ref="commonFieldAttrs"/>
IBM Toolbox for Java
427
</xs:complexType> <xs:complexType name="doubleElementType"> <xs:simpleContent> <xs:extension base="xs:double"> <xs:attribute name="index" type="xs:nonNegativeInteger" </xs:extension> </xs:simpleContent> </xs:complexType>
/>
<!-- Hex binary parameter (any number of bytes; unsigned) --> <xs:element name="hexBinaryParm" type="hexBinaryParmType" substitutionGroup="hexBinaryParmGroup" <xs:complexType name="hexBinaryParmType"> <xs:simpleContent> <xs:extension base="hexBinaryFieldType"> <!-- The field length in bytes ('length' in PCML). --> <xs:attribute name="totalBytes" type="xs:string"/> <xs:attributeGroup ref="commonParmAttrs"/> </xs:extension> </xs:simpleContent> </xs:complexType> <!-- hexBinaryParm array type --> <xs:element name="arrayOfHexBinaryParm" type="hexBinaryParmArrayType" substitutionGroup="hexBinaryParmArrayGroup" nillable="true" /> <xs:complexType name="hexBinaryParmArrayType"> <xs:sequence> <xs:element name="i" type="hexBinaryElementType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:attribute name="totalBytes" type="xs:string"/> <!-- 'count' is required if you want to input and/or output array data as XPCML. --> <xs:attribute name="count" type="xs:string" /> <xs:attributeGroup ref="commonParmAttrs"/> <xs:attributeGroup ref="commonFieldAttrs"/> </xs:complexType> <xs:complexType name="hexBinaryElementType"> <xs:simpleContent> <xs:extension base="xs:hexBinary"> <xs:attribute name="index" type="xs:nonNegativeInteger" </xs:extension> </xs:simpleContent> </xs:complexType>
/>
/>
<!-- Structure parm type --> <xs:element name="structParm" type="structParmType" substitutionGroup="structParmGroup" /> <xs:complexType name="structParmType"> <xs:complexContent> <xs:extension base="structureParmArray"> <xs:attribute name="struct" type="string50"/> <!-- Specifies whether the parameter is passed by value or reference ('passby' in PCML).--> <!-- Value only allowed for integer parameters. --> <xs:attribute name="passMode" type="passModeType"/> <!-- 'count' is required if you want to input and/or output array data as XPCML. --> <xs:attribute name="count" type="xs:string"/> </xs:extension> </xs:complexContent> </xs:complexType> <!-- Structure parm array type --> <xs:element name="arrayOfStructParm" type="structParmArrayType" substitutionGroup="structParmArrayGroup" nillable="true" /> <xs:complexType name="structParmArrayType"> <xs:sequence> <!-- struct_i tag represents struct or struct parm array elements. --> <xs:element name="struct_i" type="structElementType" minOccurs="0" maxOccurs="unbounded"/>
428
</xs:sequence> <!-- 'count' is required if you want to input and/or output array data as XPCML. --> <xs:attribute name="count" type="xs:string" /> <xs:attributeGroup ref="commonParmAttrs"/> <xs:attributeGroup ref="commonFieldAttrs"/> <xs:attribute name="struct" type="string50"/> </xs:complexType> <xs:complexType name="structElementType"> <xs:complexContent> <xs:extension base="structureParmArray"> <xs:attribute name="index" type="xs:nonNegativeInteger" </xs:extension> </xs:complexContent> </xs:complexType>
/>
<!-- Struct element --> <xs:element name="struct" type="structureParmArray" substitutionGroup="structOrProgram" /> <!-- Struct array type --> <xs:element name="arrayOfStruct" type="structArrayType" substitutionGroup="structArrayGroup" nillable="true" /> <xs:complexType name="structArrayType"> <xs:sequence> <!-- struct_i tag represents struct elements in an array. --> <xs:element name="struct_i" type="structElementType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <!-- The name of the struct. --> <xs:attribute name="name" type="string50"/> <!-- Number of elements in the array. --> <!-- 'count' is required if you want to input and/or output array data as XPCML. --> <xs:attribute name="count" type="xs:string" /> <!-- Specifies whether this is an input, output, or input-output struct ('usage' in PCML). --> <xs:attribute name="passDirection" type="passDirectionType"/> <!-- The offset to the struct within an output parameter. --> <xs:attribute name="offset" type="xs:string" /> <!-- The base location from which the 'offset' attribute is relative. --> <xs:attribute name="offsetFrom" type="xs:string" /> <!-- The number of bytes to reserve for output data for the element. --> <xs:attribute name="outputSize" type="xs:string" /> <!-- The lowest version of IBM i on which this element exists. --> <xs:attribute name="minvrm" type="string10" /> <!-- The highest version of IBM i on which this element exists. --> <xs:attribute name="maxvrm" type="string10" /> </xs:complexType> <!-- Attributes that are common to all data field types. --> <xs:attributeGroup name="commonParmAttrs"> <!-- Specifies whether this is an input, output, or input-output parameter ('usage' in PCML). --> <!-- The default value if none is specified is 'inherit'. --> <xs:attribute name="passDirection" type="passDirectionType"/> <!-- Specifies whether the parameter is passed by reference or value ('passby' in PCML). --> <!-- The default value if none is specified is 'reference'. --> <xs:attribute name="passMode" type="passModeType" /> <!-- The offset to the element within an output parameter. --> <!-- The default value if none is specified is 0. --> <xs:attribute name="offset" type="xs:string" /> <!-- The base location from which the 'offset' attribute is relative. --> <xs:attribute name="offsetFrom" type="xs:string" /> <!-- The number of bytes to reserve for output data for the element. --> <xs:attribute name="outputSize" type="xs:string" /> <!-- The lowest version of IBM i to which this field applies. --> <!-- If not specified, we assume this field applies to all versions. --> <xs:attribute name="minvrm" type="string10" /> <!-- The highest version of IBM i to which this field applies. -->
IBM Toolbox for Java
429
<!-- If not specified, we assume this field applies to all versions. --> <xs:attribute name="maxvrm" type="string10" /> </xs:attributeGroup> <xs:simpleType name="passDirectionType"> <xs:restriction base="xs:string"> <xs:enumeration value="in"/> <xs:enumeration value="inout"/> <xs:enumeration value="out"/> <xs:enumeration value="inherit"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="passModeType"> <xs:restriction base="xs:string"> <xs:enumeration value="value"/> <xs:enumeration value="reference"/> </xs:restriction> </xs:simpleType> <!-- Following types are to maintain compatibility with PCML --> <xs:simpleType name="bidiStringTypeType"> <xs:restriction base="xs:string"> <xs:enumeration value="ST4"/> <xs:enumeration value="ST5"/> <xs:enumeration value="ST6"/> <xs:enumeration value="ST7"/> <xs:enumeration value="ST8"/> <xs:enumeration value="ST9"/> <xs:enumeration value="ST10"/> <xs:enumeration value="ST11"/> <xs:enumeration value="DEFAULT"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="charType"> <xs:restriction base="xs:string"> <xs:enumeration value="onebyte"/> <xs:enumeration value="twobyte"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="trimType"> <xs:restriction base="xs:string"> <xs:enumeration value="none"/> <xs:enumeration value="left"/> <xs:enumeration value="right"/> <xs:enumeration value="both"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="returnValueType"> <xs:restriction base="xs:string"> <xs:enumeration value="void"/> <xs:enumeration value="integer"/> </xs:restriction> </xs:simpleType> <xs:complexType name="structureParmArray"> <xs:sequence> <xs:group ref="structureParm" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:attribute name="name" type="string50"/> <xs:attribute name="passDirection" type="passDirectionType"/> <xs:attribute name="offset" type="xs:string" /> <xs:attribute name="offsetFrom" type="xs:string" />
430
<xs:attribute name="outputSize" type="xs:string" /> <xs:attribute name="minvrm" type="string10" /> <xs:attribute name="maxvrm" type="string10" /> </xs:complexType> <!-- A structureParm is exactly one of the following: stringParm, intParm, shortParm, longParm, zonedDecimalParm, packedDecimalParm, floatParm, doubleParm, or hexBinaryParm. --> <xs:group name="structureParm"> <xs:choice> <xs:element ref="stringParmGroup" /> <xs:element ref="stringParmArrayGroup" /> <xs:element ref="intParmGroup" /> <xs:element ref="intParmArrayGroup" /> <xs:element ref="unsignedIntParmGroup" /> <xs:element ref="unsignedIntParmArrayGroup" /> <xs:element ref="shortParmGroup" /> <xs:element ref="shortParmArrayGroup" /> <xs:element ref="unsignedShortParmGroup" /> <xs:element ref="unsignedShortParmArrayGroup" /> <xs:element ref="longParmGroup" /> <xs:element ref="longParmArrayGroup" /> <xs:element ref="zonedDecimalParmGroup" /> <xs:element ref="zonedDecimalParmArrayGroup" /> <xs:element ref="packedDecimalParmGroup" /> <xs:element ref="packedDecimalParmArrayGroup" /> <xs:element ref="floatParmGroup" /> <xs:element ref="floatParmArrayGroup" /> <xs:element ref="doubleParmGroup" /> <xs:element ref="doubleParmArrayGroup" /> <xs:element ref="hexBinaryParmGroup" /> <xs:element ref="hexBinaryParmArrayGroup" /> <xs:element ref="structParmGroup" /> <xs:element ref="structParmArrayGroup"/> <xs:element ref="structArrayGroup"/> <xs:element ref="struct"/> </xs:choice> </xs:group> <!-- Field Definition schema. --> <!-- Define basic System i native data types. --> <xs:complexType name="zonedDecimal"> <xs:simpleContent> <xs:extension base="xs:decimal"> <xs:attribute name="totalDigits" type="xs:positiveInteger" /> <xs:attribute name="fractionDigits" type="xs:nonNegativeInteger" /> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:complexType name="packedDecimal"> <xs:simpleContent> <xs:extension base="xs:decimal"> <xs:attribute name="totalDigits" type="xs:positiveInteger" /> <xs:attribute name="fractionDigits" type="xs:nonNegativeInteger" /> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:complexType name="structureFieldArray">
IBM Toolbox for Java
431
<xs:sequence> <xs:group ref="structureField" minOccurs="1" maxOccurs="unbounded"/> </xs:sequence> <xs:attribute name="name" type="string50"/> <!-- 'count' is required if you want to input and/or output array data as XPCML. --> <xs:attribute name="count" type="xs:string"/> </xs:complexType>
<!-- Abstract type for "struct or program". --> <xs:element name="structOrProgram" abstract="true" /> <!-- Abstract type for all data field types. --> <xs:element name="stringFieldGroup" type="stringFieldType" abstract="true" /> <xs:element name="intFieldGroup" type="intFieldType" abstract="true" /> <xs:element name="unsignedIntFieldGroup" type="unsignedIntFieldType" abstract="true" /> <xs:element name="shortFieldGroup" type="shortFieldType" abstract="true" /> <xs:element name="unsignedShortFieldGroup" type="unsignedShortFieldType" abstract="true" /> <xs:element name="longFieldGroup" type="longFieldType" abstract="true" /> <xs:element name="zonedDecimalFieldGroup" type="zonedDecimalFieldType" abstract="true" /> <xs:element name="packedDecimalFieldGroup" type="packedDecimalFieldType" abstract="true" /> <xs:element name="floatFieldGroup" type="floatFieldType" abstract="true" /> <xs:element name="doubleFieldGroup" type="doubleFieldType" abstract="true" /> <xs:element name="hexBinaryFieldGroup" type="hexBinaryFieldType" abstract="true" /> <xs:element name="structFieldGroup" type="structFieldType" abstract="true" />
<!-- Declare each field element to be a specific field type. --> <xs:element name="stringField" type="stringFieldType" substitutionGroup="stringFieldGroup" nillable="true"/> <xs:element name="intField" type="intFieldType" nillable="true" substitutionGroup="intFieldGroup" /> <xs:element name="unsignedIntField" type="unsignedIntFieldType" substitutionGroup="unsignedIntFieldGroup" nillable="true"/> <xs:element name="shortField" type="shortFieldType" nillable="true" substitutionGroup="shortFieldGroup" /> <xs:element name="unsignedShortField" type="unsignedShortFieldType" nillable="true" substitutionGroup="unsignedShortFieldGroup" /> <xs:element name="longField" type="longFieldType" nillable="true" substitutionGroup="longFieldGroup" /> <xs:element name="hexBinaryField" type="hexBinaryFieldType" nillable="true" substitutionGroup="hexBinaryFieldGroup" /> <xs:element name="zonedDecimalField" type="zonedDecimalFieldType" nillable="true" substitutionGroup="zonedDecimalFieldGroup" /> <xs:element name="packedDecimalField" type="packedDecimalFieldType" nillable="true" substitutionGroup="packedDecimalFieldGroup" /> <xs:element name="doubleField" type="doubleFieldType" nillable="true" substitutionGroup="doubleFieldGroup" /> <xs:element name="floatField" type="floatFieldType" nillable="true" substitutionGroup="floatFieldGroup" /> <xs:element name="structField" type="structFieldType" nillable="true" substitutionGroup="structFieldGroup" /> <!-- A StructureField is exactly one of the following: stringField, intField, shortField, longField, zonedDecimalField, packedDecimalField, floatField, doubleField, or hexBinaryField. --> <xs:group name="structureField"> <xs:choice> <xs:element ref="stringFieldGroup"/> <xs:element ref="intFieldGroup"/> <xs:element ref="unsignedIntFieldGroup"/> <xs:element ref="shortFieldGroup"/>
432
<xs:element <xs:element <xs:element <xs:element <xs:element <xs:element <xs:element <xs:element <xs:element </xs:choice> </xs:group>
<!-- Character field --> <!-- Maps to AS400Text. --> <xs:complexType name="stringFieldType"> <xs:simpleContent> <xs:extension base="xs:string"> <!-- Number of characters. --> <xs:attribute name="length" type="xs:string"/> <!-- Indicates the field's encoding (CCSID) on the server. --> <xs:attribute name="ccsid" type="xs:string"/> <xs:attribute name="trim" type="trimType" /> <xs:attribute name="bytesPerChar" type="charType" /> <xs:attribute name="bidiStringType" type="bidiStringTypeType" /> <xs:attributeGroup ref="commonFieldAttrs"/> </xs:extension> </xs:simpleContent> </xs:complexType> <!-- hexBinary field --> <!-- Maps to AS400ByteArray. --> <xs:complexType name="hexBinaryFieldType"> <xs:simpleContent> <xs:extension base="xs:hexBinary"> <xs:attributeGroup ref="commonFieldAttrs"/> </xs:extension> </xs:simpleContent> </xs:complexType> <!-- Float field --> <!-- Maps to AS400Float4. --> <xs:complexType name="floatFieldType"> <xs:simpleContent> <xs:extension base="xs:float"> <xs:attributeGroup ref="commonFieldAttrs"/> </xs:extension> </xs:simpleContent> </xs:complexType> <!-- zonedDecimal field --> <!-- Maps to AS400ZonedDecimal. --> <xs:complexType name="zonedDecimalFieldType"> <xs:simpleContent> <xs:extension base="zonedDecimal"> <xs:attributeGroup ref="commonFieldAttrs"/> </xs:extension> </xs:simpleContent> </xs:complexType> <!-- packedDecimal field --> <!-- Maps to AS400PackedDecimal. --> <xs:complexType name="packedDecimalFieldType"> <xs:simpleContent> <!-- In DDS, "binary" values are 1-18 digits; if field length is greater than 9, then decimal positions value must be 0. -->
IBM Toolbox for Java
433
<xs:extension base="packedDecimal"> <xs:attributeGroup ref="commonFieldAttrs"/> </xs:extension> </xs:simpleContent> </xs:complexType> <!-- int field --> <!-- Maps to AS400Bin4. --> <xs:complexType name="intFieldType"> <xs:simpleContent> <xs:extension base="xs:int"> <xs:attributeGroup ref="commonFieldAttrs"/> </xs:extension> </xs:simpleContent> </xs:complexType> <!-- unsigned int field --> <!-- Maps to AS400Bin4. --> <xs:complexType name="unsignedIntFieldType"> <xs:simpleContent> <xs:extension base="xs:unsignedInt"> <xs:attributeGroup ref="commonFieldAttrs"/> </xs:extension> </xs:simpleContent> </xs:complexType> <!-- short field --> <!-- Maps to AS400Bin2. --> <xs:complexType name="shortFieldType"> <xs:simpleContent> <xs:extension base="xs:short"> <xs:attributeGroup ref="commonFieldAttrs"/> </xs:extension> </xs:simpleContent> </xs:complexType> <!-- unsigned short field --> <!-- Maps to AS400Bin2. --> <xs:complexType name="unsignedShortFieldType"> <xs:simpleContent> <xs:extension base="xs:unsignedShort"> <xs:attributeGroup ref="commonFieldAttrs"/> </xs:extension> </xs:simpleContent> </xs:complexType> <!-- long field --> <!-- Maps to AS400Bin8. --> <xs:complexType name="longFieldType"> <xs:simpleContent> <xs:extension base="xs:long"> <xs:attributeGroup ref="commonFieldAttrs"/> </xs:extension> </xs:simpleContent> </xs:complexType> <!-- double field --> <!-- Maps to AS400Float8. --> <xs:complexType name="doubleFieldType"> <xs:simpleContent> <xs:extension base="xs:double"> <xs:attributeGroup ref="commonFieldAttrs"/> </xs:extension> </xs:simpleContent> </xs:complexType>
434
<!-- struct Field --> <xs:complexType name="structFieldType"> <xs:simpleContent> <xs:extension base="xs:string"> <xs:attribute name="struct" type="string50"/> <xs:attributeGroup ref="commonFieldAttrs"/> </xs:extension> </xs:simpleContent> </xs:complexType> <!-- Attributes that are common to all data field types. --> <xs:attributeGroup name="commonFieldAttrs"> <xs:attribute name="name" type="string50"/> <xs:attribute name="columnHeading1" type="string20"/> <xs:attribute name="columnHeading2" type="string20"/> <xs:attribute name="columnHeading3" type="string20"/> <xs:attribute name="description" type="string50"/> <xs:attribute name="defaultValue" type="xs:string"/><!-- Max length of string is 65535 characters. --> <xs:attribute name="nullable" type="xs:boolean"/> <xs:attribute name="isEmptyString" type="xs:boolean"/><!-- Indicate this is an empty string. --> </xs:attributeGroup> <!-- Utility types. -->
<xs:simpleType name="ccsidType"> <xs:restriction base="xs:nonNegativeInteger"> <xs:maxInclusive value="65535"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="string10"> <xs:restriction base="xs:string"> <xs:maxLength value="10"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="string20"> <xs:restriction base="xs:string"> <xs:maxLength value="20"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="string50"> <xs:restriction base="xs:string"> <xs:maxLength value="50"/> </xs:restriction> </xs:simpleType> </xs:schema>
XPCML syntax: The XPCML schema defines several element tags, and each element tag contains attribute tags. The following table lists the different elements that you can declare and define in your XPCML source files. Each entry in the first column links to the appropriate section of the XPCML schema.
XPCML tag doubleParm arrayOfDoubleParm Description Defines a double parameter Defines a parameter that is an array of doubles Equivalent PCML tag data (type=float, length=8)
435
XPCML tag floatParm arrayOfFloatParm hexBinaryParm arrayOfHexBinaryParm intParm arrayOfIntParm longParm arrayOfLongParm packedDecimalParm arrayOfPackedDecimalParm parameterList
Defines a byte parameter represented byte (rough equivalent, represented in hex in hex) Defines a parameter that is an array of hexBinaries Defines an integer parameter Defines a parameter that is an array of integers Defines a long parameter Defines a parameter that is an array of longs Defines a packed decimal parameter Defines a parameter that is an array of packed decimals Signals that the enclosing tag represents all of the parameter definitions for the program Begins and ends the XML that describes one program call Defines a short parameter Defines a parameter that is an array of shorts Defines a string parameter Defines a parameter that is an array of strings Defines a named structure that you can specify as an argument to a program or as a field within another named structure Defines an array of structs Represents a reference to a struct tag data (type=struct) found elsewhere in the XPCML document that you want to included at a specific location in the document Defines a parameter that is an array of struct parameters Defines an unsigned integer parameter Defines a parameter that is an array of unsigned integers Defines an unsigned short parameter Defines a parameter that is an array of unsigned shorts data (type=int, length=2, precision=16) data (type=int, length=4, precision=32) struct program data (type int, length 2) data (type=packed) data (type=int, length=8) data (type=int, length=4)
arrayOfStruct structParm
436
Description Begins and ends the XPCML source file that describes the program call format Defines a zoned decimal parameter Defines a parameter that is an array of zoned decimals
zonedDecimalParm arrayOfZonedDecimalParm
XPCML tag attributes: The XPCML schema defines several element tags, and each element tag contains attribute tags. The following table lists and describes the different attributes for each element. For more specific and detailed information about XPCML tags and their attributes, see XPCML schema.
XPCML tag hexBinaryParm arrayOfHexBinaryParm doubleParm arrayOfDoubleParm floatParm arrayOfFloatParm intParm arrayOfIntParm longParm arrayOfLongParm packedDecimalParm arrayOfPackedDecimalParm parameterList Defines a double parameter Defines a parameter that is an array of doubles Defines a float parameter Defines a parameter that is an array of floats Defines an integer parameter Defines a parameter that is an array of integers Defines a long parameter Defines a parameter that is an array of longs Defines a packed decimal parameter Defines a parameter that is an array of packed decimals Signals that the enclosing tag represents all of the parameter definitions for the program Begins and ends the XML that describes one program call Defines a short parameter Defines a parameter that is an array of shorts Defines a string parameter Defines a parameter that is an array of strings Defines a named structure that you can specify as an argument to a program or as a field within another named structure
IBM Toolbox for Java
Description
float (length 8)
437
Description
Represents a reference to a struct tag data (type struct) found elsewhere in the XPCML document that you want to included at a specific location in the document Defines a parameter that is an array of struct parms Defines an unsigned integer parameter Defines a parameter that is an array of unsigned integers Defines an unsigned short parameter Defines a parameter that is an array of unsigned shorts Begins and ends the XPCML source file that describes the program call format Defines a zoned decimal parameter Defines a parameter that is an array of zoned decimals data (type zoned) data (type int, length 2, precision 16) data (type int, length 4, precision 32)
zonedDecimalParm arrayOfZonedDecimalParm
Using XPCML
Using XPCML is similar to using PCML. The following steps serve as a general outline for the actions that you need to perform to use XPCML. 1. Use XPCML to describe the specification for the program call 2. Create a ProgramCallDocument object 3. Use ProgramCallDocument.callProgram() to run the program Despite the similarities to using PCML, using XPCML offers enhanced functionality: v Have the parser automatically validate parameter values v Specify and pass values for program parameters v Retrieve the results of a program call to your server in XPCML v Transform an existing PCML document into the equivalent XPCML document v Extend the XPCML schema to define new simple and complex elements and attributes For example, IBM Toolbox for Java enables you to extend the XPCML schema to create new parameter and data types. You can use this XPCML capability to condense your XPCML source files, which makes the files easier to read and code easier to use. For more information about using XPCML, see the following pages: Converting existing PCML to XPCML: The ProgramCallDocument class contains the transformPCMLToXPCML method that enables you to transform existing PCML documents to equivalent XPCML documents. XPCML has comparable definitions for all of the elements and attributes that you can define in PCML. Using transformPCMLToXPCML() converts the PCML representation of the elements and attributes to the equivalent XPCML.
438
Note that in some cases, equivalent XPCML attributes have a different name than in PCML. For example, the attribute "usage" in PCML is the attribute "passDirection" in XPCML. For more information about how to use XPCML compared to PCML, see XPCML schema and syntax. The method takes the existing PCML document, which you pass to it as an InputStream object, and generates the equivalent XPCML as an OutputStream object. Because transformPCMLToXPCML() is a static method, you can call it without first creating a ProgramCallDocument object. Example: Converting a PCML document to an XPCML document The following example shows how to convert a PCML document (named myPCML.pcml) to an XPCML document (named myXPCML.xpcml). Note: You must specify .xpcml as the file extension for XPCML files. Using .xpcml as the file extension ensures that the ProgramCallDocument class recognizes the file as XPCML. If you do not specify an extension, ProgramCallDocument assumes that the file is PCML. PCML document myPCML.pcml
<!-- myPCML.pcml --> <pcml version="4.0"> <program name="prog1" path="/QSYS.LIB/W95LIB.LIB/PROG1.PGM"> <data type="char" name="parm1" usage="in" passby="reference" minvrm="V5R2M0" ccsid="37" length="10" init="Value 1"/> </program> </pcml>
For more information about transformPCMLToXPCML() and the ProgramCallDocument class, see the following page: ProgramCallDocument javadoc information Using XPCML to call a program on your server: After you create your XPCML file, you need to create a ProgramCallDocument object that can use the XPCML specifications and data values to call a program on your IBM i server.
IBM Toolbox for Java
439
Create an XPCML ProgramCallDocument by passing in the name of your XPCML file on the ProgramCallDocument constructor. Creating an XPCML ProgramCallDocument in this way first parses and validates your XPCML document, then creates the ProgramCallDocument object. In order to parse and validate the XPCML document, make sure that your CLASSPATH includes a fully validating XML parser. For more information about requirements to run XPCML, see the following page: Requirements for using XPCML on page 418 The following example shows how to create a ProgramCallDocument object for the XPCML file, myXPCML.xpcml.
system = new AS400(); // Create a ProgramCallDocument into which to parse the file. ProgramCallDocument xpcmlDoc = new ProgramCallDocument(system, "myXPCML.xpcml");
The only difference between creating an XPCML ProgramCallDocument and a PCML ProgramCallDocument is that you pass the constructor an XPCML document instead of a PCML document. Note: You must specify .xpcml as the file extension for XPCML files. Using .xpcml as the file extension ensures that the ProgramCallDocument class recognizes the file as XPCML. If you do not specify an extension, ProgramCallDocument assumes that the file is PCML. Using XPCML to call a program on your server After you create the ProgramCallDocument object, use any of the methods of the ProgramCallDocument class to work with your XPCML document. For example, call an IBM i program by using ProgramCallDocument.callProgram() or change the value for an XPCML input parameter before calling the server program by using the appropriate ProgramCallDocument.setValue method. The following example shows how to create a ProgramCallDocument object for an XPCML file (named myXPCML.xpcml). After creating the ProgramCallDocument object, the example calls a program (PROG1) that is specified in the XPCML document. In this case, the only difference between using XPCML and PCML is that the example passes an XPCML file to the ProgramCallDocument constructor. After your application reads and parses an XPCML document, the XPCML document functions just like a PCML document. At this point, XPCML can use any of the existing methods that PCML uses.
system = new AS400(); // Create a ProgramCallDocument into which to parse the file. ProgramCallDocument xpcmlDoc = new ProgramCallDocument(system, "myXPCML.xpcml"); // Call PROG1 boolean rc = xpcmlDoc.callProgram("PROG1");
Obtaining program call results as XPCML: After you call a server program, you can use ProgramCallDocument.getValue methods to retrieve the Java objects that represent program parameter values. Additionally, the following generateXPCML methods enable ProgramCallDocument to return the results of a program call as XPCML: v generateXPCML(String fileName): Generates results in XPCML for the entire XPCML source file that you used to construct the ProgramCallDocument object. Stores the XPCML in a file with the specified file name.
440
v generateXPCML(String pgmName, String fileName): Generates results in XPCML for only the specified program and its parameters. Stores the XPCML in a file with the specified file name. v generateXPCML(java.io.OutputStream outputStream): Generates results in XPCML for the entire XPCML source file. Stores the XPCML in the specified OutputStream object. v generateXPCML(String pgmName, java.io.OutputStream outputStream): Generates results in XPCML for only the specified program and its parameters. Stores the XPCML in the specified OutputStream object. For more information about the ProgramCallDocument class, see the ProgramCallDocument Javadoc information. The following example shows how you can construct an XPCML ProgramCallDocument, call an IBM i program, and retrieve the results of the program call as XPCML. Example: Retrieving program call results as XPCML on page 745 Related information ProgramCallDocument Javadoc Passing in parameter values as XPCML: You can set the values for program parameters in the XPCML source file and pass in the parameter values as XPCML. When the ProgramCallDocument object reads in and parses the XPCML document, it automatically calls the appropriate setValue method for each parameter specified in the XPCML. Using XPCML to pass in parameter values relieves you from writing Java code that sets the values of complicated structures and arrays. The following examples show different ways to construct arrays and pass in parameter values as XPCML: Example: Passing in parameter values as XPCML on page 748 Examples: Passing in arrays of parameter values as XPCML on page 749 Using condensed XPCML: Because XPCML is extensible, you can define new parameter types that extend those specified by the XPCML schema. Condensing XPCML extends the XPCML schema to create new data type definitions that simplify and improve the readability and usability of your XPCML documents. The following discussion assumes that you understand the XPCML schema. For more information about the XPCML schema, see the following page: XPCML schema and syntax on page 418 To condense existing XPCML source, you use the ProgramCallDocument.condenseXPCML method, which generates the following: v An extended schema that contains new type definitions for each parameter in the existing XPCML source v New XPCML source that uses the type definitions provided in the extended schema For more information about condensing your XPCML, see the following pages: Condensing existing XPCML documents on page 442
IBM Toolbox for Java
441
Example: Using condensed XPCML to create a ProgramCallDocument object on page 754 Example: Obtaining program call results as condensed XPCML on page 754 Condensing existing XPCML documents: Condensing existing XPCML documents results in more readable and usable XPCML source. To create condensed XPCML, use the ProgramCallDocument.condenseXPCML method. To call condenseXPCML(), provide the following parameters to the method: v An input stream that represents the existing XPCML v An ouput stream that repesents the condensed XPCML v An output stream that represents the new, extended schema v A name for the new schema in the appropriate format (for example, mySchema.xsd) For more information about condenseXPCML() and the ProgramCallDocument class, see the ProgramCallDocument Javadoc information. ProgramCallDocument.condenseXPCML() is a static method, which means that you do not have to instantiate a ProgramCallDocument object in order to call the method. Examples The following examples illustrate how to condense an existing XPCML document. The first example is simple and includes original XPCML source, the resulting condensed XPCML, and the extended schema. The second example is longer and more complex, so it includes the Java code that calls condenseXPCML() and only a few of the newly generated type definitions in the extended schema: Example: Condensing an existing XPCML document on page 751 Example: Condensing an existing XPCML document, including Java code on page 751 Related information ProgramCallDocument Javadoc Identifying parse errors in XPCML: When validating XPCML schema documents, a fully validating XML parser may generate warnings, non-fatal parse errors, and fatal parse errors. Warnings and non-fatal parse errors do not cause the parse to fail. You might want to examine warnings and non-fatal errors to help you determine problems with your XPCML source. Fatal parse errors cause the parse to terminate with an exception. To display warnings and non-fatal parser errors when parsing an XPCML document, turn tracing on in your application and set the trace category to PCML. Example A fully validating XML parser generates an error for any numeric parameter type that does not have a value. The following example shows sample XPCML source and the resulting non-fatal parse error: XPCML source
442
Resulting error
Tue Mar 25 15:21:44 CST 2003 [Error]: cvc-complex-type.2.2: Element 'intParm' must have no element [children], and the value must be valid.
To prevent logging this kind of error, add the nil=true attribute to the intParm element. The nil=true atttribute signals to the parser that you have deliberately left the element empty.. Here is the previous XPCML source with the nil=true atttribute added:
<program name="prog1"/> <parameterList> <intParm xsi:nil="true" name="parm1"/> </parameterList> </program>
443
Description The library in which the object resides. The library is a required portion of an integrated file system path name. The library name must be 10 or fewer characters and be followed by .lib. The name of the object that the integrated file system path name represents. The object is a required portion of an integrated file system path name. The object name must be 10 or fewer characters and be followed by .type, where type is the type of the object. Types can be found by prompting for the OBJTYPE parameter on control language (CL) commands, such as the Work with Objects (WRKOBJ) command. The type of the object. The type of the object must be specified when specifying the object. (See object above.) The type name must be 6 or fewer characters. The name of the member that this integrated file system path name represents. The member is an optional portion of an integrated file system path name. It can be specified only when the object type is FILE. The member name must be 10 or fewer characters and followed by .mbr.
object
type
member
Follow these conditions when determining and specifying the integrated file system name: v The forward slash (/) is the path separator character. v The root-level directory, called QSYS.LIB, contains the server library structure. v Objects that reside in the server library QSYS have the following format:
/QSYS.LIB/object.type
v The object type extension is the server abbreviation used for that type of object. To see a list of these types, enter a CL command that has object type as a parameter and press F4 (Prompt) for the type. For example, the Work with Objects (WRKOBJ) command has an object type parameter. The following table is a list of some commonly used object types and the abbreviation for each type:
Object type command data queue file font resource form definition library member overlay page definition page segment Abbreviation .CMD .DTAQ .FILE .FNTRSC .FORMDF .LIB .MBR .OVL .PAGDFN .PAGSET
444
Use the following descriptions to help you determine how to specify integrated file system path names:
Integrated file system name /QSYS.LIB/MY_LIB.LIB/MY_PROG.PGM /QSYS.LIB/MY_LIB.LIB/MY_QUEUE.DTAQ /QSYS.LIB/YEAR1998.LIB/MONTH.FILE/JULY.MBR Description Program MY_PROG in library MY_LIB on the server Data queue MY_QUEUE in library MY_LIB on the server Member JULY in file MONTH in library YEAR1998 on the server
See the QSYSObjectPathName class for information about building and parsing integrated file system names. For more information about integrated file system concepts, see Integrated file system concepts.
445
To connect to an IBM i server, your Java program must create an AS400 object. The AS400 object contains up to one socket connection for each IBM i server type. A service corresponds to a job on the server and is the interface to the data on the server. Note: When you create Enterprise JavaBeans (EJB), comply with the EJB specification that does not allow threads during your connection. Although turning off IBM Toolbox for Java thread support may slow your application, it is required to comply with the EJB specification. Every connection to each server has its own job on the system. A different server supports each of the following: v JDBC v v v v v Program call and command call Integrated file system Print Data queue Record-level access
Note: v The print classes use one socket connection per AS400 object if the application does not try to do two things that require the network print server at the same time. v A print class creates additional socket connections to the network print server if needed. The extra conversations are disconnected if they are not used for 5 minutes. The Java program can control the number of connections to the system. To optimize communications performance, a Java program can create multiple AS400 objects for the same server as shown in Figure 1. This creates multiple socket connections to the system. Figure 1: Java program creating multiple AS400 objects and socket connections for the same system
To conserve server resources, create only one AS400 object as shown in Figure 2. This approach reduces the number of connections, which reduces the amount of resource used on the server. Figure 2: Java program creating a single AS400 object and socket connection for the same system
446
Note: Although creating more connections increases the amount of resource used on the server, creating more connections can have a benefit. Having more connections enables your Java program to process things in parallel, which can give better throughput (transactions-per-second) and speed up your application. You can also choose to use a connection pool to manage connections as shown in Figure 3. This approach reduces the amount of time it takes to connect by reusing a connection previously established for the user. Figure 3: Java program getting a connection from an AS400ConnectionPool to a server
The following examples show how to create and use AS400 objects: Example 1: In the following example, two CommandCall objects are created that send commands to the same server. Because the CommandCall objects use the same AS400 object, only one connection to the server is created.
// Create an AS400 object. AS400 sys = new AS400("mySystem.myCompany.com"); // Create two command call objects that use // the same AS400 object. CommandCall cmd1 = new CommandCall(sys,"myCommand1"); CommandCall cmd2 = new CommandCall(sys,"myCommand2"); // Run the commands. A connection is made when the
IBM Toolbox for Java
447
// first command is run. Since they use the same // AS400 object the second command object will use // the connection established by the first command. cmd1.run(); cmd2.run();
Example 2: In the following example, two CommandCall objects are created that send commands to the same system. Because the CommandCall objects use different AS400 objects, two connections to the server are created.
// Create two AS400 objects to the same server. AS400 sys1 = new AS400("mySystem.myCompany.com"); AS400 sys2 = new AS400("mySystem.myCompany.com"); // Create two command call objects. They use // different AS400 objects. CommandCall cmd1 = new CommandCall(sys1,"myCommand1"); CommandCall cmd2 = new CommandCall(sys2,"myCommand2"); // Run the commands. A connection is made when the // first command is run. Since the second command // object uses a different AS400 object, a second // connection is made when the second command is run. cmd1.run(); cmd2.run();
Example 3: In the following example, a CommandCall object and an IFSFileInputStream object are created using the same AS400 object. Because the CommandCall object and the IFSFileInput Stream object use different services on the server, two connections are created.
// Create an AS400 object. AS400 newConn1 = new AS400("mySystem.myCompany.com"); // Create a command call object. CommandCall cmd = new CommandCall(newConn1,"myCommand1"); // Create the file object. Creating it causes the // AS400 object to connect to the file service. IFSFileInputStream file = new IFSFileInputStream(newConn1,"/myfile"); // Run the command. A connection is made to the // command service when the command is run. cmd.run();
Example 4: In the following example, an AS400ConnectionPool is used to get an IBM i connection. This example (like Example 3 above) does not specify a service, so the connection to the command service is made when the command is run.
// Create an AS400ConnectionPool. AS400ConnectionPool testPool1 = new AS400ConnectionPool(); // Create a connection. AS400 newConn1 = testPool1.getConnection("myAS400", "myUserID", "myPassword"); // Create a command call object that uses the AS400 object. CommandCall cmd = new CommandCall(newConn1,"myCommand1"); // Run the command. A connection is made to the // command service when the command is run. cmd.run(); // Return connection to pool. testPool1.returnConnectionToPool(newConn1);
Example 5: The following example uses AS400ConnectionPool to connect to a particular service when requesting the connection from the pool. This eliminates the time required to connect to the service when
448
the command is run (see Example 4 above). If the connection is returned to the pool, the next call to get a connection can return the same connection object. This means that no extra connection time is needed, either on creation or use.
// Create an AS400ConnectionPool. AS400ConnectionPool testPool1 = new AS400ConnectionPool(); // Create a connection to the AS400.COMMAND service. (Use the service number constants // defined in the AS400 class (FILE, PRINT, COMMAND, DATAQUEUE, and so on.)) AS400 newConn1 = testPool1.getConnection("myAS400", "myUserID", "myPassword", AS400.COMMAND); // Create a command call object that uses the AS400 object. CommandCall cmd = new CommandCall(newConn1,"myCommand1"); // Run the command. A connection has already been made // to the command service. cmd.run(); // Return connection to pool. testPool1.returnConnectionToPool(newConn1); // Get another connection to command service. In this case, it will return the same // connection as above, meaning no extra connection time will be needed either now or // when the command service is used. AS400 newConn2 = testPool1.getConnection("myAS400", "myUserID", "myPassword", AS400.COMMAND);
Example 2: Once a connection is started, the Java program is responsible for disconnecting, which is done either implicitly by the AS400 object, or explicitly by the Java program. A Java program disconnects by calling the disconnectService() method on the AS400 object. To improve performance, the Java program must disconnect only when the program is finished with a service. If the Java program disconnects before it is finished with a service, the AS400 object reconnects, if it is possible to reconnect, when data is needed from the service. Figure 4 shows how disconnecting the connection for the first integrated file system object connection ends only that single instance of the AS400 object connection, not all of the integrated file system object connections. Figure 4: Single object using its own service for an instance of an AS400 object is disconnected
449
Example 3: Multiple objects that use the same service and share the same AS400 object share a connection. Disconnecting ends the connection for all objects that are using the same service for each instance of an AS400 object as is shown in Figure 5. Figure 5: All objects using the same service for an instance of an AS400 object are disconnected
For example, two CommandCall objects use the same AS400 object. When disconnectService() is called, the connection is ended for both CommandCall objects. When the run() method for the second CommandCall object is called, the AS400 object must reconnect to the service:
450
// Create an AS400 object. AS400 sys = new AS400("mySystem.myCompany.com"); // Create two command call objects. CommandCall cmd1 = new CommandCall(sys,"myCommand1"); CommandCall cmd2 = new CommandCall(sys,"myCommand2"); // Run the first command cmd1.run(); // Disconnect from the command service. sys.disconnectService(AS400.COMMAND); // Run the second command. The AS400 object // must reconnect to the server. cmd2.run(); // Disconnect from the command service. // is the correct place to disconnect. sys.disconnectService(AS400.COMMAND); This
Example 4: Not all IBM Toolbox for Java classes automatically reconnect. Some method calls in the integrated file system classes do not reconnect because the file may have changed. While the file was disconnected, some other process may have deleted the file or changed its contents. In the following example, two file objects use the same AS400 object. When disconnectService() is called, the connection is ended for both file objects. The read() for the second IFSFileInputStream object fails because it no longer has a connection to the server.
// Create an AS400 object. AS400 sys = new AS400("mySystem.myCompany.com"); // Create two file objects. A connection to the // server is created when the first object is // created. The second object uses the connection // created by the first object. IFSFileInputStream file1 = new IFSFileInputStream(sys,"/file1"); IFSFileInputStream file2 = new IFSFileInputStream(sys,"/file2"); // Read from the first file, then close it. int i1 = file1.read(); file1.close(); // Disconnect from the file service. sys.disconnectService(AS400.FILE); // Attempt to read from the second file. This // fails because the connection to the file service // no longer exists. The program must either // disconnect later or have the second file use a // different AS400 object (which causes it to // have its own connection). int i2 = file2.read(); // Close the second file. file2.close(); // Disconnect from the file service. This // is the correct place to disconnect. sys.disconnectService(AS400.FILE);
451
In fact, the classes run on any platform that supports the Java 2 Software Development Kit (J2SDK) specifications. For more information about IBM i support for different Java platforms, see Support for multiple JDKs.
Comparing the IBM i Java virtual machine and the IBM Toolbox for Java classes
You always have at least two ways to access a server resource when your Java program is running on the IBM Developer Kit for Java (IBM i) Java virtual machine (JVM). You can use either of the following interfaces: v Facilities built into Java v An IBM Toolbox for Java class When deciding which interface to use, consider the following factors: v Location - Where a program runs is the most important factor in deciding which interface set to use. Does the program do the following: Run only on the client? Run only on the server? Run on both client and server, but in both cases the resource is an IBM i resource? Run on one IBM i JVM and access resources on another IBM i server? Run on different kinds of servers? If the program runs on both client and server (including an IBM i server as a client to a second IBM i server) and accesses only IBM i resources, it may be best to use the IBM Toolbox for Java interfaces. If the program must access data on many types of servers, it may be best to use Java native interfaces. v Consistency / Portability - The ability to run IBM Toolbox for Java classes on the IBM i server means that the same interfaces can be used for both client programs and server programs. When you have only one interface to learn for both client programs and server programs, you can be more productive. Writing to IBM Toolbox for Java interfaces makes your program less server portable, however. If your program must connect to an IBM i server as well as other servers, you may find it better to use the facilities that are built into Java. v Complexity - The IBM Toolbox for Java interface is built especially for easy access to an IBM i resource. Often, the only alternative to using the IBM Toolbox for Java interface is to write a program that accesses the resource and communicates with that program through Java Native Interface (JNI). You must decide whether it is more important to have better Java neutrality and write a program to access the resource, or to use the IBM Toolbox for Java interface, which is less portable. v Function - The IBM Toolbox for Java interface often provides more function than the Java interface. For example, the IBM Toolbox for Java IFSFileOutputStream class has more function than the FileOutputStream class of java.io. However, you lose server portability by using the IBM Toolbox for Java class. You must decide whether portability is more important or whether you want to take advantage of the additional function. v Resource - When running on the IBM i JVM, many of the IBM Toolbox for Java classes still make requests through the host servers. Therefore, a second job (the server job) carries out the request to access a resource. This request may take more resource than a Java native interface that runs under the job of the Java program. v IBM i server as a client - If your program runs on one IBM i server and accesses data on a second IBM i server, your best choice may be to use IBM Toolbox for Java classes. These classes provide easy access to the resource on the second IBM i server. An example of this is Data Queue access. The IBM Toolbox for Java Data Queue interfaces provide easy access to the data queue resource.
452
Running IBM Toolbox for Java classes on the IBM i Java virtual machine
There are some special considerations for running the IBM Toolbox for Java classes on the IBM Developer Kit for Java (IBM i) Java virtual machine (JVM).
Command call
Two common ways to call a command are to use one of the following: v The IBM Toolbox for Java CommandCall class v The java.lang.Runtime.exec method The CommandCall class generates a list of messages that are available to the Java program once the command completes. This list of messages is not available through java.lang.Runtime.exec(). The java.lang.Runtime.exec method is portable across many platforms, so if your program must access files on different types of servers, java.lang.Runtime.exec() is a better solution.
JDBC
Two IBM-supplied JDBC drivers are available to programs running on the IBM i JVM: v The IBM Toolbox for Java JDBC driver v The IBM Developer Kit for Java JDBC driver The IBM Toolbox for Java JDBC driver is best to use when the program is running in a client/server environment. The IBM Developer Kit for Java JDBC driver is best to use when the program is running on the server. If the same program runs on both the workstation and the server, you should load the correct driver through a system property instead of coding the driver name into your program.
Program call
Two common ways to call a program are as follows: v The ProgramCall class of the IBM Toolbox for Java v Through a Java Native Interface (JNI) call The IBM Toolbox for Java ProgramCall class has the advantage that it can call any server program.
453
You may not be able to call your server program through JNI. An advantage of JNI is that it is more portable across server platforms.
Setting system name, user ID, and password with an AS400 object in the IBM i Java virtual machine
The AS400 object allows special values for system name, user ID, and password when the Java program is running on the IBM Toolbox for Java (IBM i) Java virtual machine (JVM). When you run a program on the IBM i JVM, be aware of some special values and other considerations: v User ID and password prompting is disabled when the program runs on the server. For more information about user ID and password values in the server environment, see Summary of user ID and password values on an AS400 object. v If system name, user ID, or password is not set on the AS400 object, the AS400 object connects to the current server by using the user ID and password of the job that started the Java program. When connecting to a v4r4 or later machine, it can extend the signed-on user's password like the rest of the IBM Toolbox for Java components. v The special value, localhost, can be used as the system name. In this case, the AS400 object connects to the current server. v The special value, *current, can be used as the user ID or password on the AS400 object. In this case, the user ID or password (or both) of the job that started the Java program is used. v The special value, *current, can be used as the user ID or password on the AS400 object when the Java program is running on the IBM i JVM of one server, and the program is accessing resources on another IBM i server. In this case, the user ID and password of the job that started the Java program on the source system are used when connecting to the target system.
Examples
The following examples show how to use the AS400 object with the IBM i JVM. Example: Creating an AS400 object when the IBM i JVM is running a Java program When a Java program is running in the IBM i JVM, the program does not need to supply a system name, user ID, or password. Note: You must supply a password when using record-level access. If these values are not supplied, the AS400 object connects to the local system by using the user ID and password of the job that started the Java program. When the program is running on the IBM i JVM, setting the system name to localhost is the same as not setting the system name. The following example shows how to connect to the current server:
// Create two AS400 objects. If the Java program is running in the // IBM i JVM, the behavior of the two objects is the same. // They will connect to the current server using the user ID and // password of the job that started the Java program. AS400 sys = new AS400() AS400 sys2 = new AS400("localhost")
Example: Connecting to the current server with a different user ID and password from the program that started the job The Java program can set a user ID and password even when the program is running on the IBM i JVM. These values override the user ID and password of the job that started the Java program. In the following example, the Java program connects to the current server, but the program uses a user ID and password that differs from those of the job that started the Java program.
454
// Create an AS400 object. Connect to the current server but do // not use the user ID and password of the job that started the // program. The supplied values are used. AS400 sys = new AS400("localhost", "USR2", "PSWRD2")
Example: Connecting to a different server by using the user ID and password of the job that started the Java program A Java program that is running on one server can connect to and use the resources of other systems. If *current is used for user ID and password, the user ID and password of the job that started the Java program is used when the Java program connects to the target server. In the following example, the Java program is running on one server, but uses resources from another server. The user ID and password of the job that started the Java program are used when the program connects to the second server.
// Create an AS400 object. This program will run on one server // but will connect to a second server (called "target"). // Because *current is used for user ID and password, the user // ID and password of the job that started the program will be // used when connecting to the second server. AS400 target = new AS400("target", "*current", "*current")
Summary of user ID and password values on an AS400 object: The following table summarizes how the user ID and password values on an AS400 object are handled by a Java program running on a server compared to a Java program running on a client.
Values on AS400 object Java program running on a server Java program running on a client Prompt for system, user ID, and password
System name, user ID, and password Connect to the current server using not set the user ID and password of the job that started the program System name = localhost System name = localhost User ID = *current System name = localhost User ID = *current Password ID = *current System name = "sys" Connect to the current server using the user ID and password of the job that started the program
Error: localhost is not valid when the Java program is running on a client
Connect to server "sys" using the user ID and password of the job that started the program. "sys" can be the current server or another server Connect to the current server using the user ID and password specified by the Java program instead of the user ID and password of the job that started the program
Error: localhost is not valid when the Java program is not running on a client
455
Each Independent ASP contains all of the necessary system information associated with the data it contains. So, while the system is active, you can take the Independent ASP offline, bring it online, or switch between systems. For more information, see Independent ASPs and User ASPs. You can use the "database name" JDBC property or the setDatabaseName() method from the AS400JDBCDataSource class to specify the ASP to which you want to connect. All other IBM Toolbox for Java classes (IFSFile, Print, DataQueues, and so on) use the Independent ASP specified by the job description of the user profile that connects to the server.
Exceptions
The IBM Toolbox for Java access classes throw exceptions when device errors, physical limitations, programming errors, or user input errors occur. The exception classes are based upon the type of error that occurs instead of the location where the error originates. Most exceptions contain the following information: v Error type: The exception object that is thrown indicates the type of error that occurred. Errors of the same type are grouped together in an exception class. v Error details: The exception contains a return code to further identify the cause of the error that occurred. The return code values are constants within the exception class. v Error text: The exception contains a text string that describes the error that occurred. The string is translated in the locale of the client Java virtual machine.
456
// For every specific error that you want to track... default: System.out.println("Delete failed, rc = "); System.out.println(rc); } }
Error events
In most cases, the IBM Toolbox for Java GUI components fire error events instead of throw exceptions. An error event is a wrapper around an exception that is thrown by an internal component. You can provide an error listener that handles all error events that are fired by a particular graphical user interface component. Whenever an exception is thrown, the listener is called, and it can provide appropriate error reporting. By default, no action takes place when error events are fired. The IBM Toolbox for Java provides a graphical user interface component called ErrorDialogAdapter, which automatically displays a dialog to the user whenever an error event is fired.
Examples
The following examples show how you can handle errors and define a simple error listener. Example: Handling error events by displaying a dialog The following example shows how you can handle error events by displaying a dialog:
// // // // All the setup work to lay out a graphical user interface component is done. Now add an ErrorDialogAdapter as a listener to the component. This will report all error events fired by that component through displaying a dialog.
Example: Defining an error listener You can write a custom error listener to handle errors in a different way. Use the ErrorListener interface to accomplish this. The following example shows how to define an simple error listener that only prints errors to System.out:
class MyErrorHandler implements ErrorListener { // This method is invoked whenever an error event is fired. public void errorOccurred(ErrorEvent event) { Exception e = event.getException (); System.out.println ("Error: " + e.getMessage ()); } }
Example: Handling error events by using an error listener The following example shows how to handle error events for a graphical user interface component using this customized handler:
MyErrorHandler errorHandler = new MyErrorHandler (); component.addErrorListener (errorHandler);
IBM Toolbox for Java
457
Related reference Vaccess classes on page 249 The Vaccess package and its classes have been deprecated. You are advised to use the Access package in combination with Java Swing instead. Exceptions on page 47 The IBM Toolbox for Java access classes throw exceptions when device errors, physical limitations, programming errors, or user input errors occur. The exception classes are based upon the type of error that occurs instead of the location where the error originates. Related information ErrorDialogAdapter Javadoc
Trace class
The Trace class allows the Java program to log trace points and diagnostic messages. This information helps reproduce and diagnose problems. Note: You can also set tracing by using the trace system properties. The Trace class logs the following categories of information:
Information category Conversion Description Logs character set conversions between Unicode and code pages. This category is used only by the IBM Toolbox for Java classes. Logs the data that flows between the system and the Java program. This category is used only by the IBM Toolbox for Java classes. Logs state information. Logs additional errors that cause an exception. Traces the flow through a program. This category is used to determine how PCML interprets the data that is sent to and from the server. This category is used by IBM Toolbox for Java classes to log data flow between the client and the proxy server. Logs information about errors the program was able to recover from. This category is used to enable or disable tracing for all of the above categories at once. Trace information cannot be directly logged to this category.
Datastream
The IBM Toolbox for Java classes also use the trace categories. When a Java program enables logging, IBM Toolbox for Java information is included with the information that is recorded by the application. You can enable the trace for a single category or a set of categories. Once the categories are selected, use the setTraceOn method to turn tracing on and off. Data is written to the log using the log method. You can send trace data for different components to separate logs. Trace data, by default, is written to the default log. Use component tracing to write application-specific trace data to a separate log or standard output. By using component tracing, you can easily separate trace data for a specific application from other data.
458
Excessive logging can impact performance. Use the isTraceOn method to query the current state of the trace. Your Java program can use this method to determine whether it builds the trace record before it calls the log method. Calling the log method when logging is off is not an error, but it takes more time. The default is to write log information to standard out. To redirect the log to a file, call the setFileName() method from your Java application. In general, this works only for Java applications because most browsers do not give applets access to write to the local file system. Logging is off by default. Java programs provide a way for the user to turn on logging so that it is easy to enable logging. For example, the application can parse for a command line parameter that indicates which category of data is logged. The user can set this parameter when log information is needed.
Examples
Note: Read the Code example disclaimer for important legal information. The following examples show how to use the Trace class. Example Using setTraceOn() and writing data to a log by using the log method
// Enable diagnostic, information, and warning logging. Trace.setTraceDiagnosticOn(true); Trace.setTraceInformationOn(true); Trace.setTraceWarningOn(true); // Turn tracing on. Trace.setTraceOn(true); // ... At this point in the Java program, write to the log. Trace.log(Trace.INFORMATION, "Just entered class xxx, method xxx"); // Turning tracing off. Trace.setTraceOn(false);
Example: Using Trace In the following code, Method 2 is the preferable way to use Trace.
// Method 1 - build a trace record // then call the log method and let the trace class determine if the // data should be logged. This will work but will be slower than the // following code. String traceData = new String("Just entered class xxx, data = "); traceData = traceData + data + "state = " + state; Trace.log(Trace.INFORMATION, traceData); // Method 2 - check the log status before building the information to // log. This is faster when tracing is not active. if (Trace.isTraceOn() && Trace.isTraceInformationOn()) { String traceData = new String("just entered class xxx, data = "); traceData = traceData + data + "state = " + state; Trace.log(Trace.INFORMATION, traceData); }
459
// // // //
component log file will only contain trace information specific to that component. If a Trace file is not specified, all trace data will go to standard out with the component specified in front of each trace message.
// Trace.setFileName("c:\\bit.bucket"); // Trace.setFileName(myComponent1, "c:\\Component1.log"); // Trace.setFileName(myComponent2, "c:\\Component2.log"); Trace.setTraceOn(true); // Turn trace on. Trace.setTraceInformationOn(true); // Enable information messages. // Log component specific trace data or general IBM Toolbox for Java // trace data. Trace.setFileName("c:\\bit.bucket"); Trace.setFileName(myComponent1, "c:\\Component1.log");
IBM i optimization
There exists two versions of the IBM Toolbox for Java software, one that is optimized when running on the IBM i JVM, and another that runs the same way no matter where the IBM Toolbox for Java is run. Sign-on behavior and performance are improved when using the optimized version of the IBM Toolbox for Java software and running on the IBM i JVM and connecting to the same server.
Sign-on considerations
The version of the IBM Toolbox for Java that contains optimizations adds additional options for providing server (system) name, user ID and password information to the IBM Toolbox for Java. When accessing an IBM i resource, the IBM Toolbox for Java classes must have a system name, user ID and password. v When running on a client, the system name, user ID and password are provided by the Java program, or the IBM Toolbox for Java retrieves these values from the user through a sign-on dialog. v When running within the IBM i Java virtual machine, the IBM Toolbox for Java has one more option. It can send requests to the current (local) server using the user ID and password of the job that started the Java program.
460
With the IBM Toolbox for Java that contains optimizations, the user ID and password of the current job also can be used when a Java program that is running on one IBM i server accesses the resources on another IBM i server. In this case, the Java program sets the system name, then uses the special value "*current" for the user ID and password. The Java program can only set the password to "*current" if you are using record-level access V4R4 or later. Otherwise, when you use record-level access, "localhost" is valid for system name and "*current" is valid for user ID; however, the Java program must supply the password. A Java program sets system name, user ID, and password values in the AS400 object. To use the user ID and password of the job, the Java program can use "*current" as user ID and password, or it can use the constructor that does not have user ID and password parameters. To use the current server, the Java program can use "localhost" as the system name or use the default constructor. That is,
AS400 system = new AS400();
is the same as
AS400 system = new AS400("localhost", "*current", "*current");
Examples
The following examples show how to sign on to a server by using optimized classes. Example: Signing on when using different AS400 constructors Two AS400 objects are created in the following example. The two objects have the same behavior: they both run a command to the current server using the user ID and password of the job. One object uses the special value for the user ID and password, while the other uses the default constructor and does not set user ID or password.
// Create an AS400 object. Since the default // constructor is used and system, user ID and // password are never set, the AS400 object sends // requests to the local server using the job's // user ID and password. If this program were run // on a client, the user would be prompted for // system, user ID and password. AS400 sys1 = new AS400(); // Create an AS400 object. This object sends // requests to the local system using the job's // user ID and password. This object will not work on a client. AS400 sys2 = new AS400("localhost", "*current", "*current"); // Create two command call objects that use the AS400 objects. CommandCall cmd1 = new CommandCall(sys1,"myCommand1"); CommandCall cmd2 = new CommandCall(sys2,"myCommand2"); // Run the commands. cmd1.run(); cmd2.run();
Example: Signing on by using the user ID and password of the current job In the following example an AS400 object is created that represents a second IBM i server. Since "*current" is used, the job's user ID and password from the server running the Java program are used on the second (target) server.
461
// Create an AS400 object. This object sends // requests to a second system using the user ID // and password from the job on the current server. AS400 sys = new AS400("mySystem.myCompany.com", "*current", "*current"); // Create a command call object to run a command // on the target server. CommandCall cmd = new CommandCall(sys,"myCommand1"); // Run the command. cmd.run();
Performance improvements
With the additional classes provided by IBM i, Java programs running on the Java virtual machine for IBM i experience improved performance. Performance is improved in some cases because less communication function is used, and in other cases, an API is used instead of calling the server program.
Faster communication
For all IBM Toolbox for Java functions except JDBC and integrated file system access, Java programs running on the Java virtual machine for IBM i will run faster. The programs run faster because less communication code is used when communicating between the Java program and the server program on the server that does the request. JDBC and integrated file system access were not optimized because facilities already exist that make these functions run faster. When running on the IBM i server, you can use the JDBC driver for IBM i instead of the JDBC driver that comes with the IBM Toolbox for Java. To access files on the server, you can use java.io instead of the integrated file system access classes that come with the IBM Toolbox for Java.
462
was available and return that port to the user to be accepted. Now, you can either tell the server which port to use or specify that the default ports be used. This option eliminates the wasted time of the server determining the port for you. Use the WRKSRVTBLE command to view or change the list of ports for the server. For the port mapping improvement, a few methods have been added to AS400 class: v getServicePort v setServicePort v setServicePortsToDefault
Converters
Two classes allow faster, more efficient conversion between Java and the system: v Binary Converter: Converts between Java byte arrays and Java simple types. v Character Converter: Converts between Java String objects and IBM i code pages. Also, the IBM Toolbox for Java now incorporates its own conversion tables for over 100 commonly used CCSIDs. Previously, the IBM Toolbox for Java either deferred to Java for nearly all text conversion. If Java did not possess the correct conversion table, IBM Toolbox for Java downloaded the conversion table from the server. The IBM Toolbox for Java performs all text conversion for any CCSID of which it is aware. When it encounters an unknown CCSID, it attempts to let Java handle the conversion. At no point does the IBM Toolbox for Java attempt to download a conversion table from the server. This technique greatly reduces the amount of time it takes for an IBM Toolbox for Java application to perform text conversion. No action is required by the user to take advantage of this new text conversion; the performance gains all occur in the underlying converter tables. Related information AS400 Javadoc BinaryConverter Javadoc Character Converter Javadoc
463
AS400ToolboxJarMaker
While the JAR file format was designed to speed up the downloading of Java program files, the AS400ToolboxJarMaker generates an even faster loading IBM Toolbox for Java JAR file through its ability to create a smaller JAR file from a larger one. Also, the AS400ToolboxJarMaker class can unzip a JAR file for you to gain access to the individual content files for basic use.
Flexibility of AS400ToolboxJarMaker
All of the AS400ToolboxJarMaker functions are performed with the JarMaker class and the AS400ToolboxJarMaker subclass: v The generic JarMaker tool operates on any JAR or Zip file; it splits a JAR file or reduces the size of a JAR file by removing classes that are not used. v The AS400ToolboxJarMaker customizes and extends JarMaker functions for easier use with IBM Toolbox for Java JAR files. According to your needs, you can invoke the AS400ToolboxJarMaker methods from within your own Java program or from a command line. Call AS400ToolboxJarMaker from the command line by using the following syntax:
java utilities.JarMaker [options]
where v options = one or more of the available options For a complete set of options available to run at a command line prompt, see the following in the Javadoc: v Options for the JarMaker base class v Extended options for the AS00ToolboxJarMaker subclass
Using AS400ToolboxJarMaker
You can use AS400ToolboxJarMaker to work with JAR files in several ways: v Uncompress one file bundled within a JAR file v Split a large JAR file into smaller JAR files v Exclude any IBM Toolbox for Java files that your application does not need to run Uncompressing a JAR file Suppose you wanted to uncompress just one file bundled within a JAR file. AS400ToolboxJarMaker allows you to expand the file into one of the following: v Current directory (extract(jarFile)) v Another directory (extract(jarFile, outputDirectory)) For example, with the following code, you are extracting AS400.class and all of its dependent classes from jt400.jar:
java utilities.AS400ToolboxJarMaker -source jt400.jar -extract outputDir -requiredFile com/ibm/as400/access/AS400.class
464
Suppose you wanted to split up a large JAR file into smaller JAR files, according to your preference for maximum JAR file size. AS400ToolboxJarMaker, accordingly, provides you with the split(jarFile, splitSize) function. In the following code, jt400.jar is split into a set of smaller JAR files, none larger than 300KB:
java utilities.AS400ToolboxJarMaker -split 300
Removing unused files from a JAR file With AS400ToolboxJarMaker, you can exclude any IBM Toolbox for Java files not needed by your application by selecting only the IBM Toolbox for Java components, languages, and CCSIDs that you need to make your application run. AS400ToolboxJarMaker also provides you with the option of including or excluding the JavaBean files associated with the components you select. For example, the following command creates a JAR file that contains only those IBM Toolbox for Java classes needed to make the CommandCall and ProgramCall components of the IBM Toolbox for Java work:
java utilities.AS400ToolboxJarMaker -component CommandCall,ProgramCall
Additionally, if it is unnecessary to convert text strings between Unicode and the double byte character set (DBCS) conversion tables, you can create a 400KB byte smaller JAR file by omitting the unneeded conversion tables with the -ccsid option:
java utilities.AS400ToolboxJarMaker -component CommandCall,ProgramCall -ccsid 61952
Note: Conversion classes are not included with the program call classes. When including program call classes, you must also explicitly include the conversion classes used by your program by using the -ccsid option. JarMaker Javadoc AS400ToolboxJarMaker Javadoc
Join the community of Java programmers who use IBM JTOpen/IBM Toolbox for Java forum Toolbox for Java. This forum is an effective way to get assistance and advice from other Java programmers and sometimes from the IBM Toolbox for Java developers themselves Use the IBM Server support Web site to find out about the tools and resources Server support that help you streamline the technical planning and support for your system. Use the IBM Software Support Services Web site to find out about the wide Software support array of software support services offered by IBM.
IBM Toolbox for Java
465
Support services for the IBM Toolbox for Java are provided under the usual terms and conditions for software products. Support services include program services, voice support, and consulting services. Contact your local IBM representative for more information. Resolving IBM Toolbox for Java program defects is supported under program services and voice support, while resolving application programming and debugging issues is supported under consulting services. IBM Toolbox for Java application program interface (API) calls are supported under consulting services unless any of the following are true: v It is clearly a Java API defect, as demonstrated by re-creation in a relatively simple program. v It is a question asking for documentation clarification. v It is a question about the location of samples or documentation. All programming assistance is supported under consulting services including those program samples provided in the IBM Toolbox for Java licensed program. Additional samples may be made available on the Internet at the IBM i home page on an unsupported basis.
Problem solving information is provided with the IBM Toolbox for Java Licensed Program Product. If you believe there is a potential defect in the IBM Toolbox for Java API, a simple program that demonstrates the error will be required.
Code examples
The following list provides links to entry points for many of the examples used throughout the IBM Toolbox for Java information.
Access classes Graphical Toolbox ReportWriter classes Security classes Tips for programming Beans HTML classes Resource classes Servlet classes Examples: ToolboxME on page 694 XPCML Commtrace classes PCML RFML Simple examples Utility classes
Vaccess classes
IBM grants you a nonexclusive copyright license to use all programming code examples from which you can generate similar function tailored to your own specific needs. SUBJECT TO ANY STATUTORY WARRANTIES WHICH CANNOT BE EXCLUDED, IBM, ITS PROGRAM DEVELOPERS AND SUPPLIERS MAKE NO WARRANTIES OR CONDITIONS EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OR CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT, REGARDING THE PROGRAM OR TECHNICAL SUPPORT, IF ANY. UNDER NO CIRCUMSTANCES IS IBM, ITS PROGRAM DEVELOPERS OR SUPPLIERS LIABLE FOR ANY OF THE FOLLOWING, EVEN IF INFORMED OF THEIR POSSIBILITY: 1. LOSS OF, OR DAMAGE TO, DATA; 2. DIRECT, SPECIAL, INCIDENTAL, OR INDIRECT DAMAGES, OR FOR ANY ECONOMIC CONSEQUENTIAL DAMAGES; OR 3. LOST PROFITS, BUSINESS, REVENUE, GOODWILL, OR ANTICIPATED SAVINGS.
466
SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF DIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, SO SOME OR ALL OF THE ABOVE LIMITATIONS OR EXCLUSIONS MAY NOT APPLY TO YOU.
AS400JPing
v Example: Using AS400JPing within a Java program
BidiTransform
v Example: Using the AS400BidiTransform class to transform bidirectional text
CommandCall
v Example: Using CommandCall to run a command on the server v Example: Using CommandCall to prompt for the name of the server, command to run, and print the result
ConnectionPool
v Example: Using AS400ConnectionPool to create connections to the server
DataArea
v Example: Creating and writing to a decimal data area
DataQueue
v v v v v Example: Example: Example: Example: Example: How to create a DataQueue object, read data, and disconnect Putting data on a queue Reading data from a queue Using KeyedDataQueue to put items on a queue Using KeyedDataQueue to take items off a queue
Digital certificate
v Example: Listing digital certificates that belong to a user
EnvironmentVariable
v Example: Creating, setting, and getting environment variables
Exceptions
v Example: Catching a thrown exception, retrieving the return code, and displaying the exception text
FTP
v Example: Using the FTP class to Copy a set of files from a server directory v Example: Using the AS400FTP class to copy a set of files from a directory
IBM Toolbox for Java
467
v Example: How to use IFSJavaFile instead of java.io.File v Example: Using the IFSFile classes to list the contents of a directory on the server
JavaApplicationCall
v Example: Running a program on the server from the client that outputs "Hello World!"
JDBC
v Example: Using the JDBC driver to create and populate a table v Example: Using the JDBC driver to query a table and output its contents
Jobs
v Example: Retrieving and changing job information using the cache v Example: Listing all active jobs v Example: Printing all of the messages in the job log for a specific user v Example: Listing the job identification information for a specific user v Example: Getting a list of jobs on the server and listing the job status and the job identifier v Example: Displaying messages in the job log for a job that belongs to the current user
Message queue
v Example: How to use the message queue object v Example: Printing the contents of the message queue v Example: Retrieving and printing a message v Example: Listing the contents of the message queue v Example: Using AS400Message with CommandCall v Example: Using AS400Message with ProgramCall
NetServer
v Example: Using a NetServer object to change the name of the NetServer
Print
v Example: Asynchronously listing all spooled files using the PrintObjectListListener interface v Example: Asynchronously listing all spooled files without using the PrintObjectListListener interface v Example: Copying a spooled file using SpooledFile.copy() v Example: Creating a spooled file from an input stream v v v v Example: Example: Example: Example: Generating an SCS data stream using the SCS3812Writer class Reading an existing spooled file Reading and transforming spooled files Synchronously listing all spooled files
Permission
v Example: Set the authority of an AS400 object
468
Program call
v Example: Using ProgramCall v Example: Using ProgramCall to retrieve system status v Example: Passing parameter data with a Program parameter object
QSYSObjectPathName
v Example: Building an integrated file system name v Example: Using QSYSObjectPathName.toPath() to build an AS400 object name v Example: Using QSYSObjectPathName to parse the integrated file system path name
Record-level access
v Example: Sequentially accessing a file v Example: Using the record-level access classes to read a file v Example: Using the record-level access classes to read records by key v Example: Using the LineDataRecordWriter class
SystemStatus
v Example: Use caching with the SystemStatus class
SystemPool
v Example: Setting the maximum faults size for SystemPool
SystemValue
v Example: Using SystemValue and SystemValueList
Trace
v Example: Using the Trace.setTraceOn() method v Example: Preferred way to use Trace v Example: Using component tracing
UserGroup
v Example: Retrieving a list of users v Example: Listing all the users of a group
UserSpace
v Example: How to create a user space The following disclaimer applies to all of the IBM Toolbox for Java examples: Code example disclaimer IBM grants you a nonexclusive copyright license to use all programming code examples from which you can generate similar function tailored to your own specific needs. All sample code is provided by IBM for illustrative purposes only. These examples have not been thoroughly tested under all conditions. IBM, therefore, cannot guarantee or imply reliability, serviceability, or function of these programs.
469
All programs contained herein are provided to you "AS IS" without any warranties of any kind. The implied warranties of non-infringement, merchantability and fitness for a particular purpose are expressly disclaimed.
import java.io.*; import java.util.*; import com.ibm.as400.access.*; public class CommandCallExample extends Object { public static void main(String[] parmeters) { // Created a reader to get input from the user BufferedReader inputStream = new BufferedReader(new InputStreamReader(System.in),1);
// Declare variables to hold the system name and the command to run String systemString = null; String commandString = null; System.out.println( " " );
// Get the system name and the command to run from the user try { System.out.print("System name: "); systemString = inputStream.readLine(); System.out.print("Command: "); commandString = inputStream.readLine(); } catch (Exception e) {}; System.out.println( " " );
// Create an AS400 object. This is the system we send the command to AS400 as400 = new AS400(systemString);
// Create a command call object specifying the server that will // recieve the command.
470
try { // Run the command. if (command.run(commandString)) System.out.print( "Command successful" ); else System.out.print( "Command failed" );
// If messages were produced from the command, print them AS400Message[] messagelist = command.getMessageList(); if (messagelist.length > 0) { System.out.println( ", messages from the command:" ); System.out.println( " " ); } for (int i=0; i < messagelist.length; i++) { System.out.print ( messagelist[i].getID() ); System.out.print ( ": " ); System.out.println( messagelist[i].getText() ); } } catch (Exception e) { System.out.println( "Command " + command.getCommand() + " did not run" ); } System.exit(0); } }
471
System.out.println(""); System.out.println("Usage:"); System.out.println(""); System.out.println(" AS400ConnectionPooling system userId password"); System.out.println(""); System.out.println(""); System.out.println("For example:"); System.out.println(""); System.out.println(""); System.out.println(" AS400ConnectionPooling MySystem MyUserId MyPassword"); System.out.println(""); return; } String system = parameters[0]; String userId = parameters[1]; String password = parameters[2]; try { // Create an AS400ConnectionPool. AS400ConnectionPool testPool = new AS400ConnectionPool(); // Set a maximum of 128 connections to this pool. testPool.setMaxConnections(128); // Set a maximum lifetime for 30 minutes for connections. testPool.setMaxLifetime(1000*60*30); // 30 min Max lifetime since created. // Preconnect 5 connections to the AS400.COMMAND service. testPool.fill(system, userId, password, AS400.COMMAND, 1); System.out.println(); System.out.println("Preconnected 1 connection to the AS400.COMMAND service"); // Call getActiveConnectionCount and getAvailableConnectionCount to see how many // connections are in use and available for a particular system. System.out.println("Number of active connections: " + testPool.getActiveConnectionCount(system, userId)); System.out.println("Number of available connections for use: " + testPool.getAvailableConnectionCount(system, userId)); // Create a connection to the AS400.COMMAND service. (Use the service number // constants defined in the AS400 class (FILE, PRINT, COMMAND, DATAQUEUE, and so on.)) // Since connections have already been filled, the usual time spent connecting // to the command service is avoided. AS400 newConn1 = testPool.getConnection(system, userId, password, AS400.COMMAND); System.out.println(); System.out.println("getConnection gives out an existing connection to user"); System.out.println("Number of active connections: " + testPool.getActiveConnectionCount(system, userId)); System.out.println("Number of available connections for use: " + testPool.getAvailableConnectionCount(system, userId)); // Create a new command call object and run a command. CommandCall cmd1 = new CommandCall(newConn1); cmd1.run("CRTLIB FRED"); // Return the connection to the pool. testPool.returnConnectionToPool(newConn1); System.out.println(); System.out.println("Returned a connection to pool"); System.out.println("Number of active connections: " + testPool.getActiveConnectionCount(system, userId)); System.out.println("Number of available connections for reuse: " + testPool.getAvailableConnectionCount(system, userId));
472
// Create a connection to the AS400.COMMAND service. This will return the same // object as above for reuse. AS400 newConn2 = testPool.getConnection(system, userId, password, AS400.COMMAND); System.out.println(); System.out.println("getConnection gives out an existing connection to user"); System.out.println("Number of active connections: " + testPool.getActiveConnectionCount(system, userId)); System.out.println("Number of available connections for reuse: " + testPool.getAvailableConnectionCount(system, userId)); // Create a connection to the AS400.COMMAND service. This will create a new // connection as there are not any connections in the pool to reuse. AS400 newConn3 = testPool.getConnection(system, userId, password, AS400.COMMAND); System.out.println(); System.out.println("getConnection creates a new connection because there are no connections available"); System.out.println("Number of active connections: " + testPool.getActiveConnectionCount(system, userId)); System.out.println("Number of available connections for reuse: " + testPool.getAvailableConnectionCount(system, userId)); // Close the test pool. testPool.close(); } catch (Exception e) { // If any of the above operations failed say the pool operations failed // and output the exception. System.out.println("Pool operations failed"); System.out.println(e); e.printStackTrace(); } } }
Example 1
This brief example shows the basic use of the AS400JDBCManagedConnectionPoolDataSource class.
import javax.naming.Context; import javax.naming.InitialContext; import javax.sql.DataSource; import com.ibm.as400.access.AS400JDBCManagedConnectionPoolDataSource; import com.ibm.as400.access.AS400JDBCManagedDataSource; public class TestJDBCConnPoolSnippet { void test() { AS400JDBCManagedConnectionPoolDataSource cpds0 = new AS400JDBCManagedConnectionPoolDataSource(); // Set general datasource properties. Note that both connection pool datasource (CPDS) and managed // datasource (MDS) have these properties, and they might have different values. cpds0.setServerName(host);
473
cpds0.setDatabaseName(host);//iasp can be here cpds0.setUser(userid); cpds0.setPassword(password); cpds0.setSavePasswordWhenSerialized(true); // Set connection pooling-specific properties. cpds0.setInitialPoolSize(initialPoolSize_); cpds0.setMinPoolSize(minPoolSize_); cpds0.setMaxPoolSize(maxPoolSize_); cpds0.setMaxLifetime((int)(maxLifetime_/1000)); // convert to seconds cpds0.setMaxIdleTime((int)(maxIdleTime_/1000)); // convert to seconds cpds0.setPropertyCycle((int)(propertyCycle_/1000)); // convert to seconds //cpds0.setReuseConnections(false); // do not re-use connections // Set the initial context factory to use. System.setProperty(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory"); // Get the JNDI Initial Context. Context ctx = new InitialContext(); // Note: The following is an alternative way to set context properties locally: // Properties env = new Properties(); // env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory"); // Context ctx = new InitialContext(env); ctx.rebind("mydatasource", cpds0); // We can now do lookups on cpds, by the name "mydatasource". // Create a standard DataSource object that references it. AS400JDBCManagedDataSource mds0 = new AS400JDBCManagedDataSource(); mds0.setDescription("DataSource supporting connection pooling"); mds0.setDataSourceName("mydatasource"); ctx.rebind("ConnectionPoolingDataSource", mds0); DataSource dataSource_ = (DataSource)ctx.lookup("ConnectionPoolingDataSource"); AS400JDBCManagedDataSource mds_ = (AS400JDBCManagedDataSource)dataSource_; boolean isHealthy = mds_.checkPoolHealth(false); //check pool health Connection c = dataSource_.getConnection(); } }
Example 2
This example shows more details about how to use the AS400JDBCManagedConnectionPoolDataSource class.
import import import import import import import import import import import import import import import import import import import import import import java.awt.TextArea; java.io.BufferedReader; java.io.File; java.io.FileReader; java.io.FileInputStream; java.io.FileOutputStream; java.io.OutputStream; java.io.PrintStream; java.util.Vector; java.util.Properties; java.sql.Connection; javax.sql.DataSource; java.sql.ResultSet; java.sql.Statement; javax.naming.*; java.util.Date; java.util.ArrayList; java.util.Random; com.ibm.as400.access.AS400; com.ibm.as400.access.AS400JDBCManagedConnectionPoolDataSource; com.ibm.as400.access.AS400JDBCManagedDataSource; com.ibm.as400.access.Trace;
474
public class TestJDBCConnPool { private static final boolean DEBUG = false; // If you turn this flag on, be sure to also turn on the following flag: // AS400JDBCConnection.TESTING_THREAD_SAFETY. private static final boolean TESTING_THREAD_SAFETY = false; private static String userid; private static String password; private static String host; // Note: For consistency, all private int initialPoolSize_; private int minPoolSize_; private int maxPoolSize_; private long maxLifetime_; private long maxIdleTime_; private long propertyCycle_; private private private private private time values are stored units of milliseconds. // initial # of connections in pool // max # of connections in pool // max # of connections in pool // max lifetime (msecs) of connections in pool // max idle time (msecs) of available connections in pool // pool maintenance frequency (msecs)
int numDaemons_; // # of requester daemons to create static long timeToRunDaemons_; // total duration (msecs) to let the daemons run long daemonMaxSleepTime_; // max time (msecs) for requester daemons to sleep each cycle long daemonMinSleepTime_; // min time (msecs) for requester daemons to sleep each cycle long poolHealthCheckCycle_; // # of msecs between calls to checkPoolHealth()
private boolean keepDaemonsAlive_ = true; // When this is false, the daemons shut down. private DataSource dataSource_; private AS400JDBCManagedDataSource mds_; private final Object daemonSleepLock_ = new Object(); private Random random_ = new Random(); static { try { Class.forName("com.ibm.as400.access.AS400JDBCDriver"); } catch(Exception e){ System.out.println("Unable to register JDBC driver."); System.exit(0); } } public static void main(String[] args) { host = args[0]; userid = args[1]; password = args[2]; timeToRunDaemons_ = (new Integer(args[3])).intValue() * 1000; //milliseconds //args[3]=time to run in seconds TestJDBCConnPool cptest = new TestJDBCConnPool(); cptest.setup(); cptest.runTest(); } public void setup() { try { if (DEBUG) System.out.println("TESTING_THREAD_SAFETY flag is " + (TESTING_THREAD_SAFETY ? "true" : "false")); if (TESTING_THREAD_SAFETY) { // Adjust values for performing thread-intensive stress testing. // NOTE: This assumes that the AS400JDBCConnection class has also been modified to // not make actual connections to an actual server. // To do this, edit AS400JDBCConnection.java, changing its TESTING_THREAD_SAFETY // flag to 'false', and recompile. minPoolSize_ = 100; maxPoolSize_ = 190;
475
initialPoolSize_ = 150; // this should get reset to maxPoolSize_ numDaemons_ = 75; if (timeToRunDaemons_ == 0) { timeToRunDaemons_ = 180*1000; // 180 seconds == 3 minutes } } else { // Set more conservative values, as we'll be making actual connections to an // actual server, and we don't want to monopolize the server. minPoolSize_ = 5; maxPoolSize_ = 15; initialPoolSize_ = 9; numDaemons_ = 4; if (timeToRunDaemons_ == 0) { timeToRunDaemons_ = 15*1000; // 15 seconds } } maxLifetime_ = (int)timeToRunDaemons_ / 3; maxIdleTime_ = (int)timeToRunDaemons_ / 4; propertyCycle_ = timeToRunDaemons_ / 4; poolHealthCheckCycle_ = Math.min(timeToRunDaemons_ / 4, 20*60*1000); // at least once every 20 minutes (more frequently if shorter run-time) daemonMaxSleepTime_ = Math.min(timeToRunDaemons_ / 3, 10*1000); // at most 10 seconds (less if shorter run-time) daemonMinSleepTime_ = 20; // milliseconds if (DEBUG) System.out.println("setup: Constructing " + "AS400JDBCManagedConnectionPoolDataSource (cpds0)"); AS400JDBCManagedConnectionPoolDataSource cpds0 = new AS400JDBCManagedConnectionPoolDataSource(); // Set datasource properties. Note that both CPDS and MDS have these // properties, and they might have different values. cpds0.setServerName(host); cpds0.setDatabaseName(host);//iasp can be here cpds0.setUser(userid); cpds0.setPassword(password); cpds0.setSavePasswordWhenSerialized(true); // Set connection pooling-specific properties. cpds0.setInitialPoolSize(initialPoolSize_); cpds0.setMinPoolSize(minPoolSize_); cpds0.setMaxPoolSize(maxPoolSize_); cpds0.setMaxLifetime((int)(maxLifetime_/1000)); // convert to seconds cpds0.setMaxIdleTime((int)(maxIdleTime_/1000)); // convert to seconds cpds0.setPropertyCycle((int)(propertyCycle_/1000)); // convert to seconds //cpds0.setReuseConnections(false); // don't re-use connections // Set the initial context factory to use. System.setProperty(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory"); // Get the JNDI Initial Context. Context ctx = new InitialContext(); // Note: The following is an alternative way to set context properties locally: // Properties env = new Properties(); // env.put(Context.INITIAL_CONTEXT_FACTORY, // "com.sun.jndi.fscontext.RefFSContextFactory"); // Context ctx = new InitialContext(env); ctx.rebind("mydatasource", cpds0); // We can now do lookups on cpds, by the name"mydatasource". if (DEBUG) System.out.println("setup: lookup(\"mydatasource\"" + ")"); // AS400JDBCManagedConnectionPoolDataSource cpds1 = // (AS400JDBCManagedConnectionPoolDataSource)ctx.lookup("mydatasource"); // if (DEBUG) System.out.println("setup: cpds1.getUser() == |" + cpds1.getUser() + "|"); // Create a standard DataSource object that references it. if (DEBUG) System.out.println("setup: Constructing AS400JDBCManagedDataSource (mds0)"); AS400JDBCManagedDataSource mds0 = new AS400JDBCManagedDataSource(); mds0.setDescription("DataSource supporting connection pooling"); mds0.setDataSourceName("mydatasource");
476
ctx.rebind("ConnectionPoolingDataSource", mds0); if (DEBUG) System.out.println("setup: lookup(\"ConnectionPoolingDataSource\"" + ")"); dataSource_ = (DataSource)ctx.lookup("ConnectionPoolingDataSource"); //dataSource_.setLogWriter(output_); if (DEBUG) System.out.println("setup: dataSource_.getUser() == |" + ((AS400JDBCManagedDataSource)dataSource_).getUser() + "|"); mds_ = (AS400JDBCManagedDataSource)dataSource_; } catch (Exception e) { e.printStackTrace(); System.out.println("Setup error during Trace file creation."); } } void displayConnectionType(Connection conn, boolean specifiedDefaultId) { if (conn instanceof com.ibm.as400.access.AS400JDBCConnectionHandle) System.out.print("("+ (specifiedDefaultId ? "+" : "-") + "P)"); else System.out.print("("+ (specifiedDefaultId ? "+" : "-") + "NP)"); } /** * Gets and returns connections from and to a connection pool for a while. **/ public void runTest() { boolean ok = true; try { System.out.println("Started test run at " + new Date()); if (DEBUG) System.out.println("Checking health just after datasource creation " + "(we expect that the pool does not exist yet) ..."); if (mds_.checkPoolHealth(true)) { ok = false; System.out.println("\nERROR: Pool exists prior to first getConnection()."); } // Verify some setters/getters for JDBC properties. System.out.println("Verifying setters/getters ..."); mds_.setAccess("read only"); if (!mds_.getAccess().equals("read only")) { ok = false; System.out.println("\nERROR: getAccess() returned unexpected value: " + "|" + mds_.getAccess()+"|"); } boolean oldBool = mds_.isBigDecimal(); boolean newBool = (oldBool ? false : true); mds_.setBigDecimal(newBool); if (mds_.isBigDecimal() != newBool) { ok = false; System.out.println("\nERROR: isBigDecimal() returned unexpected value: " + "|"+mds_.isBigDecimal()+"|"); } mds_.setBigDecimal(oldBool); int oldInt = mds_.getBlockCriteria(); int newInt = (oldInt == 2 ? 1 : 2); mds_.setBlockCriteria(newInt); if (mds_.getBlockCriteria() != newInt) { ok = false; System.out.println("\nERROR: getBlockCriteria() returned unexpected value: " + "|"+mds_.getBlockCriteria()+"|"); } mds_.setBlockCriteria(oldInt); // Verify some setters and getters for socket properties. oldBool = mds_.isKeepAlive();
477
newBool = (oldBool ? false : true); mds_.setKeepAlive(newBool); if (mds_.isKeepAlive() != newBool) { ok = false; System.out.println("\nERROR: isKeepAlive() returned unexpected value: " + "|"+mds_.isKeepAlive()+"|"); } mds_.setKeepAlive(oldBool); oldInt = mds_.getReceiveBufferSize(); newInt = (oldInt == 256 ? 512 : 256); mds_.setReceiveBufferSize(newInt); if (mds_.getReceiveBufferSize() != newInt) { ok = false; System.out.println("\nERROR: getReceiveBufferSize() returned unexpected value: " + "|"+mds_.getReceiveBufferSize()+"|"); } mds_.setReceiveBufferSize(oldInt); System.out.println("CONNECTION 1"); Object o = dataSource_.getConnection(); System.out.println(o.getClass()); System.out.println("******LOOK ABOVE*******"); Connection c1 = dataSource_.getConnection(); if (DEBUG) displayConnectionType(c1, true); if (DEBUG) System.out.println("Checking health after first getConnection() ..."); if (!mds_.checkPoolHealth(true)) { ok = false; System.out.println("\nERROR: Pool is not healthy after first getConnection()."); } if (!TESTING_THREAD_SAFETY) { try { c1.setAutoCommit(false); if (DEBUG) System.out.println("SELECT * FROM QIWS.QCUSTCDT"); Statement s = c1.createStatement(); ResultSet rs = s.executeQuery("SELECT * FROM QIWS.QCUSTCDT"); while(rs.next()){ if (DEBUG) System.out.println(rs.getString(2)); } rs.close(); s.close(); } catch (Exception e) { e.printStackTrace(); if (DEBUG) System.out.println("Checking health after fatal connection error ..."); if (!mds_.checkPoolHealth(true)) { ok = false; System.out.println("\nERROR: Pool is not healthy after fatal connection " + "error."); } } } System.out.println("CONNECTION 2"); Connection c2 = dataSource_.getConnection(userid, password); if (DEBUG) displayConnectionType(c2, false); System.out.println("CONNECTION 3"); Connection c3 = dataSource_.getConnection(); if (DEBUG) displayConnectionType(c3, true); c1.close(); if (DEBUG) System.out.println("Checking health after first close() ..."); if (!mds_.checkPoolHealth(true)) { ok = false; System.out.println("\nERROR: Pool is not healthy after first close().");
478
} System.out.println("CONNECTION 4"); Connection c4 = dataSource_.getConnection(); if (DEBUG) displayConnectionType(c4, true); c1.close(); // close this one again c2.close(); c3.close(); c4.close(); if (DEBUG) System.out.println("Checking health after last close() ..."); if (!mds_.checkPoolHealth(true)) { ok = false; System.out.println("\nERROR: Pool is not healthy after last close()."); } // Start the test daemons. System.out.println("Starting test daemons"); startThreads(); // Run the test daemons for a while; check pool health periodically. long startTime = System.currentTimeMillis(); long endTime = startTime + timeToRunDaemons_; while (System.currentTimeMillis() < endTime) { System.out.print("h"); // Let the daemons run for a while, then check pool health. try { Thread.sleep(poolHealthCheckCycle_); } catch (InterruptedException ie) {} if (!mds_.checkPoolHealth(true)) { ok = false; System.out.println("\nERROR: Pool is not healthy after test daemons started."); } } // Stop the test daemons. System.out.println("\nStopping test daemons"); stopThreads(); if (DEBUG) System.out.println("Checking health after connectionGetter daemons have run..."); if (!mds_.checkPoolHealth(true)) { ok = false; System.out.println("\nERROR: Pool is not healthy after test daemons stopped."); } if (!TESTING_THREAD_SAFETY) { System.out.println("CONNECTION 5"); Connection c = dataSource_.getConnection(); if (DEBUG) displayConnectionType(c, true); c.setAutoCommit(false); if (DEBUG) System.out.println("SELECT * FROM QIWS.QCUSTCDT"); Statement s = c.createStatement(); ResultSet rs = s.executeQuery("SELECT * FROM QIWS.QCUSTCDT"); while(rs.next()){ if (DEBUG) System.out.println(rs.getString(2)); } rs.close(); s.close(); c.close(); } System.out.println("\nClosing the pool..."); mds_.closePool(); if (DEBUG) System.out.println("Checking health after pool closed ..."); Trace.setTraceJDBCOn(true); // make sure the final stats get printed out Trace.setTraceOn(true); if (!mds_.checkPoolHealth(true)) { ok = false; System.out.println("\nERROR: Pool is not healthy after pool closed."); }
479
System.out.println(); if(ok==true) System.out.println("test ran ok"); else System.out.println("test failed"); } catch (Exception e) { System.out.println(e); e.printStackTrace(); } finally { System.out.println("Ended test at " + new Date()); } } void startThreads() { // Create a bunch of threads that call getConnection(). Thread[] threads = new Thread[numDaemons_]; for (int i=0; i<numDaemons_; i++) { ConnectionGetter getter; // Flip a coin to see if this daemon will specify the default uid, or unique uid. if (random_.nextBoolean()) { getter = new ConnectionGetter(userid,password); if (TESTING_THREAD_SAFETY) { // we can use fictional userid getter = new ConnectionGetter("Thread"+i, "Pwd"+i); } else { // must use a real userid getter = new ConnectionGetter(userid,password); } } else getter = new ConnectionGetter(null, null); threads[i] = new Thread(getter, "["+i+"]"); threads[i].setDaemon(true); } // Start the threads. for (int i=0; i<numDaemons_; i++) { threads[i].start(); } } void stopThreads() { // Tell the threads to stop. keepDaemonsAlive_ = false; synchronized (daemonSleepLock_) { daemonSleepLock_.notifyAll(); } // Wait for the daemons to stop. try { Thread.sleep(3000); } catch (InterruptedException ie) {} } // ConnectionGetter -------------------------------------------------------------------/** Helper class. This daemon wakes up at random intervals and either gets another connection from the connection pool or returns a previously-gotten connection to the pool. **/ private final class ConnectionGetter implements Runnable { private String uid_; private String pwd_; private boolean useDefaultUid_; private long maxSleepTime_; private String threadName_; private boolean firstConnection_ = true;
480
ArrayList connections_ = new ArrayList(); // list of connections that this getter currently 'owns'. ConnectionGetter(String uid, String pwd) { uid_ = uid; pwd_ = pwd; if (uid_ == null) useDefaultUid_ = true; else useDefaultUid_ = false; maxSleepTime_ = daemonMaxSleepTime_; // our own copy that we can adjust } public void run() { threadName_ = Thread.currentThread().getName(); if (DEBUG) System.out.println("ConnectionGetter("+threadName_+") Starting up"); try { while (keepDaemonsAlive_) { try { // Pick a random sleep-time, between min and max values. long sleepTime = Math.max((long)(maxSleepTime_ * random_.nextFloat()), daemonMinSleepTime_); // Note: Must never call wait(0), because that waits forever. synchronized (daemonSleepLock_) { try { daemonSleepLock_.wait(sleepTime); System.out.print("."); } catch (InterruptedException ie) {} } if (!keepDaemonsAlive_) break; // Decide by chance whether to request another connection or return a // previously-obtained connection. Connection conn; if (random_.nextBoolean()) // Leave the decision to chance. { // Request another connection. if (useDefaultUid_) { if (DEBUG) System.out.println("ConnectionGetter("+threadName_+") - get()"); conn = dataSource_.getConnection(); } else { if (DEBUG) System.out.println("ConnectionGetter("+threadName_+") - " + "get("+uid_+",***)"); conn = dataSource_.getConnection(uid_, pwd_); } if (conn == null) { System.out.println("ConnectionGetter("+threadName_+") ERROR: " + "getConnection() returned null"); } else { // Occasionally "forget" that we own a connection, and neglect to // close it. // Orphaned connections should eventually exceed their maximum // lifetime and get "reaped" by the connection manager. float val = random_.nextFloat(); if (firstConnection_ || val < 0.1) { // 'orphan' a few gotten connections firstConnection_ = false; } else { connections_.add(conn); } if (DEBUG) displayConnectionType(conn, useDefaultUid_); if (conn instanceof com.ibm.as400.access.AS400JDBCConnectionHandle) { // We got a pooled connection. Try speeding up our cycle time. if (maxSleepTime_ > 100) maxSleepTime_--; else maxSleepTime_ = 100;
481
} else { // We didn't get a pooled connection. That means that the pool // must be at capacity. Slow down our cycle time a bit. maxSleepTime_ = maxSleepTime_ + 50; } } } else { // Close a connection that we currently own. if (connections_.size() != 0) { conn = (Connection)connections_.remove(0); conn.close(); } } } // inner try catch (Exception e) { e.printStackTrace(); } } // outer while } // outer try finally { if (DEBUG) System.out.println("ConnectionGetter("+threadName_+") Stopping"); // Return all the connections that I still have in my list. for (int i=0; i<connections_.size(); i++) { Connection conn = (Connection)connections_.remove(0); try { conn.close(); } catch (Exception e) { e.printStackTrace(); } } } } } // internal class 'ConnectionGetter' }
// Create field descriptions for the entry data BinaryFieldDescription msgNumber = new BinaryFieldDescription(new AS400Bin4(), "msgnum"); CharacterFieldDescription sender = new CharacterFieldDescription(new AS400Text(50), "sender"); CharacterFieldDescription timeSent = new CharacterFieldDescription(new AS400Text(8), "timesent"); CharacterFieldDescription msgText = new CharacterFieldDescription(new AS400Text(1024), "msgtext"); CharacterFieldDescription replyRequired = new CharacterFieldDescription(new AS400Text(1), "replyreq");
482
The following example uses the RecordFormat class to describe the format of the data queue entry and then dynamically uses it to retrieve a record:
RecordFormat entryFormat = new RecordFormat(); // Describe the fields in an entry on the data queue entryFormat.addFieldDescription(msgNumber); entryFormat.addFieldDescription(sender); entryFormat.addFieldDescription(timeSent); entryFormat.addFieldDescription(msgText); entryFormat.addFieldDescription(replyRequired); // Get a record based on the format of the entries on the data queue Record rec = entryFormat.getNewRecord();
Example: Defining RecordFormat statically The following example defines the record format statically, which allows many programs to use the format without coding the record format multiple times.
public class MessageEntryFormat extends RecordFormat { // The field descriptions are contained in the class static BinaryFieldDescription msgNumber = new BinaryFieldDescription(new AS400Bin4(), "msgnum"); static CharacterFieldDescription sender = new CharacterFieldDescription(new AS400Text(50), "sender"); static CharacterFieldDescription timeSent = new CharacterFieldDescription(new AS400Text(8), "timesent"); static CharacterFieldDescription msgText = new CharacterFieldDescription(new AS400Text(1024), "msgtext"); static CharacterFieldDescription replyRequired = new CharacterFieldDescription(new AS400Text(1), "replyreq"); public MessageEntryFormat() { // We will name this format for posterity super("MessageEntryFormat"); // Add the field descriptions addFieldDescription(msgNumber); addFieldDescription(sender); addFieldDescription(timeSent); addFieldDescription(msgText); addFieldDescription(replyRequired); } }
Example: Using RecordFormat statically The following example shows how a Java program can use a statically defined RecordFormat:
MessageEntryFormat entryFormat = new MessageEntryFormat(); // Get a record based on the format of the entries on the data queue Record rec = entryFormat.getNewRecord();
483
{ dqEntry = dq.read(); } catch(Exception e) { // Handle any exceptions } // Get a record object from our record format, initializing it with the data from the entry we // just read. Record rec = entryFormat.getNewRecord(dqEntry.getData()); // Output the complete entry as a String. The contents of the record are converted to Java Objects // based on the record format of the entry. System.out.println(rec.toString()); // Get the contents of the individual fields of the entry. Each field's contents are converted to // a Java Object. Integer num = (Integer)rec.getField(0); // Retrieve contents by index String s = (String)rec.getField("sender");// Retrieve contents by field name String text = (String)rec.getField(3); // Retrieve the message text // Output the data System.out.println(num + " " + s + " " + text);
Example: Using a specific Record object You can also statically define and use a Record specific to the format of this data queue, which allows you to provide get() and set() methods for the fields that are more meaningfully named than getField() and setField(). Also, by using the statically defined specific Record, you can return basic Java types instead of objects, and you can identify the return type for your user. Note that this example must explicitly cast the correct Java object.
public class MessageEntryRecord extends Record { static private RecordFormat format = new MessageEntryFormat(); public MessageEntryRecord() { super(format); } public int getMessageNumber() { // Return the message number as an int. Note: We know our record format and therefore // know the names of our fields. It is safest to get the field by name in case a field // has been inserted into the format unbeknownst to us. return ((Integer)getField("msgnum")).intValue(); } public String getMessageText() { // Return the text of the message return (String)getField("msgtext"); } public String getSender() { // Return the sender of the message return (String)getField("sender"); } public String getTimeSent() { // Return the sender of the message return (String)getField("timesent");
484
Example: Returning a new MessageEntryRecord We need to override the getNewRecord() method in the MessageEntryFormat class (in the example above) in order to return a new MessageEntryRecord. To override the method, add the following to the MessageEntryFormat class:
public Record getNewRecord(byte[] data) { Record r = new MessageEntryRecord(); r.setContents(data); return r; }
After adding the new getNewRecord() method, you can use the MessageEntryRecord to interpret the data queue entry:
// Get a record object from our record format, initializing it with the data from the entry we // just read. Note the use of the new overridden method getNewRecord(). MessageEntryRecord rec = (MessageEntryRecord)entryFormat.getNewRecord(dqEntry.getData()); // Output the complete entry as a String. The contents of the record are converted to Java Objects // based on the record format of the entry. System.out.println(rec.toString()); // Get the contents of the individual fields of the entry. Each field's contents are converted to // a Java Object. int num = rec.getMessageNumber(); // Retrieve the message number as an int String s = rec.getSender(); // Retrieve the sender String text = rec.getMessageText(); // Retrieve the message text // Output the data System.out.println(num + " " + s + " " + text);
485
import java.net.*; import com.ibm.as400.access.*; public class DQProducerExample extends Object { // Create a reader to get input from the user. static BufferedReader inputStream = new BufferedReader(new InputStreamReader(System.in),1); public static void main(String[] parameters) { System.out.println( " " ); // if the system name was not specified, display help text and exit. if (parameters.length >= 1) { try { // The first parameter is the system that contains the data queue. String system = parameters[0]; // Create an AS400 object for the server that has the data queue. AS400 as400 = new AS400(system); // Build a record format for the format of the data queue entry. // This format matches the format in the DQConsumer class. A // record consists of: // - a four byte number -- the customer number // - a four byte number -- the part number // - a 20 character string -- the part description // - a four byte number -- the number of parts in this order // First create the base data types. BinaryFieldDescription customerNumber = new BinaryFieldDescription(new AS400Bin4(), "CUSTOMER_NUMBER"); BinaryFieldDescription partNumber = new BinaryFieldDescription(new AS400Bin4(), "PART_NUMBER"); CharacterFieldDescription partName = new CharacterFieldDescription(new AS400Text(20, as400), "PART_NAME"); BinaryFieldDescription quantity = new BinaryFieldDescription(new AS400Bin4(), "QUANTITY"); // Build a record format and fill it with the base data types. RecordFormat dataFormat = new RecordFormat(); dataFormat.addFieldDescription(customerNumber); dataFormat.addFieldDescription(partNumber); dataFormat.addFieldDescription(partName); dataFormat.addFieldDescription(quantity); // Create the library that contains the data queue // using CommandCall. CommandCall crtlib = new CommandCall(as400); crtlib.run("CRTLIB JAVADEMO"); // Create the data queue object. DataQueue dq = new DataQueue(as400, "/QSYS.LIB/JAVADEMO.LIB/PRODCONS.DTAQ"); // Create the data queue just in case this is the first time this // program has run. The queue already exists exception is caught // and ignored. try { dq.create(96); } catch (Exception e) {};
486
// Get the first field of data from the user. System.out.print("Enter customer number (or 0 to quit): "); int customer = getInt(); // While there is data to put on the queue. while (customer > 0) { // Get the rest of the data for this order from the user. System.out.print("Enter part number: "); int part = getInt(); System.out.print("Enter quantity: "); int quantityToOrder = getInt(); String description = "part " + part; // Create a record based on the record format. The record // is empty now but will eventually contain the data. Record data = new Record(dataFormat); // Set the values we received from the user into the record. data.setField("CUSTOMER_NUMBER", new Integer(customer)); data.setField("PART_NUMBER", new Integer(part)); data.setField("QUANTITY", new Integer(quantityToOrder)); data.setField("PART_NAME", description); // Convert the record into a byte array. The byte array is // what is actually put to the data queue. byte [] byteData = data.getContents(); System.out.println(""); System.out.println("Writing record to the server ..."); System.out.println(""); // Write the record to the data queue. dq.write(byteData); // Get the next value from the user. System.out.print("Enter customer number (or 0 to quit): "); customer = getInt(); } } catch (Exception e) { // If any of the above operations failed say the data queue // operation failed and output the exception. System.out.println("Data Queue operation failed"); System.out.println(e); } } // Display help text when parameters are incorrect. else { System.out.println(""); System.out.println(""); System.out.println(""); System.out.println("Parameters are not correct. Command syntax is:"); System.out.println(""); System.out.println(" DQProducter system"); System.out.println(""); System.out.println("Where"); System.out.println(""); System.out.println(" system = Server that has the data queue"); System.out.println("");
IBM Toolbox for Java
487
System.out.println("For example:"); System.out.println(""); System.out.println(" DQProducerExample mySystem"); System.out.println(""); System.out.println(""); } System.exit(0); } // This is the subroutine that gets a character string from the user // and converts it into an int. static int getInt() { int i = 0; boolean Continue = true; while (Continue) { try { String s = inputStream.readLine(); i = (new Integer(s)).intValue(); Continue = false; } catch (Exception e) { System.out.println(e); System.out.print("Please enter a number ==>"); } } return i; } }
public class DQConsumerExample extends Object { public static void main(String[] parameters) {
488
System.out.println( " " ); // if a system name was not specified, display help text and exit. if (parameters.length >= 1) { try { // The first parameter is the system that contains the data queue. String system = parameters[0]; // Create an AS400 object for the server that has the data queue. AS400 as400 = new AS400(system); // Build a record format for the format of the data queue entry. // This format matches the format in the DQProducer class. A // record consists of: // - a four byte number -- the customer number // - a four byte number -- the part number // - a 20 character string -- the part description // - a four byte number -- the number of parts in this order // First create the base data types. BinaryFieldDescription customerNumber = new BinaryFieldDescription(new AS400Bin4(), "CUSTOMER_NUMBER"); BinaryFieldDescription partNumber = new BinaryFieldDescription(new AS400Bin4(), "PART_NUMBER"); CharacterFieldDescription partName = new CharacterFieldDescription(new AS400Text(20, as400), "PART_NAME" BinaryFieldDescription quantity = new BinaryFieldDescription(new AS400Bin4(), "QUANTITY" // Build a record format and fill it with the base data types. RecordFormat dataFormat = new RecordFormat(); dataFormat.addFieldDescription(customerNumber); dataFormat.addFieldDescription(partNumber); dataFormat.addFieldDescription(partName); dataFormat.addFieldDescription(quantity); // Create the data queue object that represents the data queue on // the server. DataQueue dq = new DataQueue(as400, "/QSYS.LIB/JAVADEMO.LIB/PRODCONS.DTAQ"); boolean Continue = true; // Read the first entry off the queue. The timeout value is // set to -1 so this program will wait forever for an entry. System.out.println("*** Waiting for an entry for process ***"); DataQueueEntry DQData = dq.read(-1); while (Continue) { // We just read an entry off the queue. Put the data into // a record object so the program can access the fields of // the data by name. The Record object will also convert // the data from server format to Java format. Record data = dataFormat.getNewRecord(DQData.getData()); // Get two values out of the record and display them. Integer amountOrdered = (Integer) data.getField("QUANTITY");
IBM Toolbox for Java
489
String
partOrdered
= (String)
data.getField("PART_NAME");
System.out.println("Need " + amountOrdered + " of " + partOrdered); System.out.println(" "); System.out.println("*** Waiting for an entry for process ***"); // Wait for the next entry. DQData = dq.read(-1); } } catch (Exception e) { // If any of the above operations failed say the data queue // operation failed and output the exception. System.out.println("Data Queue operation failed"); System.out.println(e); } } // Display help text when parameters are incorrect. else { System.out.println(""); System.out.println(""); System.out.println(""); System.out.println("Parameters are not correct. Command syntax is:"); System.out.println(""); System.out.println(" DQConsumerExample system"); System.out.println(""); System.out.println("Where"); System.out.println(""); System.out.println(" system = Server that has the data queue"); System.out.println(""); System.out.println("For example:"); System.out.println(""); System.out.println(" DQConsumerExample mySystem"); System.out.println(""); System.out.println(""); } System.exit(0); } }
490
// Create AS400DataTypes to convert our input parameters from Java types // to server data AS400Bin4 bin4 = new AS400Bin4(); // We need a separate AS400Text object for each parameter with a // different length because the AS400Text class requires the length to // be specified. AS400Text char8Converter = new AS400Text(8) AS400Text char20Converter = new AS400Text(20); AS400Text char10Converter = new AS400Text(10); AS400Text char1Converter = new AS400Text(1); // Populate our parameter list; we use the AS400DataType objects to // convert our Java values to byte arrays containing server data. // For the output parameter we need only specify how many bytes will // be returned parms[0] = new ProgramParameter(135); parms[1] = new ProgramParameter(bin4.toBytes(new Integer(135))); parms[2] = new ProgramParameter(char8Converter.toBytes("MBRD0100")); parms[3] = new ProgramParameter(char20Converter.toBytes("MYFILE MYLIB parms[4] = new ProgramParameter(char10COnverter.toBytes("MYMEMBER ")); parms[5] = new ProgramParameter(char1Converter.toBytes("0")); // Set the program name and parameter list qusrmbrd.setProgram("/qsys.lib/qusrmbrd.pgm", parms); // Call the program try { qusrmbrd.run(); } catch(Exception e) { // Handle any exceptions } // Get the information retrieved. Note that this is raw server data. byte[] receiverVar = parms[0].getOutputData(); // We need this to convert the time and date data AS400Text char13Converter = new AS400Text(13); // We need this to convert the text description data AS400Text char50Converter = new AS400Text(50); // Create an AS400Structure to handle the returned information AS400DataType[] dataTypeArray = new AS400DataType[11]; dataTypeArray[0] = bin4; dataTypeArray[1] = bin4; dataTypeArray[2] = char10Converter; dataTypeArray[3] = char10Converter; dataTypeArray[4] = char10Converter; dataTypeArray[5] = char10Converter; dataTypeArray[6] = char10Converter; dataTypeArray[7] = char13Converter; dataTypeArray[8] = char13Converter; dataTypeArray[9] = char50Converter; dataTypeArray[10] = char1Converter; AS400Structure returnedDataConverter = new AS400Structure(dataTypeArray); // Convert the data returned to an array of Java Objects using our // returnedDataConverter Object[] qusrmbrdInfo = dataConverter.toObject(receiverVar, 0);
"));
491
// Get the number of bytes returned Integer bytesReturned = (Integer)qusrmbrdInfo[0]; Integer bytesAvailable = (Integer)qusrmbrdInfo[1]; if (bytesReturned.intValue() != 135) { System.out.println("Wrong amount of information returned."); System.exit(0); } String fileName = (String)qusrmbrdInfo[2]; String libName = (String)qusrmbrdInfo[3]; String mbrName = (String)qusrmbrdInfo[4]; String fileAttribute = (String)qusrmbrdInfo[5]; String sourceType = (String)qusrmbrdInfo[6]; String created = (String)qusrmbrdInfo[7]; String lastChanged = (String)qusrmbrdInfo[8]; String textDesc = (String)qusrmbrdInfo[9]; String isSourceFile = (String)qusrmbrdInfo[10]; // We will just output all the information to the System.out.println(fileName + " " + libName + " " fileAttribute + sourceType + " lastChanged + " " + textDesc + screen + mbrName + " " + " + created + " " + " " + isSourceFile);
The following table lists the required parameters for the QUSRMBRD API as used in the preceding example.
QUSRMBRD parameter Receiver variable Input or output Output Type Char(*) Description Character buffer which will contain the information retrieved. Length of the character buffer provided for the receiver variable. Format specifying the type of information to be retrieved. Must be one of: v MBRD0100 v MBRD0200 v MBRD0300 The following example specifies MBRD0100. Qualified database file name Input Char(20) The qualified file name. This is the file name blank padded to 10 characters followed by the library name blank padded to 10 characters. Special values of *CURLIB and *LIBL are allowed for the library name. The name of the member blank padded to 10 characters. Special values of *FIRST and *LAST are allowed.
Input
Bin(4)
Format name
Input
Char(8)
Input
Char(10)
492
Type Char(1)
Description Whether overrides are to be processed. 0 indicates that overrides are not to be processed. This is the value we will specify.
The following table lists the type of information that the example retrieves (based on format MBRD0100, as specified in the preceding example):
Information retrieved Bytes returned Bytes available Database file name Database file library name Member name File attribute (type of file: PF, LF, DDMF) Type Bin(4) Bin(4) Char(10) Char(10) Char(10) Char(10)
Source type (type of the source source member if this is a Char(10) source file) Creation date and time Last source change date and time Member text description Source file (whether the file is a source file: 0=data file, 1=source file) Char(13) Char(13) Char(50) Char(1)
public class DQKeyedProducer extends Object { // Create a reader to get input from the user.
IBM Toolbox for Java
493
// if the system name was not specified, display help text and exit. if (parameters.length >= 1) { // The first parameter is the system that contains the data queue. String system = parameters[0];
a numeric value. The value ranges are:"); low priority"); medium priority"); high priority");
// Create an AS400 object for the server that has the data queue. AS400 as400 = new AS400(system);
// Use CommandCall to create the library that contains the // data queue. CommandCall crtlib = new CommandCall(as400); crtlib.run("CRTLIB JAVADEMO");
// Create the data queue object. QSYSObjectPathName name = new QSYSObjectPathName("JAVADEMO", "PRODCON2", "DTAQ"); KeyedDataQueue dq = new KeyedDataQueue(as400, name.getPath());
// // // // try {
Create the data queue just in case this is the first time this program has run. The queue already exists exception is caught and ignored. The length of the key is four bytes, the length of an entry is 96 bytes.
494
// Get the data from the user. System.out.print("Enter message: "); String message = inputStream.readLine(); System.out.print("Enter priority: "); int priority = getInt();
// While there is data to put on the queue. while (priority > 0) { // We want to write a java string as the entry to the queue. // Input the data queue is a byte array, however, so convert // the string to a byte array. byte [] byteData = message.getBytes("UnicodeBigUnmarked");
// The key is a number. Input to the data queue is a byte // array, however, so convert the int to a byte array; byte [] byteKey = new byte[4]; byteKey[0] = (byte) (priority >>> 24); byteKey[1] = (byte) (priority >>> 16); byteKey[2] = (byte) (priority >>> 8); byteKey[3] = (byte) (priority); System.out.println(""); System.out.println("Writing record to the server..."); System.out.println("");
// Get the next value from the user. System.out.print("Enter message: "); message = inputStream.readLine(); System.out.print("Enter priority: "); priority = getInt(); } } catch (Exception e) { // If any of the above operations failed say the data queue // operation and output the exception. System.out.println("Data Queue operation failed"); System.out.println(e); } }
495
// Display help text when parameters are incorrect. else { System.out.println(""); System.out.println(""); System.out.println(""); System.out.println("Parameters are not correct. Command syntax is:"); System.out.println(""); System.out.println(" DQKeyedProducter system"); System.out.println(""); System.out.println("Where"); System.out.println(""); System.out.println(" system = server that has the data queue"); System.out.println(""); System.out.println("For example:"); System.out.println(""); System.out.println(" DQKeyedProducer mySystem"); System.out.println(""); System.out.println(""); } System.exit(0); }
// This is the subroutine that gets a character string from the user // and converts it into an int. static int getInt() { int i = 0; boolean Continue = true; while (Continue) { try { String s = inputStream.readLine(); i = (new Integer(s)).intValue(); Continue = false; } catch (Exception e) { System.out.println(e); System.out.print("Please enter a number ==>"); } } return i; } }
496
// queue with the DQKeyedProducer example program. // // The key is a number and the data is a unicode string. This program // shows one way to convert the byte array to a Java int and to read // a byte array and convert it into a Java string. // // This is the consumer side of the producer/consumer example. It reads // entries off the queue and process them. // // Command syntax: // DQKeyedConsumer system // /////////////////////////////////////////////////////////////////////////////// import import import import java.io.*; java.util.*; java.net.*; com.ibm.as400.access.*;
public class DQKeyedConsumer extends Object { public static void main(String[] parameters) { System.out.println( " " ); // if a system name was not specified, display help text and exit. if (parameters.length >= 1) { // The first parameter is the system that contains the data queue. String system = parameters[0]; // Create byte arrays for the priority boundries: // 100 + = high priority // 50 - 100 = medium priority // 0 - 49 = low priority byte [] key0[0] key0[1] key0[2] key0[3] key0 = new byte[4]; = 0; = 0; = 0; = 0;
byte [] key50 = new byte[4]; key50[0] = (byte) (50 >>> 24); key50[1] = (byte) (50 >>> 16); key50[2] = (byte) (50 >>> 8); key50[3] = (byte) (50); byte [] key100 = new byte[4]; key100[0] = (byte) (100 >>> 24); key100[1] = (byte) (100 >>> 16); key100[2] = (byte) (100 >>> 8); key100[3] = (byte) (100); try { // Create an AS400 object for the server that has the data queue. AS400 as400 = new AS400(system); // Create the data queue object that represents the data queue // on the server. QSYSObjectPathName name = new QSYSObjectPathName("JAVADEMO", "PRODCON2", "DTAQ"); KeyedDataQueue dq = new KeyedDataQueue(as400, name.getPath());
IBM Toolbox for Java
497
KeyedDataQueueEntry DQData = null; try { boolean Continue = true; // Go until the user ends us. while (Continue) { // Look for a high priority item on the queue. If one is // found process that item. Note the peek method does not // remove the item if one is found. Also note the timeout // is 0. If an item is not found we get control back with // a null data queue entry. DQData = dq.read(key100, 0, "GE"); if (DQData != null) { processEntry(DQData); } // else no high priority item was found. // priority item. else { DQData = dq.read(key50, 0, "GE"); if (DQData != null) { processEntry(DQData); } // else no medium priority item was found, look for a low // priority item. else { DQData = dq.read(key0, 0, "GE"); if (DQData != null) { processEntry(DQData); } else { System.out.println("Nothing to process, will check again in 30 seconds"); Thread.sleep(30000); } } } } } catch (Exception e) { // If any of the above operations failed say the data queue // operation failed and output the exception. System.out.println("Could not read from the data queue."); System.out.println(e); }; } catch (Exception e) { // If any of the above operations failed say the data queue // operation failed and output the exception. System.out.println("Data Queue operation failed"); Look for a medium
498
System.out.println(e); } } // Display help text when parameters are incorrect. else { System.out.println(""); System.out.println(""); System.out.println(""); System.out.println("Parameters are not correct. Command syntax is:"); System.out.println(""); System.out.println(" DQKeyedConsumer system"); System.out.println(""); System.out.println("Where"); System.out.println(""); System.out.println(" system = Server that has the data queue"); System.out.println(""); System.out.println("For example:"); System.out.println(""); System.out.println(""); System.out.println(" DQKeyedConsumer mySystem"); System.out.println(""); System.out.println(""); } System.exit(0); } static void processEntry(KeyedDataQueueEntry DQData) { try { // The data is a string. Get the string out of the data queue entry. // In the data queue entry the data is a byte array so convert the // entry from a byte array into a string. String message = new String(DQData.getData(), "UnicodeBig"); // The key is a byte array. Get the key out of the data queue entry // and convert it into a number. byte [] keyData = DQData.getKey(); int keyValue = ((keyData[0] ((keyData[1] ((keyData[2] (keyData[3] & & & & 0xFF) << 24) + 0xFF) << 16) + 0xFF) << 8) + 0xFF); message: " + message);
} catch (Exception e) { // If any of the above operations failed say the data queue operation // failed and output the exception. System.out.println("Could not read from the data queue"); System.out.println(e); } } }
499
v v v v
Example: Creating a directory Example: Using IFSFile exceptions to track errors Example: Listing files with a .txt extension Example: Using the IFSFile listFiles() method to list the contents of a directory on page 501
500
{ case ExtendedIOException.FILE_IN_USE: System.out.println("Delete failed, file is in use "); break; case ExtendedIOException.PATH_NOT_FOUND: System.out.println("Delete failed, path not found "); break; // ... for every specific error you want to track. default: System.out.println("Delete failed, rc = "); System.out.println(rc); } }
Example: Using the IFSFile listFiles() method to list the contents of a directory
This example program uses the IBM Toolbox for Java IFS classes to list the contents of a directory on the server. Note: Read the Code example disclaimer for important legal information.
////////////////////////////////////////////////////////////////////////////////// // // IFSListFiles example. This program uses the integrated file system // classes to list the contents of a directory on the server. // // Command syntax: // IFSListFiles system directory // // For example, // IFSListFiles MySystem /path1 // ////////////////////////////////////////////////////////////////////////////////// import java.io.*; import java.util.*; import com.ibm.as400.access.*; public class IFSListFiles extends Object { public static void main(String[] parameters) {
IBM Toolbox for Java
501
System.out.println( " " ); String directoryName = ""; String system = ""; // if both parameters were not specified, display help text and exit. if (parameters.length >= 2) { // Assume the first parameter is the system name and // the second parameter is the directory name system = parameters[0]; directoryName = parameters[1]; try { // Create an AS400 object for the server that holds the files. AS400 as400 = new AS400(system);
// Create the IFSFile object for the directory. IFSFile directory = new IFSFile(as400, directoryName); // // // // // // // // // // // Generate a list of IFSFiles. Pass the listFiles method the directory filter object and the search match criteria. This method caches attribute information. For instance, when isDirectory() is called on an IFSFile object in the file array returned in the following code, no call to the server is required. However, with the user of the listFiles method, attribute information will not be refreshed automatically from the server. This means attribute information can become inconsistent with information about the server.
IFSFile[] directoryFiles = directory.listFiles(new MyDirectoryFilter(),"*"); // Tell the user if the directory doesn't exist or is empty if (directoryFiles == null) { System.out.println("The directory does not exist"); return; } else if (directoryFiles.length == 0) { System.out.println("The directory is empty"); return; } for (int i=0; i< directoryFiles.length; i++) { // Print out information about list. // Print the name of the current file System.out.print(directoryFiles[i].getName()); // Pad the output so the columns line up
502
for (int j = directoryFiles[i].getName().length(); j <18; j++) System.out.print(" "); // Print the date the file was last changed. long changeDate = directoryFiles[i].lastModified(); Date d = new Date(changeDate); System.out.print(d); System.out.print(" "); // Print if the entry is a file or directory System.out.print(" ");
if (directoryFiles[i].isDirectory()) System.out.println(""); else System.out.println(directoryFiles[i].length()); } } catch (Exception e) { // If any of the above operations failed say the list failed // and output the exception. System.out.println("List failed"); System.out.println(e); } } // Display help text when parameters are incorrect. else { System.out.println(""); System.out.println(""); System.out.println(""); System.out.println("Parameters are not correct. Command syntax is:"); System.out.println(""); System.out.println(" IFSListFiles as400 directory"); System.out.println(""); System.out.println("Where"); System.out.println(""); System.out.println(" as400 = system that contains the files"); System.out.println(" directory = directory to be listed"); System.out.println(""); System.out.println("For example:"); System.out.println(""); System.out.println(" IFSListFiles mySystem /dir1/dir2"); System.out.println(""); System.out.println(""); } System.exit(0); } } //////////////////////////////////////////////////////////////////////////// // // The directory filter class prints information from the file object. //
IBM Toolbox for Java
503
// Another way to use the filter is to simply return true or false // based on information in the file object. This lets the mainline // function decide what to do with the list of files that meet the // search criteria. // ////////////////////////////////////////////////////////////////////////////
class MyDirectoryFilter implements IFSFileFilter { public boolean accept(IFSFile file) { try { // Keep this entry. Returning true tells the IFSList object // to return this file in the list of entries returned to the // .list() method. return true; } catch (Exception e) { return false; } } }
Example: Using IFS classes to copy a file from one directory to another
This program uses the installable file system classes to copy a file from one directory to another on the server. Note: Read the Code example disclaimer for important legal information.
////////////////////////////////////////////////////////////////////////////////// // // IFSCopyFile example. This program uses the installable file system classes // to copy a file from one directory to another on the server. // // Command syntax: // IFSCopyFile system sourceName TargetName // // For example, // IFSCopyFile MySystem /path1/path2/file.ext /path3/path4/path5/file.ext // //////////////////////////////////////////////////////////////////////////////////
import java.io.*; import java.util.*; import com.ibm.as400.access.*; public class IFSCopyFile extends Object { public static void main(String[] parameters) { System.out.println( " " ); String String String byte[] sourceName targetName system buffer = = = = ""; ""; ""; new byte[1024 * 64];
504
// if all three parameters were not specified, display help text and exit. if (parameters.length > 2) { // Assume the first parameter is the system name, // the second parameter is the source name and // the third parameter is the target name. system = parameters[0]; sourceName = parameters[1]; targetName = parameters[2]; try { // Create an AS400 object for the server that holds the files. AS400 as400 = new AS400(system);
// Open the source file for exclusive access. source = new IFSFileInputStream(as400, sourceName, IFSFileInputStream.SHARE_NONE); System.out.println("Source file successfully opened");
// Open the target file for exclusive access. target = new IFSFileOutputStream(as400, targetName, IFSFileOutputStream.SHARE_NONE, false); System.out.println("Target file successfully opened");
// Read the first 64K bytes from the source file. int bytesRead = source.read(buffer);
// While there is data in the source file copy the data from // the source file to the target file. while (bytesRead > 0) { target.write(buffer, 0, bytesRead); bytesRead = source.read(buffer); } System.out.println("Data successfully copied");
// Get the last changed date/time from the source file and // set it on the target file.
505
IFSFile src = new IFSFile(as400, sourceName); long dateTime = src.lastModified(); IFSFile tgt = new IFSFile(as400, targetName); tgt.setLastModified(dateTime); System.out.println("Date/Time successfully set on target file"); System.out.println("Copy Successful"); } catch (Exception e) { // If any of the above operations failed say the copy failed // and output the exception. System.out.println("Copy failed"); System.out.println(e); } } // Display help text when parameters are incorrect. else { System.out.println(""); System.out.println(""); System.out.println(""); System.out.println("Parameters are not correct. Command syntax is:"); System.out.println(""); System.out.println(" IFSCopyFile as400 source target"); System.out.println(""); System.out.println("Where"); System.out.println(""); System.out.println(" as400 = system that contains the files"); System.out.println(" source = source file in /path/path/name format"); System.out.println(" target = target file in /path/path/name format"); System.out.println(""); System.out.println("For example:"); System.out.println(""); System.out.println(" IFSCopyFile myAS400 /dir1/dir2/a.txt /dir3/b.txt"); System.out.println(""); System.out.println(""); } System.exit(0); } }
506
import java.util.*; import com.ibm.as400.access.*; public class IFSList extends Object { public static void main(String[] parameters) { System.out.println( " " ); String directoryName = ""; String system = ""; // if both parameters were not specified, display help text and exit. if (parameters.length >= 2) { // Assume the first parameter is the system name and // the second parameter is the directory name system = parameters[0]; directoryName = parameters[1]; try { // Create an AS400 object for the server that holds the files. AS400 as400 = new AS400(system);
// Create the IFSFile object for the directory. IFSFile directory = new IFSFile(as400, directoryName);
// // // // // //
Generate the list of name. Pass the list method the directory filter object and the search match criteria. Note - this example does the processing in the filter object. An alternative is to process the list after it is returned from the list method call.
// Tell the user if the directory doesn't exist or is empty if (directoryNames == null) System.out.println("The directory does not exist"); else if (directoryNames.length == 0) System.out.println("The directory is empty"); } catch (Exception e) { // If any of the above operations failed say the list failed // and output the exception. System.out.println("List failed"); System.out.println(e); } }
IBM Toolbox for Java
507
// Display help text when parameters are incorrect. else { System.out.println(""); System.out.println(""); System.out.println(""); System.out.println("Parameters are not correct. Command syntax is:"); System.out.println(""); System.out.println(" IFSList as400 directory"); System.out.println(""); System.out.println("Where"); System.out.println(""); System.out.println(" as400 = system that contains the files"); System.out.println(" directory = directory to be listed"); System.out.println(""); System.out.println("For example:"); System.out.println(""); System.out.println(" IFSCopyFile mySystem /dir1/dir2"); System.out.println(""); System.out.println(""); } System.exit(0); } } //////////////////////////////////////////////////////////////////////////// // // The directory filter class prints information from the file object. // // Another way to use the filter is to simply return true or false // based on information in the file object. This lets the mainline // function decide what to do with the list of files that meet the // search criteria. // ////////////////////////////////////////////////////////////////////////////
class MyDirectoryFilter implements IFSFileFilter { public boolean accept(IFSFile file) { try { // Print the name of the current file System.out.print(file.getName());
// Pad the output so the columns line up for (int i = file.getName().length(); i < 18; i++) System.out.print(" ");
// Print the date the file was last changed. long changeDate = file.lastModified(); Date d = new Date(changeDate); System.out.print(d); System.out.print(" ");
508
// Keep this entry. Returning true tells the IFSList object // to return this file in the list of entries returned to the // .list() method. return true; } catch (Exception e) { return false; } } }
// Strings to be added in the WORD column of the table. private static final String words[] = { "One", "Two", "Three", "Four", "Six", "Seven", "Eight", "Nine", "Eleven", "Twelve", "Thirteen", "Fourteen", "Sixteen", "Seventeen","Eighteen", "Nineteen",
public static void main (String[] parameters) { // Check the input parameters. if (parameters.length != 3) { System.out.println("");
IBM Toolbox for Java
509
System.out.println("Usage:"); System.out.println(""); System.out.println(" JDBCPopulate system collectionName tableName"); System.out.println(""); System.out.println(""); System.out.println("For example:"); System.out.println(""); System.out.println(""); System.out.println(" JDBCPopulate MySystem MyLibrary MyTable"); System.out.println(""); return; } String system String collectionName String tableName Connection connection try { // Load the IBM Toolbox for Java JDBC driver. DriverManager.registerDriver(new com.ibm.as400.access.AS400JDBCDriver()); // Get a connection to the database. Since we do not // provide a user id or password, a prompt will appear. // // Note that we provide a default SQL schema here so // that we do not need to qualify the table name in // SQL statements. // connection = DriverManager.getConnection ("jdbc:as400://" + system + "/" + collectionName); // Drop the table if it already exists. try { Statement dropTable = connection.createStatement (); dropTable.executeUpdate ("DROP TABLE " + tableName); } catch (SQLException e) { // Ignore. } // Create the table. Statement createTable = connection.createStatement (); createTable.executeUpdate ("CREATE TABLE " + tableName + " (I INTEGER, WORD VARCHAR(20), SQUARE INTEGER, " + " SQUAREROOT DOUBLE)"); // Prepare a statement for inserting rows. Since we // execute this multiple times, it is best to use a // PreparedStatement and parameter markers. PreparedStatement insert = connection.prepareStatement ("INSERT INTO " + tableName + " (I, WORD, SQUARE, SQUAREROOT) " + " VALUES (?, ?, ?, ?)"); // Populate the table. for (int i = 1; i <= words.length; ++i) { insert.setInt (1, i); insert.setString (2, words[i-1]); insert.setInt (3, i*i); insert.setDouble (4, Math.sqrt(i)); insert.executeUpdate (); } // Output a completion message. System.out.println ("Table " + collectionName + "." + tableName + " has been populated."); } = parameters[0]; = parameters[1]; = parameters[2]; = null;
510
catch (Exception e) { System.out.println (); System.out.println ("ERROR: " + e.getMessage()); } finally { // Clean up. try { if (connection != null) connection.close (); } catch (SQLException e) { // Ignore. } } System.exit (0); }
Example 1
This brief example shows the basic use of the AS400JDBCManagedConnectionPoolDataSource class.
import javax.naming.Context; import javax.naming.InitialContext; import javax.sql.DataSource; import com.ibm.as400.access.AS400JDBCManagedConnectionPoolDataSource; import com.ibm.as400.access.AS400JDBCManagedDataSource; public class TestJDBCConnPoolSnippet { void test() { AS400JDBCManagedConnectionPoolDataSource cpds0 = new AS400JDBCManagedConnectionPoolDataSource(); // Set general datasource properties. Note that both connection pool datasource (CPDS) and managed // datasource (MDS) have these properties, and they might have different values. cpds0.setServerName(host); cpds0.setDatabaseName(host);//iasp can be here cpds0.setUser(userid); cpds0.setPassword(password); cpds0.setSavePasswordWhenSerialized(true); // Set connection pooling-specific properties. cpds0.setInitialPoolSize(initialPoolSize_); cpds0.setMinPoolSize(minPoolSize_); cpds0.setMaxPoolSize(maxPoolSize_); cpds0.setMaxLifetime((int)(maxLifetime_/1000)); // convert to seconds cpds0.setMaxIdleTime((int)(maxIdleTime_/1000)); // convert to seconds cpds0.setPropertyCycle((int)(propertyCycle_/1000)); // convert to seconds //cpds0.setReuseConnections(false); // do not re-use connections // Set the initial context factory to use.
511
System.setProperty(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory"); // Get the JNDI Initial Context. Context ctx = new InitialContext(); // Note: The following is an alternative way to set context properties locally: // Properties env = new Properties(); // env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory"); // Context ctx = new InitialContext(env); ctx.rebind("mydatasource", cpds0); // We can now do lookups on cpds, by the name "mydatasource". // Create a standard DataSource object that references it. AS400JDBCManagedDataSource mds0 = new AS400JDBCManagedDataSource(); mds0.setDescription("DataSource supporting connection pooling"); mds0.setDataSourceName("mydatasource"); ctx.rebind("ConnectionPoolingDataSource", mds0); DataSource dataSource_ = (DataSource)ctx.lookup("ConnectionPoolingDataSource"); AS400JDBCManagedDataSource mds_ = (AS400JDBCManagedDataSource)dataSource_; boolean isHealthy = mds_.checkPoolHealth(false); //check pool health Connection c = dataSource_.getConnection(); } }
Example 2
This example shows more details about how to use the AS400JDBCManagedConnectionPoolDataSource class.
import import import import import import import import import import import import import import import import import import import import import import java.awt.TextArea; java.io.BufferedReader; java.io.File; java.io.FileReader; java.io.FileInputStream; java.io.FileOutputStream; java.io.OutputStream; java.io.PrintStream; java.util.Vector; java.util.Properties; java.sql.Connection; javax.sql.DataSource; java.sql.ResultSet; java.sql.Statement; javax.naming.*; java.util.Date; java.util.ArrayList; java.util.Random; com.ibm.as400.access.AS400; com.ibm.as400.access.AS400JDBCManagedConnectionPoolDataSource; com.ibm.as400.access.AS400JDBCManagedDataSource; com.ibm.as400.access.Trace;
public class TestJDBCConnPool { private static final boolean DEBUG = false; // If you turn this flag on, be sure to also turn on the following flag: // AS400JDBCConnection.TESTING_THREAD_SAFETY. private static final boolean TESTING_THREAD_SAFETY = false; private static String userid; private static String password; private static String host; // Note: For consistency, all time values are stored units of milliseconds. private int initialPoolSize_; // initial # of connections in pool
512
private private private private private private private private private private
int minPoolSize_; int maxPoolSize_; long maxLifetime_; long maxIdleTime_; long propertyCycle_;
// // // // //
max # of connections in pool max # of connections in pool max lifetime (msecs) of connections in pool max idle time (msecs) of available connections in pool pool maintenance frequency (msecs)
int numDaemons_; // # of requester daemons to create static long timeToRunDaemons_; // total duration (msecs) to let the daemons run long daemonMaxSleepTime_; // max time (msecs) for requester daemons to sleep each cycle long daemonMinSleepTime_; // min time (msecs) for requester daemons to sleep each cycle long poolHealthCheckCycle_; // # of msecs between calls to checkPoolHealth()
private boolean keepDaemonsAlive_ = true; // When this is false, the daemons shut down. private DataSource dataSource_; private AS400JDBCManagedDataSource mds_; private final Object daemonSleepLock_ = new Object(); private Random random_ = new Random(); static { try { Class.forName("com.ibm.as400.access.AS400JDBCDriver"); } catch(Exception e){ System.out.println("Unable to register JDBC driver."); System.exit(0); } } public static void main(String[] args) { host = args[0]; userid = args[1]; password = args[2]; timeToRunDaemons_ = (new Integer(args[3])).intValue() * 1000; //milliseconds //args[3]=time to run in seconds TestJDBCConnPool cptest = new TestJDBCConnPool(); cptest.setup(); cptest.runTest(); } public void setup() { try { if (DEBUG) System.out.println("TESTING_THREAD_SAFETY flag is " + (TESTING_THREAD_SAFETY ? "true" : "false")); if (TESTING_THREAD_SAFETY) { // Adjust values for performing thread-intensive stress testing. // NOTE: This assumes that the AS400JDBCConnection class has also been modified to // not make actual connections to an actual server. // To do this, edit AS400JDBCConnection.java, changing its TESTING_THREAD_SAFETY // flag to 'false', and recompile. minPoolSize_ = 100; maxPoolSize_ = 190; initialPoolSize_ = 150; // this should get reset to maxPoolSize_ numDaemons_ = 75; if (timeToRunDaemons_ == 0) { timeToRunDaemons_ = 180*1000; // 180 seconds == 3 minutes } } else { // Set more conservative values, as we'll be making actual connections to an // actual server, and we don't want to monopolize the server. minPoolSize_ = 5; maxPoolSize_ = 15; initialPoolSize_ = 9; numDaemons_ = 4; if (timeToRunDaemons_ == 0) { timeToRunDaemons_ = 15*1000; // 15 seconds } }
513
maxLifetime_ = (int)timeToRunDaemons_ / 3; maxIdleTime_ = (int)timeToRunDaemons_ / 4; propertyCycle_ = timeToRunDaemons_ / 4; poolHealthCheckCycle_ = Math.min(timeToRunDaemons_ / 4, 20*60*1000); // at least once every 20 minutes (more frequently if shorter run-time) daemonMaxSleepTime_ = Math.min(timeToRunDaemons_ / 3, 10*1000); // at most 10 seconds (less if shorter run-time) daemonMinSleepTime_ = 20; // milliseconds if (DEBUG) System.out.println("setup: Constructing " + "AS400JDBCManagedConnectionPoolDataSource (cpds0)"); AS400JDBCManagedConnectionPoolDataSource cpds0 = new AS400JDBCManagedConnectionPoolDataSource(); // Set datasource properties. Note that both CPDS and MDS have these // properties, and they might have different values. cpds0.setServerName(host); cpds0.setDatabaseName(host);//iasp can be here cpds0.setUser(userid); cpds0.setPassword(password); cpds0.setSavePasswordWhenSerialized(true); // Set connection pooling-specific properties. cpds0.setInitialPoolSize(initialPoolSize_); cpds0.setMinPoolSize(minPoolSize_); cpds0.setMaxPoolSize(maxPoolSize_); cpds0.setMaxLifetime((int)(maxLifetime_/1000)); // convert to seconds cpds0.setMaxIdleTime((int)(maxIdleTime_/1000)); // convert to seconds cpds0.setPropertyCycle((int)(propertyCycle_/1000)); // convert to seconds //cpds0.setReuseConnections(false); // don't re-use connections // Set the initial context factory to use. System.setProperty(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory"); // Get the JNDI Initial Context. Context ctx = new InitialContext(); // Note: The following is an alternative way to set context properties locally: // Properties env = new Properties(); // env.put(Context.INITIAL_CONTEXT_FACTORY, // "com.sun.jndi.fscontext.RefFSContextFactory"); // Context ctx = new InitialContext(env); ctx.rebind("mydatasource", cpds0); // We can now do lookups on cpds, by the name"mydatasource". if (DEBUG) System.out.println("setup: lookup(\"mydatasource\"" + ")"); // AS400JDBCManagedConnectionPoolDataSource cpds1 = // (AS400JDBCManagedConnectionPoolDataSource)ctx.lookup("mydatasource"); // if (DEBUG) System.out.println("setup: cpds1.getUser() == |" + cpds1.getUser() + "|"); // Create a standard DataSource object that references it. if (DEBUG) System.out.println("setup: Constructing AS400JDBCManagedDataSource (mds0)"); AS400JDBCManagedDataSource mds0 = new AS400JDBCManagedDataSource(); mds0.setDescription("DataSource supporting connection pooling"); mds0.setDataSourceName("mydatasource"); ctx.rebind("ConnectionPoolingDataSource", mds0); if (DEBUG) System.out.println("setup: lookup(\"ConnectionPoolingDataSource\"" + ")"); dataSource_ = (DataSource)ctx.lookup("ConnectionPoolingDataSource"); //dataSource_.setLogWriter(output_); if (DEBUG) System.out.println("setup: dataSource_.getUser() == |" + ((AS400JDBCManagedDataSource)dataSource_).getUser() + "|"); mds_ = (AS400JDBCManagedDataSource)dataSource_; } catch (Exception e) { e.printStackTrace(); System.out.println("Setup error during Trace file creation."); }
514
} void displayConnectionType(Connection conn, boolean specifiedDefaultId) { if (conn instanceof com.ibm.as400.access.AS400JDBCConnectionHandle) System.out.print("("+ (specifiedDefaultId ? "+" : "-") + "P)"); else System.out.print("("+ (specifiedDefaultId ? "+" : "-") + "NP)"); } /** * Gets and returns connections from and to a connection pool for a while. **/ public void runTest() { boolean ok = true; try { System.out.println("Started test run at " + new Date()); if (DEBUG) System.out.println("Checking health just after datasource creation " + "(we expect that the pool does not exist yet) ..."); if (mds_.checkPoolHealth(true)) { ok = false; System.out.println("\nERROR: Pool exists prior to first getConnection()."); } // Verify some setters/getters for JDBC properties. System.out.println("Verifying setters/getters ..."); mds_.setAccess("read only"); if (!mds_.getAccess().equals("read only")) { ok = false; System.out.println("\nERROR: getAccess() returned unexpected value: " + "|" + mds_.getAccess()+"|"); } boolean oldBool = mds_.isBigDecimal(); boolean newBool = (oldBool ? false : true); mds_.setBigDecimal(newBool); if (mds_.isBigDecimal() != newBool) { ok = false; System.out.println("\nERROR: isBigDecimal() returned unexpected value: " + "|"+mds_.isBigDecimal()+"|"); } mds_.setBigDecimal(oldBool); int oldInt = mds_.getBlockCriteria(); int newInt = (oldInt == 2 ? 1 : 2); mds_.setBlockCriteria(newInt); if (mds_.getBlockCriteria() != newInt) { ok = false; System.out.println("\nERROR: getBlockCriteria() returned unexpected value: " + "|"+mds_.getBlockCriteria()+"|"); } mds_.setBlockCriteria(oldInt); // Verify some setters and getters for socket properties. oldBool = mds_.isKeepAlive(); newBool = (oldBool ? false : true); mds_.setKeepAlive(newBool); if (mds_.isKeepAlive() != newBool) { ok = false; System.out.println("\nERROR: isKeepAlive() returned unexpected value: " + "|"+mds_.isKeepAlive()+"|"); } mds_.setKeepAlive(oldBool); oldInt = mds_.getReceiveBufferSize(); newInt = (oldInt == 256 ? 512 : 256); mds_.setReceiveBufferSize(newInt); if (mds_.getReceiveBufferSize() != newInt) { ok = false; System.out.println("\nERROR: getReceiveBufferSize() returned unexpected value: " + "|"+mds_.getReceiveBufferSize()+"|"); }
515
mds_.setReceiveBufferSize(oldInt); System.out.println("CONNECTION 1"); Object o = dataSource_.getConnection(); System.out.println(o.getClass()); System.out.println("******LOOK ABOVE*******"); Connection c1 = dataSource_.getConnection(); if (DEBUG) displayConnectionType(c1, true); if (DEBUG) System.out.println("Checking health after first getConnection() ..."); if (!mds_.checkPoolHealth(true)) { ok = false; System.out.println("\nERROR: Pool is not healthy after first getConnection()."); } if (!TESTING_THREAD_SAFETY) { try { c1.setAutoCommit(false); if (DEBUG) System.out.println("SELECT * FROM QIWS.QCUSTCDT"); Statement s = c1.createStatement(); ResultSet rs = s.executeQuery("SELECT * FROM QIWS.QCUSTCDT"); while(rs.next()){ if (DEBUG) System.out.println(rs.getString(2)); } rs.close(); s.close(); } catch (Exception e) { e.printStackTrace(); if (DEBUG) System.out.println("Checking health after fatal connection error ..."); if (!mds_.checkPoolHealth(true)) { ok = false; System.out.println("\nERROR: Pool is not healthy after fatal connection " + "error."); } } } System.out.println("CONNECTION 2"); Connection c2 = dataSource_.getConnection(userid, password); if (DEBUG) displayConnectionType(c2, false); System.out.println("CONNECTION 3"); Connection c3 = dataSource_.getConnection(); if (DEBUG) displayConnectionType(c3, true); c1.close(); if (DEBUG) System.out.println("Checking health after first close() ..."); if (!mds_.checkPoolHealth(true)) { ok = false; System.out.println("\nERROR: Pool is not healthy after first close()."); } System.out.println("CONNECTION 4"); Connection c4 = dataSource_.getConnection(); if (DEBUG) displayConnectionType(c4, true); c1.close(); // close this one again c2.close(); c3.close(); c4.close(); if (DEBUG) System.out.println("Checking health after last close() ..."); if (!mds_.checkPoolHealth(true)) { ok = false; System.out.println("\nERROR: Pool is not healthy after last close()."); }
516
// Start the test daemons. System.out.println("Starting test daemons"); startThreads(); // Run the test daemons for a while; check pool health periodically. long startTime = System.currentTimeMillis(); long endTime = startTime + timeToRunDaemons_; while (System.currentTimeMillis() < endTime) { System.out.print("h"); // Let the daemons run for a while, then check pool health. try { Thread.sleep(poolHealthCheckCycle_); } catch (InterruptedException ie) {} if (!mds_.checkPoolHealth(true)) { ok = false; System.out.println("\nERROR: Pool is not healthy after test daemons started."); } } // Stop the test daemons. System.out.println("\nStopping test daemons"); stopThreads(); if (DEBUG) System.out.println("Checking health after connectionGetter daemons have run..."); if (!mds_.checkPoolHealth(true)) { ok = false; System.out.println("\nERROR: Pool is not healthy after test daemons stopped."); } if (!TESTING_THREAD_SAFETY) { System.out.println("CONNECTION 5"); Connection c = dataSource_.getConnection(); if (DEBUG) displayConnectionType(c, true); c.setAutoCommit(false); if (DEBUG) System.out.println("SELECT * FROM QIWS.QCUSTCDT"); Statement s = c.createStatement(); ResultSet rs = s.executeQuery("SELECT * FROM QIWS.QCUSTCDT"); while(rs.next()){ if (DEBUG) System.out.println(rs.getString(2)); } rs.close(); s.close(); c.close(); } System.out.println("\nClosing the pool..."); mds_.closePool(); if (DEBUG) System.out.println("Checking health after pool closed ..."); Trace.setTraceJDBCOn(true); // make sure the final stats get printed out Trace.setTraceOn(true); if (!mds_.checkPoolHealth(true)) { ok = false; System.out.println("\nERROR: Pool is not healthy after pool closed."); } System.out.println(); if(ok==true) System.out.println("test ran ok"); else System.out.println("test failed"); } catch (Exception e) { System.out.println(e); e.printStackTrace(); } finally { System.out.println("Ended test at " + new Date()); } } void startThreads()
517
{ // Create a bunch of threads that call getConnection(). Thread[] threads = new Thread[numDaemons_]; for (int i=0; i<numDaemons_; i++) { ConnectionGetter getter; // Flip a coin to see if this daemon will specify the default uid, or unique uid. if (random_.nextBoolean()) { getter = new ConnectionGetter(userid,password); if (TESTING_THREAD_SAFETY) { // we can use fictional userid getter = new ConnectionGetter("Thread"+i, "Pwd"+i); } else { // must use a real userid getter = new ConnectionGetter(userid,password); } } else getter = new ConnectionGetter(null, null); threads[i] = new Thread(getter, "["+i+"]"); threads[i].setDaemon(true); } // Start the threads. for (int i=0; i<numDaemons_; i++) { threads[i].start(); } } void stopThreads() { // Tell the threads to stop. keepDaemonsAlive_ = false; synchronized (daemonSleepLock_) { daemonSleepLock_.notifyAll(); } // Wait for the daemons to stop. try { Thread.sleep(3000); } catch (InterruptedException ie) {} } // ConnectionGetter -------------------------------------------------------------------/** Helper class. This daemon wakes up at random intervals and either gets another connection from the connection pool or returns a previously-gotten connection to the pool. **/ private final class ConnectionGetter implements Runnable { private String uid_; private String pwd_; private boolean useDefaultUid_; private long maxSleepTime_; private String threadName_; private boolean firstConnection_ = true; ArrayList connections_ = new ArrayList(); // list of connections that this getter currently 'owns'. ConnectionGetter(String uid, String pwd) { uid_ = uid; pwd_ = pwd; if (uid_ == null) useDefaultUid_ = true; else useDefaultUid_ = false; maxSleepTime_ = daemonMaxSleepTime_; // our own copy that we can adjust } public void run() { threadName_ = Thread.currentThread().getName(); if (DEBUG) System.out.println("ConnectionGetter("+threadName_+") Starting up"); try
518
{ while (keepDaemonsAlive_) { try { // Pick a random sleep-time, between min and max values. long sleepTime = Math.max((long)(maxSleepTime_ * random_.nextFloat()), daemonMinSleepTime_); // Note: Must never call wait(0), because that waits forever. synchronized (daemonSleepLock_) { try { daemonSleepLock_.wait(sleepTime); System.out.print("."); } catch (InterruptedException ie) {} } if (!keepDaemonsAlive_) break; // Decide by chance whether to request another connection or return a // previously-obtained connection. Connection conn; if (random_.nextBoolean()) // Leave the decision to chance. { // Request another connection. if (useDefaultUid_) { if (DEBUG) System.out.println("ConnectionGetter("+threadName_+") - get()"); conn = dataSource_.getConnection(); } else { if (DEBUG) System.out.println("ConnectionGetter("+threadName_+") - " + "get("+uid_+",***)"); conn = dataSource_.getConnection(uid_, pwd_); } if (conn == null) { System.out.println("ConnectionGetter("+threadName_+") ERROR: " + "getConnection() returned null"); } else { // Occasionally "forget" that we own a connection, and neglect to // close it. // Orphaned connections should eventually exceed their maximum // lifetime and get "reaped" by the connection manager. float val = random_.nextFloat(); if (firstConnection_ || val < 0.1) { // 'orphan' a few gotten connections firstConnection_ = false; } else { connections_.add(conn); } if (DEBUG) displayConnectionType(conn, useDefaultUid_); if (conn instanceof com.ibm.as400.access.AS400JDBCConnectionHandle) { // We got a pooled connection. Try speeding up our cycle time. if (maxSleepTime_ > 100) maxSleepTime_--; else maxSleepTime_ = 100; } else { // We didn't get a pooled connection. That means that the pool // must be at capacity. Slow down our cycle time a bit. maxSleepTime_ = maxSleepTime_ + 50; } } } else { // Close a connection that we currently own. if (connections_.size() != 0) { conn = (Connection)connections_.remove(0); conn.close(); } } } // inner try catch (Exception e) {
519
e.printStackTrace(); } } // outer while } // outer try finally { if (DEBUG) System.out.println("ConnectionGetter("+threadName_+") Stopping"); // Return all the connections that I still have in my list. for (int i=0; i<connections_.size(); i++) { Connection conn = (Connection)connections_.remove(0); try { conn.close(); } catch (Exception e) { e.printStackTrace(); } } } } } // internal class 'ConnectionGetter' }
// Format a string so that it has the specified width. private static String format (String s, int width) { String formattedString; // The string is shorter than specified width, // so we need to pad with blanks. if (s.length() < width) { StringBuffer buffer = new StringBuffer (s); for (int i = s.length(); i < width; ++i) buffer.append (" "); formattedString = buffer.toString(); } // Otherwise, we need to truncate the string. else formattedString = s.substring (0, width); return formattedString; }
520
// Check the input parameters. if (parameters.length != 3) { System.out.println(""); System.out.println("Usage:"); System.out.println(""); System.out.println(" JDBCQuery system collectionName tableName"); System.out.println(""); System.out.println(""); System.out.println("For example:"); System.out.println(""); System.out.println(""); System.out.println(" JDBCQuery mySystem qiws qcustcdt"); System.out.println(""); return; } String system String collectionName String tableName Connection connection try { // Load the IBM Toolbox for Java JDBC driver. DriverManager.registerDriver(new com.ibm.as400.access.AS400JDBCDriver()); // Get a connection to the database. Since we do not // provide a user id or password, a prompt will appear. connection = DriverManager.getConnection ("jdbc:as400://" + system); DatabaseMetaData dmd = connection.getMetaData (); // Execute the query. Statement select = connection.createStatement (); ResultSet rs = select.executeQuery ( "SELECT * FROM " + collectionName + dmd.getCatalogSeparator() + tableName); // Get information about the result set. Set the column // width to whichever is longer: the length of the label // or the length of the data. ResultSetMetaData rsmd = rs.getMetaData (); int columnCount = rsmd.getColumnCount (); String[] columnLabels = new String[columnCount]; int[] columnWidths = new int[columnCount]; for (int i = 1; i <= columnCount; ++i) { columnLabels[i-1] = rsmd.getColumnLabel (i); columnWidths[i-1] = Math.max (columnLabels[i-1].length(), rsmd.getColumnDisplaySize (i)); } // Output the column headings. for (int i = 1; i <= columnCount; ++i) { System.out.print (format (rsmd.getColumnLabel(i), columnWidths[i-1])); System.out.print (" "); } System.out.println (); // Output a dashed line. StringBuffer dashedLine; for (int i = 1; i <= columnCount; ++i) { for (int j = 1; j <= columnWidths[i-1]; ++j) System.out.print ("-"); System.out.print (" "); } System.out.println (); // Iterate throught the rows in the result set and output // the columns for each row.
IBM Toolbox for Java
521
while (rs.next ()) { for (int i = 1; i <= columnCount; ++i) { String value = rs.getString (i); if (rs.wasNull ()) value = "<null>"; System.out.print (format (value, columnWidths[i-1])); System.out.print (" "); } System.out.println (); } } catch (Exception e) { System.out.println (); System.out.println ("ERROR: " + e.getMessage()); } finally { // Clean up. try { if (connection != null) connection.close (); } catch (SQLException e) { // Ignore. } } System.exit (0); }
public class listJobs2 extends Object { // Create an object in case we want to call // any non-staic methods. public static void main(String[] parameters) { listJobs2 me = new listJobs2();
522
me.Main(parameters); System.exit(0); }
void Main(String[] parameters) { // If a system was not specified, display help text and exit. if (parameters.length == 0) { showHelp(); return; } // Assign the parameters to variables. The // first parameter is assumed to be the system // name the second is a userID and the third // is a password. String systemName = parameters[0]; String userID = null; String password = null; if (parameters.length > 1) userID = parameters[1].toUpperCase(); if (parameters.length >= 2) password = parameters[2].toUpperCase(); System.out.println(" ");
try { // // // AS400 as400 = Create an AS400 object using the system name specified by the user. Set the userid and password if specified by the user. new AS400(parameters[0]);
");
// Create a jobList object. This object is used // to retrieve the list of active jobs on the server. JobList jobList = new JobList(as400); // Get the list of active jobs. Enumeration list = jobList.getJobs(); // For each job in the list ... while (list.hasMoreElements()) {
523
// Get a job off the list. If a userID was // specified then print identification information // only if the job's user matches the userID. If // no userID was specified then print information // for every job on the system. Job j = (Job) list.nextElement(); if (userID != null) { if (j.getUser().trim().equalsIgnoreCase(userID)) { System.out.println(j.getName().trim() + "." + j.getUser().trim() + "." + j.getNumber()); } } else System.out.println(j.getName().trim() + "." + j.getUser().trim() + "." + j.getNumber()); } } catch (Exception e) { System.out.println("Unexpected error"); e.printStackTrace(); } }
// Display help text when parameters are incorrect. void showHelp() { System.out.println(""); System.out.println(""); System.out.println(""); System.out.println("Parameters are not correct. Command syntax is:"); System.out.println(""); System.out.println(" listJobs2 System UserID Password"); System.out.println(""); System.out.println("Where"); System.out.println(""); System.out.println(" System = server to connect to"); System.out.println(" UserID = valid userID on that system "); System.out.println(" Password = password for the UserID (optional)"); System.out.println(""); System.out.println("For example:"); System.out.println(""); System.out.println(" listJobs2 MYAS400 JavaUser pwd1"); System.out.println(""); System.out.println(""); } }
524
// // // Command syntax: // listJobs system userID password // // (UserID and password are optional) // ///////////////////////////////////////////////////////////////////////// import java.io.*; import java.util.*; import com.ibm.as400.access.*; public class listJobs extends Object { public static void main(String[] parameters) { listJobs me = new listJobs(); me.Main(parameters); System.exit(0); }
void Main(String[] parameters) { // If a system was not specified, display help text and exit. if (parameters.length == 0) { showHelp(); return; } // Set up AS400 object parms. The first is the system name and must // be specified by the user. The second and third are optional. They // are the userid and password. Convert the userid and password // to uppercase before setting them on the AS400 object. String userID = null; String password = null; if (parameters.length > 1) userID = parameters[1].toUpperCase(); if (parameters.length >= 2) password = parameters[2].toUpperCase(); System.out.println(" "); try { // Create an AS400 object using the system name specified by the user. AS400 as400 = new AS400(parameters[0]); // If a userid and/or password was specified, set them on the // AS400 object. if (userID != null) as400.setUserId(userID); if (password != null) as400.setPassword(password); // Create a job list object. Input parm is the AS400 we want job // information from. JobList jobList = new JobList(as400);
IBM Toolbox for Java
525
// Get a list of jobs running on the server. Enumeration listOfJobs = jobList.getJobs(); // For each job in the list print information about the job. while (listOfJobs.hasMoreElements()) { printJobInfo((Job) listOfJobs.nextElement(), as400); } } catch (Exception e) { System.out.println("Unexpected error"); System.out.println(e); } }
void printJobInfo(Job job, AS400 as400) { // Create AS400Bin4 AS400Text AS400Text AS400Text AS400Text AS400Text AS400Text the various converters we need bin4Converter = new AS400Bin4( ); text26Converter = new AS400Text(26, text16Converter = new AS400Text(16, text10Converter = new AS400Text(10, text8Converter = new AS400Text(8, text6Converter = new AS400Text(6, text4Converter = new AS400Text(4,
// We have the job name/number/etc. from the list request. // make a server API call to get the status of the job. try { // Create a program call object ProgramCall pgm = new ProgramCall(as400); // The server program we call has five parameters ProgramParameter[] parmlist = new ProgramParameter[5]; // The first parm is a byte array that holds the output // data. We will allocate a 1k buffer for output data. parmlist[0] = new ProgramParameter( 1024 );
// The second parm is the size of our output data buffer (1K). Integer iStatusLength = new Integer( 1024 ); byte[] statusLength = bin4Converter.toBytes( iStatusLength ); parmlist[1] = new ProgramParameter( statusLength ); // The third parm is the name of the format of the data. // We will use format JOBI0200 because it has job status. byte[] statusFormat = text8Converter.toBytes("JOBI0200"); parmlist[2] = new ProgramParameter( statusFormat ); // The fourth parm is the job name is format "name user number". // Name must be 10 characters, user must be 10 characters and // number must be 6 characters. We will use a text converter // to do the conversion and padding. byte[] jobName = text26Converter.toBytes(job.getName()); int i = text10Converter.toBytes(job.getUser(), jobName, 10);
526
parmlist[3] = new ProgramParameter( jobName ); // The last paramter is job identifier. We will leave this blank. byte[] jobID = text16Converter.toBytes(" "); parmlist[4] = new ProgramParameter( jobID ); // Run the program. if (pgm.run( "/QSYS.LIB/QUSRJOBI.PGM", parmlist )==false) { // if the program failed display the error message. AS400Message[] msgList = pgm.getMessageList(); System.out.println(msgList[0].getText()); } else { // else the program worked. Output the status followed by // the jobName.user.jobID byte[] as400Data = parmlist[0].getOutputData(); System.out.print(" " + text4Converter.toObject(as400Data, 107) + " System.out.println(job.getName().trim() + "." + job.getUser().trim() + "." + job.getNumber() + " "); } } catch (Exception e) { System.out.println(e); } }
");
// Display help text when parameters are incorrect. void showHelp() { System.out.println(""); System.out.println(""); System.out.println(""); System.out.println("Parameters are not correct. Command syntax is:"); System.out.println(""); System.out.println(" listJobs System UserID Password"); System.out.println(""); System.out.println("Where"); System.out.println(""); System.out.println(" System = server to connect to"); System.out.println(" UserID = valid userID on that system (optional)"); System.out.println(" Password = password for the UserID (optional)"); System.out.println(""); System.out.println("For example:"); System.out.println(""); System.out.println(" listJobs MYAS400 JavaUser pwd1"); System.out.println(""); System.out.println(""); } }
527
528
// Look through the list to find a job for the current user. while (list.hasMoreElements() && Continue) { Job j = (Job) list.nextElement(); if (j.getUser().trim().equalsIgnoreCase(userID)) { // A job matching the current user was found. Create // a job log object for this job. JobLog jlog = new JobLog(system, j.getName(), j.getUser(), j.getNumber()); // Enumerate the messages in the job log then print them. Enumeration messageList = jlog.getMessages(); while (messageList.hasMoreElements()) { AS400Message message = (AS400Message) messageList.nextElement(); System.out.println(message.getText()); } // We found one job matching the current user so exit. Continue = false; } } } catch (Exception e) { System.out.println ("Error: " + e.getMessage ()); } System.exit(0); } }
529
// to override from the default printer file...we will override // the output queue and the copies value. parms.setParameter(PrintObject.ATTR_COPIES, 4); if (outputQueue != null) { parms.setParameter(PrintObject.ATTR_OUTPUT_QUEUE, outputQueue.getPath()); } out = new SpooledFileOutputStream(system, parms, null, null); // read from the inputstream in until end of stream, passing all data // to the spooled file output stream. do { bytesRead = in.read(buf); if (bytesRead != -1) { out.write(buf, 0, bytesRead); } } while (bytesRead != -1); out.close(); // close the spooled file // get a reference to the new spooled file
530
SpooledFileOutputStream out; PrintParameterList parms = new PrintParameterList(); SCS3812Writer scsWtr; // Process the arguments. if (args.length >= 1) { system = new AS400(args[0]); // Create an AS400 object } else { system = new AS400(DEFAULT_SYSTEM); } if (args.length >= 2) // Set the outq { parms.setParameter(PrintObject.ATTR_OUTPUT_QUEUE, args[1]); } else { parms.setParameter(PrintObject.ATTR_OUTPUT_QUEUE, DEFAULT_OUTQ); } out = new SpooledFileOutputStream(system, parms, null, null); scsWtr = new SCS3812Writer(out, 37); // Write the contents of the spool file. scsWtr.setLeftMargin(1.0); scsWtr.absoluteVerticalPosition(6); scsWtr.setFont(scsWtr.FONT_COURIER_BOLD_5); scsWtr.write(" Java Printing"); scsWtr.newLine(); scsWtr.newLine(); scsWtr.setCPI(10); scsWtr.write("This document was created using the IBM Toolbox for Java."); scsWtr.newLine(); scsWtr.write("The rest of this document shows some of the things that"); scsWtr.newLine(); scsWtr.write("can be done with the SCS3812Writer class."); scsWtr.newLine(); scsWtr.newLine(); scsWtr.setUnderline(true); scsWtr.write("Setting fonts:"); scsWtr.setUnderline(false); scsWtr.newLine(); scsWtr.setFont(scsWtr.FONT_COURIER_10); scsWtr.write("Courier font "); scsWtr.setFont(scsWtr.FONT_COURIER_BOLD_10); scsWtr.write(" Courier bold font "); scsWtr.setFont(scsWtr.FONT_COURIER_ITALIC_10); scsWtr.write(" Courier italic font "); scsWtr.newLine(); scsWtr.setBold(true); scsWtr.write("Courier bold italic font "); scsWtr.setBold(false); scsWtr.setCPI(10); scsWtr.newLine(); scsWtr.newLine(); scsWtr.setUnderline(true); scsWtr.write("Lines per inch:"); scsWtr.setUnderline(false); scsWtr.newLine(); scsWtr.write("The following lines should print at 8 lines per inch."); scsWtr.newLine(); scsWtr.newLine(); scsWtr.setLPI(8); scsWtr.write("Line one"); scsWtr.newLine(); scsWtr.write("Line two"); scsWtr.newLine(); scsWtr.write("Line three"); scsWtr.newLine(); scsWtr.write("Line four"); scsWtr.newLine(); scsWtr.write("Line five"); scsWtr.newLine(); scsWtr.write("Line six"); scsWtr.newLine(); scsWtr.write("Line seven"); scsWtr.newLine(); scsWtr.write("Line eight"); scsWtr.newLine(); scsWtr.endPage(); scsWtr.setLPI(6); scsWtr.setSourceDrawer(1); scsWtr.setTextOrientation(0);
IBM Toolbox for Java
531
scsWtr.absoluteVerticalPosition(6); scsWtr.write("This page should print in portrait orientation from drawer 1."); scsWtr.endPage(); scsWtr.setSourceDrawer(2); scsWtr.setTextOrientation(90); scsWtr.absoluteVerticalPosition(6); scsWtr.write("This page should print in landscape orientation from drawer 2."); scsWtr.endPage(); scsWtr.close(); System.out.println("Sample spool file created."); System.exit(0); } catch (Exception e) { // Handle error. System.out.println("Exception occured while creating spooled file. " + e); System.exit(0); } } }
532
Example of PrintObjectTransformedInputStream Note: Read the Code example disclaimer for important legal information. The following example shows how to create a PrintObjectTransformedInputStream object for reading data formatted as TIFF. A TIFF (G4 compression) workstation customization object is used to specify the data transform.
// Create a spooled file SpooledFile splF = createSpooledFile(); // Set up print parameter list PrintParameterList printParms = new PrintParameterList(); printParms.setParameter(PrintObject.ATTR_WORKSTATION_CUST_OBJECT, "/QSYS.LIB/QWPTIFFG4.WSCST"); printParms.setParameter(PrintObject.ATTR_MFGTYPE, "*WSCST"); // Create a transformed input stream from the spooled file PrintObjectTransformedInputStream is = splF.getTransformedInputStream(printParms);
Example of PrintObjectTransformedInputStream using manufacturer type and model Note: Read the Code example disclaimer for important legal information. The following example shows how to create a PrintObjectTransformedInputStream object for reading data formatted for output to an ASCII printer. A manufacturer type and model of *HP4 is used to specify the data transform.
// Create a spooled file SpooledFile splF = createSpooledFile(); // Set up print parameter list PrintParameterList printParms = new PrintParameterList(); printParms.setParameter(PrintObject.ATTR_MFGTYPE, "*HP4");
IBM Toolbox for Java
533
// Create a transformed input stream from the spooled file PrintObjectTransformedInputStream is = splF.getTransformedInputStream(printParms);
public class NPExampleListSplfAsynch extends Object implements PrintObjectListListener { private AS400 system_; private boolean fListError; private boolean fListClosed; private boolean fListCompleted; private Exception listException; private int listObjectCount; public NPExampleListSplfAsynch(AS400 system) { system_ = system; } // list all spooled files on the server asynchronously using a listener public void listSpooledFiles() { fListError = false; fListClosed = false; fListCompleted = false; listException = null; listObjectCount = 0; try { String strSpooledFileName; boolean fCompleted = false; int listed = 0, size; if( system_ == null ) { system_ = new AS400(); } System.out.println(" Now receiving all spooled files Asynchronously using a listener"); SpooledFileList splfList = new SpooledFileList(system_);
534
// set filters, all users, on all queues splfList.setUserFilter("*ALL"); splfList.setQueueFilter("/QSYS.LIB/%ALL%.LIB/%ALL%.OUTQ"); // add the listener. splfList.addPrintObjectListListener(this); // open the list, openAsynchronously returns immediately splfList.openAsynchronously(); do { // wait for the list to have at least 25 objects or to be done waitForWakeUp(); fCompleted = splfList.isCompleted(); size = splfList.size(); // output the names of all objects added to the list // since we last woke up while (listed < size) { if (fListError) { System.out.println(" Exception on list - " + listException); break; } if (fListClosed) { System.out.println(" The list was closed before it completed!"); break; } SpooledFile splf = (SpooledFile)splfList.getObject(listed++); if (splf != null) { // output this spooled file name strSpooledFileName = splf.getStringAttribute(SpooledFile.ATTR_SPOOLFILE); System.out.println(" spooled file = " + strSpooledFileName); } } } while (!fCompleted); // clean up after we are done with the list splfList.close(); splfList.removePrintObjectListListener(this); } catch( ExtendedIllegalStateException e ) { System.out.println(" The list was closed before it completed!"); } catch( Exception e ) { // ...handle any other exceptions... e.printStackTrace(); } } // This is where the foreground thread waits to be awaken by the // the background thread when the list is updated or it ends. private synchronized void waitForWakeUp() throws InterruptedException
IBM Toolbox for Java
535
{ // don''t go back to sleep if the listener says the list is done if (!fListCompleted) { wait(); } } // The following methods implement the PrintObjectListListener interface // This method is invoked when the list is closed. public void listClosed(PrintObjectListEvent event) { System.out.println("*****The list was closed*****"); fListClosed = true; synchronized(this) { // Set flag to indicate that the list has // completed and wake up foreground thread. fListCompleted = true; notifyAll(); } } // This method is invoked when the list is completed. public void listCompleted(PrintObjectListEvent event) { System.out.println("*****The list has completed*****"); synchronized (this) { // Set flag to indicate that the list has // completed and wake up foreground thread. fListCompleted = true; notifyAll(); } } // This method is invoked if an error occurs while retrieving // the list. public void listErrorOccurred(PrintObjectListEvent event) { System.out.println("*****The list had an error*****"); fListError = true; listException = event.getException(); synchronized(this) { // Set flag to indicate that the list has // completed and wake up foreground thread. fListCompleted = true; notifyAll(); } } // This method is invoked when the list is opened. public void listOpened(PrintObjectListEvent event) { System.out.println("*****The list was opened*****"); listObjectCount = 0; } // This method is invoked when an object is added to the list. public void listObjectAdded(PrintObjectListEvent event) { // every 25 objects we'll wake up the foreground // thread to get the latest objects... if( (++listObjectCount % 25) == 0 ) {
536
System.out.println("*****25 more objects added to the list*****"); synchronized (this) { // wake up foreground thread notifyAll(); } } } public static void main( String args[] ) { NPExampleListSplfAsynch list = new NPExampleListSplfAsynch(new AS400()); try{ list.listSpooledFiles(); } catch( Exception e ) { e.printStackTrace(); } System.exit(0); } }
537
system_ = new AS400(); } System.out.println( "Now receiving all spooled files Asynchronously without using a listener"); SpooledFileList splfList = new SpooledFileList(system_); // set filters, all users, on all queues splfList.setUserFilter("*ALL"); splfList.setQueueFilter("/QSYS.LIB/%ALL%.LIB/%ALL%.OUTQ"); // open list, openAsynchronously() returns immediately // we have not added any listeners... splfList.openAsynchronously(); System.out.println(" Do some processing before waiting..."); // ... do some processing here while the list is being built.... System.out.println(" Now wait for list to complete."); // wait for the list to complete splfList.waitForListToComplete(); Enumeration enum = splfList.getObjects(); // output the name of all objects on the list while( enum.hasMoreElements() ) { SpooledFile splf = (SpooledFile)enum.nextElement(); if (splf != null) { // output this spooled file's name strSpooledFileName = splf.getStringAttribute(SpooledFile.ATTR_SPOOLFILE); System.out.println(" spooled file = " + strSpooledFileName); } } // clean up after we are done with the list splfList.close(); } catch( Exception e ) { // ...handle any exceptions... e.printStackTrace(); } } public static void main( String args[] ) { NPExampleListSplfAsynch2 list = new NPExampleListSplfAsynch2(new AS400()); try{ list.listSpooledFiles(); } catch( Exception e ) { e.printStackTrace(); } System.exit(0); } }
538
539
// clean up after we are done with the list splfList.close(); } catch( Exception e ) { // ...handle any exceptions... e.printStackTrace(); } } public static void main( String args[] ) { NPExampleListSplfSynch list = new NPExampleListSplfSynch(new AS400()); try{ list.listSpooledFiles(); } catch( Exception e ) { e.printStackTrace(); } System.exit(0); } }
public class PCSystemStatusExample extends Object { public static void main(String[] parameters) { System.out.println( " " );
// if a system was not specified, display help text and exit. if (parameters.length >= 1) { try { // Create an AS400 object for the server that contains the // program. Assume the first parameter is the system name.
540
// Create the path to the program. QSYSObjectPathName programName = new QSYSObjectPathName("QSYS", "QWCRSSTS", "PGM");
// Create the program call object. Assocate the object with the // AS400 object that represents the server we get status from. ProgramCall getSystemStatus = new ProgramCall(as400);
// Create the program parameter list. This program has five // parameters that will be added to this list. ProgramParameter[] parmlist = new ProgramParameter[5];
// The server program returns data in parameter 1. It is an output // parameter. Allocate 64 bytes for this parameter. parmlist[0] = new ProgramParameter( 64 );
// Parameter 2 is the buffer size of parm 1. It is a numeric input // parameter. Sets its value to 64, convert it to the server format, // then add the parm to the parm list. AS400Bin4 bin4 = new AS400Bin4( ); Integer iStatusLength = new Integer( 64 ); byte[] statusLength = bin4.toBytes( iStatusLength ); parmlist[1] = new ProgramParameter( statusLength );
// Parameter 3 is the status-format parameter. It is a string input // parameter. Set the string value, convert it to the server format, // then add the parameter to the parm list. AS400Text text1 = new AS400Text(8, as400); byte[] statusFormat = text1.toBytes("SSTS0200"); parmlist[2] = new ProgramParameter( statusFormat );
// Parameter 4 is the reset-statistics parameter. It is a string input // parameter. Set the string value, convert it to the server format, // then add the parameter to the parm list. AS400Text text3 = new AS400Text(10, as400); byte[] resetStats = text3.toBytes("*NO "); parmlist[3] = new ProgramParameter( resetStats );
// Parameter 5 is the error info parameter. // parameter. Add it to the parm list. byte[] errorInfo = new byte[32];
It is an input/output
541
// Set the program to call and the parameter list to the program // call object. getSystemStatus.setProgram(programName.getPath(), parmlist );
// // // //
Run the program then sleep. We run the program twice because the first set of results are inflated. If we discard the first set of results and run the command again five seconds later the number will be more accurate.
getSystemStatus.run(); Thread.sleep(5000);
// Run the program if (getSystemStatus.run()!=true) { // // // // If the program did not run get the list of error messages from the program object and display the messages. The error would be something like program-not-found or not-authorized to the program.
AS400Message[] msgList = getSystemStatus.getMessageList(); System.out.println("The program did not run. for (int i=0; i<msgList.length; i++) { System.out.println(msgList[i].getText()); } } // Else the program did run. else { // Create a server to Java numeric converter. This converter // will be used in the following section to convert the numeric // output from the server format to Java format. AS400Bin4 as400Int = new AS400Bin4( ); Server messages:");
// Get the results of the program. Output data is in // a byte array in the first parameter. byte[] as400Data = parmlist[0].getOutputData();
// CPU utilization is a numeric field starting at byte // 32 of the output buffer. Convert this number from the // server format to Java format and output the number. Integer cpuUtil = (Integer)as400Int.toObject( as400Data, 32 );
542
// DASD utilization is a numeric field starting at byte // 52 of the output buffer. Convert this number from the // server format to Java format and output the number. Integer dasdUtil = (Integer)as400Int.toObject( as400Data, 52 ); dasdUtil = new Integer(dasdUtil.intValue()/10000); System.out.print("Dasd Utilization: "); System.out.print(dasdUtil); System.out.println("%");
// Number of jobs is a numeric field starting at byte // 36 of the output buffer. Convert this number from the // server format to Java format and output the number. Integer nj = (Integer)as400Int.toObject( as400Data, 36 ); System.out.print("Active jobs: "); System.out.println(nj); } // This program is done running program so disconnect from // the command server on the server. Program call and command // call use the same server on the server. as400.disconnectService(AS400.COMMAND); } catch (Exception e) { // If any of the above operations failed say the program failed // and output the exception. System.out.println("Program call failed"); System.out.println(e); } } // Display help text when parameters are incorrect. else { System.out.println(""); System.out.println(""); System.out.println(""); System.out.println("Parameters are not correct. Command syntax is:"); System.out.println(""); System.out.println(" PCSystemStatusExample myServer"); System.out.println(""); System.out.println("Where"); System.out.println(""); System.out.println(" myServer = get status of this server "); System.out.println(""); System.out.println("For example:"); System.out.println(""); System.out.println(" PCSystemStatusExample mySystem"); System.out.println(""); System.out.println(""); }
543
System.exit(0); } }
import java.io.*; import java.util.*; import com.ibm.as400.access.*; public class RLSequentialAccessExample { public static void main(String[] parmeters) { // Created a reader to get input from the user BufferedReader inputStream = new BufferedReader(new InputStreamReader(System.in),1); // Declare variables to hold the system name, library, file and member names String systemName = ""; String library = ""; String file = ""; String member = ""; // Get the system name and and file to display from the user System.out.println(); try { System.out.print("System name: "); systemName = inputStream.readLine(); System.out.print("Library in which the file exists: "); library = inputStream.readLine(); System.out.print("File name: "); file = inputStream.readLine(); System.out.print("Member name (press enter for first member): "); member = inputStream.readLine(); if (member.equals("")) { member = "*FIRST"; } System.out.println(); } catch (Exception e) {
544
System.out.println("Error obtaining user input."); e.printStackTrace(); System.exit(0); } // Create AS400 object and connect for the record level access service. AS400 system = new AS400(systemName); try { system.connectService(AS400.RECORDACCESS); } catch(Exception e) { System.out.println("Unable to connect for record level access."); System.out.println("Check the readme file for special instructions regarding record level access"); e.printStackTrace(); System.exit(0); } // Create a QSYSObjectPathName object to obtain the integrated file system path name form // of the file to be displayed. QSYSObjectPathName filePathName = new QSYSObjectPathName(library, file, member, "MBR"); // Create a SequentialFile object representing the file to be displayed SequentialFile theFile = new SequentialFile(system, filePathName.getPath()); // Retrieve the record format for the file AS400FileRecordDescription recordDescription = new AS400FileRecordDescription(system, filePathName.getPath()); try { RecordFormat[] format = recordDescription.retrieveRecordFormat(); // Set the record format for the file theFile.setRecordFormat(format[0]); // Open the file for reading. Read 100 records at a time if possible. theFile.open(AS400File.READ_ONLY, 100, AS400File.COMMIT_LOCK_LEVEL_NONE); // Display each record in the file System.out.println("Displaying file " + library.toUpperCase() + "/" + file.toUpperCase() + "(" + theFile.getMemberName().trim() + "):"); Record record = theFile.readNext(); while (record != null) { System.out.println(record); record = theFile.readNext(); } System.out.println(); // Close the file theFile.close(); // Disconnect from the record level access service system.disconnectService(AS400.RECORDACCESS); } catch (Exception e) { System.out.println("Error occurred attempting to display the file."); e.printStackTrace(); try { // Close the file theFile.close();
IBM Toolbox for Java
545
} catch(Exception x) { } // Disconnect from the record level access service system.disconnectService(AS400.RECORDACCESS); System.exit(0); } // Make sure that the application ends; see readme for details System.exit(0); } }
public class RLReadFile extends Object { public static void main(String[] parameters) { String system = ""; // Continue only if a system name was specified. if (parameters.length >= 1) { try { // Assume the first parameter is the system name. system = parameters[0]; // Create an AS400 object for the server that has the file. AS400 as400 = new AS400(system); // Create a record description for the file. The file is QCUSTCDT
546
// in library QIWS. ZonedDecimalFieldDescription customerNumber = new ZonedDecimalFieldDescription(new AS400ZonedDecimal(6,0), "CUSNUM"); CharacterFieldDescription lastName = new CharacterFieldDescription(new AS400Text(8, as400), "LSTNAM"); CharacterFieldDescription initials = new CharacterFieldDescription(new AS400Text(3, as400), "INIT"); CharacterFieldDescription street = new CharacterFieldDescription(new AS400Text(13, as400), "STREET"); CharacterFieldDescription city = new CharacterFieldDescription(new AS400Text(6, as400), "CITY"); CharacterFieldDescription state = new CharacterFieldDescription(new AS400Text(2, as400), "STATE"); ZonedDecimalFieldDescription zipCode = new ZonedDecimalFieldDescription(new AS400ZonedDecimal(5,0), "ZIPCOD"); ZonedDecimalFieldDescription creditLimit = new ZonedDecimalFieldDescription(new AS400ZonedDecimal(4,0), "CDTLMT"); ZonedDecimalFieldDescription chargeCode = new ZonedDecimalFieldDescription(new AS400ZonedDecimal(1,0), "CHGCOD"); ZonedDecimalFieldDescription balanceDue = new ZonedDecimalFieldDescription(new AS400ZonedDecimal(6,2), "BALDUE"); ZonedDecimalFieldDescription creditDue = new ZonedDecimalFieldDescription(new AS400ZonedDecimal(6,2), "CDTDUE"); // The record format name must be specified for a DDM file. // In the case of the QCUSTCDT file, its record format is called CUSREC. RecordFormat qcustcdt = new RecordFormat("CUSREC"); qcustcdt.addFieldDescription(customerNumber); qcustcdt.addFieldDescription(lastName); qcustcdt.addFieldDescription(initials); qcustcdt.addFieldDescription(street); qcustcdt.addFieldDescription(city); qcustcdt.addFieldDescription(state); qcustcdt.addFieldDescription(zipCode); qcustcdt.addFieldDescription(creditLimit); qcustcdt.addFieldDescription(chargeCode); qcustcdt.addFieldDescription(balanceDue); qcustcdt.addFieldDescription(creditDue); // Create the sequential file object that represents the // file on the server. We use a QSYSObjectPathName object // to get the name of the file into the correct format. QSYSObjectPathName fileName = new QSYSObjectPathName("QIWS", "QCUSTCDT", "FILE"); SequentialFile file = new SequentialFile(as400, fileName.getPath()); // Let the file object know the format of the records.
IBM Toolbox for Java
547
file.setRecordFormat(qcustcdt); // // // // Open the file for read-only access. Specify a blocking factor of 10 (the file object will get 10 records when it accesses the server for data). Do not use commitment control.
file.open(SequentialFile.READ_ONLY, 10, SequentialFile.COMMIT_LOCK_LEVEL_NONE); // Read the first record of the file. Record data = file.readNext(); // Loop while there are records in the file (while we have not // reached end-of-file). while (data != null) { // // // // // // Display the record only if balance due is greater than zero. In that case display the customer name and the balance due. The following code pulls fields out of the record by field name. As the field is retrieved from the record it is converted from server format to Java format.
if (((BigDecimal)data.getField("BALDUE")).floatValue() > 0.0) { System.out.print((String) data.getField("INIT") + " "); System.out.print((String) data.getField("LSTNAM") + " "); System.out.println((BigDecimal) data.getField("BALDUE")); } // Read the next record in the file. data = file.readNext(); } // When there are no more records to read, disconnect from the server. as400.disconnectAllServices(); } catch (Exception e) { // If any of the above operations failed, print an error message // and output the exception. System.out.println("Could not read the file"); System.out.println(e); } } // Display help text when parameters are incorrect. else { System.out.println("");
548
System.out.println(""); System.out.println(""); System.out.println("Parameters are not correct. Command syntax is:"); System.out.println(""); System.out.println(" RLReadFile as400"); System.out.println(""); System.out.println("Where"); System.out.println(""); System.out.println(" as400 = system that contains the file"); System.out.println(""); System.out.println("For example:"); System.out.println(""); System.out.println(" RLReadFile mySystem"); System.out.println(""); System.out.println(""); System.out.println("Note, this program reads data base file QIWS/QCUSTCDT. System.out.println(""); System.out.println(""); } System.exit(0); } }
");
public class RLKeyedFileExample { public static void main(String[] parameters) { // Created a reader to get input from the user BufferedReader inputStream = new BufferedReader(new InputStreamReader(System.in),1); // Declare variables to hold the system name, library, file and member names
IBM Toolbox for Java
549
String systemName = ""; String library = ""; // Get the system name from the user System.out.println(); try { System.out.print("System name: "); systemName = inputStream.readLine(); System.out.print("Library in which to create file QCUSTCDTKY: "); library = inputStream.readLine(); } catch(Exception e) { System.out.println("Error obtaining user input."); e.printStackTrace(); System.exit(0); } // Create AS400 object and connect for the record level access service. AS400 system = new AS400(systemName); try { system.connectService(AS400.RECORDACCESS); } catch(Exception e) { System.out.println("Unable to connect for record level access."); System.out.println("Check the readme file for special instructions regarding record level access"); e.printStackTrace(); System.exit(0); } RecordFormat qcustcdtFormat = null; try { // Create the RecordFormat object for creating the file. The record format for the new // file will be the same as the record format for file QIWS/QCUSTCDT. However we will // make the CUSNUM field a key field. AS400FileRecordDescription recordDescription = new AS400FileRecordDescription(system, "/QSYS.LIB/QIWS.LIB/QCUSTCDT.FILE"); // There is only one record format for the file, so take the first (and only) element // of the RecordFormat array returned as the RecordFormat for the file. System.out.println("Retrieving record format of QIWS/QCUSTCDT..."); qcustcdtFormat = recordDescription.retrieveRecordFormat()[0]; // Indicate that CUSNUM is a key field qcustcdtFormat.addKeyFieldDescription("CUSNUM"); } catch(Exception e) { System.out.println("Unable to retrieve record format from QIWS/QCUSTCDT"); e.printStackTrace(); System.exit(0); } // Create the keyed file object that represents the // file we will create on the server. We use a QSYSObectPathName object // to get the name of the file into the correct format. QSYSObjectPathName fileName = new QSYSObjectPathName(library, "QCUSTCDTKY", "*FILE", "MBR"); KeyedFile file = new KeyedFile(system, fileName.getPath());
550
try { System.out.println("Creating file " + library + "/QCUSTCDTKY..."); // Create the file using the qcustcdtFormat object file.create(qcustcdtFormat, "Keyed QCUSTCDT file"); // Populate the file with the records contained in QIWS/QCUSTCDT copyRecords(system, library); // Open the file for read-only access. Because we will be randomly // accessing the file, specify a blocking factor of 1. The // commit lock level parameter will be ignored since commitment // control has not been started. file.open(AS400File.READ_ONLY, 1, AS400File.COMMIT_LOCK_LEVEL_NONE); // Assume that we want to display the information for customers // 192837, 392859 and 938472 // The CUSNUM field is a zoned decimal field of length 6 with // no decimal positions. Therefore, the key field value is // represented with a BigDecimal. BigDecimal[] keyValues = {new BigDecimal(192837), new BigDecimal(392859), new BigDecimal(938472)}; // Create the key for reading the records. // is specified with an Object[] Object[] key = new Object[1]; Record data = null; for (int i = 0; i < keyValues.length; i++) { // Setup the key for reading key[0] = keyValues[i]; // Read the record for customer number keyValues[i] data = file.read(key); if (data != null) { // Display the record only if balance due is greater than // zero. In that case display the customer name and // the balance due. The following code pulls fields out // of the record by field name. As the field is retrieved // from the record it is converted from the server format to // Java format. if (((BigDecimal)data.getField("BALDUE")).floatValue() > 0.0) { System.out.print((String) data.getField("INIT") + " "); System.out.print((String) data.getField("LSTNAM") + " "); System.out.println((BigDecimal) data.getField("BALDUE")); } } } // All done with the file file.close(); // Get rid of the file from the user's system file.delete(); } catch(Exception e) { System.out.println("Unable to create/read from QTEMP/QCUSTCDT"); e.printStackTrace(); try {
IBM Toolbox for Java
551
file.close(); // Get rid of the file from the user's system file.delete(); } catch(Exception x) { } } // All done with record level access; disconnect from the // record-level access server. system.disconnectService(AS400.RECORDACCESS); System.exit(0); } public static void copyRecords(AS400 system, String library) { // Use the CommandCall class to run the CPYF command to copy the records // in QIWS/QCUSTCDT to QTEMP/QCUSTCDT CommandCall c = new CommandCall(system, "CPYF FROMFILE(QIWS/QCUSTCDT) TOFILE(" + library + "/QCUSTCDTKY) MBROPT(*REPLACE)"); try { System.out.println("Copying records from QIWS/QCUSTCDT to " + library + "/QCUSTCDTKY..."); c.run(); AS400Message[] msgs = c.getMessageList(); if (!msgs[0].getID().equals("CPC2955")) { System.out.println("Unable to populate " + library + "/QCUSTCDTKY"); for (int i = 0; i < msgs.length; i++) { System.out.println(msgs[i]); } System.exit(0); } } catch(Exception e) { System.out.println("Unable to populate " + library + "/QCUSTCDTKY"); System.exit(0); } } }
552
public class UserListExample { public { // // if { } try { // Create an AS400 object. The system name was passed // as the first command line argument. AS400 system = new AS400 (args[0]); // The group name was passed as the second command line // argument. String groupName = args[1]; // Create the user list object. UserList userList = new UserList (system); // Get a list of the users in the given group. userList.setUserInfo (UserList.MEMBER); userList.setGroupInfo (groupName); Enumeration enum = userList.getUsers (); // Iterate through the list and print out the // users' names and descriptions. while (enum.hasMoreElements ()) { User u = (User) enum.nextElement (); System.out.println ("User name: " + u.getName ()); System.out.println ("Description: " + u.getDescription ()); System.out.println (""); } } catch (Exception e) { System.out.println ("Error: " + e.getMessage ()); } System.exit (0); } } static void main (String[] args) If a system and group were not specified, then display help text and exit. (args.length != 2) System.out.println("Usage: return; UserListExample system group");
Examples: JavaBeans
This section lists the code examples that are provided throughout the IBM Toolbox for Java bean information. The following disclaimer applies to all of the IBM Toolbox for Java examples: Code example disclaimer IBM grants you a nonexclusive copyright license to use all programming code examples from which you can generate similar function tailored to your own specific needs.
IBM Toolbox for Java
553
All sample code is provided by IBM for illustrative purposes only. These examples have not been thoroughly tested under all conditions. IBM, therefore, cannot guarantee or imply reliability, serviceability, or function of these programs. All programs contained herein are provided to you "AS IS" without any warranties of any kind. The implied warranties of non-infringement, merchantability and fitness for a particular purpose are expressly disclaimed.
class BeanExample { AS400 as400_ = new AS400(); CommandCall cmd_ = new CommandCall( as400_ ); BeanExample() { // Whenever the system is connected or disconnected print a // comment. Do this by adding a listener to the AS400 object. // When a system is connected or disconnected, the AS400 object // will call this code. as400_.addConnectionListener (new ConnectionListener() { public void connected(ConnectionEvent event) { System.out.println( "System connected." ); } public void disconnected(ConnectionEvent event) { System.out.println( "System disconnected." ); } } ); // Whenever a command runs to completion print a comment. Do this // by adding a listener to the commandCall object. The commandCall // object will call this code when it runs a command. cmd_.addActionCompletedListener( new ActionCompletedListener() {
554
public void actionCompleted(ActionCompletedEvent event) { System.out.println( "Command completed." ); } } ); } void runCommand() { try { // Run a command. The listeners will print comments when the // system is connected and when the command has run to // completion. cmd_.run( "TESTCMD PARMS" ); } catch (Exception ex) { System.out.println( ex ); } } public static void main(String[] parameters) { BeanExample be = new BeanExample(); be.runCommand(); System.exit(0); } }
555
v Edit the bean properties. (To edit, select the bean and then right-click to display a window, which has Properties as an option.) Change the label of the Button to Run command, as shown in Figure 2. Figure 2: Changing the label of the button to Run command
Change the system name of the AS400 bean to TestSys Change the user ID of the AS400 bean to TestUser, as shown in Figure 3. Figure 3: Changing the name of the user ID to TestUser
556
Change the command of the CommandCall bean to SNDMSG MSG('Testing') TOUSR('TESTUSER'), as shown in Figure 4. Figure 4: Changing the command of the CommandCall bean
v Connect the AS400 bean to the CommandCall bean. The method you use to do this varies between bean builders. For this example, do the following: Select the CommandCall bean and then click the right mouse button
IBM Toolbox for Java
557
Connect Connectable Features system from the list of features as shown in Figure 5. the AS400 bean this from the pop-up menu that appears over the AS400 bean
v Connect the button to the CommandCall bean. Select the Button bean and then click the right mouse button Select Connect Select actionPerformed Select the CommandCall bean Select Connectable Features from the pop-up menu that appears Select run() from the list of methods as shown in Figure 6. Figure 6: Connecting a method to a button
558
When you are finished, the VisualAge Visual Composition Editor window might look like Figure 7. Figure 7: VisualAge Visual Composition Editor window - Finished bean example
559
560
Size a panel using the dynamic panel manager: How the dynamic panel manager dynamically sizes the panel at runtime v Editable combobox: Coding a data bean for an editable combobox The following examples show you how the GUI Builder can help you to create a variety of GUI elements: v Panels: Creating a sample panel and the data bean code that runs the panel v Deckpanes: Creating a deckpane and what a final deckpane may look like v v v v v Property sheets: Creating a property sheet and what a final property sheet may look like Split panes: Creating a split pane and what a final split pane may look like Tabbed panes: Creating a tabbed pane and what a final tabbed pane may look like Wizards: Creating a wizard and what the final product may look like Toolbars: Creating a tool bar and what a final tool bar may look like
v Menu bars: Creating a menu bar and what a final menu bar may look like v Help: Generating a Help Document and split the Help Document into topic pages. Also, see Editing Help Documents generated by GUI builder v Sample: Shows what a whole PDML program may look like, including panels, a property sheet, a wizard, select/deselect, and menu options. The following disclaimer applies to all of the IBM Toolbox for Java examples: Code example disclaimer IBM grants you a nonexclusive copyright license to use all programming code examples from which you can generate similar function tailored to your own specific needs. All sample code is provided by IBM for illustrative purposes only. These examples have not been thoroughly tested under all conditions. IBM, therefore, cannot guarantee or imply reliability, serviceability, or function of these programs. All programs contained herein are provided to you "AS IS" without any warranties of any kind. The implied warranties of non-infringement, merchantability and fitness for a particular purpose are expressly disclaimed.
561
By selecting the label, you can change its text in the Properties window. In this example, the same has been done for the pushbutton, changing its text to "Close". Figure 2: GUI Builder windows: Changing text in the Properties window
Text field The text field will contain data and, therefore, you can set several properties that will allow the GUI Builder to perform some additional work. For this example, you set the Data Class property to the name of a bean class named SampleBean. This databean will supply the data for this text field. Figure 3: GUI Builder windows: Setting the Data Class property
562
Set the Attribute property to the name of the bean property that will contain the data. In this case, the name is UserData. Figure 4: GUI Builder windows: Setting the Attribute property
Following the above steps binds the UserData property to this text field. At run-time, the Graphical Toolbox obtains the initial value for this field by calling SampleBean.getUserData. The modified value is then sent back to the application when the panel closes by calling SampleBean.setUserData.
563
Specify that the user is required to supply some data, and that the data must be a string with a maximum length of 15 characters. Figure 5: GUI Builder windows: Setting the maximum length of the text field
Indicate that the context-sensitive help for the text field will be the help topic associated with the label "Enter some data". Figure 6: GUI Builder windows: Setting context-sensitive help for the text field
Button Modify the style property to give the button default emphasis. Figure 7: GUI Builder windows: Setting the Style property to give the button default emphasis
564
Set the ACTION property to COMMIT, which causes the setUserData method on the bean to be called when the button is selected. Figure 8: GUI Builder windows: Setting the Action property to COMMIT
Before you save the panel, set properties at the level of the PDML file to generate both the online help skeleton and the Java bean. Then you save the file by clicking on the window. When prompted, specify a file name of MyGUI.pdml. icon in the GUI Builder
Figure 9: GUI Builder windows: Setting properties to generate the online help skeleton and the Java bean
565
Generated files
After you save the panel definition, you can look at the files produced by the GUI Builder. PDML file Here is the content of MyGUI.pdml to give you an idea of how the Panel Definition Markup Language works. Because you use PDML only through the tools provided by the Graphical Toolbox, it is not necessary to understand the format of this file in detail:
<!-- Generated by GUI Builder --> <PDML version="2.0" source="JAVA" basescreensize="1280x1024"> <PANEL name="PANEL1"> <TITLE>PANEL1<TITLE> <SIZE>351,162<</SIZE> <LABEL name="LABEL1""> <TITLE>PANEL1.LABEL1</TITLE> <LOCATION>18,36</LOCATION> <SIZE>94,18</SIZE> <HELPLINK>PANEL1.LABEL1</HELPLINK> </LABEL> <TEXTFIELD name="TEXTFIELD1"> <TITLE>PANEL1.TEXTFIELD1</TITLE> <LOCATION>125,31</LOCATION> <SIZE>191,26</SIZE> <DATACLASS>SampleBean</DATACLASS> <ATTRIBUTE>UserData</ATTRIBUTE> <STRING minlength="0" maxlength="15"/> <HELPALIAS>LABEL1</HELPALIAS> </TEXTFIELD> <BUTTON name="BUTTON1"> <TITLE>PANEL1.BUTTON1</TITLE> <LOCATION>125,100</LOCATION> <SIZE>100,26</SIZE> <STYLE>DEFAULT<</STYLE> <ACTION>COMMIT</ACTION> <HELPLINK>PANEL1.BUTTON1</HELPLINK> </BUTTON> </PANEL> </PDML>
Resource bundle Associated with every PDML file is a resource bundle. In this example, the translatable resources were saved in a PROPERTIES file, which is called MyGUI.properties. Notice that the PROPERTIES file also contains customization data for the GUI Builder.
##Generated by GUI Builder BUTTON_1=Close TEXT_1= @GenerateHelp=1 @Serialize=0 @GenerateBeans=1 LABEL_1=Enter some data: PANEL_1.Margins=18,18,18,18,18,18 PANEL_1=Simple Example
JavaBean The example also generated a Java source code skeleton for the JavaBean object. Here is the content of SampleBean.java:
import com.ibm.as400.ui.framework.java.*; public class SampleBean extends Object implements DataBean {
566
private String m_sUserData; public String getUserData() { return m_sUserData; } public void setUserData(String s) { m_sUserData = s; } public Capabilities getCapabilities() { return null; } public void verifyChanges() { } public void save() { } public void load() { m_sUserData =""; } }
Note that the skeleton already contains an implementation of the gettor and settor methods for the UserData property. The other methods are defined by the DataBean interface and, therefore, are required. The GUI Builder has already invoked the Java compiler for the skeleton and produced the corresponding class file. For the purposes of this simple example, you do not need to modify the bean implementation. In a real Java application you would typically modify the load and save methods to transfer data from an external data source. The default implementation of the other two methods is often sufficient. For more information, see the documentation on the DataBean interface in the Javadocs for the PDML runtime framework. Help file The GUI Builder also creates an HTML framework called a Help Document. Help writers can easily manage help information by editing this file. For more information, see the following topics: v Creating the Help Document v Editing Help Documents generated by GUI builder
567
// Initialize the object bean.load(); // Set up to pass the bean to the panel manager DataBean[] beans = { bean }; // // // // // Create the panel manager. Parameters: 1. PDML file as a resource name 2. Name of panel to display 3. List of data objects that supply panel data 4. An AWT Frame to make the panel modal
PanelManager pm = null; try { pm = new PanelManager("MyGUI", "PANEL_1", beans, new Frame()); } catch (DisplayManagerException e) { // Something didn't work, so display a message and exit e.displayUserMessage(null); System.exit(1); } // Display the panel - we give up control here pm.setVisible(true); // Echo the saved user data System.out.println("SAVED USER DATA: '" + bean.getUserData() + "'"); // Exit the application System.exit(0); } }
It is the responsibility of the calling program to initialize the bean object or objects by calling load. If the data for a panel is supplied by multiple bean objects, then each of the objects must be initialized before passing them to the Graphical Toolbox environment. The class com.ibm.as400.ui.framework.java.PanelManager supplies the API for displaying standalone windows and dialogs. The name of the PDML file as supplied on the constructor is treated as a resource name by the Graphical Toolbox - the directory, ZIP file, or JAR file containing the PDML must be identified in the classpath. Because a Frame object is supplied on the constructor, the window will behave as a modal dialog. In a real Java application, this object might be obtained from a suitable parent window for the dialog. Because the window is modal, control does not return to the application until the user closes the window. At that point, the application simply echoes the modified user data and exits.
568
If the user presses F1 while focus is on the text field, the Graphical Toolbox will display a help browser containing the online help skeleton that the GUI Builder generated. Figure 11: The Simple Example online help skeleton
You can edit the HTML and add actual help content for the help topics shown. If the data in the text field is not valid (for example, if the user clicked on the Close button without supplying a value), the Graphical Toolbox will display an error message and return focus to the field so that data can be entered.
569
For information about how to run this sample as an applet, see Using the Graphical Toolbox in a Browser. Related information Package com.ibm.as400.ui.framework.java summary
Editable Comboboxes
When the bean generator creates a gettor and settor for an Editable ComboBox, by default it returns a String on the settor and takes a string parameter on the gettor. It can be useful to change the settor to take an Object class and the gettor to return an Object type. This allows you to determine the user selection using ChoiceDescriptors. If a type of Object is detected for the gettor and settor, the system will expect either a ChoiceDescriptor or a type Object instead of a formatted string. The following example assumes that Editable is an editable ComboBox that has either a Double value, uses a system value, or is not set.
public Object getEditable() { if (m_setting == SYSTEMVALUE) { return new ChoiceDescriptor("choice1","System Value"); } else if (m_setting == NOTSET) { return new ChoiceDescriptor("choice2","Value not set"); } else { return m_doubleValue; } }
Similarly, when a type of Object is detected for the gettor and settor, the system will return an Object which is either a ChoiceDescriptor containing the selected choice or a type Object.
public void setEditable(Object item) { if (ChoiceDescriptor.class.isAssignableForm(obj.getClass())) { if (((ChoiceDescriptor)obj).getName().equalsIgnoreCase("choice1")) m_setting = SYSTEMVALUE; else m_setting = NOTSET;
570
public class RecordListFormPaneExample { public { // // if { } try { // Create an AS400 object. The system name was passed // as the first command line argument. AS400 system = new AS400 (args[0]); // Create a frame. JFrame f = new JFrame ("RecordListFormPane example"); // Create an error dialog adapter. This will display // any errors to the user. ErrorDialogAdapter errorHandler = new ErrorDialogAdapter (f); // // // // // // // Create a record list form pane to present the contents of the database. Note we create the form pane, add the error listener, then set the system and file name. Creating the form pane and setting its parameters can be done in one step as follows: RecordListFormPane formPane = new RecordListFormPane (system, args[1]); The potential problem is there is no error listener yet
IBM Toolbox for Java
static void main (String[] args) If a system and fileName was not specified, then display help text and exit. (args.length != 2) System.out.println("Usage: return; RecordListFormPaneExample system fileName");
571
// so if the file name is not correct, there is no place // to display the error. RecordListFormPane formPane = new RecordListFormPane(); formPane.addErrorListener (errorHandler); formPane.setSystem(system); formPane.setFileName(args[1]); // Retrieve the information from the system. formPane.load (); // When the frame closes, exit. f.addWindowListener (new WindowAdapter () { public void windowClosing (WindowEvent event) { System.exit (0); } }); // Layout the frame with the form pane. f.getContentPane ().setLayout (new BorderLayout ()); f.getContentPane ().add ("Center", formPane); f.pack (); f.show (); } catch (Exception e) { System.out.println ("Error: " + e.getMessage ()); System.exit (0); } } }
to display a From the menu bar on the GUI Builder File window, click the Insert New Panel icon panel builder where you can insert the components for your panel. The toolbar buttons on the Panel window represent various components that you can add to the panel. Select the component you want and then click on the place you want to position it. The following picture shows a panel that has been created with several of the options available to you.
572
The sample panel in Figure 1 uses the following DataBean code to bring together the various components:
import com.ibm.as400.ui.framework.java.*; public class PanelSampleDataBean extends Object implements DataBean { private String m_sName; private Object m_oFavoriteFood; private ChoiceDescriptor[] m_cdFavoriteFood; private Object m_oAge; private String m_sFavoriteMusic; public String getName() { return m_sName; } public void setName(String s) { m_sName = s; } public Object getFavoriteFood() { return m_oFavoriteFood; } public void setFavoriteFood(Object o) { m_oFavoriteFood = o; } public ChoiceDescriptor[] getFavoriteFoodChoices() { return m_cdFavoriteFood; } public Object getAge() {
IBM Toolbox for Java
573
return m_oAge; } public void setAge(Object o) { m_oAge = o; } public String getFavoriteMusic() { return m_sFavoriteMusic; } public void setFavoriteMusic(String s) { m_sFavoriteMusic = s; } public Capabilities getCapabilities() { return null; } public void verifyChanges() { } public void save() { System.out.println("Name = " + m_sName); System.out.println("Favorite Food = " + m_oFavoriteFood); System.out.println("Age = " + m_oAge); String sMusic = ""; if (m_sFavoriteMusic != null) { if (m_sFavoriteMusic.equals("RADIOBUTTON1")) sMusic = "Rock"; else if (m_sFavoriteMusic.equals("RADIOBUTTON2")) sMusic = "Jazz"; else if (m_sFavoriteMusic.equals("RADIOBUTTON3")) sMusic = "Country"; } System.out.println("Favorite Music = " + sMusic); } public void load() { m_sName = "Sample Name"; m_oFavoriteFood = null; m_cdFavoriteFood = new ChoiceDescriptor[0]; m_oAge = new Integer(50); m_sFavoriteMusic = "RADIOBUTTON1"; } }
The panel is the most simple component available within the GUI Builder, but from a simple panel you can build great UI applications.
574
From the menu bar on the GUI Builder File window, click the Insert Deck Pane tool button to display a panel builder where you can insert the components for your deck pane. In the following example, three components are added. Figure 1: Creating a Deck Pane with GUI Builder
After you create the deck pane, click the Preview tool button until you select the View menu. Figure 2: Previewing the Deck Pane with GUI Builder
575
From the Deck Pane View menu, select the component you want to view. For this example, you can choose to view the PanelSample, TABBEDPANE1, or the TablePanel. The following figures illustrate what you see when you view these components. Figure 3: Viewing the PanelSample with GUI Builder
576
From the menu bar on the GUI Builder File window, click the Insert Property Sheet icon a panel builder where you can insert the components for your property sheet. Figure 1: Creating a Property Sheet with GUI Builder
to display
After you create the property sheet, use the from three tabs.
577
to From the menu bar on the GUI Builder File window, click the Insert Split Pane tool button display a panel builder where you can insert the components you want in your split pane. In the following example, two components are added. Figure 1: Creating a Split Pane with GUI Builder
After you create the split pane, click the Preview tool button 2. Figure 2: Previewing the Split Pane with GUI Builder
578
to display a From the menu bar on the GUI Builder File window, click the Insert Tabbed Pane icon panel builder where you can insert the components for your tabbed pane. In the following example, two components are added. Figure 1: Creating a Tabbed Pane in GUI Builder
After you create the tabbed pane, click the Preview tool button Figure 2: Previewing the Tabbed Pane with GUI Builder
to preview it.
579
to display a panel builder where you can add panels to the wizard. Figure 1: Creating a Wizard with GUI Builder
After you have create the wizard, use the Preview tool button
to preview it. Figure 2 shows the panel that first displays for this example.
580
Figure 2 shows the second panel that displays when the user selects Rock and clicks Next. Figure 3: Previewing the second wizard panel with GUI Builder
Clicking Next on the second wizard panel displays the final wizard panel, as shown in Figure 4. Figure 4: Previewing the final wizard panel with GUI Builder
581
After you create the toolbar, click the Preview tool button use the toolbar to display either a property sheet or wizard. Figure 2: Previewing the Tool Bar with GUI Builder
582
After you create the menu, use the Preview tool button to preview it. For this example, from the newly created Launch menu you can select either Property Sheet or Wizard. The following figures illustrate what you see when you select these menu items. Figure 2: GUI Builder: Viewing Property Sheet on the Launch menu
583
584
The GUI Builder creates an HTML framework called a Help Document, which you can edit. In order to be used at runtime, the topics within the PDML file need to be separated into individual HTML files. When you run Help Document to HTML Processing, the topics are broken into individual files and put into a subdirectory named after the Help Document and PDML file. The runtime environment expects the individual HTML files to be in a subdirectory with the same name as the Help Document and PDML file. The Help Document to HTML Processing dialog gathers the information needed and calls the HelpDocSplitter program to do the processing: Figure 2: Help Document to HTML Processing dialog
The Help Document to HTML Processing is started from a command prompt by typing:
jre com.ibm.as400.ui.tools.hdoc2htmViewer
585
Running this command requires that your classpath be set up correctly. To use the Help Document to HTML Processing, you first select the Help Document that has the same name as the PDML file. Next, you specify a subdirectory with the same name as the Help Document and PDML file for output. Select "Process" to complete the processing. You can split up the help document from the command line with the following command:
jre com.ibm.as400.ui.tools.HelpDocSplitter "helpdocument.htm" [output directory]
This command runs the processing that breaks up the file. You provide the name of the Help Document as input along with an optional output directory. By default, a subdirectory of the same name as the Help Document is created and the resulting files are put in that directory. This is an example of what a help file may look like: Figure 3: GUI Builder help file example
586
When you use the dynamic panel manager, while the size of the panel and the panel controls changes, the size of the text does not. The panel allows you to perform the following actions: v Launch a property sheet v Launch a wizard v Display the samples listed in the left pane Launching the property sheet You can launch the property sheet by clicking the Property Sheet toolbar button or by using the Launch menu. Being able to choose between the toolbar and the menu illustrates linking menu items. Figure 4 shows Property Sheet being selected from Launch menu on the GUI Builder example main window. Figure 4: Selecting Property Sheet from the Launch menu
Selecting Property Sheet displays the panel in Figure 5. Figure 5: Property Sheet Sample dialog
587
When the Property Sheet Sample first appears, Tab 1 displays by default. Launching the wizard You can launch the wizard by clicking the Wizard toolbar button or by using the Launch menu. Being able to choose between the toolbar and the menu illustrates linking menu items. Figure 9 shows how the first wizard dialog gives you many options. Figure 9: Selecting Rock in the first wizard dialog
In the first wizard dialog, select Rock and click Next to display the second wizard dialog as shown in Figure 10. Figure 10: The second wizard dialog (after selecting Rock)
588
On the second wizard dialog, click Next to display the final wizard dialog as shown in Figure 11. Figure 11: The final wizard dialog
However, this example has been programmed to have a loop. Select Country in the first wizard dialog (Figure 12), then click Next to display the second wizard dialog (Figure 13). Clicking Next in the second wizard dialog loops back to display the first dialog again (Figure 14) instead of the final wizard dialog. Figure 12: Selecting Country in the first wizard dialog
589
In other words, the programmer has determined that nobody can select country as their favorite form of music. Displaying the samples From the GUI Builder example main window, you can also select other functions from the left pane below the toolbar. Figure 15 shows how selecting Panel in the left pane displays the Panel sample in the right pane. Figure 15: Selecting Panel in the left pane
590
The Panel sample has been programmed with an option to disable the image. Select Disable Image to display the same screen with the image shaded, as shown in Figure 16. Figure 16: Selecting Disable Image in the right pane
The Panel sample also illustrates the drop-down list box option, as shown in Figure 17. Figure 17: Selecting an item from the Favorite Food list in the right pane
Figure 18 shows how selecting Tabbed Pane in the left pane of the GUI Builder example main window displays the Tabbed Pane sample in the right pane. Figure 18: Selecting Tabbed Pane in the left pane
591
Figure 19 shows the results of selecting the Panel Sample tab in the right pane. Figure 19: Selecting the Panel Sample tab in the right pane
Select Tab 1 again (in the right pane), then click Disable Age Field on Tab 2 to deselect it. Figure 20: Selecting Disable Age Field on Tab 2 in the right pane
592
Selecting the Disable Age Field on Tab 2 option deactivates and grays out the Age field in the Panel Sample tab, as shown in Figure 21. Figure 21: Result of disabling age in the Panel Sample tab
Selecting Table Pane in the left pane of the GUI Builder example main window illustrates the use of a table panel with a custom renderer and a custom cell editor, as shown in Figure 22. Figure 22: Selecting Table Panel in the left pane
593
Example: Creating a TextFormInput object Example: Creating a PasswordFormInput object Example: Creating a RadioFormInput object Example: Creating a CheckboxFormInput object v Example Creating HTMLHeading objects v Example: Using the HTMLHyperlink class v Example: Using the HTMLImage class v HTMLList examples Example: Creating ordered lists Example: Creating unordered lists Example: Creating nested lists v Example: Creating HTMLMeta tags v Example: Creating HTMLParameter tags v Example: Creating HTMLServlet tags
594
v Example: Using the HTMLText class v HTMLTree examples Example: Using the HTMLTree class Example: Creating a traversable integrated file system tree v Layout form classes: Example: Using the GridLayoutFormPanel class Example: Using the LineLayoutFormPanel class Example: Using the TextAreaFormElement class Example: Using the LabelFormOutput class Example: Using the SelectFormElement class Example: Using the SelectOption class Example: Using the RadioFormInputGroup class
v v v v v
v Example: Using the RadioFormInput class v Example: Using the HTMLTable classes Example: Using the HTMLTableCell class Example: Using the HTMLTableRow class Example: Using the HTMLTableHeader class Example: Using the HTMLTableCaption class You can also use the HTML and servlet classes together, like in this example. The following disclaimer applies to all of the IBM Toolbox for Java examples: Code example disclaimer IBM grants you a nonexclusive copyright license to use all programming code examples from which you can generate similar function tailored to your own specific needs. All sample code is provided by IBM for illustrative purposes only. These examples have not been thoroughly tested under all conditions. IBM, therefore, cannot guarantee or imply reliability, serviceability, or function of these programs. All programs contained herein are provided to you "AS IS" without any warranties of any kind. The implied warranties of non-infringement, merchantability and fitness for a particular purpose are expressly disclaimed.
595
import java.awt.Color; import javax.servlet.*; import javax.servlet.http.*; import com.ibm.as400.access.*; import com.ibm.as400.util.html.*; public class HTMLExample extends HttpServlet { // Determines if user already exists in the list of registrants. private static boolean found = false; // Registration information will be stored here String regPath = "c:\\registration.txt"; public void init(ServletConfig config) { try { super.init(config); } catch(Exception e) { e.printStackTrace(); } } /** * Process the GET request. * @param req The request. * @param res The response. **/ public void doGet (HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { res.setContentType("text/html"); ServletOutputStream out = res.getOutputStream(); // Display the Web using the new HTML classes out.println(showHTML()); out.close(); } public void doPost (HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { String nameStr = req.getParameter("name"); String emailStr = req.getParameter("email"); String errorText = ""; // Output stream to write to the servlet ServletOutputStream out = res.getOutputStream(); res.setContentType("text/html"); // Check name & e-mail parameters for valid values if (nameStr.length() == 0) errorText += "Customer Name not entered. "; if (emailStr.length() == 0) errorText += "E-mail not entered. " ;
596
// If name & e-mail have both been provided, continue. if (errorText.length() == 0) { try { //Create the registration.txt file FileWriter f = new FileWriter(regPath, true); BufferedWriter output = new BufferedWriter(f); //buffered reader for searching the file BufferedReader in = new BufferedReader(new FileReader(regPath)); String line = in.readLine(); // reset the found flag found = false; // Check to see if this customer has already registered // or has already used the same e-mail address while (!found) { // if file is empty or end of file reached. if (line == null) break; // if customer already registered if ((line.equals("Customer Name: " + nameStr)) || (line.equals("Email address: " + emailStr))) { // Output a message to the customer saying they have // already registered out.println ("<HTML> " + "<TITLE> Toolbox Registration</TITLE> " + "<META HTTP-EQUIV=\"pragma\" content=\"no-cache\"> " + "<BODY BGCOLOR=\"blanchedalmond\" TEXT=\"black\"> " ); out.println ("<P><HR>" + "<P>" + nameStr + "</B>, you have already registered using that " + "<B>Name</B> or <B>E-mail address</B>." + "<P> Thank You!...<P><HR>"); // Create a HTMLHyperlink object and display it out.println ("<UL><LI>" + new HTMLHyperlink("./customer.HTMLExample", "Back to Registration Form") + "</UL></BODY></HTML>"); found = true; break; } else // read the next line line = in.readLine(); } // String object to hold data submitted from the HTML Form String data; // If the users name or e-mail aren't found in our // text file, continue. if (!found) { //-----------------------------------------------------------// Insert the new customer info into a file output.newLine();
IBM Toolbox for Java
597
output.write("Customer Name: " + nameStr); output.newLine(); output.write("Email address: " + emailStr); output.newLine(); //-----------------------------------------------------------//-----------------------------------------------------------//Getting "USE" checkbox from form data = req.getParameter("use"); if(data != null) { output.write("Currently Using Toolbox: " + data); output.newLine(); } //-----------------------------------------------------------//-----------------------------------------------------------//Getting "More Information" checkbox from form data = req.getParameter("contact"); if (data != null) { output.write("Requested More Information: " + data); output.newLine(); } //-----------------------------------------------------------//-----------------------------------------------------------//Getting "AS400 Version" from form data = req.getParameter("version"); if (data != null) { if (data.equals("multiple versions")) { data = req.getParameter("MultiList"); output.write("Multiple Versions: " + data); } else output.write("AS400 Version: " + data); output.newLine(); } //-----------------------------------------------------------//-----------------------------------------------------------//Getting "Current Projects" from form data = req.getParameter("interest"); if (data != null) { output.write("Using Java or Interested In: " + data); output.newLine(); } //-----------------------------------------------------------//-----------------------------------------------------------//Getting "Platforms" from form data = req.getParameter("platform"); if (data != null) { output.write("Platforms: " + data); output.newLine(); if (data.indexOf("Other") >= 0) {
598
output.write("Other Platforms: " + req.getParameter("OtherPlatforms")); output.newLine(); } } //-----------------------------------------------------------//-----------------------------------------------------------//Getting "Number of IBM i servers" from form data = req.getParameter("list1"); if (data != null) { output.write("Number of IBM i servers: " + data); output.newLine(); } //-----------------------------------------------------------//-----------------------------------------------------------//Getting "Comments" from form data = req.getParameter("comments"); if (data != null && data.length() > 0) { output.write("Comments: " + data); output.newLine(); } //-----------------------------------------------------------//-----------------------------------------------------------//Getting "Attachment" data = req.getParameter("myAttachment"); if (data != null && data.length() > 0) { output.write("Attachment File: " + data); output.newLine(); } //-----------------------------------------------------------//-----------------------------------------------------------//Getting Hidden "Copyright" infomation data = req.getParameter("copyright"); if (data != null) { output.write(data); output.newLine(); } //-----------------------------------------------------------output.flush(); output.close(); // Print a thanks to the customer out.println("<HTML>"); out.println("<TITLE>Thank You!</TITLE>"); out.println("<META HTTP-EQUIV=\"pragma\" content=\"no-cache\"> "); out.println("<BODY BGCOLOR=\"blanchedalmond\">"); out.println("<HR><P>Thank You for Registering, <B>" + nameStr + "</B>!<P><HR>"); // Create a HTMLHyperlink object and display it out.println("<UL><LI>" + new HTMLHyperlink("./customer.HTMLExample", "Back to Registration Form")); out.println("</UL></BODY></HTML>"); }
IBM Toolbox for Java
599
} catch (Exception e) { // Show error in browser out.println("<HTML>"); out.println("<TITLE>ERROR!</TITLE>"); out.println("<META HTTP-EQUIV=\"pragma\" content=\"no-cache\"> "); out.println("<BODY BGCOLOR=\"blanchedalmond\">"); out.println("<BR><B>Error Message:</B><P>"); out.println(e + "<P>"); // Create a HTMLHyperlink object and display it out.println("<UL><LI>" + new HTMLHyperlink("./customer.HTMLExample", "Back to Registration Form")); out.println("</UL></BODY></HTML>"); e.printStackTrace(); } } else { // Output a message to the customer saying customer name & // e-mail not entered. Please try again out.println ("<HTML> " + "<TITLE>Invalid Registration Form</TITLE> " + "<META HTTP-EQUIV=\"pragma\" content=\"no-cache\"> " + "<BODY BGCOLOR=\"blanchedalmond\" TEXT=\"black\"> " ); out.println ("<HR><B>ERROR</B> in customer data - <P><B>" + errorText + "</B><P>Please Try Again... <HR>"); // Create a HTMLHyperlink object and display it out.println("<UL><LI>" + new HTMLHyperlink("./customer.HTMLExample", "Back to Registration Form") + "</UL></BODY></HTML>"); } // Close the writer out.close(); } public void destroy(ServletConfig config) { // do nothing } public String getServletInfo() { return "My Product Registration"; } private String showHTML() { // String Buffer to hold HTML Page StringBuffer page = new StringBuffer(); // Create the HTML Form object HTMLForm form = new HTMLForm("/servlet/customer.HTMLExample");; HTMLText txt; // Build the beginning of the HTML Page and add it to the String Buffer
600
page.append("<HTML>\n"); page.append("<TITLE> Welcome!!</TITLE>\n"); page.append("<HEAD><SCRIPT LANGUAGE=\"JavaScript\"> function test(){alert(\"This is a sample script executed with a ButtonFormInput.\")}</SCRIPT></HEAD>"); page.append("<META HTTP-EQUIV=\"pragma\" content=\"no-cache\">\n"); page.append("<BODY BGCOLOR=\"blanchedalmond\" TEXT=\"black\"><BR>\n"); try { //-------------------------------------------------------------------// Create page title using HTML Text txt = new HTMLText("Product Registration"); txt.setSize(5); txt.setBold(true); txt.setColor(new Color(199, 21, 133)); txt.setAlignment(HTMLConstants.CENTER); // Add HTML Text to the String Buffer page.append(txt.getTag(true) + "<HR><BR>\n"); //-------------------------------------------------------------------//-------------------------------------------------------------------// Create a Line Layout LineLayoutFormPanel line = new LineLayoutFormPanel(); txt = new HTMLText("Enter your name and e-mail address:"); txt.setSize(4); line.addElement(txt); // Add the Line Layout to String Buffer page.append(line.toString()); page.append("<BR>"); //-------------------------------------------------------------------//-------------------------------------------------------------------// Set the HTML Form METHOD form.setMethod(HTMLForm.METHOD_POST); //-------------------------------------------------------------------//-------------------------------------------------------------------// Create a Text input for the name. TextFormInput user = new TextFormInput("name"); user.setSize(25); user.setMaxLength(40); // Create a Text input for the email address. TextFormInput email = new TextFormInput("email"); email.setSize(30); email.setMaxLength(40); // Create a ImageFormInput ImageFormInput img = new ImageFormInput("Submit Form", "..\\images\\myPiimages/c.gif"); img.setAlignment(HTMLConstants.RIGHT); //-------------------------------------------------------------------//-------------------------------------------------------------------// Create a LineLayoutFormPanel object for the name & e-mail address LineLayoutFormPanel line2 = new LineLayoutFormPanel(); // Add elements to the line form line2.addElement(new LabelFormElement("Name:")); line2.addElement(user); // Create and add a Label Element to the Line Layout line2.addElement(new LabelFormElement("E-mail:")); line2.addElement(email); line2.addElement(img);
IBM Toolbox for Java
601
//-------------------------------------------------------------------//-------------------------------------------------------------------// Create Questions line layout LineLayoutFormPanel line3 = new LineLayoutFormPanel(); // Add elements to the line layout line3.addElement(new LineLayoutFormPanel()); line3.addElement(new CheckboxFormInput("use", "yes", "Do you currently use the Toolbox?", false)); line3.addElement(new LineLayoutFormPanel()); line3.addElement(new CheckboxFormInput( "contact", "yes", "Would you like information about future Toolbox releases?", true)); line3.addElement(new LineLayoutFormPanel()); //-------------------------------------------------------------------//-------------------------------------------------------------------// Create Version Radio Group RadioFormInputGroup group = new RadioFormInputGroup("version"); // Add Radio Form Inputs to the Group group.add(new RadioFormInput("version", "v3r2", "V3R2", group.add(new RadioFormInput("version", "v4r1", "V4R1", group.add(new RadioFormInput("version", "v4r2", "V4R2", group.add(new RadioFormInput("version", "v4r3", "V4R3", group.add(new RadioFormInput("version", "v4r4", "V4R4", group.add(new RadioFormInput("version", "multiple versions", "Multiple Versions? Which ones:", false)); false)); false)); false)); false)); false));
//Create a Select Form Element SelectFormElement mlist = new SelectFormElement("MultiList"); mlist.setMultiple(true); mlist.setSize(3); //Create the SelectOption SelectOption SelectOption SelectOption SelectOption Options option1 option2 option3 option4 option5 for the Select Form Element = mlist.addOption("V3R2", "v3r2"); = mlist.addOption("V4R1", "v4r1"); = mlist.addOption("V4R2", "v4r2"); = mlist.addOption("V4R3", "v4r3"); = mlist.addOption("V4R4", "v4r4");
// Create HTML text txt = new HTMLText("Current Server Level:"); txt.setSize(4); // Create Grid Layout GridLayoutFormPanel grid1 = new GridLayoutFormPanel(3); // Add radio group & select form element to the grid grid1.addElement(txt); grid1.addElement(group); grid1.addElement(mlist); //-------------------------------------------------------------------//-------------------------------------------------------------------// Create Grid Layout for interests GridLayoutFormPanel grid2 = new GridLayoutFormPanel(1); txt = new HTMLText("Current Projects or Area of Interest: " +
602
"(check all that apply)"); txt.setSize(4); // Add elements to Grid Layout grid2.addElement(new LineLayoutFormPanel()); grid2.addElement(txt); // Create and add a Checkbox to the Grid Layout grid2.addElement(new CheckboxFormInput("interest", "applications", "Applications", true)); grid2.addElement(new CheckboxFormInput("interest", "applets", "Applets", false)); grid2.addElement(new CheckboxFormInput("interest", "servlets", "Servlets", false)); //-------------------------------------------------------------------//-------------------------------------------------------------------// Create Line Layout for platforms LineLayoutFormPanel line4 = new LineLayoutFormPanel(); txt = new HTMLText("Client Platforms Used: " + "(check all that apply)"); txt.setSize(4); // Add elements to Line Layout line4.addElement(new LineLayoutFormPanel()); line4.addElement(txt); line4.addElement(new LineLayoutFormPanel()); line4.addElement(new CheckboxFormInput("platform", "95", "Windows95", false)); line4.addElement(new CheckboxFormInput("platform", "98", "Windows98", false)); line4.addElement(new CheckboxFormInput("platform", "NT", "WindowsNT", false)); line4.addElement(new CheckboxFormInput("platform", "OS2", "OS/2", false)); line4.addElement(new CheckboxFormInput("platform", "AIX", "AIX", false)); line4.addElement(new CheckboxFormInput("platform", "Linux", "Linux", false)); line4.addElement(new CheckboxFormInput("platform", "AS400", "System i", false)); line4.addElement(new CheckboxFormInput("platform", "Other", "Other:", false)); TextFormInput other = new TextFormInput("OtherPlatforms"); other.setSize(20); other.setMaxLength(50); line4.addElement(other); //-------------------------------------------------------------------//-------------------------------------------------------------------IBM Toolbox for Java
603
// Create a Line Layout for number of servers LineLayoutFormPanel grid3 = new LineLayoutFormPanel(); txt = new HTMLText( "How many System i servers do you have?"); txt.setSize(4); // Create a Select Form Element for number of servers owned SelectFormElement list = new SelectFormElement("list1"); // Create and add the Select Options to the Select Form Element List SelectOption opt0 = list.addOption("0", "zero"); SelectOption opt1 = list.addOption("1", "one", true); SelectOption opt2 = list.addOption("2", "two"); SelectOption opt3 = list.addOption("3", "three"); SelectOption opt4 = list.addOption("4", "four"); SelectOption opt5 = new SelectOption("5+", "FiveOrMore", false); list.addOption(opt5); // Add Elements to the Grid Layout grid3.addElement(new LineLayoutFormPanel()); grid3.addElement(txt); grid3.addElement(list); //-------------------------------------------------------------------//-------------------------------------------------------------------// Create a Grid Layout for Product Comments GridLayoutFormPanel grid4 = new GridLayoutFormPanel(1); txt = new HTMLText("Product Comments:"); txt.setSize(4); // Add elements to the Grid Layout grid4.addElement(new LineLayoutFormPanel()); grid4.addElement(txt); // Create a Text Area Form grid4.addElement(new TextAreaFormElement("comments", 5, 75)); grid4.addElement(new LineLayoutFormPanel()); //-------------------------------------------------------------------//-------------------------------------------------------------------// Create a Grid Layout GridLayoutFormPanel grid5 = new GridLayoutFormPanel(2); txt = new HTMLText("Would you like to sign on to a server?"); txt.setSize(4); // Create a Text input and Label for the system name. TextFormInput sys = new TextFormInput("system"); LabelFormElement sysLabel = new LabelFormElement("System:"); // Create a Text input and Label for the userid. TextFormInput uid = new TextFormInput("uid"); LabelFormElement uidLabel = new LabelFormElement("UserID"); // Create a Password input and Label for the password. PasswordFormInput pwd = new PasswordFormInput("pwd"); LabelFormElement pwdLabel = new LabelFormElement("Password"); // Add the Text inputs, password inputs, and Labels to the grid grid5.addElement(sysLabel); grid5.addElement(sys); grid5.addElement(uidLabel); grid5.addElement(uid); grid5.addElement(pwdLabel); grid5.addElement(pwd); //-------------------------------------------------------------------//-------------------------------------------------------------------// Add the various panels created to the HTML Form
604
// in the order you wish them to appear form.addElement(line2); form.addElement(line3); form.addElement(grid1); form.addElement(grid2); form.addElement(line4); form.addElement(grid3); form.addElement(grid4); form.addElement(txt); form.addElement(new LineLayoutFormPanel()); form.addElement(grid5); form.addElement(new LineLayoutFormPanel()); form.addElement( new HTMLText("Submit an attachment Here: <br />")); // Add a File Input to the form form.addElement(new FileFormInput("myAttachment")); form.addElement(new ButtonFormInput("button", "TRY ME!", "test()")); // Adds a empty Line Layout, which in turn // adds a line break <br /> to the form form.addElement(new LineLayoutFormPanel()); form.addElement(new LineLayoutFormPanel()); form.addElement(new SubmitFormInput("submit", "Register")); form.addElement(new LineLayoutFormPanel()); form.addElement(new LineLayoutFormPanel()); form.addElement(new ResetFormInput("reset", "Reset")); // Add a Hidden Input to the form form.addElement(new HiddenFormInput("copyright", "(C) Copyright IBM Corp. 1999, 1999")); //-------------------------------------------------------------------// Add the entire HTML Form to the String Buffer page.append(form.toString()); } catch(Exception e) { e.printStackTrace(); } // Add the Ending HTML tags to the Buffer page.append("</BODY>\n"); page.append("</HTML>\n"); // Return the entire HTML page string return page.toString(); } }
605
to build customer applications! Attachment File: U:\wiedrich\servlet\temp.html (C) Copyright IBM Corp. 1999, 1999 v Customer Name: Barney Rubble Email address: [email protected] Currently Using Toolbox: yes AS400 Version: v4r4 Using Java or Interested In: servlets Platforms: OS2 Number of System i servers: FiveOrMore (C) Copyright IBM Corp. 1999, 1999 v Customer Name: George Jetson Email address: [email protected] Requested More Information: yes AS400 Version: v4r2 Using Java or Interested In: applications Platforms: NT,Other Other Platforms: Solaris Number of System i servers: one Comments: This is my first time using this! Very Cool! (C) Copyright IBM Corp. 1999, 1999 v Customer Name: Clark Kent Email address: [email protected] AS400 Version: v4r2 Number of System i servers: one (C) Copyright IBM Corp. 1999, 1999 Related reference Example: Using the HTML form classes on page 595 The following IBM Toolbox for Java example shows you how to use the HTML form classes.
606
/** * An example of using the HTMLTree and FileTreeElement classes in a servlet. **/ public class TreeNav extends HttpServlet { public void init(ServletConfig config) throws ServletException { super.init(config); // // // // // // // // // The Toolbox uses a set of default icons to represents expanded, collapsed, and documents within the HTMLTree. To enhance those icons, the Toolbox ships three gifs (expanded.gif, collapsed.gif, bullet.gif) in the jt400Servlet.jar file. Browsers do not have the ability to find gifs in a JAR or zip file, so those images need to be extracted from the JAR file and placed in the appropriate webserver directory (by default it is the /html directory). Then uncomment the following lines of code and specify the correct location in the these set methods. The location can be absolute or relative.
HTMLTreeElement.setExpandedGif("/images/expanded.gif"); HTMLTreeElement.setCollapsedGif("/images/collapsed.gif"); HTMLTreeElement.setDocGif("/images/bullet.gif"); } /** * Process the GET request. * @param req The request. * @param res The response. **/ public void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { HttpSession session = req.getSession(true); HTMLTree fileTree = (HTMLTree)session.getValue("filetree"); // If this session does not already have a file tree, then // create the initial tree. if (fileTree == null) fileTree = createTree(req, resp, req.getRequestURI()); // Set the Http servlet request on the HTMLTree. fileTree.setHttpServletRequest(req); resp.setContentType("text/html"); PrintWriter out = resp.getWriter(); out.println("<html>\n"); out.println(new HTMLMeta("Expires", "Mon, 03 Jan 1990 13:00:00 GMT")); out.println("<body>\n"); // Get the tag for the HTMLTree. out.println(fileTree.getTag()); out.println("</body>\n"); out.println("</html>\n"); out.close(); // Set the session tree value, so when entering this servlet for
IBM Toolbox for Java
607
// the second time, the FileTree object will be reused. session.putValue("filetree", fileTree); } /** * Process the POST request. * @param req The request. * @param res The response. **/ public void doPost (HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { res.setContentType("text/html"); ServletOutputStream out = res.getOutputStream(); } /** * This method will create the initial HTMLTree. **/ private HTMLTree createTree(HttpServletRequest req, HttpServletResponse resp, String uri) { // Create an HTMLTree object. HTMLTree tree = new HTMLTree(req); try { // Create a URLParser object. URLParser urlParser = new URLParser(uri); AS400 sys = new AS400(CPUStatus.systemName_, "javactl", "jteam1"); // Create a File object and set the root IFS directory. IFSJavaFile root = new IFSJavaFile(sys, "/QIBM"); // Create a Filter and list all of the directories. DirFilter filter = new DirFilter(); //File[] dirList = root.listFiles(filter); // Get the list of files that satisfy the directory filter. String[] list = root.list(filter); File[] dirList = new File[list.length]; // // // // // // // // We don't want to require webservers to use JDK1.2 because most webserver JVM's are slower to upgrade to the latest JDK level. The most efficient way to create these file objects is to use the listFiles(filter) method in JDK1.2 which would be done like the following, instead of using the list(filter) method and then converting the returned string arrary into the appropriate File array. File[] dirList = root.listFiles(filter);
for (int j=0; j<dirList.length; ++j) { if (root instanceof IFSJavaFile) dirList[j] = new IFSJavaFile((IFSJavaFile)root, list[j]); else dirList[j] = new File(list[j]); } for (int i=0; i<dirList.length; i++) { // Create a FileTreeElement for each directory in the list. FileTreeElement node = new FileTreeElement(dirList[i]); // Create a ServletHyperlink for the expand/collapse icons. ServletHyperlink sl = new ServletHyperlink(urlParser.getURI());
608
//sl.setHttpServletResponse(resp); node.setIconUrl(sl); // Create a ServletHyperlink to the TreeList servlet, which will // display the contents of thie FileTreeElement (directory). ServletHyperlink tl = new ServletHyperlink("/servlet/TreeList"); tl.setTarget("list"); // If the ServletHyperlink doesn't have a name, then set it to the // name of the directory. if (tl.getText() == null) tl.setText(dirList[i].getName()); // Set the TextUrl for the FileTreeElement. node.setTextUrl(tl); // Add the FileTreeElement to the HTMLTree. tree.addElement(node); } } catch (Exception e) { e.printStackTrace(); } return tree; } public void destroy(ServletConfig config) { // do nothing } public String getServletInfo() { return "FileTree Navigation"; } }
Example: Creating a traversable integrated file system tree (File one of three)
This IBM Toolbox for Java example code, in conjunction with the code in the other two example files, displays an HTMLTree and FileListElement in a servlet. The three files in the example are: v FileTreeExample.java - this file, which generates the HTML frames and starts the servlet v TreeNav.java - builds and manages the tree v TreeList.java - displays the contents of selections made in the TreeNav.java class Note: Read the Code example disclaimer for important legal information.
/////////////////////////////////////////////////////////////////////////////// // // This source is an example of using the HTML package // classes, which allow you to easily build HTML and File Trees. // /////////////////////////////////////////////////////////////////////////////// import java.io.PrintWriter; import java.io.IOException; import javax.servlet.*; import javax.servlet.http.*; import com.ibm.as400.util.html.HTMLMeta;
609
// // An example of using frames to display an HTMLTree and FileListElement // in a servlet. // public class FileTreeExample extends HttpServlet { public void init(ServletConfig config) throws ServletException { super.init(config); } /** * Process the GET request. * @param req The request. * @param res The response. **/ public void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); // Set up two frames. The first, a navigation frame, will display // the HTMLTree, which will contain FileTreeElements and allow // navigation of the File system. The second frame will display/list // the contents of a selected directory from the navigation frame. PrintWriter out = resp.getWriter(); out.println("<html>\n"); out.println(new HTMLMeta("Expires","Mon, 04 Jan 1990 13:00:00 GMT")); out.println("<frameset cols=\"25%,*\">"); out.println("<frame frameborder=\"5\" src=\"/servlet/TreeNav\" name=\"nav\">"); out.println("<frame frameborder=\"3\" src=\"/servlet/TreeList\" name=\"list\">"); out.println("</frameset>"); out.println("</html>\n"); out.close(); } /** * Process the POST request. * @param req The request. * @param res The response. **/ public void doPost (HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { res.setContentType("text/html"); ServletOutputStream out = res.getOutputStream(); } public void destroy(ServletConfig config) { // do nothing } public String getServletInfo() { return "FileTree Servlet"; } }
610
Example: Creating a traversable integrated file system tree (File two of three)
This example code, in conjunction with the code in the other two example files, displays an HTMLTree and FileListElement in a servlet. The three files in the example are: v FileTreeExample.java - generates the HTML frames and starts the servlet v TreeNav.java - this file, which builds and manages the tree v TreeList.java - displays the contents of selections made in the TreeNav.java class Note: Read the Code example disclaimer for important legal information.
////////////////////////////////////////////////////////////////////////////////// // // This source is an example of using the IBM Toolbox for Java HTML // package classes, which allow you to easily build HTML and File Trees. // ////////////////////////////////////////////////////////////////////////////////// import java.io.File; import java.io.PrintWriter; import java.io.IOException; import javax.servlet.*; import javax.servlet.http.*; import import import import import import import import import com.ibm.as400.access.AS400; com.ibm.as400.access.IFSJavaFile; com.ibm.as400.util.html.HTMLMeta; com.ibm.as400.util.html.HTMLTree; com.ibm.as400.util.html.HTMLTreeElement; com.ibm.as400.util.html.URLParser; com.ibm.as400.util.html.DirFilter; com.ibm.as400.util.html.FileTreeElement; com.ibm.as400.util.servlet.ServletHyperlink;
// // An example of using the HTMLTree and FileTreeElement classes // in a servlet. // public class TreeNav extends HttpServlet { private AS400 sys_; public void init(ServletConfig config) throws ServletException { super.init(config); // Create an AS400 object. sys_ = new AS400("mySystem", "myUserID", "myPassword"); // // // // // // // // // IBM Toolbox for Java uses a set of default icons to represents expanded, collapsed, and documents within the HTMLTree. To enhance those icons, IBM Toolbox for Java ships three gifs (expanded.gif, collapsed.gif, bullet.gif) in the jt400Servlet.jar file. Browsers do not have the ability to find gifs in a JAR or zip file, so you need to extract those images from the JAR file and place them in the appropriate webserver directory (by default it is the /html directory). Then change the following lines of code to specify the correct location in the set methods. The location can be absolute or relative.
611
} /** * Process the GET request. * @param req The request. * @param res The response. **/ public void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // Use session data to remember the state of the tree. HttpSession session = req.getSession(true); HTMLTree fileTree = (HTMLTree)session.getValue("filetree"); // If this session does not already have a file tree, then // create the initial tree. if (fileTree == null) fileTree = createTree(req, resp, req.getRequestURI()); // Set the Http servlet request on the HTMLTree. fileTree.setHttpServletRequest(req); resp.setContentType("text/html"); PrintWriter out = resp.getWriter(); out.println("<html>\n"); out.println(new HTMLMeta("Expires","Mon, 03 Jan 1990 13:00:00 GMT")); out.println("<body>\n"); // Get the tag for the HTMLTree. out.println(fileTree.getTag()); out.println("</body>\n"); out.println("</html>\n"); out.close(); // Set the session tree value, so when entering this servlet for // the second time, the FileTree object will be reused. session.putValue("filetree", fileTree); } /** * Process the POST request. * @param req The request. * @param res The response. **/ public void doPost (HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { res.setContentType("text/html"); ServletOutputStream out = res.getOutputStream(); } /** * This method will create the initial HTMLTree. **/ private HTMLTree createTree(HttpServletRequest req, HttpServletResponse resp, String uri) { // Create an HTMLTree object. HTMLTree tree = new HTMLTree(req); try {
612
// Create a URLParser object. URLParser urlParser = new URLParser(uri); // Create a File object and set the root IFS directory. IFSJavaFile root = new IFSJavaFile(sys_, "/QIBM"); // Create a Filter. DirFilter filter = new DirFilter(); // Get the list of files that satisfy the directory filter. String[] list = root.list(filter); File[] dirList = new File[list.length]; // // // // // // // // We don't want to require webservers to use JDK1.2 because most webserver JVM's are slower to upgrade to the latest JDK level. The most efficient way to create these file objects is to use the listFiles(filter) method in JDK1.2 which would be done like the following, instead of using the list(filter) method and then converting the returned string arrary into the appropriate File array. File[] dirList = root.listFiles(filter);
for (int j=0; j<dirList.length; ++j) { if (root instanceof IFSJavaFile) dirList[j] = new IFSJavaFile((IFSJavaFile)root, list[j]); else dirList[j] = new File(list[j]); } for (int i=0; i<dirList.length; i++) { // Create a FileTreeElement for each directory in the list. FileTreeElement node = new FileTreeElement(dirList[i]); // Create a ServletHyperlink for the expand/collapse icons. ServletHyperlink sl = new ServletHyperlink(urlParser.getURI()); sl.setHttpServletResponse(resp); node.setIconUrl(sl); // Create a ServletHyperlink to the TreeList servlet, which will // display the contents of thie FileTreeElement (directory). ServletHyperlink tl = new ServletHyperlink("/servlet/TreeList"); tl.setTarget("list"); // If the ServletHyperlink doesn't have a name, then set it to the // name of the directory. if (tl.getText() == null) tl.setText(dirList[i].getName()); // Set the TextUrl for the FileTreeElement. node.setTextUrl(tl); // Add the FileTreeElement to the HTMLTree. tree.addElement(node); } sys_.disconnectAllServices(); } catch (Exception e) { e.printStackTrace(); } return tree;
IBM Toolbox for Java
613
} public void destroy(ServletConfig config) { // do nothing } public String getServletInfo() { return "FileTree Navigation"; } }
import javax.servlet.*; import javax.servlet.http.*; /** * An example of using the FileListElement class in a servlet. **/ public class TreeList extends HttpServlet { private AS400 sys_; /** * Process the GET request. * @param req The request. * @param res The response. **/ public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html");
614
try { PrintWriter out = resp.getWriter(); out.println("<html>\n"); out.println(new HTMLMeta("Expires", "Mon, 02 Jan 1990 13:00:00 GMT")); out.println("<body>\n"); // If the path parameter is not null, then the user has selected an // element from the FileTreeElement list in the navigation frame. if (req.getPathInfo() != null) { // Create a FileListElement passing in an AS400 system object and // the Http servlet request. The request will contain the necessary // path information to list out the contents of the FileTreeElement // (directory) selected. FileListElement fileList = new FileListElement(sys_, req); // // // Alternately, create a FileListElement from a NetServer share name and share path. FileListElement fileList = new FileListElement(sys_, req, "TreeShare", "/QIBM/ProdData/HTTP/Public/jt400");
// Display the FileListElement contents. out.println(fileList.list()); } // Display this HTMLHeading if no FileTreeElement has been selected. else { HTMLHeading heading = new HTMLHeading(1,"An HTML File List Example"); heading.setAlign(HTMLConstants.CENTER); out.println(heading.getTag()); } out.println("</body>\n"); out.println("</html>\n"); out.close(); } catch (Exception e) { e.printStackTrace(); } } /** * Process the POST request. * @param req The request. * @param res The response. **/ public void doPost (HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { res.setContentType("text/html"); ServletOutputStream out = res.getOutputStream(); } public void init(ServletConfig config) throws ServletException { super.init(config);
IBM Toolbox for Java
615
The Java code example above generates the following HTML code:
<table align="center" border="1"> <caption>Customer Account Balances - January 1, 2000</caption> <tr> <th>ACCOUNT</th> <th>NAME</th> <th>BALANCE</th> </tr> <tr align="center"> <td>0000001</td> <td>Customer1</td> <td>100.00</td> </tr> <tr align="center">
616
<td>0000002</td> <td>Customer2</td> <td>200.00</td> </tr> <tr align="center"> <td>0000003</td> <td>Customer3</td> <td>550.00</td> </tr> </table>
The following table shows how the HTML code above displays in a Web browser.
Table 3. Customer Account Balances - January 1, 2000 ACCOUNT 0000001 0000002 0000003 NAME Customer1 Customer2 Customer3 BALANCE 100.00 200.00 550.00
617
length="4" length="4" length="10" length="7" length="6" length="1" length="4" length="10" length="8" length="1" length="1" length="4" length="8" length="4" length="1" length="10"
usage="output"/> usage="output"/> usage="output"/> usage="output"/> usage="output"/> usage="output"/> usage="output"/> usage="output"/> usage="output"/> usage="output"/> usage="output"/> usage="output"/> usage="output"/> usage="output"/> usage="output"/> usage="output"/>
<!-- Program QSYRUSRI and its parameter list for retrieving USRI0100 format --> <program name="qsyrusri" path="/QSYS.lib/QSYRUSRI.pgm"> <data name="receiver" type="struct" struct="usri0100" usage="output"/> <data name="receiverLength" type="int" length="4" usage="input" /> <data name="format" type="char" length="8" usage="input" init="USRI0100"/> <data name="profileName" type="char" length="10" usage="input" init="*CURRENT"/> <data name="errorCode" type="int" length="4" usage="input" init="0"/> </program> </pcml>
// Example program to call "Retrieve User Information" (QSYRUSRI) API public class qsyrusri { public qsyrusri() { } public static void main(String[] argv) { AS400 as400System; // com.ibm.as400.access.AS400 ProgramCallDocument pcml; // com.ibm.as400.data.ProgramCallDocument boolean rc = false; // Return code from ProgramCallDocument.callProgram() String msgId, msgText; // Messages returned from the server Object value; // Return value from ProgramCallDocument.getValue() System.setErr(System.out); // Construct AS400 without parameters, user will be prompted as400System = new AS400(); try { // Uncomment the following to get debugging information //com.ibm.as400.data.PcmlMessageLog.setTraceEnabled(true);
618
System.out.println("Beginning PCML Example.."); System.out.println(" Constructing ProgramCallDocument for QSYRUSRI API..."); // Construct ProgramCallDocument // First parameter is system to connect to // Second parameter is pcml resource name. In this example, // serialized PCML file "qsyrusri.pcml.ser" or // PCML source file "qsyrusri.pcml" must be found in the classpath. pcml = new ProgramCallDocument(as400System, "qsyrusri"); // Set input parameters. Several parameters have default values // specified in the PCML source. Do not need to set them using Java code. System.out.println(" Setting input parameters..."); pcml.setValue("qsyrusri.receiverLength", new Integer((pcml.getOutputsize("qsyrusri.receiver")))); // Request to call the API // User will be prompted to sign on to the system System.out.println(" Calling QSYRUSRI API requesting information for the sign-on user."); rc = pcml.callProgram("qsyrusri"); // If return code is false, we received messages from the server if(rc == false) { // Retrieve list of server messages AS400Message[] msgs = pcml.getMessageList("qsyrusri"); // Iterate through messages and write them to standard output for (int m = 0; m < msgs.length; m++) { msgId = msgs[m].getID(); msgText = msgs[m].getText(); System.out.println(" " + msgId + " - " + msgText); } System.out.println("** Call to QSYRUSRI failed. See messages above **"); System.exit(0); } // Return code was true, call to QSYRUSRI succeeded // Write some of the results to standard output else { value = pcml.getValue("qsyrusri.receiver.bytesReturned"); System.out.println(" Bytes returned: " + value); value = pcml.getValue("qsyrusri.receiver.bytesAvailable"); System.out.println(" Bytes available: " + value); value = pcml.getValue("qsyrusri.receiver.userProfile"); System.out.println(" Profile name: " + value); value = pcml.getValue("qsyrusri.receiver.previousSignonDate"); System.out.println(" Previous signon date:" + value); value = pcml.getValue("qsyrusri.receiver.previousSignonTime"); System.out.println(" Previous signon time:" + value); } } catch (PcmlException e) { System.out.println(e.getLocalizedMessage()); e.printStackTrace(); System.out.println("*** Call to QSYRUSRI failed. ***"); System.exit(0); } System.exit(0); } // End main() }
619
<!-- Program QGYOLAUS and its parameter list for retrieving AUTU0150 format --> <program name="qgyolaus" path="/QSYS.lib/QGY.lib/QGYOLAUS.pgm" parseorder="listInfo receiver"> <data name="receiver" type="struct" struct="autu0150" usage="output" count="listInfo.rcdsReturned" outputsize="receiverLength" /> <data name="receiverLength" type="int" length="4" usage="input" init="16384" /> <data name="listInfo" type="struct" struct="listInfo" usage="output" /> <data name="rcdsToReturn" type="int" length="4" usage="input" init="264" /> <data name="format" type="char" length="10" usage="input" init="AUTU0150" /> <data name="selection" type="char" length="10" usage="input" init="*USER" /> <data name="member" type="char" length="10" usage="input" init="*NONE" /> <data name="errorCode" type="int" length="4" usage="input" init="0" /> </program> <!-- Program QGYGTLE returned additional "records" from the list created by QGYOLAUS. --> <program name="qgygtle" path="/QSYS.lib/QGY.lib/QGYGTLE.pgm" parseorder="listInfo receiver"> <data name="receiver" type="struct" struct="autu0150" usage="output" count="listInfo.rcdsReturned" outputsize="receiverLength" /> <data name="receiverLength" type="int" length="4" usage="input" init="16384" /> <data name="requestHandle" type="byte" length="4" usage="input" /> <data name="listInfo" type="struct" struct="listInfo" usage="output" /> <data name="rcdsToReturn" type="int" length="4" usage="input" init="264" /> <data name="startingRcd" type="int" length="4" usage="input" /> <data name="errorCode" type="int" length="4" usage="input" init="0" /> </program>
620
<!-- Program QGYCLST closes the list, freeing resources on the server --> <program name="qgyclst" path="/QSYS.lib/QGY.lib/QGYCLST.pgm" > <data name="requestHandle" type="byte" length="4" usage="input" /> <data name="errorCode" type="int" length="4" usage="input" init="0" /> </program> </pcml>
// Example program to call "Retrieve List of Authorized Users" (QGYOLAUS) API public class qgyolaus { public static void main(String[] argv) { AS400 as400System; // com.ibm.as400.access.AS400 ProgramCallDocument pcml; // com.ibm.as400.data.ProgramCallDocument boolean rc = false; // Return code from ProgramCallDocument.callProgram() String msgId, msgText; // Messages returned from the server Object value; // Return value from ProgramCallDocument.getValue() int[] indices = new int[1]; // Indices for access array value int nbrRcds, // Number of records returned from QGYOLAUS and QGYGTLE nbrUsers; // Total number of users retrieved String listStatus; // Status of list on the server byte[] requestHandle = new byte[4]; System.setErr(System.out); // Construct AS400 without parameters, user will be prompted as400System = new AS400(); try { // Uncomment the following to get debugging information //com.ibm.as400.data.PcmlMessageLog.setTraceEnabled(true); System.out.println("Beginning PCML Example.."); System.out.println(" Constructing ProgramCallDocument for QGYOLAUS API..."); // Construct ProgramCallDocument // First parameter is system to connect to // Second parameter is pcml resource name. In this example, // serialized PCML file "qgyolaus.pcml.ser" or // PCML source file "qgyolaus.pcml" must be found in the classpath. pcml = new ProgramCallDocument(as400System, "qgyolaus"); // All input parameters have default values specified in the PCML source. // Do not need to set them using Java code. // Request to call the API // User will be prompted to sign on to the system System.out.println(" Calling QGYOLAUS API requesting information for the sign-on user."); rc = pcml.callProgram("qgyolaus"); // If return code is false, we received messages from the server if(rc == false) { // Retrieve list of server messages AS400Message[] msgs = pcml.getMessageList("qgyolaus");
621
// Iterate through messages and write them to standard output for (int m = 0; m < msgs.length; m++) { msgId = msgs[m].getID(); msgText = msgs[m].getText(); System.out.println(" " + msgId + " - " + msgText); } System.out.println("** Call to QGYOLAUS failed. See messages above **"); System.exit(0); } // Return code was true, call to QGYOLAUS succeeded // Write some of the results to standard output else { boolean doneProcessingList = false; String programName = "qgyolaus"; nbrUsers = 0; while (!doneProcessingList) { nbrRcds = pcml.getIntValue(programName + ".listInfo.rcdsReturned"); requestHandle = (byte[]) pcml.getValue(programName + ".listInfo.rqsHandle"); // Iterate through list of users for (indices[0] = 0; indices[0] < nbrRcds; indices[0]++) { value = pcml.getValue(programName + ".receiver.name", indices); System.out.println("User: " + value); value = pcml.getValue(programName + ".receiver.description", indices); System.out.println("\t\t" + value); } nbrUsers += nbrRcds; // See if we retrieved all the users. // If not, subsequent calls to "Get List Entries" (QGYGTLE) // would need to be made to retrieve the remaining users in the list. listStatus = (String) pcml.getValue(programName + ".listInfo.listStatus"); if ( listStatus.equals("2") // List is marked as "Complete" || listStatus.equals("3") ) // Or list is marked "Error building" { doneProcessingList = true; } else { programName = "qgygtle"; // Set input parameters for QGYGTLE pcml.setValue("qgygtle.requestHandle", requestHandle); pcml.setIntValue("qgygtle.startingRcd", nbrUsers + 1); // Call "Get List Entries" (QGYGTLE) to get more users from list rc = pcml.callProgram("qgygtle"); // If return code is false, we received messages from the server if(rc == false) { // Retrieve list of server messages AS400Message[] msgs = pcml.getMessageList("qgygtle"); // Iterate through messages and write them to standard output for (int m = 0; m < msgs.length; m++) { msgId = msgs[m].getID(); msgText = msgs[m].getText(); System.out.println(" " + msgId + " - " + msgText); }
622
System.out.println("** Call to QGYGTLE failed. See messages above **"); System.exit(0); } // Return code was true, call to QGYGTLE succeeded } } System.out.println("Number of users returned:
" + nbrUsers);
// Call the "Close List" (QGYCLST) API pcml.setValue("qgyclst.requestHandle", requestHandle); rc = pcml.callProgram("qgyclst"); } } catch(PcmlException e) { System.out.println(e.getLocalizedMessage()); e.printStackTrace(); System.out.println("*** Call to QGYOLAUS failed. ***"); System.exit(0); } System.exit(0); } }
<struct name="rwAccessList" count="nbrOfReadWriteHostNames" offset="dispToReadWriteHostNames" offsetfrom="receiver"> <data name="lengthOfEntry" type="int" length="4" /> <data name="lengthOfHostName" type="int" length="4" /> <data name="hostName" type="char" length="lengthOfHostName" /> <data type="byte" length="0"
IBM Toolbox for Java
623
offset="lengthOfEntry" /> </struct> <struct name="rootAccessList" count="nbrOfRootHostNames" offset="dispToRootHostNames" offsetfrom="receiver"> <data name="lengthOfEntry" type="int" length="4" /> <data name="lengthOfHostName" type="int" length="4" /> <data name="hostName" type="char" length="lengthOfHostName" /> <data type="byte" length="0" offset="lengthOfEntry" /> </struct> <struct name="accessHostNames" count="nbrOfAccessHostNames" offset="dispToAccessHostNames" offsetfrom="receiver" > <data name="lengthOfEntry" type="int" length="4" /> <data name="lengthOfHostName" type="int" length="4" /> <data name="hostName" type="char" length="lengthOfHostName" /> <data type="byte" length="0" offset="lengthOfEntry" /> </struct> <struct name="hostOptions" offset="dispToHostOptions" offsetfrom="receiver" count="nbrOfHostOptions"> <data name="lengthOfEntry" type="int" length="4" /> <data name="dataFileCodepage" type="int" length="4" /> <data name="pathNameCodepage" type="int" length="4" /> <data name="writeModeFlag" type="int" length="4" /> <data name="lengthOfHostName" type="int" length="4" /> <data name="hostName" type="char" length="lengthOfHostName" /> <data type="byte" length="0" offset="lengthOfEntry" /> </struct> <data type="byte" length="0" offset="lengthOfEntry" /> </struct> <struct name="returnedRcdsFdbkInfo"> <data name="bytesReturned" <data name="bytesAvailable" <data name="nbrOfNFSExportEntries" <data name="handle" </struct> type="int" type="int" type="int" type="int" length="4" length="4" length="4" length="4" /> /> /> />
<program name="qznfrtve" path="/QSYS.lib/QZNFRTVE.pgm" parseorder="returnedRcdsFdbkInfo receiver" > <data name="receiver" type="struct" struct="receiver" usage="output" count="returnedRcdsFdbkInfo.nbrOfNFSExportEntries" outputsize="receiverLength"/> <data name="receiverLength" type="int" length="4" usage="input" init="4096" /> <data name="returnedRcdsFdbkInfo" type="struct" struct="returnedRcdsFdbkInfo" usage="output" /> <data name="formatName" type="char" length="8" usage="input" init="EXPE0100" /> <data name="objectPathName" type="char" length="lengthObjPathName" usage="input" init="*FIRST" /> <data name="lengthObjPathName" type="int" length="4" usage="input" init="6" /> <data name="ccsidObjectPathName" type="int" length="4" usage="input" init="0" /> <data name="desiredCCSID" type="int" length="4" usage="input" init="0" /> <data name="handle" type="int" length="4" usage="input" init="0" /> <data name="errorCode" type="int" length="4" usage="input" init="0" /> </program> </pcml>
// Example program to call "Retrieve NFS Exports" (QZNFRTVE) API public class qznfrtve {
624
public static void main(String[] argv) { AS400 as400System; // com.ibm.as400.access.AS400 ProgramCallDocument pcml; // com.ibm.as400.data.ProgramCallDocument boolean rc = false; // Return code from ProgramCallDocument.callProgram() String msgId, msgText; // Messages returned from the server Object value; // Return value from ProgramCallDocument.getValue() System.setErr(System.out); // Construct AS400 without parameters, user will be prompted as400System = new AS400(); int[] indices = new int[2]; // Indices for access array value int nbrExports; // Number of exports returned int nbrOfReadWriteHostNames, nbrOfRWHostNames, nbrOfRootHostNames, nbrOfAccessHostnames, nbrOfHostOpts; try { // Uncomment the following to get debugging information // com.ibm.as400.data.PcmlMessageLog.setTraceEnabled(true); System.out.println("Beginning PCML Example.."); System.out.println(" Constructing ProgramCallDocument for QZNFRTVE API..."); // Construct ProgramCallDocument // First parameter is system to connect to // Second parameter is pcml resource name. In this example, // serialized PCML file "qznfrtve.pcml.ser" or // PCML source file "qznfrtve.pcml" must be found in the classpath. pcml = new ProgramCallDocument(as400System, "qznfrtve"); // Set input parameters. Several parameters have default values // specified in the PCML source. Do not need to set them using Java code. System.out.println(" Setting input parameters..."); pcml.setValue("qznfrtve.receiverLength", new Integer( ( pcml.getOutputsize("qznfrtve.receiver")))); // Request to call the API // User will be prompted to sign on to the system System.out.println(" Calling QZNFRTVE API requesting NFS exports."); rc = pcml.callProgram("qznfrtve"); if (rc == false) { // Retrieve list of server messages AS400Message[] msgs = pcml.getMessageList("qznfrtve"); // Iterate through messages and write them to standard output for (int m = 0; m < msgs.length; m++) { msgId = msgs[m].getID(); msgText = msgs[m].getText(); System.out.println(" " + msgId + " - " + msgText); } System.out.println("** Call to QZNFRTVE failed. See messages above **"); System.exit(0); } // Return code was true, call to QZNFRTVE succeeded // Write some of the results to standard output else { nbrExports = pcml.getIntValue("qznfrtve.returnedRcdsFdbkInfo.nbrOfNFSExportEntries"); // Iterate through list of exports for (indices[0] = 0; indices[0] < nbrExports; indices[0]++) { value = pcml.getValue("qznfrtve.receiver.pathName", indices);
IBM Toolbox for Java
625
System.out.println("Path name = " + value); // Iterate and write out Read Write Host Names for this export nbrOfReadWriteHostNames = pcml.getIntValue("qznfrtve.receiver.nbrOfReadWriteHostNames", indices); for(indices[1] = 0; indices[1] < nbrOfReadWriteHostNames; indices[1]++) { value = pcml.getValue("qznfrtve.receiver.rwAccessList.hostName", indices); System.out.println(" Read/write access host name = " + value); } // Iterate and write out Root Host Names for this export nbrOfRootHostNames = pcml.getIntValue("qznfrtve.receiver.nbrOfRootHostNames", indices); for(indices[1] = 0; indices[1] < nbrOfRootHostNames; indices[1]++) { value = pcml.getValue("qznfrtve.receiver.rootAccessList.hostName", indices); System.out.println(" Root access host name = " + value); } // Iterate and write out Access Host Names for this export nbrOfAccessHostnames = pcml.getIntValue("qznfrtve.receiver.nbrOfAccessHostNames", indices); for(indices[1] = 0; indices[1] < nbrOfAccessHostnames; indices[1]++) { value = pcml.getValue("qznfrtve.receiver.accessHostNames.hostName", indices); System.out.println(" Access host name = " + value); } // Iterate and write out Host Options for this export nbrOfHostOpts = pcml.getIntValue("qznfrtve.receiver.nbrOfHostOptions", indices); for(indices[1] = 0; indices[1] < nbrOfHostOpts; indices[1]++) { System.out.println(" Host options:"); value = pcml.getValue("qznfrtve.receiver.hostOptions.dataFileCodepage", indices); System.out.println(" Data file code page = " + value); value = pcml.getValue("qznfrtve.receiver.hostOptions.pathNameCodepage", indices); System.out.println(" Path name code page = " + value); value = pcml.getValue("qznfrtve.receiver.hostOptions.writeModeFlag", indices); System.out.println(" Write mode flag = " + value); value = pcml.getValue("qznfrtve.receiver.hostOptions.hostName", indices); System.out.println(" Host name = " + value); } } // end for loop iterating list of exports } // end call to QZNFRTVE succeeded } catch(PcmlException e) { System.out.println(e.getLocalizedMessage()); e.printStackTrace(); System.exit(-1); } System.exit(0); } // end main() }
626
IBM grants you a nonexclusive copyright license to use all programming code examples from which you can generate similar function tailored to your own specific needs. All sample code is provided by IBM for illustrative purposes only. These examples have not been thoroughly tested under all conditions. IBM, therefore, cannot guarantee or imply reliability, serviceability, or function of these programs. All programs contained herein are provided to you "AS IS" without any warranties of any kind. The implied warranties of non-infringement, merchantability and fitness for a particular purpose are expressly disclaimed.
public class JSPRunReport { public static void main(String args[]) { FileOutputStream fileout = null;
627
/** specify the URL that contains the data you want to use in your report **/ String JSPurl = args[0]; URL jspurl = null; try { jspurl = new URL(JSPurl); } catch (MalformedURLException e) {} /** get output PDF file name **/ String filename = args[1]; try { fileout = new FileOutputStream(filename); } catch (FileNotFoundException e) {} /** set up page format **/ Paper paper = new Paper(); paper.setSize(612,792); paper.setImageableArea(18, 18, 576, 756); PageFormat pf = new PageFormat(); pf.setPaper(paper); /** create a PDFContext object and cast FileOutputStream as an OutputStream **/ PDFContext pdfcontext = new PDFContext((OutputStream)fileout, pf); System.out.println( Ready to parse XSL document ); /** create the JSPReportProcessor object and set the template to the specified JSP **/ JSPReportProcessor jspprocessor = new JSPReportProcessor(pdfcontext); try { jspprocessor.setTemplate(jspurl); } catch (NullPointerException np){ String mes = np.getMessage(); System.out.println(mes); System.exit(0); } /** process the report **/ try { jspprocessor.processReport(); } catch (IOException e) { String mes = e.getMessage(); System.out.println(mes); System.exit(0); } catch (SAXException se) { String mes = se.getMessage(); System.out.println(mes); System.exit(0); } System.exit(0); } }
628
<?xml version="1.0"?> <!-Copyright (c) 1999 The Apache Software Foundation. --> <%@ <%@ <%@ <%@ page page page page session="false"%> language="java" contentType="text/html" %> import="java.lang.*" %> import="java.util.*" %> All rights reserved.
<%-- <jsp:useBean id='cust_table' scope='page' class='table.JSPcust_table'/> --%> <%! String[][] cust_data = new String [4][5]; public void jspInit() { //cust_record_field [][] cust_data; // cust_record holds customer name, customer address, customer city, customer state, // customer zip String String String String [] [] [] [] cust_record_1 cust_record_2 cust_record_3 cust_record_4 = = = = = = = = {"IBM","3602 4th St","Rochester","Mn","55901"}; {"HP","400 2nd","Springfield","Mo","33559"}; {"Wolzack","34 Hwy 52N","Lansing","Or","67895"}; {"Siems","343 60th","Salem","Tx","12345"};
<!-- First test of parse and compose. --> <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> <fo:layout-master-set> <fo:simple-page-master master-name="theMaster" > <fo:region-body region-name="theRegion" margin-left=".2in"/> </fo:simple-page-master> <fo:page-sequence-master master-name="theMaster"> <fo:single-page-master-reference master-name="thePage"/> </fo:page-sequence-master> </fo:layout-master-set> <fo:page-sequence master-name="theMaster"> <fo:flow flow-name="theRegion"> <fo:block> <fo:block text-align="center"> NORCAP </fo:block> <fo:block space-before=".2in" text-align="center">PAN PACIFIC HOTEL IN SAN FRANCISCO </fo:block> <fo:block text-align="center"> FRIDAY, DECEMBER 8-9, 2000 </fo:block> </fo:block> <fo:block space-before=".5in" font-size="8pt"> <fo:table table-layout="fixed"> <fo:table-column column-width="3in"/> <fo:table-column column-width="3in"/> <fo:table-column column-width="3in"/> <fo:table-column column-width="3in"/> <fo:table-column column-width="3in"/> <fo:table-body> <fo:table-row> <fo:table-cell column-number="1"> <fo:block border-bottom-style="solid">NAME</fo:block> </fo:table-cell> <fo:table-cell column-number="2"> <fo:block border-bottom-style="solid">ADDRESS</fo:block>
IBM Toolbox for Java
629
</fo:table-cell> <fo:table-cell column-number="3"> <fo:block border-bottom-style="solid">CITY</fo:block> </fo:table-cell> <fo:table-cell column-number="4"> <fo:block border-bottom-style="solid">STATE</fo:block> </fo:table-cell> <fo:table-cell column-number="5"> <fo:block border-bottom-style="solid">ZIP CODE</fo:block> </fo:table-cell> </fo:table-row> <% // add row to table for(int i = 0; i <= 3; i++) { String[] _array = cust_data[i]; %> <fo:table-row> <fo:table-cell column-number="1"> <fo:block space-before=".1in"> <% if(_array[0].equals("IBM")) { %> <fo:inline background-color="blue"> <% out.print(_array[0]); %> </fo:inline> <% } else { %> <% out.print(_array[0]); %> <% } %> </fo:block> </fo:table-cell> <fo:table-cell column-number="2"> <fo:block space-before=".1in"> <% out.print(_array[1]); %> </fo:block> </fo:table-cell> <fo:table-cell column-number="3"> <fo:block space-before=".1in"> <% out.print(_array[2]); %> </fo:block> </fo:table-cell> <fo:table-cell column-number="4"> <fo:block space-before=".1in"> <% out.print(_array[3]); %> </fo:block> </fo:table-cell> <fo:table-cell column-number="5"> <fo:block space-before=".1in"> <% out.print(_array[4]); %> </fo:block> </fo:table-cell> </fo:table-row> <% } // end row while %> </fo:table-body> </fo:table> </fo:block> </fo:flow> </fo:page-sequence> </fo:root>
630
public class PCLRunReport { public static void main(String args[]) { SpooledFileOutputStream fileout = null; String xmldocumentName = args[0]; String xsldocumentName = args[1]; String sys = "<system>"; String user = "<user>"; String pass = "<password>"; /* Insert server name */ /* Insert user profile name */ /* Insert password */
AS400 system = new AS400(sys, user, pass); /* Insert output queue */ String outqname = "/QSYS.LIB/qusrsys.LIB/<outq>.OUTQ"; OutputQueue outq = new OutputQueue(system, outqname); PrintParameterList parms = new PrintParameterList(); parms.setParameter(PrintObject.ATTR_OUTPUT_QUEUE, outq.getPath()); try{
IBM Toolbox for Java
631
fileout = new SpooledFileOutputStream(system, parms, null, null); } catch (Exception e) {} /** set up page format **/ Paper paper = new Paper(); paper.setSize(612,792); paper.setImageableArea(18, 36, 576, 720); PageFormat pf = new PageFormat(); pf.setPaper(paper); /** create a PCLContext object and case FileOutputStream as an OutputStream **/ PCLContext pclcontext = new PCLContext((OutputStream)fileout, pf); System.out.println("Ready to parse XSL document"); /** create the XSLReportProcessor object **/ XSLReportProcessor xslprocessor = new XSLReportProcessor(pclcontext); try { xslprocessor.setXMLDataSource(xmldocumentName); } catch (SAXException se) { String mes = se.getMessage(); System.out.println(mes); System.exit(0); } catch (IOException ioe) { String mes = ioe.getMessage(); System.out.println(mes); System.exit(0); } catch (NullPointerException np){ String mes = np.getMessage(); System.out.println(mes); System.exit(0); } /** set the template to the specified XML data source **/ try { xslprocessor.setTemplate(xsldocumentName); } catch (NullPointerException np){ String mes = np.getMessage(); System.out.println(mes); System.exit(0); } catch (IOException e) { String mes = e.getMessage(); System.out.println(mes); System.exit(0); } catch (SAXException se) { String mes = se.getMessage(); System.out.println(mes); System.exit(0); } /** process the report **/ try { xslprocessor.processReport(); } catch (IOException e) { String mes = e.getMessage(); System.out.println(mes); System.exit(0); }
632
633
<FINANCIAL> <ASSUMABLE> I assume so. </ASSUMABLE> <OWNER-CARRY> Too heavy. </OWNER-CARRY> <ASSESMENTS> $150,000 </ASSESMENTS> <DUES> $100 </DUES> <TAXES> $2,000 </TAXES> <LENDER> Fly by nite mortgage co. </LENDER> <EARNEST> Burt </EARNEST> <DIRECTIONS> North, south, east, west </DIRECTIONS> </FINANCIAL> <REMARKS> </REMARKS> <CONTACTS> <COMPANY> <NAME> Noplace Realty </NAME> <ADDRESS> 12 Main Street </ADDRESS> <CITY> Lowell, MA </CITY> <ZIP> 34567 </ZIP> </COMPANY> <AGENT> <NAME> Mary Jones </NAME> <ADDRESS> </ADDRESS> <CITY> </CITY> <ZIP> </ZIP> </AGENT> <OWNER> <NAME> </NAME> <ADDRESS> </ADDRESS> <CITY> </CITY> <ZIP> </ZIP> </OWNER>
634
<TENANT> Yes. </TENANT> <COMMISION> 15% </COMMISION> </CONTACTS> </RESIDENTIAL-LISTING> <RESIDENTIAL-LISTING VERSION="061698" ID="ID1289"> <GENERAL> <IMAGE FORMAT="JPG" WIDTH="300" HEIGHT="150" SRC="house2.jpg"> </IMAGE> <MLS> <MLS-CODE SECURITY="Restricted"> 30298877 </MLS-CODE> <MLS-SOURCE SECURITY="Public"> <NAME> Mary the Realtor </NAME> <PHONE> 1-617-555-3333 </PHONE> <FAX> 1-617-555-4444 </FAX> <WEB> <EMAIL> [email protected] </EMAIL> <SITE> www.bigbucks.com </SITE> </WEB> </MLS-SOURCE> </MLS> <TYPE> Home </TYPE> <PRICE> $200,000 </PRICE> <AGE UNITS="MONTHS"> 3 </AGE> <LOCATION COUNTRY="USA" STATE="CO" COUNTY="MIDDLESEX" SECURITY="Public"> <ADDRESS> 1 Main Street </ADDRESS> <CITY> Boulder </CITY> <ZIP> 11111 </ZIP> </LOCATION> <STRUCTURE> <NUM-BEDS>
IBM Toolbox for Java
635
2 </NUM-BEDS> <NUM-BATHS> 2 </NUM-BATHS> </STRUCTURE> <DATES> <LISTING-DATE> 4/3/98 </LISTING-DATE> </DATES> <LAND-AREA UNITS="ACRES"> 0.01 </LAND-AREA> </GENERAL> <FEATURES> <DISCLOSURES> In your dreams. </DISCLOSURES> <UTILITIES> Yes </UTILITIES> <EXTRAS> Pest control included. </EXTRAS> <CONSTRUCTION> Wallboard and glue </CONSTRUCTION> <ACCESS> Front door. </ACCESS> </FEATURES> <FINANCIAL> <ASSUMABLE> I assume so. </ASSUMABLE> <OWNER-CARRY> Too heavy. </OWNER-CARRY> <ASSESMENTS> $150,000 </ASSESMENTS> <DUES> $100 </DUES> <TAXES> $2,000 </TAXES> <LENDER> Fly by nite mortgage co. </LENDER> <EARNEST> Burt </EARNEST> <DIRECTIONS> North, south, east, west </DIRECTIONS> </FINANCIAL> <REMARKS> </REMARKS>
636
<CONTACTS> <COMPANY> <NAME> Noplace Realty </NAME> <ADDRESS> 12 Main Street </ADDRESS> <CITY> Lowell, MA </CITY> <ZIP> 34567 </ZIP> </COMPANY> <AGENT> <NAME> Mary Jones </NAME> <ADDRESS> </ADDRESS> <CITY> </CITY> <ZIP> </ZIP> </AGENT> <OWNER> <NAME> </NAME> <ADDRESS> </ADDRESS> <CITY> </CITY> <ZIP> </ZIP> </OWNER> <TENANT> Yes. </TENANT> <COMMISION> 15% </COMMISION> </CONTACTS> </RESIDENTIAL-LISTING> <RESIDENTIAL-LISTING VERSION="061698" ID="ID1290"> <GENERAL> <IMAGE FORMAT="JPG" WIDTH="300" HEIGHT="150" SRC="house3.jpg"> </IMAGE> <MLS> <MLS-CODE SECURITY="Restricted"> 20079877 </MLS-CODE> <MLS-SOURCE SECURITY="Public"> <NAME> Bob the Realtor </NAME> <PHONE> 1-617-555-1212 </PHONE> <FAX> 1-617-555-1313 </FAX> <WEB> <EMAIL>
IBM Toolbox for Java
637
[email protected] </EMAIL> <SITE> www.bigbucks.com </SITE> </WEB> </MLS-SOURCE> </MLS> <TYPE> Apartment </TYPE> <PRICE> $65,000 </PRICE> <AGE UNITS="YEARS"> 30 </AGE> <LOCATION COUNTRY="USA" STATE="MA" COUNTY="MIDDLESEX" SECURITY="Public"> <ADDRESS> 25 Which Ave. </ADDRESS> <CITY> Cambridge </CITY> <ZIP> 02139 </ZIP> </LOCATION> <STRUCTURE> <NUM-BEDS> 3 </NUM-BEDS> <NUM-BATHS> 1 </NUM-BATHS> </STRUCTURE> <DATES> <LISTING-DATE> 3/5/97 </LISTING-DATE> </DATES> <LAND-AREA UNITS="ACRES"> 0.05 </LAND-AREA> </GENERAL> <FEATURES> <DISCLOSURES> In your dreams. </DISCLOSURES> <UTILITIES> Yes </UTILITIES> <EXTRAS> Pest control included. </EXTRAS> <CONSTRUCTION> Wallboard and glue </CONSTRUCTION>
638
<ACCESS> Front door. </ACCESS> </FEATURES> <FINANCIAL> <ASSUMABLE> I assume so. </ASSUMABLE> <OWNER-CARRY> Too heavy. </OWNER-CARRY> <ASSESMENTS> $150,000 </ASSESMENTS> <DUES> $100 </DUES> <TAXES> $2,000 </TAXES> <LENDER> Fly by nite mortgage co. </LENDER> <EARNEST> Burt </EARNEST> <DIRECTIONS> North, south, east, west </DIRECTIONS> </FINANCIAL> <REMARKS> </REMARKS> <CONTACTS> <COMPANY> <NAME> Noplace Realty </NAME> <ADDRESS> 12 Main Street </ADDRESS> <CITY> Lowell, MA </CITY> <ZIP> 34567 </ZIP> </COMPANY> <AGENT> <NAME> Mary Jones </NAME> <ADDRESS> </ADDRESS> <CITY> </CITY> <ZIP> </ZIP> </AGENT> <OWNER> <NAME> </NAME> <ADDRESS> </ADDRESS> <CITY>
IBM Toolbox for Java
639
</CITY> <ZIP> </ZIP> </OWNER> <TENANT> Yes. </TENANT> <COMMISION> 15% </COMMISION> </CONTACTS> </RESIDENTIAL-LISTING> <RESIDENTIAL-LISTING VERSION="061698" <GENERAL> ID="ID1291">
<IMAGE FORMAT="JPG" WIDTH="300" HEIGHT="150" SRC="house4.jpg"> </IMAGE> <MLS> <MLS-CODE SECURITY="Restricted"> 29389877 </MLS-CODE> <MLS-SOURCE SECURITY="Public"> <NAME> Mary the Realtor </NAME> <PHONE> 1-617-555-3333 </PHONE> <FAX> 1-617-555-4444 </FAX> <WEB> <EMAIL> [email protected] </EMAIL> <SITE> www.bigbucks.com </SITE> </WEB> </MLS-SOURCE> </MLS> <TYPE> Home </TYPE> <PRICE> $449,000 </PRICE> <AGE UNITS="YEARS"> 7 </AGE> <LOCATION COUNTRY="USA" STATE="MA" COUNTY="MIDDLESEX" SECURITY="Public"> <ADDRESS> 100 Any Road </ADDRESS> <CITY> Lexington </CITY> <ZIP> 02421 </ZIP> </LOCATION>
640
<STRUCTURE> <NUM-BEDS> 7 </NUM-BEDS> <NUM-BATHS> 3 </NUM-BATHS> </STRUCTURE> <DATES> <LISTING-DATE> 6/8/98 </LISTING-DATE> </DATES> <LAND-AREA UNITS="ACRES"> 2.0 </LAND-AREA> </GENERAL> <FEATURES> <DISCLOSURES> In your dreams. </DISCLOSURES> <UTILITIES> Yes </UTILITIES> <EXTRAS> Pest control included. </EXTRAS> <CONSTRUCTION> Wallboard and glue </CONSTRUCTION> <ACCESS> Front door. </ACCESS> </FEATURES> <FINANCIAL> <ASSUMABLE> I assume so. </ASSUMABLE> <OWNER-CARRY> Too heavy. </OWNER-CARRY> <ASSESMENTS> $300,000 </ASSESMENTS> <DUES> $100 </DUES> <TAXES> $2,000 </TAXES> <LENDER> Fly by nite mortgage co. </LENDER> <EARNEST> Burt </EARNEST> <DIRECTIONS> North, south, east, west </DIRECTIONS> </FINANCIAL>
641
<REMARKS> </REMARKS> <CONTACTS> <COMPANY> <NAME> Noplace Realty </NAME> <ADDRESS> 12 Main Street </ADDRESS> <CITY> Lowell, MA </CITY> <ZIP> 34567 </ZIP> </COMPANY> <AGENT> <NAME> Mary Jones </NAME> <ADDRESS> </ADDRESS> <CITY> </CITY> <ZIP> </ZIP> </AGENT> <OWNER> <NAME> </NAME> <ADDRESS> </ADDRESS> <CITY> </CITY> <ZIP> </ZIP> </OWNER> <TENANT> Yes. </TENANT> <COMMISION> 15% </COMMISION> </CONTACTS> </RESIDENTIAL-LISTING> </RESIDENTIAL-LISTINGS>
642
</fo:simple-page-master> <fo:page-sequence-master master-name="theMaster"> <fo:single-page-master-reference master-name="thePage" /> </fo:page-sequence-master> </fo:layout-master-set> <fo:page-sequence master-name="theMaster"> <fo:flow flow-name="theRegion"> <xsl:apply-templates/> </fo:flow> </fo:page-sequence> </fo:root> </xsl:template> <xsl:template match="RESIDENTIAL-LISTING"> <fo:block font-family="Times New Roman" font-weight="normal" font-size="24pt" background-color="silver" padding-before="5px" padding-after="5px" padding-start="5px" padding-end="5px" border-before-style="solid" border-before-color="blue" border-after-style="solid" border-after-color="blue" border-start-style="solid" border-start-color="blue" border-end-style="solid" border-end-color="blue"> <fo:character character="y" background-color="blue" border-before-style="solid" border-before-color="yellow" border-after-style="solid" border-after-color="yellow" border-start-style="solid" border-start-color="yellow" border-end-style="solid" border-end-color="yellow" /> </fo:block> </xsl:template> </xsl:stylesheet>
ResourceList
v v v Example: Getting and printing the contents of a ResourceList Example: Using generic code to access a ResourceList Example: Presenting a resource list in a servlet
Presentation
v Example: Using Presentations The following disclaimer applies to all of the IBM Toolbox for Java examples: Code example disclaimer IBM grants you a nonexclusive copyright license to use all programming code examples from which you can generate similar function tailored to your own specific needs. All sample code is provided by IBM for illustrative purposes only. These examples have not been thoroughly tested under all conditions. IBM, therefore, cannot guarantee or imply reliability, serviceability, or function of these programs.
IBM Toolbox for Java
643
All programs contained herein are provided to you "AS IS" without any warranties of any kind. The implied warranties of non-infringement, merchantability and fitness for a particular purpose are expressly disclaimed.
644
645
RJob Javadoc
Examples
Example: Printing the contents of a ResourceList Here is an example of generic code that prints some of the contents of a ResourceList:
void printContents(ResourceList resourceList, long numberOfItems) throws ResourceException { // Open the list and wait for the requested number of items // to become available. resourceList.open(); resourceList.waitForResource(numberOfItems); for(long i = 0; i < numberOfItems; ++i) { System.out.println(resourceList.resourceAt(i)); } }
Example: Using ResourceMetaData to access every attribute supported by a resource This is an example of generic code that prints the value of every attribute supported by a resource:
void printAllAttributeValues(Resource resource) throws ResourceException { // Get the attribute meta data. ResourceMetaData[] attributeMetaData = resource.getAttributeMetaData(); // Loop through all attributes and print the values. for(int i = 0; i < attributeMetaData.length; ++i) { Object attributeID = attributeMetaData[i].getID(); Object value = resource.getAttributeValue(attributeID); System.out.println("Attribute " + attributeID + " = " + value); } }
646
This is an example of generic code that resets all attributes of a ChangeableResource to their default values:
void resetAttributeValues(ChangeableResource resource) throws ResourceException { // Get the attribute meta data. ResourceMetaData[] attributeMetaData = resource.getAttributeMetaData(); // Loop through all attributes. for(int i = 0; i < attributeMetaData.length; ++i) { // If the attribute is changeable (not read only), then // reset its value to the default. if (! attributeMetaData[i].isReadOnly()) { Object attributeID = attributeMetaData[i].getID(); Object defaultValue = attributeMetaData[i].getDefaultValue(); resource.setAttributeValue(attributeID, defaultValue); } } // Commit all of the attribute changes. resource.commitAttributeChanges(); }
Examples: RFML
This section lists the code examples that are provided throughout the documentation of the IBM Toolbox for Java RFML component. v Example: Using RFML compared to using IBM Toolbox for Java Record classes v Example: RFML source file The following disclaimer applies to all of the IBM Toolbox for Java examples: Code example disclaimer IBM grants you a nonexclusive copyright license to use all programming code examples from which you can generate similar function tailored to your own specific needs. All sample code is provided by IBM for illustrative purposes only. These examples have not been thoroughly tested under all conditions. IBM, therefore, cannot guarantee or imply reliability, serviceability, or function of these programs. All programs contained herein are provided to you "AS IS" without any warranties of any kind. The implied warranties of non-infringement, merchantability and fitness for a particular purpose are expressly disclaimed.
647
<recordformat name="cusrec"> <data <data <data <data <data <data <data <data <data <data <data name="cusnum" name="lstnam" name="init" name="street" name="city" name="state" name="zipcod" name="cdtlmt" name="chgcod" name="baldue" name="cdtdue" type="zoned" type="char" type="char" type="char" type="char" type="char" type="zoned" type="zoned" type="zoned" type="zoned" type="zoned" length="6" precision="0" init="0"/> length="8" ccsid="37" init="A"/> length="3" ccsid="37" init="B"/> length="13" ccsid="37" init="C"/> length="6" ccsid="37" init="D"/> length="2" ccsid="37" init="E"/> length="5" init="1"/> length="4" init="2"/> length="1" init="3"/> length="6" precision="2" init="4"/> length="6" precision="2" init="5"/>
</recordformat> <recordformat name="cusrec1"> <data <data <data <data <data <data <data <data <data <data <data name="cusnum" name="lstnam" name="init" name="street" name="city" name="state" name="zipcod" name="cdtlmt" name="chgcod" name="baldue" name="cdtdue" type="zoned" length="6" precision="0" init="0"/> type="char" length="8" ccsid="37" init="A"/> type="char" length="3" ccsid="37" init="B"/> type="char" length="13" ccsid="37" init="C"/> type="char" length="6" ccsid="37" init="D"/> type="char" length="2" ccsid="37" init="E"/> type="zoned" length="5" init="1"/> type="zoned" length="4" init="2"/> type="zoned" length="1" init="3"/> type="struct" struct="balance"/> type="struct" struct="balance"/>
</recordformat> <recordformat name="cusrecAscii"> <data <data <data <data <data <data <data <data <data <data <data name="cusnum" name="lstnam" name="init" name="street" name="city" name="state" name="zipcod" name="cdtlmt" name="chgcod" name="baldue" name="cdtdue" type="zoned" type="char" type="char" type="char" type="char" type="char" type="zoned" type="zoned" type="zoned" type="zoned" type="zoned" length="6" precision="0" init="0"/> length="8" init="A"/> length="3" init="B"/> length="13" init="C"/> length="6" init="D"/> length="2" init="E"/> length="5" init="1"/> length="4" init="2"/> length="1" init="3"/> length="6" precision="2" init="4"/> length="6" precision="2" init="5"/>
</recordformat> <struct name="balance"> <data name="amount" type="zoned" length="6" precision="2" init="7"/> </struct> </rfml>
Related reference Example: Using RFML compared to using IBM Toolbox for Java Record classes on page 407 This example illustrates the differences between using RFML and using the IBM Toolbox for Java Record classes.
Example: Using a profile token credential to swap the IBM i thread identity
The following code example shows you how to use a profile token credential to swap the IBM i thread identity and perform work on behalf of a specific user.
648
Note: Read the Code example disclaimer for important legal information. | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
// Create a single-use ProfileTokenCredential with a 60 second timeout. AS400 system = new AS400(); ProfileTokenCredential pt = new ProfileTokenCredential(); pt.setSystem(system); pt.setTimeoutInterval(60); pt.setTokenType(ProfileTokenCredential.TYPE_SINGLE_USE); // A valid user ID and password must be substituted. pt.setTokenExtended("user", "password"); // Swap the OS/400 thread identity, retrieving a credential to // Swap back to the original identity later. AS400Credential cr = pt.swap(true); // Create a second AS400 object AS400 system2 = new AS400(); CommandCall cmd = new CommandCall(system); // Perform work under the swapped identity at this point. // Swap back to the original OS/400 thread identity. cr.swap(); // Clean up the credentials. cr.destroy(); pt.destroy(); system.disconnectAllServices(); system2.disconnectAllServices();
649
HTML source generated from the Java source by the using HTMLTableConverter
Using the HTMLTableConverter class on page 239 in the Java source example above generates the following HTML code.
<table> <tr> <th>Customer ID</th> <th>Order Number</th> </tr> <tr> <td>777-53-4444</td> <td>12345-XYZ</td>
650
651
HTML source generated from the Java source by the using HTMLTableConverter Using the HTMLTableConverter class in the Java source example above generates the following HTML code.
<table> <tr> <th>CNUM</th> <th>LNAM</th> <th>INIT</th> <th>STR</th> <th>CTY</th> <th>STATE</th> <th>ZIP</th> <th>CTLMT</th> <th>CHGCOD</th> <th>BDUE</th> <th>CTDUE</th> </tr> <tr> <td>938472</td> <td>Henning </td> <td>G K</td> <td>4859 Elm Ave </td> <td>Dallas</td> <td>TX</td> <td align="right">75217</td> <td align="right">5000</td> <td align="right">3</td> <td align="right">37.00</td> <td align="right">0.00</td> </tr> <tr> <td>839283</td> <td>Jones </td> <td>B D</td> <td>21B NW 135 St</td> <td>Clay </td> <td>NY</td> <td align="right">13041</td> <td align="right">400</td> <td align="right">1</td> <td align="right">100.00</td> <td align="right">0.00</td> </tr> <tr> <td>392859</td> <td>Vine </td> <td>S S</td> <td>PO Box 79 </td> <td>Broton</td> <td>VT</td> <td align="right">5046</td> <td align="right">700</td> <td align="right">1</td> <td align="right">439.00</td> <td align="right">0.00</td> </tr> </table>
How a browser displays the generated HTML The following table shows how the HTML source code looks when viewed in a browser.
CNUM LNAM 938472 Henning INIT GK STR 4859 Elm Ave CTY Dallas STATE TX ZIP 75217 CTLMT CHGCOD 5000 3 BDUE 37.00 CTDUE 0.00
652
INIT BD SS
STATE NY VT
HTML source generated from the Java source by the using HTMLTableConverter Using the HTMLTableConverter class in the Java source example above generates the following HTML code.
<table border="2" cellpadding="1" cellspacing="1"> <tr> <th>Customer Number</th> <th>Last Name</th> <th>Initials</th>
IBM Toolbox for Java
653
<th>Street Address</th> <th>City</th> <th>State</th> <th>Zip Code</th> <th>Credit Limit</th> <th>Charge Code</th> <th>Balance Due</th> <th>Credit Due</th> </tr> <tr> <td>938472</td> <td>Henning </td> <td>G K</td> <td>4859 Elm Ave </td> <td>Dallas</td> <td>TX</td> <td align="right">75217</td> <td align="right">5000</td> <td align="right">3</td> <td align="right">37.00</td> <td align="right">0.00</td> </tr> <tr> <td>839283</td> <td>Jones </td> <td >B D</td> <td>21B NW 135 St</td> <td>Clay </td> <td>NY</td> <td align="right">13041</td> <td align="right">400</td> <td align="right">1</td> <td align="right">100.00</td> <td align="right">0.00</td> </tr> <tr> <td>392859</td> <td>Vine </td> <td>S S</td> <td>PO Box 79 </td> <td>Broton</td> <td>VT</td> <td align="right">5046</td> <td align="right">700</td> <td align="right">1</td> <td align="right">439.00</td> <td align="right">0.00</td> </tr> <tr> <td>938485</td> <td>Johnson </td> <td>J A</td> <td>3 Alpine Way </td> <td>Helen </td> <td>GA</td> <td align="right">30545</td> <td align="right">9999</td> <td align="right">2</td> <td align="right">3987.50</td> <td align="right">33.50</td> </tr> <tr> <td>397267</td> <td>Tyron </td> <td>W E</td> <td>13 Myrtle Dr </td>
654
<td>Hector</td> <td>NY</td> <td align="right">14841</td> <td align="right">1000</td> <td align="right">1</td> <td align="right">0.00</td> <td align="right">0.00</td> </tr> <tr> <td>389572</td> <td>Stevens </td> <td>K L</td> <td>208 Snow Pass</td> <td>Denver</td> <td>CO</td> <td align="right">80226</td> <td align="right">400</td> <td align="right">1</td> <td align="right">58.75</td> <td align="right">1.50</td> </tr> <tr> <td>846283</td> <td>Alison </td> <td>J S</td> <td>787 Lake Dr </td> <td>Isle </td> <td>MN</td> <td align="right">56342</td> <td align="right">5000</td> <td align="right">3</td> <td align="right">10.00</td> <td align="right">0.00</td> </tr> <tr> <td>475938</td> <td>Doe </td> <td>J W</td> <td>59 Archer Rd </td> <td>Sutter</td> <td>CA</td> <td align="right">95685</td> <td align="right">700</td> <td align="right">2</td> <td align="right">250.00</td> <td align="right">100.00</td> </tr> <tr> <td>693829</td> <td>Thomas </td> <td>A N</td> <td>3 Dove Circle</td> <td>Casper</td> <td>WY</td> <td align="right">82609</td> <td align="right">9999</td> <td align="right">2</td> <td align="right">0.00</td> <td align="right">0.00</td> </tr> <tr> <td>593029</td> <td>Williams</td> <td>E D</td> <td>485 SE 2 Ave </td> <td>Dallas</td> <td>TX</td>
IBM Toolbox for Java
655
<td align="right">75218</td> <td align="right">200</td> <td align="right">1</td> <td align="right">25.00</td> <td align="right">0.00</td> </tr> <tr> <td>192837</td> <td>Lee </td> <td>F L</td> <td>5963 Oak St </td> <td>Hector</td> <td>NY</td> <td align="right">14841</td> <td align="right">700</td> <td align="right">2</td> <td align="right">489.50</td> <td align="right">0.50</td> </tr> <tr> <td>583990</td> <td>Abraham </td> <td>M T</td> <td>392 Mill St </td> <td>Isle </td> <td>MN</td> <td align="right">56342</td> <td align="right">9999</td> <td align="right">3</td> <td align="right">500.00</td> <td align="right">0.00</td> </tr> </table>
How a browser displays the generated HTML The following table shows how the HTML source code looks when viewed in a browser.
Customer Last Number Name 938472 839283 392859 938485 397267 389572 846283 475938 693829 593029 Henning Jones Vine Johnson Tyron Stevens Alison Doe Thomas Williams Initials GK BD SS JA WE KL JS JW AN ED Street Address 4859 Elm Ave 21B NW 135 St City Dallas Clay State TX NY VT GA NY CO MN CA WY TX Zip Code 75217 13041 5046 30545 14841 80226 56342 95685 82609 75218 Credit Limit 5000 400 700 9999 1000 400 5000 700 9999 200 Charge Code 3 1 1 2 1 1 3 2 2 1 Balance Due 37.00 100.00 439.00 3987.50 0.00 58.75 10.00 250.00 0.00 25.00 Credit Due 0.00 0.00 0.00 33.50 0.00 1.50 0.00 100.00 0.00 0.00
PO Box 79 Broton 3 Alpine Way 13 Myrtle Dr 208 Snow Pass 787 Lake Dr 59 Archer Rd 3 Dove Circle 485 SE 2 Ave Helen Hector Denver Isle Sutter Casper Dallas
656
Initials FL
City Hector
State NY MN
Charge Code 2 3
Abraham M T
import com.ibm.as400.util.servlet.HTMLFormConverter; import com.ibm.as400.util.servlet.SQLResultSetRowData; import com.ibm.as400.access.AS400; import com.ibm.as400.access.AS400JDBCDriver; /** * An example of using the HTMLFormConverter class in a servlet. */ public class HTMLFormConverterExample extends HttpServlet { private String userId_ = "myUserId"; private String password_ = "myPwd"; private AS400 system_; private Connection databaseConnection_;
// Perform cleanup before returning to the main HTML form. public void cleanup() { try { // Close the database connection. if (databaseConnection_ != null) { databaseConnection_.close(); databaseConnection_ = null; }
IBM Toolbox for Java
657
} catch (Exception e) { e.printStackTrace (); } } // Convert the row data to formatted HTML. private HTMLTable[] convertRowData(SQLResultSetRowData rowData) { try { // Create the converter, which will generate HTML from // the result set that comes back from the database query. HTMLFormConverter converter = new HTMLFormConverter(); // Set the form attributes. converter.setBorderWidth(3); converter.setCellPadding(2); converter.setCellSpacing(4); // Convert the row data to HTML. HTMLTable[] htmlTable = converter.convertToForms(rowData); return htmlTable; } catch (Exception e) { e.printStackTrace (); return null; } } // Return the response to the client. public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println(showHtmlMain()); out.close(); } // Handle the data posted to the form. public void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { SQLResultSetRowData rowData = new SQLResultSetRowData(); HTMLTable[] htmlTable = null; // Get the current session object or create one if needed. HttpSession session = request.getSession(true); ServletOutputStream out = response.getOutputStream(); response.setContentType("text/html"); Hashtable parameters = getRequestParameters (request); // Retrieve the row data and HTML table values for this session. rowData = (SQLResultSetRowData) session.getValue("sessionRowData"); htmlTable = (HTMLTable[]) session.getValue("sessionHtmlTable");
658
// if this is the first time through, show first record if (parameters.containsKey("getRecords")) { rowData = getAllRecords(parameters, out); if (rowData != null) { // Set the row data value for this session. session.putValue("sessionRowData", rowData); // Position to the first record. rowData.first(); // Convert the row data to formatted HTML. htmlTable = convertRowData(rowData); if (htmlTable != null) { rowData.first(); session.putValue("sessionHtmlTable", htmlTable); out.println(showHtmlForRecord(htmlTable, 0)); } } } // If the "Return To Main" button was pressed, // go back to the main HTML form else if (parameters.containsKey("returnToMain")) { session.invalidate(); cleanup(); out.println(showHtmlMain()); } // if the "First" button was pressed, show the first record else if (parameters.containsKey("getFirstRecord")) { rowData.first(); out.println(showHtmlForRecord(htmlTable, 0)); } // if the "Previous" button was pressed, show the previous record else if (parameters.containsKey("getPreviousRecord")) { if (!rowData.previous()) { rowData.first(); } out.println(showHtmlForRecord(htmlTable, rowData.getCurrentPosition())); } // if the "Next" button was pressed, show the next record else if (parameters.containsKey("getNextRecord")) { if (!rowData.next()) { rowData.last(); } out.println(showHtmlForRecord(htmlTable, rowData.getCurrentPosition())); } // if the "Last" button was pressed, show the last record else if (parameters.containsKey("getLastRecord")) { rowData.last(); out.println(showHtmlForRecord(htmlTable, rowData.getCurrentPosition())); } // if none of the above, there must have been an error else { out.println(showHtmlForError("Internal error occurred. Unexpected parameters.")); }
IBM Toolbox for Java
659
// Save the row data value for this session so the current position // is updated in the object associated with this session. session.putValue("sessionRowData", rowData); // Close the output stream out.close(); } // Get all the records from the file input by the user. private SQLResultSetRowData getAllRecords(Hashtable parameters, ServletOutputStream out) throws IOException { SQLResultSetRowData records = null; try { // Get the system, library and file name from the parameter list. String sys = ((String) parameters.get("System")).toUpperCase(); String lib = ((String) parameters.get("Library")).toUpperCase(); String file = ((String) parameters.get("File")).toUpperCase(); if ((sys == null || sys.equals("")) || (lib == null || lib.equals("")) || (file == null || file.equals(""))) { out.println(showHtmlForError("Invalid system, file or library name.")); } else { // Get the connection to the server. getDatabaseConnection (sys, out); if (databaseConnection_ != null) { Statement sqlStatement = databaseConnection_.createStatement(); // Query the database to get the result set. String query = "SELECT * FROM " + lib + "." + file; ResultSet rs = sqlStatement.executeQuery (query); boolean rsHasRows = rs.next(); // position cursor to first row
// Show error message if the file contains no record; // otherwise, set row data to result set data. if (!rsHasRows) { out.println(showHtmlForError("No records in the file.")); } else { records = new SQLResultSetRowData (rs); } // Don't close the Statement before we're done using // the ResultSet or bad things may happen. sqlStatement.close(); } } } catch (Exception e) { e.printStackTrace (); out.println(showHtmlForError(e.toString())); } return records; }
660
// Establish a database connection. private void getDatabaseConnection (String sysName, ServletOutputStream out) throws IOException { if (databaseConnection_ == null) { try { databaseConnection_ = DriverManager.getConnection("jdbc:as400://sysName,userId_,password_ ); } catch (Exception e) { e.printStackTrace (); out.println(showHtmlForError(e.toString())); } } } // Gets the parameters from an HTTP servlet request. private static Hashtable getRequestParameters (HttpServletRequest request) { Hashtable parameters = new Hashtable (); Enumeration enum = request.getParameterNames(); while (enum.hasMoreElements()) { String key = (String) enum.nextElement(); String value = request.getParameter (key); parameters.put (key, value); } return parameters; } // Get the servlet information. public String getServletInfo() { return "HTMLFormConverterExample"; } // Perform initialization steps. public void init(ServletConfig config) { try { super.init(config); // Register the JDBC driver try { DriverManager.registerDriver(new AS400JDBCDriver()); } catch (Exception e) { System.out.println("JDBC Driver not found"); } } catch (Exception e) { e.printStackTrace(); } }
661
// Set the page header info. private String showHeader(String title) { StringBuffer page = new StringBuffer(); page.append("<html><head><title>" + title + "</title>"); page.append("</head><body bgcolor=\"blanchedalmond\">"); return page.toString (); } // Show the HTML page with the appropriate error information. private String showHtmlForError(String message) { String title = "Error"; StringBuffer page = new StringBuffer(); page.append (showHeader (title)); try { // Create the HTML Form object HTMLForm errorForm = new HTMLForm("HTMLFormConverterExample"); // Set up so that doPost() gets called when the form is submitted. errorForm.setMethod(HTMLForm.METHOD_POST); // Create a single-column panel to which the // HTML elements will be added. GridLayoutFormPanel grid = new GridLayoutFormPanel(); // Create the text element for the error and add it to the panel. HTMLText text = new HTMLText(message); text.setBold(true); text.setColor(Color.red); grid.addElement(text); // Create the button to return to main and add it to the panel. grid.addElement(new SubmitFormInput("returnToMain", "Return to Main")); // Add the panel to the HTML form. errorForm.addElement(grid); page.append(errorForm.toString()); } catch (Exception e) { e.printStackTrace (); } page.append("</body></html>"); return page.toString(); } // Show the HTML form for an individual record. private String showHtmlForRecord(HTMLTable[] htmlTable, int position) { String title = "HTMLFormConverter Example"; StringBuffer page = new StringBuffer(); page.append (showHeader (title)); page.append("<h1>" + title + "</h1>"); try { // Create the HTML Form object HTMLForm recForm = new HTMLForm("HTMLFormConverterExample"); // Set up so that doPost() gets called when the form is submitted.
662
recForm.setMethod(HTMLForm.METHOD_POST); // Set up a single-column panel layout, within which to arrange // the generated HTML elements. GridLayoutFormPanel grid = new GridLayoutFormPanel(); // Create and add a table caption that keeps track // of the current record. HTMLText recNumText = new HTMLText("Record number: " + (position + 1)); recNumText.setBold(true); grid.addElement(recNumText); // Set up a two-column panel layout, within which to arrange // the table and text to comment on the converter output. GridLayoutFormPanel tableGrid = new GridLayoutFormPanel(2); tableGrid.addElement(htmlTable[position]); HTMLText comment = new HTMLText(" <---- Output from the HTMLFormConverter class"); comment.setBold(true); comment.setColor(Color.blue); tableGrid.addElement(comment); // Add the table line to the panel. grid.addElement(tableGrid); // Set up a single-row panel layout, within which to arrange // the buttons for moving through the record list. LineLayoutFormPanel buttonLine = new LineLayoutFormPanel(); buttonLine.addElement(new SubmitFormInput("getFirstRecord", "First")); buttonLine.addElement(new SubmitFormInput("getPreviousRecord", "Previous")); buttonLine.addElement(new SubmitFormInput("getNextRecord", "Next")); buttonLine.addElement(new SubmitFormInput("getLastRecord", "Last")); // Set up another single-row panel layout for the // Return To Main button. LineLayoutFormPanel returnToMainLine = new LineLayoutFormPanel(); returnToMainLine.addElement(new SubmitFormInput("returnToMain", "Return to Main")); // Add the lines containing the buttons to the grid panel. grid.addElement(buttonLine); grid.addElement(returnToMainLine); // Add the panel to the form. recForm.addElement(grid); // Add the form to the HTML page. page.append(recForm.toString()); } catch (Exception e) { e.printStackTrace (); } page.append("</body></html>"); return page.toString(); } // Show the main HTML form (request input for system, file, // and library name). private String showHtmlMain() { String title = "HTMLFormConverter Example"; StringBuffer page = new StringBuffer(); page.append (showHeader (title)); page.append("<h1>" + title + "</h1>");
663
// Create the HTML Form object HTMLForm mainForm = new HTMLForm("HTMLFormConverterExample"); try { // Set up so that doPost() gets called when the form is submitted. mainForm.setMethod(HTMLForm.METHOD_POST); // Add a brief description to the form. HTMLText desc = new HTMLText("<P>This example uses the HTMLFormConverter class " + "to convert data retrieved from a server " + "file. The converter produces an array of HTML " + "tables. Each entry in the array is a record from " + "the file. " + "Records are displayed one at a time, " + "giving you buttons to move forward or backward " + "through the list of records.</P>"); mainForm.addElement(desc); // Add instructions to the form. HTMLText instr = new HTMLText("<P>Please input the name of the server, " + "and the file and library name for the file you " + "wish to access. Then push the Show Records " + "button to continue.</P>"); mainForm.addElement(instr); // Create a grid layout panel and add the system, file // and library input fields. GridLayoutFormPanel panel = new GridLayoutFormPanel(2); LabelFormElement sysPrompt = new LabelFormElement("Server: "); TextFormInput system = new TextFormInput("System"); system.setSize(10); LabelFormElement filePrompt = new LabelFormElement("File name: "); TextFormInput file = new TextFormInput("File"); file.setSize(10); LabelFormElement libPrompt = new LabelFormElement("Library name: "); TextFormInput library = new TextFormInput("Library"); library.setSize(10); panel.addElement(sysPrompt); panel.addElement(system); panel.addElement(filePrompt); panel.addElement(file); panel.addElement(libPrompt); panel.addElement(library); // Add the panel to the form. mainForm.addElement(panel); // Create the submit button and add it to the form. mainForm.addElement(new SubmitFormInput("getRecords", "Show Records")); } catch (Exception e) { e.printStackTrace (); } page.append(mainForm.toString()); page.append("</body></html>");
664
return page.toString(); } }
665
<tr> <form> <td><input type="submit" name="getFirstRecord" value="First" /> <input type="submit" name="getPreviousRecord" value="Previous" /> <input type="submit" name="getNextRecord" value="Next" /> <input type="submit" name="getLastRecord" value="Last" /> <br /> </td> </tr> <tr> <td><input type="submit" name="returnToMain" value="Return to Main" /> <br /> </td> </tr> </table> </form>
import com.ibm.as400.util.html.*; import com.ibm.as400.util.servlet.*; import com.ibm.as400.access.*; /* An example of using IBM Toolbox for Java classes in a servlet. Schemas of SQL databases on the server: File . . . . . . Library . . . Field LICENSE USER_ID E_MAIL WHEN_ADDED TIME_STAMP File . . . . . . Library . . . Field LICENSE REPORTER DATE_ADDED TIME_ADDED TIME_STAMP LOCATION COLOR CATEGORY */ LICENSES LIGHTSON Type CHARACTER CHARACTER CHARACTER DATE TIMESTAMP REPORTS LIGHTSON Type CHARACTER CHARACTER DATE TIME TIMESTAMP CHARACTER CHARACTER CHARACTER Length 10 10 Nulls NOT NULL NOT NULL NOT NULL NOT NULL NOT NULL NOT NULL NOT NULL NOT NULL Length 10 10 20 Nulls NOT NULL NOT NULL WITH DEFAULT NOT NULL NOT NULL WITH DEFAULT NOT NULL WITH DEFAULT
10 10 10
666
private AS400 system_; private String password_; // password for the server and for the SQL database private java.sql.Connection databaseConnection_;
public void destroy (ServletConfig config) { try { if (databaseConnection_ != null) { databaseConnection_.close(); } } catch (Exception e) { e.printStackTrace (); } } public void doGet (HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { HttpSession session = request.getSession(); response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println(showHtmlMain()); out.close(); } public void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession session = request.getSession(true); ServletOutputStream out = response.getOutputStream(); response.setContentType("text/html"); Hashtable parameters = getRequestParameters (request); if (parameters.containsKey("askingToReport")) out.println (showHtmlForReporting ()); else if (parameters.containsKey("askingToRegister")) out.println (showHtmlForRegistering ()); else if (parameters.containsKey("askingToUnregister")) out.println(showHtmlForUnregistering()); else if (parameters.containsKey("askingToListRegistered")) out.println (showHtmlForListingAllRegistered ()); else if (parameters.containsKey("askingToListReported")) out.println (showHtmlForListingAllReported ()); else if (parameters.containsKey("returningToMain")) out.println (showHtmlMain ()); else { // None of the above, so assume the user has filled out a form // and is submitting information. Grab the incoming info // and do the requested action. if (parameters.containsKey("submittingReport")) { String acknowledgement = reportLightsOn (parameters, out); out.println (showAcknowledgement(acknowledgement)); } else if (parameters.containsKey("submittingRegistration")) { String acknowledgement = registerLicense (parameters, out); out.println (showAcknowledgement(acknowledgement)); }
667
else if (parameters.containsKey("submittingUnregistration")) { String acknowledgement = unregisterLicense (parameters, out); out.println (showAcknowledgement(acknowledgement)); } else { out.println (showAcknowledgement("Error (internal): " + "Neither Report, Register, " + "Unregister, ListRegistered, or ListReported.")); } } out.close(); // Close the output stream. } // Gets the parameters from an HTTP servlet request, and packages them // into a hashtable for convenience. private static Hashtable getRequestParameters (HttpServletRequest request) { Hashtable parameters = new Hashtable (); Enumeration enum = request.getParameterNames(); while (enum.hasMoreElements()) { String key = (String) enum.nextElement(); String value = request.getParameter (key); parameters.put (key, value); } return parameters; } // Removes blanks and hyphens from a String, and sets it to all uppercase. private static String normalize (String oldString) { if (oldString == null || oldString.length() == 0) return null; StringBuffer newString = new StringBuffer (); for (int i=0; i<oldString.length(); i++) { if (oldString.charAt(i) != ' ' && oldString.charAt(i) != '-') newString.append (oldString.charAt(i)); } return newString.toString().toUpperCase(); } // Composes a list of single-quoted strings. private static String quoteList (String[] inList) { StringBuffer outList = new StringBuffer(); for (int i=0; i<inList.length; i++) { outList.append ("'" + inList[i] + "'"); if (i<inList.length-1) outList.append (","); } return outList.toString(); } public String getServletInfo () { return "Lights-On Servlet"; } private AS400 getSystem () { try { if (system_ == null)
668
{ system_ = new AS400(); // Note: It would be better to get these values // from a properties file. String sysName = "MYSYSTEM"; // TBD String userId = "MYUSERID"; // TBD String password = "MYPASSWD"; // TBD system_.setSystemName(sysName); system_.setUserId(userId); system_.setPassword(password); password_ = password; system_.connectService(AS400.DATABASE); system_.connectService(AS400.FILE); system_.addPasswordCacheEntry(sysName, userId, password_); } } catch (Exception e) { e.printStackTrace (); system_ = null; } return system_; } public void init (ServletConfig config) { boolean rc; try { super.init(config); // Register the JDBC driver. try { java.sql.DriverManager.registerDriver(new com.ibm.as400.access.AS400JDBCDriver()); } catch (Exception e) { System.out.println("JDBC Driver not found"); } } catch (Exception e) { e.printStackTrace(); } } private void getDatabaseConnection () { if (databaseConnection_ == null) { try { databaseConnection_ = java.sql.DriverManager.getConnection( "jdbc:as400://" + getSystem().getSystemName() + "/" + "LIGHTSON", getSystem().getUserId(), password_ ); } catch (Exception e) { e.printStackTrace (); } } } private String registerLicense (Hashtable parameters, ServletOutputStream out) { String licenseNum = normalize ((String)parameters.get("licenseNum")); String eMailAddress = (String)parameters.get("eMailAddress"); StringBuffer acknowledgement = new StringBuffer(); if (licenseNum == null || licenseNum.length() == 0)
IBM Toolbox for Java
669
acknowledgement.append ("Error: License number not specified.\n"); if (eMailAddress == null || eMailAddress.length() == 0) acknowledgement.append ("Error: Notification e-mail address not specified.\n"); if (acknowledgement.length() == 0) { try { // Insert the new license number and e-mail address into the database. getDatabaseConnection (); Statement sqlStatement = databaseConnection_.createStatement(); // Issue the request. String cmd = "INSERT INTO LICENSES (LICENSE, E_MAIL) VALUES (" + quoteList(new String[] {licenseNum, eMailAddress}) + ")"; sqlStatement.executeUpdate(cmd); sqlStatement.close(); // Acknowledge the request. acknowledgement.append ("License number " + licenseNum + " has been registered."); acknowledgement.append ("Notification e-mail address is: " + eMailAddress); } catch (Exception e) { e.printStackTrace (); } } return acknowledgement.toString(); } private String unregisterLicense (Hashtable parameters, ServletOutputStream out) { String licenseNum = normalize ((String)parameters.get("licenseNum")); StringBuffer acknowledgement = new StringBuffer(); if (licenseNum == null || licenseNum.length() == 0) acknowledgement.append ("Error: License number not specified.\n"); if (acknowledgement.length() == 0) { try { // Remove the specified license number and e-mail address from database. getDatabaseConnection (); Statement sqlStatement = databaseConnection_.createStatement(); // Delete the row(s) from the LICENSES database. String cmd = "DELETE FROM LICENSES WHERE LICENSE = '" + licenseNum + "'"; sqlStatement.executeUpdate(cmd); sqlStatement.close(); // Acknowledge the request. acknowledgement.append ("License number " + licenseNum + " has been unregistered."); } catch (Exception e) { e.printStackTrace (); } } return acknowledgement.toString(); } private String reportLightsOn (Hashtable parameters, ServletOutputStream out) { String licenseNum = normalize ((String)parameters.get("licenseNum")); String location = (String)parameters.get("location"); String color = (String)parameters.get("color"); String category = (String)parameters.get("category"); StringBuffer acknowledgement = new StringBuffer(); if (licenseNum == null || licenseNum.length() == 0)
670
acknowledgement.append ("Error: License number not specified."); if (acknowledgement.length() == 0) { try { // Report "lights on" for a specified vehicle. getDatabaseConnection (); Statement sqlStatement = databaseConnection_.createStatement(); // Add an entry to the REPORTS database. String cmd = "INSERT INTO REPORTS (LICENSE, LOCATION, COLOR, CATEGORY) VALUES (" + quoteList(new String[] {licenseNum, location, color, category}) + ")"; sqlStatement.executeUpdate(cmd); sqlStatement.close(); // Acknowledge the request. acknowledgement.append ("License number " + licenseNum + " has been reported. } catch (Exception e) { e.printStackTrace (); } } return acknowledgement.toString(); } private String showHeader (String title) { StringBuffer page = new StringBuffer(); page.append("<html><head><title>" + title + "</title>"); page.append("</head><body bgcolor=\"blanchedalmond\">"); return page.toString (); } private String showAcknowledgement (String acknowledgement) { String title = "Acknowledgement"; StringBuffer page = new StringBuffer(); page.append (showHeader (title)); try { HTMLForm form = new HTMLForm("LightsOn"); GridLayoutFormPanel grid = new GridLayoutFormPanel(); HTMLText text = new HTMLText(acknowledgement); if (acknowledgement.startsWith("Error")) text.setBold(true); grid.addElement(text); grid.addElement(new SubmitFormInput("returningToMain", "Home")); form.addElement(grid); page.append(form.toString()); } catch (Exception e) { e.printStackTrace (); } page.append("</body></html>"); return page.toString(); } private String showHtmlMain () { String title = "Lights-On tool"; StringBuffer page = new StringBuffer(); page.append (showHeader (title)); page.append("<h1>" + title + "</h1>"); // Create the HTML Form object.
IBM Toolbox for Java
Thanks!");
671
HTMLForm mainForm = new HTMLForm("LightsOn"); GridLayoutFormPanel grid = new GridLayoutFormPanel(); try { // Set up so that doPost() gets called when the form is submitted. mainForm.setMethod(HTMLForm.METHOD_POST); // Create some buttons. grid.addElement(new SubmitFormInput("askingToReport", "Report a vehicle with lights on")); grid.addElement(new SubmitFormInput("askingToRegister", "Register my license number")); grid.addElement(new SubmitFormInput("askingToUnregister", "Unregister my license number")); grid.addElement(new SubmitFormInput("askingToListRegistered", "List all registered licenses")); grid.addElement(new SubmitFormInput("askingToListReported", "List all vehicles with lights on")); mainForm.addElement(grid); } catch (Exception e) { e.printStackTrace (); } page.append(mainForm.toString()); page.append("</body></html>"); return page.toString(); } private String showHtmlForReporting () { String title = "Report a vehicle with lights on"; StringBuffer page = new StringBuffer(); page.append (showHeader (title)); page.append("<h1>" + title + "</h1>"); // Create the HTML Form object. HTMLForm reportForm = new HTMLForm("LightsOn"); GridLayoutFormPanel grid = new GridLayoutFormPanel(2); try { // Set up so that doPost() gets called when the form is submitted. reportForm.setMethod(HTMLForm.METHOD_POST); TextFormInput licenseNum = new TextFormInput("licenseNum"); licenseNum.setSize(10); licenseNum.setMaxLength(10); // Add elements to the line form grid.addElement(new LabelFormElement("Vehicle license number:")); grid.addElement(licenseNum); // Create a radio button group and add the radio buttons. RadioFormInputGroup colorGroup = new RadioFormInputGroup("color"); colorGroup.add("color", colorGroup.add("color", colorGroup.add("color", colorGroup.add("color", colorGroup.add("color", colorGroup.add("color", colorGroup.add("color", colorGroup.add("color", "white", "white", true); "black", "black", false); "gray", "gray", false); "red", "red", false); "yellow", "yellow", false); "green", "green", false); "blue", "blue", false); "brown", "brown", false);
// Create a selection list for category of vehicle. SelectFormElement category = new SelectFormElement("category"); category.addOption("sedan", "sedan", true); category.addOption("convertible", "convertibl"); // 10-char field in DB category.addOption("truck", "truck"); category.addOption("van", "van");
672
category.addOption("SUV", "SUV"); category.addOption("motorcycle", "motorcycle"); category.addOption("other", "other"); // Create a selection list for vehicle location (building number). SelectFormElement location = new SelectFormElement("location"); location.addOption("001", "001", true); location.addOption("002", "002"); location.addOption("003", "003"); location.addOption("005", "005"); location.addOption("006", "006"); location.addOption("015", "015"); grid.addElement(new LabelFormElement("Color:")); grid.addElement(colorGroup); grid.addElement(new LabelFormElement("Vehicle type:")); grid.addElement(category); grid.addElement(new LabelFormElement("Building:")); grid.addElement(location); grid.addElement(new SubmitFormInput("submittingReport", "Submit report")); grid.addElement(new SubmitFormInput("returningToMain", "Home")); reportForm.addElement(grid); } catch (Exception e) { e.printStackTrace (); } page.append(reportForm.toString()); page.append("</body></html>"); return page.toString(); } private String showHtmlForRegistering () { String title = "Register my license number"; StringBuffer page = new StringBuffer(); page.append (showHeader (title)); page.append("<h1>" + title + "</h1>"); // Create the HTML Form object. HTMLForm registrationForm = new HTMLForm("LightsOn"); // Set up a two-column panel layout, within which to arrange // the generated HTML elements. GridLayoutFormPanel grid = new GridLayoutFormPanel(2); try { // Set up so that doPost() gets called when the form is submitted. registrationForm.setMethod(HTMLForm.METHOD_POST); TextFormInput licenseNum = new TextFormInput("licenseNum"); licenseNum.setSize(10); licenseNum.setMaxLength(10); TextFormInput eMailAddress = new TextFormInput("eMailAddress"); eMailAddress.setMaxLength(20); grid.addElement(new LabelFormElement("License number:")); grid.addElement(licenseNum); grid.addElement(new LabelFormElement("E-mail notification address:"));
IBM Toolbox for Java
673
grid.addElement(eMailAddress); grid.addElement(new SubmitFormInput("submittingRegistration", "Register")); grid.addElement(new SubmitFormInput("returningToMain", "Home")); registrationForm.addElement(grid); } catch (Exception e) { e.printStackTrace (); } page.append(registrationForm.toString()); page.append("</body></html>"); return page.toString(); } private String showHtmlForUnregistering () { String title = "Unregister my license number"; StringBuffer page = new StringBuffer(); page.append (showHeader (title)); page.append("<h1>" + title + "</h1>"); // Create the HTML Form object. HTMLForm unregistrationForm = new HTMLForm("LightsOn"); GridLayoutFormPanel grid = new GridLayoutFormPanel(2); try { // Set up so that doPost() gets called when the form is submitted. unregistrationForm.setMethod(HTMLForm.METHOD_POST); // Create the LineLayoutFormPanel object. TextFormInput licenseNum = new TextFormInput("licenseNum"); licenseNum.setSize(10); licenseNum.setMaxLength(10); grid.addElement(new LabelFormElement("Vehicle license number:")); grid.addElement(licenseNum); grid.addElement(new SubmitFormInput("submittingUnregistration", "Unregister")); grid.addElement(new SubmitFormInput("returningToMain", "Home")); unregistrationForm.addElement(grid); } catch (Exception e) { e.printStackTrace (); CharArrayWriter cWriter = new CharArrayWriter(); PrintWriter pWriter = new PrintWriter (cWriter, true); e.printStackTrace (pWriter); page.append (cWriter.toString()); } page.append(unregistrationForm.toString()); page.append("</body></html>"); return page.toString(); } private String showHtmlForListingAllRegistered () { String title = "All registered licenses"; StringBuffer page = new StringBuffer(); page.append (showHeader (title));
674
try { // Create the HTML Form object. HTMLForm mainForm = new HTMLForm("LightsOn"); // Set up a single-column panel layout, within which to arrange // the generated HTML elements. GridLayoutFormPanel grid = new GridLayoutFormPanel(); // Specify the layout for the generated table. HTMLTable table = new HTMLTable(); table.setAlignment(HTMLConstants.LEFT); table.setBorderWidth(3); // Create and add the table caption and header. HTMLTableCaption caption = new HTMLTableCaption(); caption.setAlignment(HTMLConstants.TOP); caption.setElement(title); table.setCaption(caption); table.setHeader(new String[] { "License", "Date added" } ); // Create the converter, which will generate table HTML from // the result set that comes back from the database query. HTMLTableConverter converter = new HTMLTableConverter(); converter.setTable(table); getDatabaseConnection (); Statement sqlStatement = databaseConnection_.createStatement(); // First pre-query the database to verify that it's not empty. String query = "SELECT COUNT(*) FROM LICENSES"; ResultSet rs = sqlStatement.executeQuery (query); rs.next(); // position cursor to first row int rowCount = rs.getInt(1); if (rowCount == 0) { page.append ("<font size=4 color=red>No vehicles have been reported.</font>"); } else { query = "SELECT LICENSE,WHEN_ADDED FROM LICENSES"; rs = sqlStatement.executeQuery (query); SQLResultSetRowData rowData = new SQLResultSetRowData (rs); HTMLTable[] generatedHtml = converter.convertToTables(rowData); grid.addElement(generatedHtml[0]); } sqlStatement.close(); // Note: Mustn't close statement before we're done using result set. grid.addElement(new SubmitFormInput("returningToMain", "Home")); mainForm.addElement(grid); page.append(mainForm.toString()); } catch (Exception e) { e.printStackTrace (); } page.append("</body></html>"); return page.toString(); } private String showHtmlForListingAllReported () { String title = "All vehicles with lights on"; StringBuffer page = new StringBuffer(); page.append (showHeader (title)); try
IBM Toolbox for Java
675
{ // Create the HTML Form object. HTMLForm form = new HTMLForm("LightsOn"); // Set up a single-column panel layout, within which to arrange // the generated HTML elements. GridLayoutFormPanel grid = new GridLayoutFormPanel(); // Specify the layout for the generated table. HTMLTable table = new HTMLTable(); table.setAlignment(HTMLConstants.LEFT); table.setBorderWidth(3); // Create and add the table caption and header. HTMLTableCaption caption = new HTMLTableCaption(); caption.setAlignment(HTMLConstants.TOP); caption.setElement(title); table.setCaption(caption); table.setHeader(new String[] { "License", "Color", "Category", "Date", "Time" } ); // Create the converter, which will generate table HTML from // the result set that comes back from the database query. HTMLTableConverter converter = new HTMLTableConverter(); converter.setTable(table); getDatabaseConnection (); Statement sqlStatement = databaseConnection_.createStatement(); // First pre-query the database to verify that it's not empty. String query = "SELECT COUNT(*) FROM REPORTS"; ResultSet rs = sqlStatement.executeQuery (query); rs.next(); // position cursor to first row int rowCount = rs.getInt(1); if (rowCount == 0) { page.append ("<font size=4 color=red>No vehicles have been reported.</font>"); } else { query = "SELECT LICENSE,COLOR,CATEGORY,DATE_ADDED,TIME_ADDED FROM REPORTS"; rs = sqlStatement.executeQuery (query); SQLResultSetRowData rowData = new SQLResultSetRowData (rs); HTMLTable[] generatedHtml = converter.convertToTables(rowData); grid.addElement(generatedHtml[0]); } sqlStatement.close(); // Note: Mustn't close statement before we're done using result set. grid.addElement(new SubmitFormInput("returningToMain", "Home")); form.addElement(grid); page.append(form.toString()); } catch (Exception e) { e.printStackTrace (); } page.append("</body></html>"); return page.toString(); } }
676
For links to many of the other examples provided in the IBM Toolbox for Java information, see Code examples. Use the following list to view the simple programming examples: v Calling commands v Using message queues v Using record-level access v Using JDBC classes to create and populate a table v Displaying a list of server jobs in a GUI The following disclaimer applies to all of the IBM Toolbox for Java examples: Code example disclaimer IBM grants you a nonexclusive copyright license to use all programming code examples from which you can generate similar function tailored to your own specific needs. All sample code is provided by IBM for illustrative purposes only. These examples have not been thoroughly tested under all conditions. IBM, therefore, cannot guarantee or imply reliability, serviceability, or function of these programs. All programs contained herein are provided to you "AS IS" without any warranties of any kind. The implied warranties of non-infringement, merchantability and fitness for a particular purpose are expressly disclaimed.
3. Open a text editor and type the first simple programming example Note: Make sure to leave out the text that refers to the Notes (for example, Note 1, Note 2, and so on). Save the new document with the name CmdCall.java. 4. Start a command session on your workstation and use the following command to compile the simple programming example:
javac CmdCall.java
5. In the command session, type the following command to run the simple programming example:
java CmdCall
677
Note: Read the Code example disclaimer for important legal information.
//////////////////////////////////////////////////// // // This source is an example of "Job List". // ///////////////////////////////////////////////////// // // The access classes are in the com.ibm.as400.access.package. // Import this package to use the IBM Toolbox for Java classes. // ///////////////////////////////////////////////////// import com.ibm.as400.access.*; public class CmdCall { public static void main(String[] args) { // Like other Java classes, IBM Toolbox for Java classes // throw exceptions when something goes wrong. These must // be caught by programs that use IBM Toolbox for Java. try Note 1 { AS400 system = new AS400(); CommandCall cc = new CommandCall(system); Note 2 cc.run("CRTLIB MYLIB"); Note 3 AS400Message[] ml = cc.getMessageList(); Note 4 for (int i=0; i<ml.length; i++) { System.out.println(ml[i].getText()); Note 5 } } catch (Exception e) { e.printStackTrace(); } System.exit(0); } }
1. IBM Toolbox for Java uses the "AS400" object to identify the target server. If you construct the AS400 object with no parameters, IBM Toolbox for Java prompts for the system name, userid and password. The AS400 class also includes a constructor that takes the system name, userid and password. 2. Use the IBM Toolbox for Java CommandCall object to send commands to the server. When you create the CommandCall object, you pass it an AS400 object so that it knows which server is the target of the command. 3. Use the run() method on the command call object to run a command. 4. The result of running a command is a list of IBM i messages. IBM Toolbox for Java represents these messages as AS400Message objects. When the command is complete, you get the resulting messages from the CommandCall object. 5. Print the message text. Also available are the message ID, message severity, and other information. This program prints only the message text.
678
Use the following as an example for your program. Note: Read the Code example disclaimer for important legal information.
////////////////////////////////////////////////////////////////////////////////// // // Example using the Message Queue function of the IBM Toolbox for Java // // This source is an example of IBM Toolbox for Java "Message Queue". // ////////////////////////////////////////////////////////////////////////////////// package examples; Note 1
public class displayMessages extends Object { public static void main(String[] parameters) Note 3 { displayMessages me = new displayMessages(); me.Main(parameters); Note 4 System.exit(0); } void displayMessage() { } void Main(String[] parms) { try Note 6 { // IBM Toolbox for Java code goes here } catch (Exception e) { e.printStackTrace(); Note 7 } } } Note 5
1. This class is in the 'examples' package. Java uses packages to avoid name conflicts between Java class files. 2. This line makes all of the IBM Toolbox for Java classes in the access package available to this program. The classes in the access package have the common prefix com.ibm.as400. By using an import statement, the program can refer to a class using just its name, not its fully-qualified name. For example, you can reference the AS400 class by using AS400, instead of com.ibm.as400.AS400. 3. This class has a main method; therefore, it can be run as an application. To invoke the program, you run java examples.displayMessages. Note that case must match when running the program. Because an IBM Toolbox for Java class is used, jt400.zip must be in the classpath environment variable. 4. The main method mentioned in Note 3 is static. One of the restrictions of static methods is that static methods can call only other static methods in their class. To avoid this restriction, many java programs create an object, and then do initialization processing in a method called Main. The Main() method can call any other method in the displayMessages object.
IBM Toolbox for Java
679
5. The IBM Toolbox for Java creates threads on behalf of the application to carry out IBM Toolbox for Java activity. If the program does not issue System.exit(0) at termination time, the program may not terminate normally. For example, suppose this program was run from a Windows 95 DOS prompt. Without this line, the command prompt does not return when the program finished. The user has to enter Ctrl-C to get a command prompt. 6. The IBM Toolbox for Java code throws exceptions that your program must catch. 7. This program displays the text of the exception while the program is performing error processing. Exceptions thrown by the IBM Toolbox for Java are translated, so the text of the exception will be the same as the language of the workstation. [ Next part ]
Note 1 Note 2
680
{ e.printStackTrace(); } } }
1. A program uses the AS400 object to designate which server to connect to. With one exception, all programs that need resources from a server must have an AS400 object. The exception is JDBC. If your program uses JDBC, then the IBM Toolbox for Java JDBC driver creates the AS400 object for the program. 2. This program assumes the first command line parameter is the name of the server. If a parameter is passed to the program, the setSystemName method of the AS400 object is used to set the system name. The AS400 object also needs server sign-on information: v If the program is running on a workstation, the IBM Toolbox for Java program prompts the user for a user ID and password. Note: If a system name is not specified as a command line parameter, the AS400 object also prompts for the system name. v If the program is running on the IBM i JVM, then the user ID and password of the user running the Java program is used. In this case, the user does not specify a system name, but lets the system name default to the name of the system that the program is running on. [ Previous part | Next part ]
681
void Main(String[] parms) { try { AS400 system = new AS400(); if (parms.length > 0) system.setSystemName(parms[0]); MessageQueue queue = new MessageQueue(system, MessageQueue.CURRENT); Enumeration e = queue.getMessages(); while (e.hasMoreElements()) { QueuedMessage message = (QueuedMessage) e.nextElement(); System.out.println(message.getText()); Note 4 } } catch (Exception e) { e.printStackTrace(); } } } Note 3 Note 2 Note 1
1. The purpose of this program is to display messages in a server message queue. The MessageQueue object of the IBM Toolbox for Java is used for this task. When the message queue object is constructed, the parameters are the AS400 object and the message queue name. The AS400 object indicates which server contains the resource, and the message queue name identifies which message queue on the server. In this case, a constant is used, which tells the message queue object to access the queue of the signed-on user. 2. The message queue object gets a list of messages from the server. A connection to the server is made at this point. 3. Remove a message from the list. The message is in the IBM Toolbox for Java program's QueuedMessage object. 4. Print the text of the message. [ Previous part ]
682
// ////////////////////////////////////////////////////////////////////////////////// import java.io.*; import java.util.*; import com.ibm.as400.access.*; public class RLSequentialAccessExample { public static void main(String[] parameters) { BufferedReader inputStream = new BufferedReader(new InputStreamReader(System.in),1); String String String String systemName = ""; library = ""; file = ""; member = "";
System.out.println(); try { System.out.print("System name: "); systemName = inputStream.readLine(); System.out.print("Library in which the file exists: "); library = inputStream.readLine(); System.out.print("File name: "); file = inputStream.readLine(); System.out.print("Member name (press enter for first member): "); member = inputStream.readLine(); if (member.equals("")) { member = "*FIRST"; } System.out.println(); } catch (Exception e) { System.out.println("Error obtaining user input."); e.printStackTrace(); System.exit(0); } AS400 system = new AS400(systemName); Note 1 try { system.connectService(AS400.RECORDACCESS); } catch(Exception e) { System.out.println("Unable to connect for record level access."); System.out.println("Check the programmer's guide setup file for special instructions regarding record level access"); e.printStackTrace(); System.exit(0); } QSYSObjectPathName filePathName = new QSYSObjectPathName(library, file, member, "MBR"); SequentialFile theFile = new SequentialFile(system, filePathName.getPath()); Note 3 Note 2
683
AS400FileRecordDescription recordDescription = new AS400FileRecordDescription(system, filePathName.getPath()); try { RecordFormat[] format = recordDescription.retrieveRecordFormat(); Note 4 theFile.setRecordFormat(format[0]); Note 5 Note 6
theFile.open(AS400File.READ_ONLY, 100, AS400File.COMMIT_LOCK_LEVEL_NONE); System.out.println("Displaying file " + library.toUpperCase() + "/" + file.toUpperCase() + "(" + theFile.getMemberName().trim() + "):"); Record record = theFile.readNext(); while (record != null) { System.out.println(record); record = theFile.readNext(); } System.out.println(); theFile.close(); Note 8 Note 7
system.disconnectService(AS400.RECORDACCESS); Note 9 } catch (Exception e) { System.out.println("Error occurred attempting to display the file."); e.printStackTrace(); try { // Close the file theFile.close(); } catch(Exception x) { } system.disconnectService(AS400.RECORDACCESS); System.exit(0); } // Make sure that the application ends; see readme for details System.exit(0); } }
1. This line of code creates an AS400 object and connects to the record-level access service. 2. This line creates a QSYSObjectPathName object that obtains the integrated file system path name form of the object to be displayed. 3. This statement creates an object that represents an existing sequential file on the server you are connected to. This sequential file is the file that will be displayed. 4. These lines retrieve the record format of the file. 5. This line sets the record format for the file. 6. This line opens the selected file for reading. It will read 100 records at a time, when it is possible.
684
7. This line of code reads each record in sequence. 8. This line closes the file. 9. This line disconnects from the record-level access service. [ Next part ]
Note 1
try { SequentialFile theFile = new SequentialFile(system, filePathName); // Begin Note Two CharacterFieldDescription lastNameField = new CharacterFieldDescription(new AS400Text(20), "LNAME"); CharacterFieldDescription firstNameField = new CharacterFieldDescription(new AS400Text(20), "FNAME"); BinaryFieldDescription yearsOld = new BinaryFieldDescription(new AS400Bin4(), "AGE"); RecordFormat fileFormat = new RecordFormat("RF"); fileFormat.addFieldDescription(lastNameField); fileFormat.addFieldDescription(firstNameField); fileFormat.addFieldDescription(yearsOld); theFile.create(fileFormat, "A file of names and ages"); // End Note Two Note 2
theFile.open(AS400File.READ_WRITE, 1, AS400File.COMMIT_LOCK_LEVEL_NONE); // Begin Note Three Record newData = fileFormat.getNewRecord(); newData.setField("LNAME", "Doe"); newData.setField("FNAME", "John"); newData.setField("AGE", new Integer(63)); theFile.write(newData); // End Note Three Note 3
IBM Toolbox for Java
685
theFile.close(); } catch(Exception e) { System.out.println("An error has occurred: "); e.printStackTrace(); } system.disconnectService(AS400.RECORDACCESS); System.exit(0); } }
1. (args[0]) in the previous line and MYFILE.FILE are pieces of code that are prerequisites for the rest of the example to run. The program assumes that the library MYLIB exists on the server and that the user has access to it. 2. The text within the Java comments labeled "Begin Note Two" and "End Note Two" shows how to create a record format yourself instead of getting the record format from an existing file. The last line in this block creates the file on the server. 3. The text within the Java comments labeled "Begin Note Three" and "End Note Three" shows a way to create a record and then write it to a file. [ Previous part ]
686
if (parameters.length != 3) { System.out.println(""); System.out.println("Usage:"); System.out.println(""); System.out.println(" JDBCPopulate system collectionName tableName"); System.out.println(""); System.out.println(""); System.out.println("For example:"); System.out.println(""); System.out.println(""); System.out.println(" JDBCPopulate MySystem MyLibrary MyTable"); System.out.println(""); return; } String system String collectionName String tableName Connection connection = parameters[0]; = parameters[1]; = parameters[2]; = null; Note 1
try { DriverManager.registerDriver(new com.ibm.as400.access.AS400JDBCDriver()); connection = DriverManager.getConnection ("jdbc:as400://" + system + "/" + collectionName); Note 2 try { Statement dropTable = connection.createStatement (); dropTable.executeUpdate ("DROP TABLE " + tableName); } catch (SQLException e) { } Statement createTable = connection.createStatement (); createTable.executeUpdate ("CREATE TABLE " + tableName + " (I INTEGER, WORD VARCHAR(20), SQUARE INTEGER, " + " SQUAREROOT DOUBLE)"); Note 4 PreparedStatement insert = connection.prepareStatement ("INSERT INTO " + tableName + " (I, WORD, SQUARE, SQUAREROOT) " + " VALUES (?, ?, ?, ?)"); Note 5 for (int i = 1; i <= words.length; ++i) { insert.setInt (1, i); insert.setString (2, words[i-1]); insert.setInt (3, i*i); insert.setDouble (4, Math.sqrt(i)); insert.executeUpdate (); Note 6 } System.out.println ("Table " + collectionName + "." + tableName + " has been populated."); } catch (Exception e) { System.out.println (); System.out.println ("ERROR: " + e.getMessage()); } finally { try { if (connection != null) connection.close (); Note 7 } catch (SQLException e) {
Note 3
687
1. This line loads the IBM Toolbox for Java JDBC driver. A JDBC driver is necessary to mediate between JDBC and the database you are working with. 2. This statement connects to the database. A prompt will appear for the user ID and password. A default SQL schema is provided so that you will not need to qualify the table name in SQL statements. 3. These lines delete the table if it already exists. 4. These lines create the table. 5. This line prepares a statement that will insert rows into the table. Because you will be executing this statement several times, you should use a PreparedStatement and parameter markers. 6. This block of code populates the table for you; every time the loop is executed, it inserts a row into the table. 7. Now that the table has been created and filled in, this statement closes the connection to the database. [ Next part ]
688
for (int i = s.length(); i < width; ++i) buffer.append (" "); formattedString = buffer.toString(); } // Otherwise, we need to truncate the string. else formattedString = s.substring (0, width); return formattedString; } public static void main (String[] parameters) { // Check the input parameters. if (parameters.length != 3) { System.out.println(""); System.out.println("Usage:"); System.out.println(""); System.out.println(" JDBCQuery system collectionName tableName"); System.out.println(""); System.out.println(""); System.out.println("For example:"); System.out.println(""); System.out.println(""); System.out.println(" JDBCQuery mySystem qiws qcustcdt"); System.out.println(""); return; } String system String collectionName String tableName Connection connection try { DriverManager.registerDriver(new com.ibm.as400.access.AS400JDBCDriver()); // Get a connection to the database. Since we do not // provide a user id or password, a prompt will appear. connection = DriverManager.getConnection ("jdbc:as400://" + system); DatabaseMetaData dmd = connection.getMetaData (); Note 2 // Execute the query. Statement select = connection.createStatement (); ResultSet rs = select.executeQuery ("SELECT * FROM " + collectionName + dmd.getCatalogSeparator() + tableName); Note 1 = parameters[0]; = parameters[1]; = parameters[2]; = null;
Note 3
// Get information about the result set. Set the column // width to whichever is longer: the length of the label // or the length of the data. ResultSetMetaData rsmd = rs.getMetaData (); int columnCount = rsmd.getColumnCount (); Note 4 String[] columnLabels = new String[columnCount]; int[] columnWidths = new int[columnCount]; for (int i = 1; i <= columnCount; ++i) { columnLabels[i-1] = rsmd.getColumnLabel (i); columnWidths[i-1] = Math.max (columnLabels[i-1].length(), rsmd.getColumnDisplaySize (i)); } // Output the column for (int i = 1; i <= System.out.print System.out.print
Note 5
689
} System.out.println (); // Output a dashed line. StringBuffer dashedLine; for (int i = 1; i <= columnCount; ++i) { for (int j = 1; j <= columnWidths[i-1]; ++j) System.out.print ("-"); System.out.print (" "); } System.out.println (); // Iterate throught the rows in the result set and output // the columns for each row. while (rs.next ()) { for (int i = 1; i <= columnCount; ++i) { String value = rs.getString (i); if (rs.wasNull ()) value = "<null>"; Note 6 System.out.print (format (value, columnWidths[i-1])); System.out.print (" "); } System.out.println (); } } catch (Exception e) { System.out.println (); System.out.println ("ERROR: " + e.getMessage()); } finally { // Clean up. try { if (connection != null) connection.close (); } catch (SQLException e) { // Ignore. } } System.exit (0); } }
1. This line loads the IBM Toolbox for Java JDBC driver. A JDBC driver mediates between JDBC and the database with which you are working. 2. This line retrieves the connection's meta data, an object that describes many of the characteristics of the database. 3. This statement executes the query on the specified table. 4. These lines retrieve information about the table. 5. These lines set the column width to either the length of the label or the length of the data, whichever is longer. 6. This block of code iterates through all of the rows in the table and displays the contents of each column in each row. [ Previous part ]
690
import com.ibm.as400.access.*; import com.ibm.as400.vaccess.*; import javax.swing.*; Note 3 import java.awt.*; import java.awt.event.*; public class GUIExample {
public static void main(String[] parameters) Note 4 { GUIExample example = new GUIExample(parameters); } public GUIExample(String[] parameters) { try Note 5 { // Create an AS400 object. //The system name was passed as the first command line argument. AS400 system = new AS400 (parameters[0]); Note 6 VJobList jobList = new VJobList (system); // Create a frame. JFrame frame = new JFrame ("Job List Example"); Note 7 Note 8
// Create an error dialog adapter. This will display any errors to the user. ErrorDialogAdapter errorHandler = new ErrorDialogAdapter (frame); Note 9 // Create an explorer pane to present the job list. AS400ExplorerPane explorerPane = new AS400ExplorerPane (jobList); explorerPane.addErrorListener (errorHandler); Note 11 Note 10
// Use load to load the information from the system. explorerPane.load(); Note 12 // When the frame closes, exit the program. frame.addWindowListener (new WindowAdapter () Note 13 { public void windowClosing (WindowEvent event) { System.exit(0); } } ); // Layout the frame with the explorer pane. frame.getContentPane().setLayout(new BorderLayout() ); frame.getContentPane().add("Center", explorerPane); Note 14
IBM Toolbox for Java
691
frame.pack(); frame.show(); }
Note 15
Note 16
1. This class is in the examples package. Java uses packages to avoid name conflicts between Java class files. 2. This line makes all of the IBM Toolbox for Java classes in the vaccess package available to this program. The classes in the vaccess package have the common prefix com.ibm.as400.vaccess. By using an import statement, the program calls the name instead of the package plus name. For example, you can reference the AS400ExplorerPane class by using AS400ExplorerPane, not com.ibm.as400.AS400ExplorerPane. 3. This line makes all of the Java Foundation Classes (JFC) in the Swing package available to this program. Java programs that use the IBM Toolbox for Java vaccess (GUI) classes need JDK 1.1.2 plus Java Swing 1.0.3 from Sun Microsystems, Inc. Swing is available with Sun's JFC 1.1. 4. This class has a main method so it can be run as an application. To invoke the program, run "java examples.GUIExample serverName", where serverName is the name of your server. Either the jt400.zip or jt400.jar must be in your classpath for this to work. 5. The IBM Toolbox for Java code throws exceptions that your program must catch. 6. The AS400 class is used by IBM Toolbox for Java. This class manages sign-on information, creates and maintains socket connections, and sends and receives data. In this example, the program will pass the server name to the AS400 object. 7. The VJobList class is used by the IBM Toolbox for Java to represent a list of server jobs that can be displayed in a vaccess (GUI) component. Notice that the AS400 object is used to specify the server on which the list resides. 8. This line constructs a frame or a top-level window that will be used to display the job list. 9. ErrorDialogAdapter is an IBM Toolbox for Java graphical user interface (GUI) component that is created to automatically display a dialog window whenever an error event occurs in the application. 10. This line creates an AS400ExplorerPane, a graphical user interface (GUI) that represents a hierarchy of objects within a server resource. The AS400ExplorerPane presents a tree on the left side rooted at the VJobList and the details of the resource in the right side. This only initializes the pane to a default state and does not load the contents of the VJobList to the pane. 11. This line adds the error handler you created in step nine as a listener on the VJobList graphical user interface (GUI) component. 12. This line loads the contents of the JobList into the ExplorerPane. This method must be called explicitly to communicate to and load information from the server. This gives the application control over when the communication with the server will occur. With this you can: v Load the contents before adding the pane to a frame. The frame does not appear until all the information is loaded, as in this example. v Load the contents after adding the pane to a frame and displaying that frame. The frame appears with a "wait cursor" and the information is filled in as it is loaded. 13. This line adds a window listener so that the application ends when the frame closes. 14. This line adds the job list graphical user interface GUI component to the center of the controlling frame. 15. This line calls the show method to make the window visible to the user.
692
16. IBM Toolbox for Java exceptions are translated so the text will appear in the language of the workstation. For example, this program displays the text of the exception as its error processing. 17. The IBM Toolbox for Java creates threads to carry out IBM Toolbox for Java activity. If the program does not do System.exit(0) when it is terminated, the program may not exit normally. For example, if the program was run from a Windows 95 DOS prompt without this line, the command prompt does not return when the program finished.
Managing connections
v v v v Example: Example: Example: Example: Making a connection to the system with a CommandCall object Making two connections to the system with a CommandCall object Creating CommandCall and IFSFileInputStream objects with an AS400 object Using AS400ConnectionPool to preconnect to the system
v Example: Using AS400ConnectionPool to preconnect to a specific service on the system, then reuse the connection
Exceptions
v Example: Using exceptions
Error events
v Example: Handling error events v Example: Defining an error listener v Example: Using a customized handler to handle error events
Trace
v Example: Using trace v Example: Using setTraceOn() v Example: Using component trace
Optimization
v Example: Creating two AS400 objects v Example: Using an AS400 object to represent a second server The following disclaimer applies to all of the IBM Toolbox for Java examples: Code example disclaimer IBM grants you a nonexclusive copyright license to use all programming code examples from which you can generate similar function tailored to your own specific needs.
693
All sample code is provided by IBM for illustrative purposes only. These examples have not been thoroughly tested under all conditions. IBM, therefore, cannot guarantee or imply reliability, serviceability, or function of these programs. All programs contained herein are provided to you "AS IS" without any warranties of any kind. The implied warranties of non-infringement, merchantability and fitness for a particular purpose are expressly disclaimed.
Examples: ToolboxME
This section lists the code examples that are provided throughout the IBM Toolbox for Java 2 Micro Edition documentation. v ToolboxME example: JdbcDemo.java on page 364 v Example: Using ToolboxME, MIDP, and JDBC v Example: Using ToolboxME, MIDP, and IBM Toolbox for Java on page 702 The following disclaimer applies to all of the IBM Toolbox for Java examples: Code example disclaimer IBM grants you a nonexclusive copyright license to use all programming code examples from which you can generate similar function tailored to your own specific needs. All sample code is provided by IBM for illustrative purposes only. These examples have not been thoroughly tested under all conditions. IBM, therefore, cannot guarantee or imply reliability, serviceability, or function of these programs. All programs contained herein are provided to you "AS IS" without any warranties of any kind. The implied warranties of non-infringement, merchantability and fitness for a particular purpose are expressly disclaimed.
694
import com.ibm.as400.micro.*; public class JdbcMidpBid extends MIDlet implements CommandListener { private static int BID_PROPERTY = 0; private Display display; private TextField urlText = new TextField("urltext", "jdbc:as400://mySystem;user=myUid;password=myPwd;", 65, TextField.ANY); private TextField jdbcmeText = new TextField("jdbcmetext", "meserver=myMEServer", 40, TextField.ANY); private TextField jdbcmeTraceText = new TextField("jdbcmetracetext", "0", 10, TextField.ANY); private final static String GETBIDS = "No bids are available, select here to download bids"; private List main = new List("JdbcMe Bid Demo", Choice.IMPLICIT); private List listings = null; private Form aboutBox; private Form bidForm; private Form settingsForm; private int bidRow = 0; private String bidTarget = null; private String bidTargetKey = null; private TextField bidText = new TextField("bidtext", "", 10, TextField.NUMERIC); private Form errorForm = null; private private private private private Command exitCommand = new Command("Exit", Command.SCREEN, 0); Command backCommand = new Command("Back", Command.SCREEN, 0); Command cancelCommand = new Command("Cancel", Command.SCREEN, 0); Command goCommand = new Command("Go", Command.SCREEN, 1); Displayable onErrorGoBackTo = null;
/* * Construct a new JdbcMidpBid. */ public JdbcMidpBid() { display = Display.getDisplay(this); } /** * Show the main screen */ public void startApp() { main.append("Show Bids", null); main.append("Get New Bids", null); main.append("Settings", null); main.append("About", null); main.addCommand(exitCommand); main.setCommandListener(this); display.setCurrent(main); } public void commandAction(Command c, Displayable s) { // All exitCommand processing is the same. if (c == exitCommand) { destroyApp(false); notifyDestroyed();
IBM Toolbox for Java
695
return; } if (s instanceof List) { List current = (List)s; // An action occurred on the main page if (current == main) { int idx = current.getSelectedIndex(); switch (idx) { case 0: // Show current bids showBids(); break; case 1: // Get New Bids getNewBids(); break; case 2: // Settings doSettings(); break; case 3: // About aboutBox(); break; default : break; } return; } // current == main // An action occurred on the listings page if (current == listings) { if (c == backCommand) { display.setCurrent(main); return; } if (c == List.SELECT_COMMAND) { int idx = listings.getSelectedIndex(); String stext = listings.getString(idx); if (stext.equals(GETBIDS)) { getNewBids(); return; } int commaIdx = stext.indexOf(','); bidTargetKey = stext.substring(0, commaIdx); bidTarget = stext.substring(commaIdx+1) + "\n"; // Also keep track of which offline result set row // This is. It happens to be the same as the index // in the list. bidRow = idx; bidOnProperty(); } } // current == listings return; } // instanceof List if (s instanceof Form) { Form current = (Form)s; if (current == errorForm) { if (c == backCommand) display.setCurrent(onErrorGoBackTo);
696
return; } // errorForm if (current == settingsForm) { if (c == backCommand) { // Done with settings. display.setCurrent(main); settingsForm = null; return; } } // settingsForm if (current == aboutBox) { if (c == backCommand) { // Done with about box. display.setCurrent(main); aboutBox = null; return; } } if (current == bidForm) { if (c == cancelCommand) { display.setCurrent(listings); bidForm = null; return; } if (c == goCommand) { submitBid(); if (display.getCurrent() != bidForm) { // If we're no longer positioned at the // bidForm, we will get rid of it. bidForm = null; } return; } return; } // current == bidForm } // instanceof Form } public void aboutBox() { aboutBox = new Form("aboutbox"); aboutBox.setTitle("About"); aboutBox.append(new StringItem("", "Midp RealEstate example for JdbcMe ")); aboutBox.addCommand(backCommand); aboutBox.setCommandListener(this); display.setCurrent(aboutBox); } /** * The settings form. */ public void doSettings() { settingsForm = new Form("settingsform"); settingsForm.setTitle("Settings"); settingsForm.append(new StringItem("", "DB URL")); settingsForm.append(urlText); settingsForm.append(new StringItem("", "JdbcMe server"));
IBM Toolbox for Java
697
settingsForm.append(jdbcmeText); settingsForm.append(new StringItem("", "Trace")); settingsForm.addCommand(backCommand); settingsForm.setCommandListener(this); display.setCurrent(settingsForm); } /** * Show the bid screen for the bid target * that we selected. */ public void bidOnProperty() { StringItem item = new StringItem("", bidTarget); bidText = new TextField("bidtext", "", 10, TextField.NUMERIC); bidText.setString(""); bidForm = new Form("bidform"); bidForm.setTitle("Submit a bid for:"); BID_PROPERTY = 0; bidForm.append(item); bidForm.append(new StringItem("", "Your bid:")); bidForm.append(bidText); bidForm.addCommand(cancelCommand); bidForm.addCommand(goCommand); bidForm.setCommandListener(this); display.setCurrent(bidForm); } /** * Update the listings card with the * current list of bids that we are interested in. */ public void getNewBids() { // Reset the old listing listings = null; listings = new List("JdbcMe Bids", Choice.IMPLICIT); java.sql.Connection conn = null; Statement stmt = null; try { conn = DriverManager.getConnection(urlText.getString() + ";" + jdbcmeText.getString()); stmt = conn.createStatement(); // Since we do not want the prepared statement to persist, // a normal statement is really better in this environemnt. String sql = "select mls, address, currentbid from qjdbcme.realestate where currentbid <> 0"; boolean results =((JdbcMeStatement)stmt).executeToOfflineData(sql, "JdbcMidpBidListings", 0, 0); if (results) { setupListingsFromOfflineData(); } else { listings.append("No bids found", null); listings.addCommand(backCommand); listings.setCommandListener(this); }
698
} catch (Exception e) { // Currently no valid listings retrieved, so lets // reset it to empty. listings = new List("JdbcMe Bids", Choice.IMPLICIT); listings.append(GETBIDS, null); listings.addCommand(backCommand); listings.setCommandListener(this); // Return to main after showing the error. showError(main, e); return; } finally { if (conn != null) { try { conn.close(); } catch (Exception e) { } } conn = null; stmt = null; } showBids(); } public void setupListingsFromOfflineData() { // Skip the first four rows in the record store // (eyecatcher, version, num columns, sql column // types) // and each subsequent row in the record store is // a single column. Our query returns 3 columns which // we will return concatenated as a single string. ResultSet rs = null; listings.addCommand(backCommand); listings.setCommandListener(this); try { int i = 5; int max = 0; StringBuffer buf = new StringBuffer(20); // Creator and dbtype unused in MIDP rs = new JdbcMeOfflineResultSet("JdbcMidpBidListings", 0, 0); if (rs == null) { // New listings... listings = new List("JdbcMe Bids", Choice.IMPLICIT); listings.append(GETBIDS, null); listings.addCommand(backCommand); listings.setCommandListener(this); return; } i = 0; String s = null; while (rs.next()) { ++i;
699
s = rs.getString(1); buf.append(s); buf.append(","); s = rs.getString(2); buf.append(s); buf.append(", $"); s = rs.getString(3); buf.append(s); listings.append(buf.toString(), null); buf.setLength(0); } if (i == 0) { listings.append("No bids found", null); return; } } catch (Exception e) { // Currently no valid listings retrieved, so lets // reset it to empty. listings = new List("JdbcMe Bids", Choice.IMPLICIT); listings.append(GETBIDS, null); listings.addCommand(backCommand); listings.setCommandListener(this); // Return to main after showing the error. showError(main, e); return; } finally { if (rs != null) { try { rs.close(); } catch (Exception e) { } rs = null; } System.gc(); } } /** * Update the listings card with the * current list of bids that we are interested in. */ public void submitBid() { java.sql.Connection conn = null; Statement stmt = null; try { conn = DriverManager.getConnection(urlText.getString() + ";" + jdbcmeText.getString()); stmt = conn.createStatement(); // Since we do not want the prepared statement to persist, // a normal statement is really better in this environemnt.
700
StringBuffer buf = new StringBuffer(100); buf.append("Update QJdbcMe.RealEstate Set CurrentBid = "); buf.append(bidText.getString()); buf.append(" Where MLS = '"); buf.append(bidTargetKey); buf.append("' and CurrentBid < "); buf.append(bidText.getString()); String sql = buf.toString(); int updated = stmt.executeUpdate(sql); if (updated == 1) { // BID Accepted. String oldS = listings.getString(bidRow); int commaIdx = bidTarget.indexOf(','); String bidAddr = bidTarget.substring(0, commaIdx); String newS = bidTargetKey + "," + bidAddr + ", $" + bidText.getString(); ResultSet rs = null; try { // Creator and dbtype unused in MIDP rs = new JdbcMeOfflineResultSet("JdbcMidpBidListings", 0, 0); rs.absolute(bidRow+1); rs.updateString(3, bidText.getString()); rs.close(); } catch (Exception e) { if (rs != null) rs.close(); } // Also update our live list of that result set. listings.set(bidRow, newS, null); display.setCurrent(listings); conn.commit(); } else { conn.rollback(); throw new SQLException("Failed to bid, someone beat you to it"); } } catch (SQLException e) { // Return to the bid form after showing the error. showError(bidForm, e); return; } finally { if (conn != null) { try { conn.close(); } catch (Exception e) { } } conn = null; stmt = null; }
701
// Exit without exception, then show the current bids showBids(); } /** * Show an error condition. */ public void showError(Displayable d, Exception e) { String s = e.toString(); onErrorGoBackTo = d; errorForm = new Form("Error"); errorForm.setTitle("SQL Error"); errorForm.append(new StringItem("", s)); errorForm.addCommand(backCommand); errorForm.setCommandListener(this); display.setCurrent(errorForm); } /** * Show the current bids. */ public void showBids() { if (listings == null) { // If we have no current listings, lets set // them up. listings = new List("JdbcMe Bids", Choice.IMPLICIT); setupListingsFromOfflineData(); } display.setCurrent(listings); } /** * Time to pause, free any space we do not need right now. */ public void pauseApp() { display.setCurrent(null); } /** * Destroy must cleanup everything. */ public void destroyApp(boolean unconditional) { } }
702
To create a working version of the source code and to obtain the required PCML source for running server commands, you must download the example. You also may want to review the instructions for creating and running the example program. Note: Read the Code example disclaimer for important legal information.
////////////////////////////////////////////////////////////////////////////////// // // ToolboxME example. This program is an example that shows how // ToolboxME can use PCML to access data and services. // // This application requires that the qsyrusri.pcml file is present in the // CLASSPATH of the MEServer. // ////////////////////////////////////////////////////////////////////////////////// import java.io.*; import java.sql.*; import java.util.Hashtable; import javax.microedition.midlet.*; import javax.microedition.lcdui.*; import javax.microedition.rms.*; import com.ibm.as400.micro.*; public class ToolboxMidpDemo extends MIDlet implements CommandListener { private Display display_; // A ToolboxME system object. private AS400 system_; private List // Create a form private Form private Form private Form private Form private Form main_ = new List("ToolboxME MIDP Demo", Choice.IMPLICIT); for each component. signonForm_; cmdcallForm_; pgmcallForm_; dataqueueForm_; aboutForm_; each component. SIGN_ON = COMMAND_CALL = PROGRAM_CALL = DATA_QUEUE = ABOUT = "SignOn"; "CommandCall"; "ProgramCall"; "DataQueue"; "About";
// Visable Text for static final String static final String static final String static final String static final String
static final String NOT_SIGNED_ON = "Not signed on."; static final String DQ_READ = "Read"; static final String DQ_WRITE = "Write"; // A ticker to display the signon status. private Ticker ticker_ = new Ticker(NOT_SIGNED_ON); // Commands that can private static final private static final private static final private static final private static final private static final private static final private Displayable be performed. Command actionExit_ = Command actionBack_ = Command actionGo_ = Command actionClear_ = Command actionRun_ = Command actionSignon_ = Command actionSignoff_= onErrorGoBackTo_; new new new new new new new Command("Exit", Command.SCREEN, 0); Command("Back", Command.SCREEN, 0); Command("Go", Command.SCREEN, 1); Command("Clear", Command.SCREEN, 1); Command("Run", Command.SCREEN, 1); Command(SIGN_ON, Command.SCREEN, 1); Command("SignOff", Command.SCREEN, 1);
703
// TextFields for the SignOn form. private TextField signonSystemText_ = new TextField("System", "rchasdm3", 20, TextField.ANY); private TextField signonUidText_ = new TextField("UserId", "JAVA", 10, TextField.ANY); // TBD temporary private TextField signonPwdText_ = new TextField("Password", "JTEAM1", 10, TextField.PASSWORD); private TextField signonServerText_ = new TextField("MEServer", "localhost", 10, TextField.ANY); private StringItem signonStatusText_ = new StringItem("Status", NOT_SIGNED_ON); // TextFields for the CommandCall form. // TBD: max size; TBD: TextBox??? private TextField cmdText_ = new TextField("Command", "CRTLIB FRED", 256, TextField.ANY); private StringItem cmdMsgText_ = new StringItem("Messages", null); private StringItem cmdStatusText_ = new StringItem("Status", null); // TextFields for the ProgramCall form. private StringItem pgmMsgDescription_ = new StringItem("Messages", null); private StringItem pgmMsgText_ = new StringItem("Messages", null); // TextFields for the DataQueue form. private TextField dqInputText_ = new TextField("Data to write", "Hi there", 30, TextField.ANY); private StringItem dqOutputText_ = new StringItem("DQ contents", null); private ChoiceGroup dqReadOrWrite_ = new ChoiceGroup("Action", Choice.EXCLUSIVE, new String[] { DQ_WRITE, DQ_READ}, null); private StringItem dqStatusText_ = new StringItem("Status", null); /** * Creates a new ToolboxMidpDemo. **/ public ToolboxMidpDemo() { display_ = Display.getDisplay(this); // Note: The KVM-based demo used TabbedPane for the main panel. // MIDP has no similar class, so we use a List instead. } /** * Show the main screen. * Implements abstract method of class Midlet. **/ protected void startApp() { main_.append(SIGN_ON, null); main_.append(COMMAND_CALL, null); main_.append(PROGRAM_CALL, null); main_.append(DATA_QUEUE, null); main_.append(ABOUT, null); main_.addCommand(actionExit_); main_.setCommandListener(this); display_.setCurrent(main_); } // Implements method of interface CommandListener. public void commandAction(Command action, Displayable dsp) { // All 'exit' and 'back' processing is the same. if (action == actionExit_) { destroyApp(false); notifyDestroyed(); }
704
else if (action == actionBack_) { // Return to main menu. display_.setCurrent(main_); } else if (dsp instanceof List) { List current = (List)dsp; // An action occurred on the main page if (current == main_) { int idx = current.getSelectedIndex(); switch (idx) { case 0: // SignOn showSignonForm(); break; case 1: // CommandCall showCmdForm(); break; case 2: // ProgramCall showPgmForm(); break; case 3: // DataQueue showDqForm(); break; case 4: // About showAboutForm(); break; default: // None of the above feedback("Internal error: Unhandled selected index in main: " + idx, AlertType.ERROR); break; } } // current == main else feedback("Internal error: The Displayable object is a List but is not main_.", AlertType.ERROR); } // instanceof List else if (dsp instanceof Form) { Form current = (Form)dsp; if (current == signonForm_) { if (action == actionSignon_) { // Create a ToolboxME system object. system_ = new AS400(signonSystemText_.getString(), signonUidText_.getString(), signonPwdText_.getString(), signonServerText_.getString()); try { // Connect to the server. system_.connect(); // Set the signon status text. signonStatusText_.setText("Signed on."); // Display a confirmation dialog that the user is signed on. feedback("Successfully signed on.", AlertType.INFO, main_); // Replace the SignOn button with SignOff.
IBM Toolbox for Java
705
signonForm_.removeCommand(actionSignon_); signonForm_.addCommand(actionSignoff_); // Update the ticker. ticker_.setString("... Signed on to '" + signonSystemText_.getString() + "' as '" + signonUidText_.getString() + "' via '" + signonServerText_.getString() + "' ... "); } catch (Exception e) { e.printStackTrace(); // Set the signon status text. signonStatusText_.setText(NOT_SIGNED_ON); feedback("Signon failed. } } else if (action == actionSignoff_) { if (system_ == null) feedback("Internal error: System is null.", AlertType.ERROR); else { try { // Disconnect from the server. system_.disconnect(); system_ = null; // Set the signon status text. signonStatusText_.setText(NOT_SIGNED_ON); // Display a confirmation dialog that the user is no longer signed on. feedback("Successfully signed off.", AlertType.INFO, main_); // Replace the SignOff button with SignOn. signonForm_.removeCommand(actionSignoff_); signonForm_.addCommand(actionSignon_); // Update the ticker. ticker_.setString(NOT_SIGNED_ON); } catch (Exception e) { feedback(e.toString(), AlertType.ERROR); e.printStackTrace(); signonStatusText_.setText("Error."); feedback("Error during signoff.", AlertType.ERROR); } } } else // None of the above. { feedback("Internal error: Action is not recognized.", AlertType.INFO); } } // signonForm_ else if (current == cmdcallForm_) { if (action == actionRun_) { // If the user has not signed on, display an alert. if (system_ == null) " + e.getMessage(), AlertType.ERROR);
706
{ feedback(NOT_SIGNED_ON, AlertType.ERROR); return; } // Get the command the user entered in the wireless device. String cmdString = cmdText_.getString(); // If the command was not specified, display an alert. if (cmdString == null || cmdString.length() == 0) feedback("Specify command.", AlertType.ERROR); else { try { // Run the command. String[] messages = CommandCall.run(system_, cmdString); StringBuffer status = new StringBuffer("Command completed with "); // Check to see if their are any messages. if (messages.length == 0) { status.append("no returned messages."); cmdMsgText_.setText(null); cmdStatusText_.setText("Command completed successfully."); } else { if (messages.length == 1) status.append("1 returned message."); else status.append(messages.length + " returned messages."); // If there are messages, display only the first message. cmdMsgText_.setText(messages[0]); cmdStatusText_.setText(status.toString()); } repaint(); } catch (Exception e) { feedback(e.toString(), AlertType.ERROR); e.printStackTrace(); feedback("Error when running command.", AlertType.ERROR); } } } else if (action == actionClear_) { // Clear the command text and messages. cmdText_.setString(""); cmdMsgText_.setText(null); cmdStatusText_.setText(null); repaint(); } else // None of the above. {
IBM Toolbox for Java
707
feedback("Internal error: Action is not recognized.", AlertType.INFO); } } // cmdcallForm_ else if (current == pgmcallForm_) { if (action == actionRun_) { // If the user is not signed on before doing a program call, display an alert. if (system_ == null) { feedback(NOT_SIGNED_ON, AlertType.ERROR); return; } pgmMsgText_.setText(null); // See the PCML example in the IBM Toolbox for Java information. String pcmlName = "qsyrusri.pcml"; // The PCML file we want to use. String apiName = "qsyrusri"; // Create a hashtable that contains the input parameters for the program call. Hashtable parmsToSet = new Hashtable(2); parmsToSet.put("qsyrusri.receiverLength", "2048"); parmsToSet.put("qsyrusri.profileName", signonUidText_.getString().toUpperCase()); // Create a string array that contains the output parameters to retrieve. String[] parmsToGet = { "qsyrusri.receiver.userProfile", "qsyrusri.receiver.previousSignonDate", "qsyrusri.receiver.previousSignonTime", "qsyrusri.receiver.daysUntilPasswordExpires"}; // A string array containing the descriptions of the parameters to display. String[] displayParm = { "Profile", "Last signon Date", "Last signon Time", "Password Expired (days)"}; try { // Run the program. String[] valuesToGet = ProgramCall.run(system_, pcmlName, apiName, parmsToSet, parmsToGet); // Create a StringBuffer and add each of the parameters we retreived. StringBuffer txt = new StringBuffer(); txt.append(displayParm[0] + ": " + valuesToGet[0] + "\n"); char[] c = valuesToGet[1].toCharArray(); txt.append(displayParm[1] + ": " + c[3] + c[4] + "/" + c[5] + c[6] + "/" + c[1] + c[2] + "\n"); char[] d = valuesToGet[2].toCharArray(); txt.append(displayParm[2] + ": " + d[0] + d[1] + ":" + d[2] + d[3] + "\n"); txt.append(displayParm[3] + ": " + valuesToGet[3] + "\n"); // Set the displayable text of the program call results. pgmMsgText_.setText(txt.toString()); StringBuffer status = new StringBuffer("Program completed with "); if (valuesToGet.length == 0) { status.append("no returned values.");
708
feedback(status.toString(), AlertType.INFO); } else { if (valuesToGet.length == 1) status.append("1 returned value."); else status.append(valuesToGet.length + " returned values."); feedback(status.toString(), AlertType.INFO); } } catch (Exception e) { feedback(e.toString(), AlertType.ERROR); e.printStackTrace(); feedback("Error when running program.", AlertType.ERROR); } } else if (action == actionClear_) { // Clear the program call results. pgmMsgText_.setText(null); repaint(); } } // pgmcallForm_ else if (current == dataqueueForm_) // DataQueue { if (action == actionGo_) { // If the user has not signed on before performing Data Queue actions, // display an alert. if (system_ == null) { feedback(NOT_SIGNED_ON, AlertType.ERROR); return; } // Create a library to create the data queue in. try { CommandCall.run(system_, "CRTLIB FRED"); } catch (Exception e) { } // Run a command to create a data queue. try { CommandCall.run(system_, "CRTDTAQ FRED/MYDTAQ MAXLEN(2000)"); } catch (Exception e) { feedback("Error when creating data queue. " + e.getMessage(), AlertType.WARNING); } try { // See which action was selected (Read or Write). if (dqReadOrWrite_.getString(dqReadOrWrite_.getSelectedIndex()).equals(DQ_WRITE)) {
IBM Toolbox for Java
709
// Write dqOutputText_.setText(null); // Get the text from the wireless device input to be written to // the data queue. if (dqInputText_.getString().length() == 0) dqStatusText_.setText("No data specified."); else { // Write to the data queue. DataQueue.write(system_, "/QSYS.LIB/FRED.LIB/MYDTAQ.DTAQ", dqInputText_.getString().getBytes() ); dqInputText_.setString(null); // Display the status. dqStatusText_.setText("The 'write' operation completed."); } } else // Read { // Read from the data queue. byte[] b = DataQueue.readBytes(system_, "/QSYS.LIB/FRED.LIB/MYDTAQ.DTAQ"); // Determine if the data queue contained entries or not // and display the appropriate message. if (b == null) { dqStatusText_.setText("No dataqueue entries are available."); dqOutputText_.setText(null); } else if (b.length == 0) { dqStatusText_.setText("Dataqueue entry has no data."); dqOutputText_.setText(null); } else { dqStatusText_.setText("The 'read' operation completed."); dqOutputText_.setText(new String(b)); } } repaint(); } catch (Exception e) { e.printStackTrace(); feedback(e.toString(), AlertType.ERROR); feedback("Error when running command. } } // actionGo_ else if (action == actionClear_) { // Clear the data queue form. dqInputText_.setString(""); dqOutputText_.setText(null); dqReadOrWrite_.setSelectedFlags(new boolean[] { true, false}); " + e.getMessage(), AlertType.ERROR);
710
dqStatusText_.setText(null); repaint(); } else // None of the above. { feedback("Internal error: Action is not recognized.", AlertType.INFO); } } // dataqueueForm_ else if (current == aboutForm_) // "About". { // Should never reach here, since the only button is "Back". } // None of the above. else feedback("Internal error: Form is not recognized.", AlertType.ERROR); } // instanceof Form else feedback("Internal error: Displayable object not recognized.", AlertType.ERROR); }
/** * Displays the "About" form. **/ private void showAboutForm() { // If the about form is null, create and append it. if (aboutForm_ == null) { aboutForm_ = new Form(ABOUT); aboutForm_.append(new StringItem(null, "This is a MIDP example application that uses the " + "IBM Toolbox for Java Micro Edition (ToolboxME).")); aboutForm_.addCommand(actionBack_); aboutForm_.setCommandListener(this); } display_.setCurrent(aboutForm_); }
/** * Displays the "SignOn" form. **/ private void showSignonForm() { // Create the signon form. if (signonForm_ == null) { signonForm_ = new Form(SIGN_ON); signonForm_.append(signonSystemText_); signonForm_.append(signonUidText_); signonForm_.append(signonPwdText_); signonForm_.append(signonServerText_); signonForm_.append(signonStatusText_); signonForm_.addCommand(actionBack_); signonForm_.addCommand(actionSignon_); signonForm_.setCommandListener(this); signonForm_.setTicker(ticker_); } display_.setCurrent(signonForm_); }
711
/** * Displays the "CommandCall" form. **/ private void showCmdForm() { // Create the command call form. if (cmdcallForm_ == null) { cmdcallForm_ = new Form(COMMAND_CALL); cmdcallForm_.append(cmdText_); cmdcallForm_.append(cmdMsgText_); cmdcallForm_.append(cmdStatusText_); cmdcallForm_.addCommand(actionBack_); cmdcallForm_.addCommand(actionClear_); cmdcallForm_.addCommand(actionRun_); cmdcallForm_.setCommandListener(this); cmdcallForm_.setTicker(ticker_); } display_.setCurrent(cmdcallForm_); }
/** * Displays the "ProgramCall" form. **/ private void showPgmForm() { // Create the program call form. if (pgmcallForm_ == null) { pgmcallForm_ = new Form(PROGRAM_CALL); pgmcallForm_.append(new StringItem(null, "This calls the Retrieve User Information (QSYRUSRI) " + "API, and returns information about the current " + "user profile.")); pgmcallForm_.append(pgmMsgText_); pgmcallForm_.addCommand(actionBack_); pgmcallForm_.addCommand(actionClear_); pgmcallForm_.addCommand(actionRun_); pgmcallForm_.setCommandListener(this); pgmcallForm_.setTicker(ticker_); } display_.setCurrent(pgmcallForm_); } /** * Displays the "DataQueue" form. **/ private void showDqForm() { // Create the data queue form. if (dataqueueForm_ == null) { dataqueueForm_ = new Form(DATA_QUEUE); dataqueueForm_.append(dqInputText_); dataqueueForm_.append(dqOutputText_); dataqueueForm_.append(dqReadOrWrite_); dataqueueForm_.append(dqStatusText_); dataqueueForm_.addCommand(actionBack_); dataqueueForm_.addCommand(actionClear_); dataqueueForm_.addCommand(actionGo_);
712
dataqueueForm_.setCommandListener(this); dataqueueForm_.setTicker(ticker_); } display_.setCurrent(dataqueueForm_); } private void feedback(String text, AlertType type) { feedback(text, type, display_.getCurrent()); } /** * This method is used to create a dialog and display feedback * information using an Alert to the user. **/ private void feedback(String text, AlertType type, Displayable returnToForm) { System.err.flush(); System.out.flush(); Alert alert = new Alert("Alert", text, null, type); if (type == AlertType.INFO) alert.setTimeout(3000); // milliseconds else alert.setTimeout(Alert.FOREVER); // Require user to dismiss the alert. display_.setCurrent(alert, returnToForm); } // Force a repaint of the current form. private void repaint() { Alert alert = new Alert("Updating display ...", null, null, AlertType.INFO); alert.setTimeout(1000); // milliseconds display_.setCurrent(alert, display_.getCurrent()); }
/** * Time to pause, free any space we don't need right now. * Implements abstract method of class Midlet. **/ protected void pauseApp() { display_.setCurrent(null); }
/** * Destroy must cleanup everything. * Implements abstract method of class Midlet. **/ protected void destroyApp(boolean unconditional) { // Disconnect from the server if the Midlet is being destroyed or exited. if (system_ != null) { try { system_.disconnect();
IBM Toolbox for Java
713
} catch (Exception e) { } } } }
AS/400ToolboxJarMaker
v Example: Extracting AS400.class and all its dependent classes from jt400.jar v Example: Splitting jt400.jar into a set of 300KB files v Example: Removing unused files from a JAR file v Example: Creating a 400KB smaller JAR file by omitting the conversion tables with the -ccsid parameter
CommandPrompter
v Example: Using CommandPrompter to prompt for and run a command The following disclaimer applies to all of the IBM Toolbox for Java examples: Code example disclaimer IBM grants you a nonexclusive copyright license to use all programming code examples from which you can generate similar function tailored to your own specific needs. All sample code is provided by IBM for illustrative purposes only. These examples have not been thoroughly tested under all conditions. IBM, therefore, cannot guarantee or imply reliability, serviceability, or function of these programs. All programs contained herein are provided to you "AS IS" without any warranties of any kind. The implied warranties of non-infringement, merchantability and fitness for a particular purpose are expressly disclaimed.
714
import com.ibm.as400.access.AS400Message; import com.ibm.as400.access.CommandCall; import javax.swing.JFrame; import java.awt.FlowLayout; public class Prompter { public static void main ( String args[] ) throws Exception { JFrame frame = new JFrame(); frame.getContentPane().setLayout(new FlowLayout()); AS400 system = new AS400("mySystem", "myUserId", "myPasswd"); String cmdName = args[0]; // Launch the CommandPrompter CommandPrompter cp = new CommandPrompter(frame, system, cmdName); if (cp.showDialog() == CommandPrompter.OK) { String cmdString = cp.getCommandString(); System.out.println("Command string: " + cmdString); // Run the command that was built in the prompter. CommandCall cmd = new CommandCall(system, cmdString); if (!cmd.run()) { AS400Message[] msgList = cmd.getMessageList(); for (int i = 0; i < msgList.length; ++i) { System.out.println(msgList[i].getText()); } } } System.exit(0); } }
AS400Panes
v Example: Creating an AS400DetailsPane to present the list of users defined on the systemAS400DetailsPane v Example: Loading the contents of a details pane before adding it to a frame v Example: Using an AS400ListPane to present a list of users v Example: Using an AS400DetailsPane to display messages returned from a command call v Example: Using an AS400TreePane to display a tree view of a directory v Example: Using an AS400ExplorerPane to present various print resources
Command call
v Example: Creating a CommandCallButton v Example: Adding the ActionCompletedListener to process all IBM i messages that a command generates v Example: Using the CommandCallMenuItem
Data queues
v Example: Creating a DataQueueDocument v Example: Using a DataQueueDocument
715
Error events
v Example: Handling error events v Example: Defining an error listener v Example: Using a customized handler to handle error events
JDBC
v Example: Using the JDBC driver to create and populate a table v Example: Using the JDBC driver to query a table and output its contents v Example: Creating an AS400JDBCDataSourcePane
Jobs
v Example: Creating a VJobList and presenting the list in an AS400ExplorerPane v Example: Presenting a list of jobs in an explorer pane
Messages
v Example: Using VMessageQueue
Program call
v Example: Creating a ProgramCallMenuItem v Example: Processing all program generated IBM i messages v Example: Adding two parameters v Example: Using a ProgramCallButton in an application
Print
v Example: Using VPrinter v Example: VPrinterOutput
Record-level access
v Example: Creating a RecordListTablePane object to display all records less than or equal to a key v Example: Using RecordListFormPane
SpooledFileViewer
v Example: Creating a Spooled File Viewer to view a spooled file previously created on the system
SQL
v Example: Using SQLQueryBuilderPane v Example: Using SQLResultSetTablePane
System values
v Example: Creating a system value GUI using the AS400Explorer pane
716
The following disclaimer applies to all of the IBM Toolbox for Java examples: Code example disclaimer IBM grants you a nonexclusive copyright license to use all programming code examples from which you can generate similar function tailored to your own specific needs. All sample code is provided by IBM for illustrative purposes only. These examples have not been thoroughly tested under all conditions. IBM, therefore, cannot guarantee or imply reliability, serviceability, or function of these programs. All programs contained herein are provided to you "AS IS" without any warranties of any kind. The implied warranties of non-infringement, merchantability and fitness for a particular purpose are expressly disclaimed.
public class VUserListExample { private static AS400ListPane listPane; public { // // if { } try { // Create an AS400 object. The system name is passed // as the first command line argument. AS400 system = new AS400 (args[0]); // Create a VUserList. This represents a list of users // displayed in the list pane. VUserList userList = new VUserList (system);
IBM Toolbox for Java
static void main (String[] args) If a system is not specified, display help text and exit. (args.length != 1) System.out.println("Usage: return; VUserListExample system");
717
// Create a frame. JFrame f = new JFrame ("VUserList example"); // Create an error dialog adapter. This displays // any errors to the user. ErrorDialogAdapter errorHandler = new ErrorDialogAdapter (f); // Create a list pane to display the user list. // Use load to get the information from the server. listPane = new AS400ListPane (userList); listPane.addErrorListener (errorHandler); listPane.load (); // When the frame closes, report the selected // users and exit. f.addWindowListener (new WindowAdapter () { public void windowClosing (WindowEvent event) { reportSelectedUsers (); System.exit (0); } }); // Layout the frame with the list pane. f.getContentPane ().setLayout (new BorderLayout ()); f.getContentPane ().add ("Center", listPane); f.pack (); f.show (); } catch (Exception e) { System.out.println ("Error: " + e.getMessage ()); System.exit (0); } } private static void reportSelectedUsers () { VObject[] selectedUsers = listPane.getSelectedObjects (); if (selectedUsers.length == 0) System.out.println ("No users were selected."); else { System.out.println ("The selected users were:"); for (int i = 0; i < selectedUsers.length; ++i) System.out.println (selectedUsers[i]); } } }
718
// // This source is an example of IBM Toolbox for Java "VMessageList". // ///////////////////////////////////////////////////////////////////////// import import import import import com.ibm.as400.access.*; com.ibm.as400.vaccess.*; javax.swing.*; java.awt.*; java.awt.event.*;
public class VMessageListExample { public { // // if { } try { // Create an AS400 object. The system name was passed // as the first command line argument. AS400 system = new AS400 (args[0]); // Create a CommandCall object a run the command. CommandCall command = new CommandCall (system); command.run ("CRTLIB FRED"); // Create a VMessageList object with the messages // returned from the command call. VMessageList messageList = new VMessageList (command.getMessageList ()); // Create a frame. JFrame f = new JFrame ("VMessageList example"); // Create an error dialog adapter. This will display // any errors to the user. ErrorDialogAdapter errorHandler = new ErrorDialogAdapter (f); // Create a details pane to display the message list. // Use load to load the information. AS400DetailsPane detailsPane = new AS400DetailsPane (messageList); detailsPane.addErrorListener (errorHandler); detailsPane.load (); // When the frame closes, exit. f.addWindowListener (new WindowAdapter () { public void windowClosing (WindowEvent event) { System.exit (0); } }); // Layout the frame with the details pane. f.getContentPane ().setLayout (new BorderLayout ()); f.getContentPane ().add ("Center", detailsPane); f.pack (); f.show (); } catch (Exception e)
IBM Toolbox for Java
static void main (String[] args) If a system was not specified, then display help text and exit. (args.length != 1) System.out.println("Usage: return; VMessageListExample system");
719
public class VIFSDirectoryExample { public { // // if { } try { // Create an AS400 object. The system name was passed // as the first command line argument. AS400 system = new AS400 (args[0]); // Create a VIFSDirectory object which represents the root // of the directory tree that we are going to show. VIFSDirectory directory = new VIFSDirectory (system, "/QIBM/ProdData"); // Create a frame. JFrame f = new JFrame ("VIFSDirectory example"); // Create an error dialog adapter. This will display // any errors to the user. ErrorDialogAdapter errorHandler = new ErrorDialogAdapter (f); // Create a tree pane to present the directories hierarchically. // Load the information from the system. AS400TreePane treePane = new AS400TreePane (directory); treePane.addErrorListener (errorHandler); static void main (String[] args) If a system was not specified, then display help text and exit. (args.length != 1) System.out.println("Usage: return; VIFSDirectoryExample system");
720
treePane.load (); // When the frame closes, exit. f.addWindowListener (new WindowAdapter () { public void windowClosing (WindowEvent event) { System.exit (0); } }); // Layout the frame with the tree pane. f.getContentPane ().setLayout (new BorderLayout ()); f.getContentPane ().add ("Center", treePane); f.pack (); f.show (); } catch (Exception e) { System.out.println ("Error: " + e.getMessage ()); System.exit (0); } } }
Example: Using VPrinters Note: Read the Code example disclaimer for important legal information.
///////////////////////////////////////////////////////////////////////// // // VPrinters example. This program presents various network // print resources with an explorer pane. // // Command syntax: // VPrintersExample system // // This source is an example of IBM Toolbox for Java "VPrinters". // ///////////////////////////////////////////////////////////////////////// import import import import import com.ibm.as400.access.*; com.ibm.as400.vaccess.*; javax.swing.*; java.awt.*; java.awt.event.*;
public class VPrintersExample { public { // // if { } try { // Create an AS400 object. The system name was passed // as the first command line argument. AS400 system = new AS400 (args[0]);
IBM Toolbox for Java
static void main (String[] args) If a system was not specified, then display help text and exit. (args.length != 1) System.out.println("Usage: return; VPrintersExample system");
721
// Create a VPrinters object which represents the list // of printers attached to the system. VPrinters printers = new VPrinters (system); // Create a frame. JFrame f = new JFrame ("VPrinters example"); // Create an error dialog adapter. This will display // any errors to the user. ErrorDialogAdapter errorHandler = new ErrorDialogAdapter (f); // Create an explorer pane to present the network print resources. // Use load to load the information from the system. AS400ExplorerPane explorerPane = new AS400ExplorerPane (printers); explorerPane.addErrorListener (errorHandler); explorerPane.load (); // When the frame closes, exit. f.addWindowListener (new WindowAdapter () { public void windowClosing (WindowEvent event) { System.exit (0); } }); // Layout the frame with the explorer pane. f.getContentPane ().setLayout (new BorderLayout ()); f.getContentPane ().add ("Center", explorerPane); f.pack (); f.show (); } catch (Exception e) { System.out.println ("Error: " + e.getMessage ()); System.exit (0); } } }
722
public { // // if { } try {
static void main (String[] args) If a system was not specified, then display help text and exit. (args.length != 1) System.out.println("Usage: return; CommandCallMenuItemExample system");
// Create an AS400 object. The system name was passed // as the first command line argument. AS400 system = new AS400 (args[0]); // Create a frame. f = new JFrame ("Command call menu item example" // Create an error dialog adapter. This will display // any errors to the user. ErrorDialogAdapter errorHandler = new ErrorDialogAdapter (f); // Create a CommandCallMenuItem object to run the command. CommandCallMenuItem menuItem = new CommandCallMenuItem ("Clear library FRED", null, system, "CLRLIB FRED"); menuItem.addErrorListener (errorHandler); // Add an action completed listener to display any // returned messages in a dialog. menuItem.addActionCompletedListener (new ActionCompletedListener () { public void actionCompleted (ActionCompletedEvent event) { // Get the message list from the event source. CommandCallMenuItem item = (CommandCallMenuItem) event.getSource (); AS400Message[] messageList = item.getMessageList (); // Use an AS400DetailsPane to display the messages. VMessageList vmessageList = new VMessageList (messageList); AS400DetailsPane messageDetails = new AS400DetailsPane (vmessageList); messageDetails.load (); // Show the details in a dialog. JDialog dialog = new JDialog(f); dialog.getContentPane().setLayout(new BorderLayout()); dialog.getContentPane().add("Center"messageDetails); dialog.pack(); dialog.setVisible(true); } }); // Create a menu with the item. JMenu menu = new JMenu ("Server Command Calls"); menu.add (menuItem); JMenuBar menuBar = new JMenuBar (); menuBar.add (menu); f.getRootPane ().setJMenuBar (menuBar);
IBM Toolbox for Java
723
// When the frame closes, exit. f.addWindowListener (new WindowAdapter () { public void windowClosing (WindowEvent event) { System.exit (0); } }); // Layout the frame with the details pane. f.getContentPane ().setLayout (new BorderLayout ()); f.setSize (300, 400); f.show (); } catch (Exception e) { System.out.println ("Error: " + e.getMessage ()); System.exit (0); } } }
public class DataQueueDocumentExample { private static DataQueueDocument private static JTextField private static boolean public { // // if { }
static void main (String[] args) If a system or read|write was not specified, then display help text and exit. (args.length != 2) System.out.println("Usage: return; DataQueueDocumentExample system read|write");
rw = args[1].equalsIgnoreCase ("read"); String mode = rw ? "Read" : "Write"; try { // Create two frames.
724
JFrame f = new JFrame ("Data queue document example - " + mode); // Create an error dialog adapter. This will display // any errors to the user. ErrorDialogAdapter errorHandler = new ErrorDialogAdapter (f); // Create a working cursor adapter. This will adjust // the cursor whenever a data queue is read or written. WorkingCursorAdapter cursorAdapter = new WorkingCursorAdapter (f); // Create an AS400 object. The system name was passed // as the first command line argument. AS400 system = new AS400 (args[0]); // Create the data queue path name. QSYSObjectPathName dqName = new QSYSObjectPathName ("QGPL", "JAVATALK", "DTAQ"); // Make sure the the data queue exists. DataQueue dq = new DataQueue (system, dqName.getPath ()); try { dq.create (200); } catch (Exception e) { // Ignore exceptions. Most likely, the data queue // already exists. } // Create a DataQueueDocument object. dqDocument = new DataQueueDocument (system, dqName.getPath ()); dqDocument.addErrorListener (errorHandler); dqDocument.addWorkingListener (cursorAdapter); // Create a text field used to present the document. text = new JTextField (dqDocument, "", 40); text.setEditable (! rw); // When the program runs, we need a way to control when // the reads and writes take place. We will let the // use control this with a button. Button button = new Button (mode); button.addActionListener (new ActionListener () { public void actionPerformed (ActionEvent event) { if (rw) dqDocument.read (); else { dqDocument.write (); text.setText (""); } } }); // When the the frame closes, exit. f.addWindowListener (new WindowAdapter () { public void windowClosing (WindowEvent event) { System.exit (0); } }); // Layout the frame. f.getContentPane ().setLayout (new FlowLayout ()); f.getContentPane ().add (text);
IBM Toolbox for Java
725
f.getContentPane ().add (button); f.pack (); f.show (); } catch (Exception e) { System.out.println ("Error: " + e.getMessage ()); System.exit (0); } } }
public class FileDialogExample extends Object { public static void main(String[] parameters) { System.out.println( " " ); // if a system name was not specified, display help text and exit. if (parameters.length >= 1) { // The first parameter is the system that contains the files. String system = parameters[0]; try { // Create an AS400 object for the server that contains the files. // Connect to the file server on the server. Connect now so // the sign-on screen is displayed now. AS400 as400 = new AS400(system); as400.connectService(AS400.FILE); // Create a frame to hold the dialog. Frame frame = new Frame(); // Create the file dialog object. IFSFileDialog fileDialog = new IFSFileDialog(frame, "File Open", as400); // Create the list of filters the user can choose then add the filters // to the dialog. FileFilter[] filterList = { new FileFilter("All files (*.*)", "*.*"), new FileFilter("Executables (*.exe)", "*.exe"), new FileFilter("HTML files (*.html)", "*.html"), new FileFilter("Images (*.gif)", "*.gif"), new FileFilter("Text files (*.txt)", "*.txt")}; fileDialog.setFileFilter(filterList, 0); // Set the text for the "OK" button on the dialog.
726
fileDialog.setOkButtonText("Open"); // Set the text for the "Cancel" button on the dialog. fileDialog.setCancelButtonText("Cancel"); // Set the initial directory for the dialog. fileDialog.setDirectory("/"); // Display the dialog and wait until the user presses OK or Cancel int pressed = fileDialog.showDialog(); // If the user pressed OK, get the fully qualified path and name // of the file they chose. if (pressed == IFSFileDialog.OK) { System.out.println("User selected: " + fileDialog.getAbsolutePath()); } // Else if the user pressed cancel, display a message. else if (pressed == IFSFileDialog.CANCEL) { System.out.println("User pressed cancel"); } else System.out.println("User didn't press Open or Cancel"); } catch(Exception e) { // If any of the above operations failed say the dialog operation // failed and output the exception. System.out.println("Dialog operation failed"); System.out.println(e); } } // Display help text when parameters are incorrect. else { System.out.println(""); System.out.println(""); System.out.println(""); System.out.println("Parameters are not correct. Command syntax is:"); System.out.println(""); System.out.println(" FileDialogExample system"); System.out.println(""); System.out.println("Where"); System.out.println(""); System.out.println(" system = IBM i"); System.out.println(""); System.out.println("For example:"); System.out.println(""); System.out.println(""); System.out.println(" FileDialogExample mySystem"); System.out.println(""); System.out.println(""); } System.exit(0); } }
IBM Toolbox for Java
727
public { // // if { } try {
static void main (String[] args) If a system or path was not specified, then display help text and exit. (args.length != 2) System.out.println("Usage: return; IFSTextFileDocumentExample system path");
// Create two frames. JFrame f = new JFrame ("IFS text file document example"); // Create an error dialog adapter. This will display // any errors to the user. ErrorDialogAdapter errorHandler = new ErrorDialogAdapter (f); // Create a working cursor adapter. This will adjust // the cursor whenever the text file is read or written. WorkingCursorAdapter cursorAdapter = new WorkingCursorAdapter (f); // Create an AS400 object. The system name was passed // as the first command line argument. AS400 system = new AS400 (args[0]); // Create and load the IFS text file document. document = new IFSTextFileDocument (system, args[1]); document.addErrorListener (errorHandler); document.addWorkingListener (cursorAdapter); document.load (); // Create the text pane used to present the document.
728
text = new JTextPane (document); text.setSize (new Dimension (500, 500)); // Set up a scroll pane to use with the text pane. JScrollPane scroll = new JScrollPane (text); scroll.setHorizontalScrollBarPolicy (JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); scroll.setVerticalScrollBarPolicy (JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); // Create a menu bar with a single menu. MenuBar menuBar = new MenuBar (); Menu menu = new Menu ("File"); menuBar.add (menu); // Add menu items to load and save. MenuItem load = new MenuItem ("Load"); load.addActionListener (new ActionListener () { public void actionPerformed (ActionEvent event) { document.load (); } }); menu.add (load); MenuItem save = new MenuItem ("Save"); save.addActionListener (new ActionListener () { public void actionPerformed (ActionEvent event) { document.save (); } }); menu.add (save); // When the the frame closes, exit. f.addWindowListener (new WindowAdapter () { public void windowClosing (WindowEvent event) { System.exit (0); } }); // Layout the frame. f.getContentPane ().setLayout (new BorderLayout ()); f.getContentPane ().add ("Center", scroll); f.setMenuBar (menuBar); f.pack (); f.show (); } catch (Exception e) { System.out.println ("Error: " + e.getMessage ()); System.exit (0); } } }
AS400 JDBCDataSourcePane
The AS400JDBCDataSourcePane class presents the property values of an AS400JDBCDataSource object. Optionally, changes can be made to the AS400JDBCDataSource object. AS400JDBCDataSourcePane extends JComponent. To use an AS400JDBCDataSourcePane to display the properties of a data source, the data source can either be specified on the AS400JDBCDataSourcePane
IBM Toolbox for Java
729
constructor or set after the AS400JDBCDataSourcePane has been created using setDataSource(). Changes made to the graphical user interface (GUI) can be applied to the data source object using applyChanges().
730
// // This source is an example of IBM Toolbox for Java "AS400ExplorerPane". // ///////////////////////////////////////////////////////////////////////// import import import import import com.ibm.as400.access.*; com.ibm.as400.vaccess.*; javax.swing.*; java.awt.*; java.awt.event.*;
public class VJobListExample { public { // // if { } try { // Create an AS400 object. The system name was passed // as the first command line argument. AS400 system = new AS400 (args[0]); // Create a VJobList object which represents the list // of jobs named QZDASOINIT. VJobList jobList = new VJobList (system); jobList.setName ("QZDASOINIT"); // Create a frame. JFrame f = new JFrame ("Job list example"); // Create an error dialog adapter. This will display // any errors to the user. ErrorDialogAdapter errorHandler = new ErrorDialogAdapter (f); // Create an explorer pane to present the job list. // Use load to load the information from the system. AS400ExplorerPane explorerPane = new AS400ExplorerPane (jobList); explorerPane.addErrorListener (errorHandler); explorerPane.load (); // When the frame closes, exit. f.addWindowListener (new WindowAdapter () { public void windowClosing (WindowEvent event) { System.exit (0); } }); // Layout the frame with the explorer pane. f.getContentPane ().setLayout (new BorderLayout ()); f.getContentPane ().add ("Center", explorerPane); f.pack (); f.show (); } catch (Exception e) { System.out.println ("Error: " + e.getMessage ()); System.exit (0);
IBM Toolbox for Java
static void main (String[] args) If a system was not specified, then display help text and exit. (args.length != 1) System.out.println("Usage: return; VJobListExample system");
731
} } }
public class VMessageQueueExample { public { // // if { } try { // Create an AS400 object. The system name was passed // as the first command line argument. AS400 system = new AS400 (args[0]); // Force the user to sign on so that we know the user id. system.connectService (AS400.COMMAND); // Create a VMessageQueue object which represents the // current user's message queue. VMessageQueue queue = new VMessageQueue (system, QSYSObjectPathName.toPath ("QUSRSYS", system.getUserId (), "MSGQ")); // Create a frame. JFrame f = new JFrame ("Message queue example"); // Create an error dialog adapter. This will display // any errors to the user. ErrorDialogAdapter errorHandler = new ErrorDialogAdapter (f); // Create an explorer pane to present the message queue. // Use load to load the information from the system. static void main (String[] args) If a system was not specified, then display help text and exit. (args.length != 1) System.out.println("Usage: return; VMessageQueueExample system");
732
AS400ExplorerPane explorerPane = new AS400ExplorerPane (queue); explorerPane.addErrorListener (errorHandler); explorerPane.load (); // When the frame closes, exit. f.addWindowListener (new WindowAdapter () { public void windowClosing (WindowEvent event) { System.exit (0); } }); // Layout the frame with the explorer pane. f.getContentPane ().setLayout (new BorderLayout ()); f.getContentPane ().add ("Center", explorerPane); f.pack (); f.show (); } catch (Exception e) { System.out.println ("Error: " + e.getMessage ()); System.exit (0); } } }
public class ProgramCallButtonExample { private private private private // // // // // ProgramParameter JTextField JTextField JTextField parm1, parm2, parm3, parm4, parm5; cpuField; dasdField; jobsField;
Create a ProgramCallButtonExample object, then call the non-static version of main(). If we don't to this then the class variables (parm1, parm2, ...) must be declared static. If they are static they cannot be used by the action completed listener in Java 1.1.7 or 1.1.8.
IBM Toolbox for Java
733
public static void main (String[] args) { ProgramCallButtonExample me = new ProgramCallButtonExample(); me.Main(args); } public { // // if { } try { // Create a frame. JFrame f = new JFrame ("Program call button example"); // Create an error dialog adapter. This will display // any errors to the user. ErrorDialogAdapter errorHandler = new ErrorDialogAdapter (f); // Create an AS400 object. The system name was passed // as the first command line argument. AS400 system = new AS400 (args[0]); // Create the program path name. QSYSObjectPathName programName = new QSYSObjectPathName ("QSYS", "QWCRSSTS", "PGM"); // Create a ProgramCallButton object. The button // will have the text "Refresh" and no icon. ProgramCallButton button = new ProgramCallButton ("Refresh", null); button.setSystem (system); button.setProgram (programName.getPath ()); button.addErrorListener (errorHandler); // The first parameter is an 64 byte output parameter. parm1 = new ProgramParameter (64); button.addParameter (parm1); // We use the second parameter to set the buffer size // of the first parameter. We will always set this to // 64. Remember that we need to convert the Java int // value 64 to the format used on the server. AS400Bin4 parm2Converter = new AS400Bin4 (); byte[] parm2Bytes = parm2Converter.toBytes (64); parm2 = new ProgramParameter (parm2Bytes); button.addParameter (parm2); // The third parameter is the status format. We will // always use "SSTS0200". This is a String value, and // again we need to convert it to the format used on the server. AS400Text parm3Converter = new AS400Text (8, system); byte[] parm3Bytes = parm3Converter.toBytes ("SSTS0200"); parm3 = new ProgramParameter (parm3Bytes); button.addParameter (parm3); // The fourth parameter is the reset statistics parameter. // We will always pass "*NO" as a 10 character String. AS400Text parm4Converter = new AS400Text (10, system); byte[] parm4Bytes = parm4Converter.toBytes ("*NO "); parm4 = new ProgramParameter (parm4Bytes); button.addParameter (parm4); void Main (String[] args) If a system was not specified, then display help text and exit. (args.length != 1) System.out.println("Usage: return; ProgramCallButtonExample system");
734
// The fifth parameter is for error information. It // is an input/output parameter. We will not use it // for this example, but we need to set it to something, // or else the number of parameters will not match // what the server is expecting. byte[] parm5Bytes = new byte[32]; parm5 = new ProgramParameter (parm5Bytes, 0); button.addParameter (parm5); // When the program runs, we will get a bunch of data. // We need a way to display that data to the user. // In this case, we will just use simple labels and text // fields. JLabel cpuLabel = new JLabel ("CPU Utilitization: "); cpuField = new JTextField (10); cpuField.setEditable (false); JLabel dasdLabel = new JLabel ("DASD Utilitization: "); dasdField = new JTextField (10); dasdField.setEditable (false); JLabel jobsLabel = new JLabel ("Number of active jobs: "); jobsField = new JTextField (10); jobsField.setEditable (false); // When the frame closes, exit. f.addWindowListener (new WindowAdapter () { public void windowClosing (WindowEvent event) { System.exit (0); } }); // When the program is called, we need to process the // information that comes back in the first parameter. // The format of the data in this parameter was documented // by the program we are calling. button.addActionCompletedListener (new ActionCompletedListener () { public void actionCompleted (ActionCompletedEvent event) { try { // Get the data from the first parameter. // It is in the server format. byte[] parm1Bytes = parm1.getOutputData (); // Each of the pieces of data that we need // is an int. We can create one converter // to do all of our conversions. AS400Bin4 parm1Converter = new AS400Bin4 (); // Get the CPU utilitization starting at byte 32. // Set this value in the corresponding text field. int cpu = parm1Converter.toInt (parm1Bytes, 32); cpuField.setText (Integer.toString (cpu / 10) + "%"); // Get the DASD utilitization starting at byte 52. // Set this value in the corresponding text field. int dasd = parm1Converter.toInt (parm1Bytes, 52); dasdField.setText (Integer.toString (dasd / 10000) + "%"); // Get the number of active jobs starting at byte 36. // Set this value in the corresponding text field. int jobs = parm1Converter.toInt (parm1Bytes, 36);
IBM Toolbox for Java
735
jobsField.setText (Integer.toString (jobs)); } catch (Exception e) { e.printStackTrace(); } } }); // Layout the frame. JPanel outputPanel = new JPanel (); outputPanel.setLayout (new GridLayout (3, 2, 5, 5)); outputPanel.add (cpuLabel); outputPanel.add (cpuField); outputPanel.add (dasdLabel); outputPanel.add (dasdField); outputPanel.add (jobsLabel); outputPanel.add (jobsField); Panel buttonPanel = new Panel (); buttonPanel.add (button); f.getContentPane ().setLayout (new BorderLayout ()); f.getContentPane ().add ("Center", outputPanel); f.getContentPane ().add ("South", buttonPanel); f.pack (); f.show (); } catch (Exception e) { System.out.println ("Error: " + e.getMessage ()); System.exit (0); } } }
public class VPrinterExample { public static void main (String[] args) { // If the user does not supply a printer name then show printer information // for a printer called OS2VPRT; String printerName = "OS2VPRT";
736
// If a system was not specified, then display help text and // exit. if (args.length == 0) { System.out.println("Usage: VPrinterExample system printer"); return; } // If the user specified a name, use it instead of the default. if (args.length > 1) printerName = args[1]; try { // Create an AS400 object. The system name was passed // as the first command line argument. AS400 system = new AS400 (args[0]); // Create a Printer object (from the Toolbox access package) // which represents the printer, then create a VPrinter // object to graphically show the spooled files on the printer. Printer printer = new Printer(system, printerName); VPrinter vprinter = new VPrinter(printer); // Create a frame to hold our window. JFrame f = new JFrame ("VPrinter Example"); // Create an error dialog adapter. This will display // any errors to the user. ErrorDialogAdapter errorHandler = new ErrorDialogAdapter (f); // Create an explorer pane to present the printer and its spooled // files. Use load to load the information from the system. AS400ExplorerPane explorerPane = new AS400ExplorerPane (vprinter); explorerPane.addErrorListener (errorHandler); explorerPane.load (); // When the frame closes, exit. f.addWindowListener (new WindowAdapter () { public void windowClosing (WindowEvent event) { System.exit (0); } }); // Layout the frame with the explorer pane. f.getContentPane ().setLayout (new BorderLayout ()); f.getContentPane ().add ("Center", explorerPane); f.pack (); f.show (); } catch (Exception e) { System.out.println ("Error: " + e.getMessage ()); System.exit (0); } } }
737
Note: Read the Code example disclaimer for important legal information.
///////////////////////////////////////////////////////////////////////// // // VPrinters example. This program presents various network // print resources with an explorer pane. // // Command syntax: // VPrintersExample system // // This source is an example of IBM Toolbox for Java "VPrinters". // ///////////////////////////////////////////////////////////////////////// import import import import import com.ibm.as400.access.*; com.ibm.as400.vaccess.*; javax.swing.*; java.awt.*; java.awt.event.*;
public class VPrintersExample { public { // // if { } try { // Create an AS400 object. The system name was passed // as the first command line argument. AS400 system = new AS400 (args[0]); // Create a VPrinters object which represents the list // of printers attached to the system. VPrinters printers = new VPrinters (system); // Create a frame. JFrame f = new JFrame ("VPrinters example"); // Create an error dialog adapter. This will display // any errors to the user. ErrorDialogAdapter errorHandler = new ErrorDialogAdapter (f); // Create an explorer pane to present the network print resources. // Use load to load the information from the system. AS400ExplorerPane explorerPane = new AS400ExplorerPane (printers); explorerPane.addErrorListener (errorHandler); explorerPane.load (); // When the frame closes, exit. f.addWindowListener (new WindowAdapter () { public void windowClosing (WindowEvent event) { System.exit (0); } }); // Layout the frame with the explorer pane. f.getContentPane ().setLayout (new BorderLayout ()); f.getContentPane ().add ("Center", explorerPane); static void main (String[] args) If a system was not specified, then display help text and exit. (args.length != 1) System.out.println("Usage: return; VPrintersExample system");
738
f.pack (); f.show (); } catch (Exception e) { System.out.println ("Error: " + e.getMessage ()); System.exit (0); } } }
VPrinterOutput Example
This example program presents a list of spooled files on the server. All spooled files, or only spooled files for a specific user, can be displayed. Note: Read the Code example disclaimer for important legal information.
////////////////////////////////////////////////////////////////////////////////// // // VPrinterOutput example. This program presents a list of spooled // files on the server. All spooled files, or spooled files for // a specific user can be displayed. // // Command syntax: // VPrinterOutputExample system <user> // // (User is optional, if not specified all spooled files on the system // will be displayed. Caution - listing all spooled files on the system // and take a long time) // ////////////////////////////////////////////////////////////////////////////////// import import import import import com.ibm.as400.access.*; com.ibm.as400.vaccess.*; javax.swing.*; java.awt.*; java.awt.event.*;
public class VPrinterOutputExample { public static void main (String[] args) { // If a system was not specified, display help text and exit. if (args.length == 0) { System.out.println("Usage: VPrinterOutputExample system <user>"); return; } try { // Create an AS400 object. The system name was passed // as the first command line argument. AS400 system = new AS400 (args[0]); system.connectService(AS400.PRINT); // Create the VPrinterOutput object. VPrinterOutput printerOutput = new VPrinterOutput(system); // If a user was specified as a command line parameter, tell // the printerObject to get spooled files only for that user. if (args.length > 1)
IBM Toolbox for Java
739
printerOutput.setUserFilter(args[1]); // Create a frame to hold our window. JFrame f = new JFrame ("VPrinterOutput Example"); // Create an error dialog adapter. This will display // any errors to the user. ErrorDialogAdapter errorHandler = new ErrorDialogAdapter (f); // Create an details pane to present the list of spooled files. // Use load to load the information from the system. AS400DetailsPane detailsPane = new AS400DetailsPane (printerOutput); detailsPane.addErrorListener (errorHandler); detailsPane.load (); // When the frame closes, exit. f.addWindowListener (new WindowAdapter () { public void windowClosing (WindowEvent event) { System.exit (0); } }); // Layout the frame with the details pane. f.getContentPane ().setLayout (new BorderLayout ()); f.getContentPane ().add ("Center", detailsPane); f.pack (); f.show (); } catch (Exception e) { System.out.println ("Error: " + e.getMessage ()); System.exit (0); } } }
740
// This is the main java calls. Here we create an instance of our // class and call our own Main() method. We do this to avoid // problems with static. Java has some restrictions with static // methods using non-static data, especially when it comes to // inner classes. The code is cleaner if we keep the amount of // static data and methods to a minimum. public static void main (String[] args) { SQLQueryBuilderPaneExample me = new SQLQueryBuilderPaneExample(); me.Main(args); } public { // // if { } try { // Register the IBM Toolbox for Java JDBC driver. DriverManager.registerDriver (new AS400JDBCDriver ()); // Create an SQLConnection object. The system name was passed // as the first command line argument. connection = new SQLConnection ("jdbc:as400://" + args[0]); // Create a frame. JFrame f = new JFrame ("SQLQueryBuilderPane example"); // Create an error dialog adapter. This will display // any errors to the user. errorHandler = new ErrorDialogAdapter (f); // Create a SQL query builder pane to present the query // builder. Load the data that is needed for the query // builder from the system. queryBuilderPane = new SQLQueryBuilderPane (connection); queryBuilderPane.addErrorListener (errorHandler); queryBuilderPane.load (); // Create a button which will display the results of // the generated query in a form pane in another frame. JButton resultSetButton = new JButton ("Show result set"); resultSetButton.addActionListener (new ActionListener ()
IBM Toolbox for Java
void Main (String[] args) If a system was not specified, then display help text and exit. (args.length != 1) System.out.println("Usage: return; SQLQueryBuilderPaneExample system");
741
{ public void actionPerformed (ActionEvent event) { showFormPane (queryBuilderPane.getQuery ()); } }); // When the frame closes, exit. f.addWindowListener (new WindowAdapter () { public void windowClosing (WindowEvent event) { System.exit (0); } }); // Layout the frame with the query builder pane. f.getContentPane ().setLayout (new BorderLayout ()); f.getContentPane ().add ("Center", queryBuilderPane); f.getContentPane ().add ("South", resultSetButton); f.pack (); f.show (); } catch (Exception e) { System.out.println ("Error: " + e.getMessage ()); System.exit (0); } }
private void showFormPane (String query) { // Create a new frame for the results of the query. JFrame f = new JFrame (query); // Create a SQL result set form pane to present the results // of the query. Load the results from the system. SQLResultSetFormPane formPane = new SQLResultSetFormPane (connection, query); formPane.addErrorListener (errorHandler); formPane.load (); // Layout the frame with the form pane. f.getContentPane ().setLayout (new BorderLayout ()); f.getContentPane ().add ("Center", formPane); f.pack (); f.show (); } }
742
// // Command syntax: // SQLResultSetTablePaneExample system table // // This source is an example of IBM Toolbox for Java "SQLQueryBuilderPane", // "SQLResultSetFormPane", and "SQLStatementButton". // ///////////////////////////////////////////////////////////////////////// import import import import import import com.ibm.as400.access.*; com.ibm.as400.vaccess.*; javax.swing.*; java.awt.*; java.awt.event.*; java.sql.*;
document; tablePane;
public { // // if { } try {
static void main (String[] args) If a system was not specified, then display help text and exit. (args.length != 2) System.out.println("Usage: return; SQLResultSetTablePaneExample system table");
// Register the IBM Toolbox for Java JDBC driver. DriverManager.registerDriver (new AS400JDBCDriver ()); // Create an SQLConnection object. The system name was passed // as the first command line argument. This connection is // shared by all components. SQLConnection connection = new SQLConnection ("jdbc:as400://" + args[0]); // Create a frame. JFrame f = new JFrame ("SQLResultSetTablePane example"); // Create an error dialog adapter. This will display // any errors to the user. This error handler is shared // by all components. ErrorDialogAdapter errorHandler = new ErrorDialogAdapter (f); // Create a SQL statement document which allows the // user to enter a query. document = new SQLStatementDocument (connection, ""); document.addErrorListener (errorHandler); // Create a text field for presenting the document. JTextField textField = new JTextField (document, "Enter a SQL statement here.", 50); // Create a button that deletes all rows of the table. SQLStatementButton deleteAllButton = new SQLStatementButton ("Delete all rows"); deleteAllButton.setConnection (connection); deleteAllButton.setSQLStatement ("DELETE FROM " + args[1]);
IBM Toolbox for Java
743
deleteAllButton.addErrorListener (errorHandler); // Create a SQL result set table pane to present the results // of a query. Load the contents immediately. tablePane = new SQLResultSetTablePane (connection, "SELECT * FROM " + args[1]); tablePane.addErrorListener (errorHandler); tablePane.load (); // When enter is pressed in the text field, // execute the SQL statement and update the table pane. textField.addKeyListener (new KeyAdapter () { public void keyPressed (KeyEvent event) { if (event.getKeyCode () == KeyEvent.VK_ENTER) { // If the SQL statement is a SELECT, then // let the table pane execute it, otherwise, // let the document execute it. String sql = document.getSQLStatement (); if (sql.toUpperCase ().startsWith ("SELECT")) { try { tablePane.setQuery (sql); } catch (Exception e) { // Ignore. } tablePane.load (); } else document.execute (); } } }); // When all rows are deleted using the button, then // update the table pane. deleteAllButton.addActionCompletedListener (new ActionCompletedListener () { public void actionCompleted (ActionCompletedEvent event) { tablePane.load (); } }); // When the frame closes, exit. f.addWindowListener (new WindowAdapter () { public void windowClosing (WindowEvent event) { System.exit (0); } }); // Layout the frame with the query builder pane. f.getContentPane ().setLayout (new BorderLayout ()); f.getContentPane ().add ("North", textField); f.getContentPane ().add ("Center", tablePane); f.getContentPane ().add ("South", deleteAllButton); f.pack (); f.show (); } catch (Exception e) {
744
Examples: XPCML
This section lists the code examples that are provided throughout the documentation of the IBM Toolbox for Java XPCML component. v Example: Condensing an existing XPCML document on page 751 v Example: Condensing an existing XPCML document, including Java code on page 751 v Example: Using condensed XPCML to create a ProgramCallDocument object on page 754 v Example: Obtaining program call results as condensed XPCML on page 754 v Example: Retrieving program call results as XPCML v Example: Passing in parameter values as XPCML on page 748 v Examples: Passing in arrays of parameter values as XPCML on page 749 v Example: Converting a PCML document to an XPCML document on page 439 The following disclaimer applies to all of the IBM Toolbox for Java examples: Code example disclaimer IBM grants you a nonexclusive copyright license to use all programming code examples from which you can generate similar function tailored to your own specific needs. All sample code is provided by IBM for illustrative purposes only. These examples have not been thoroughly tested under all conditions. IBM, therefore, cannot guarantee or imply reliability, serviceability, or function of these programs. All programs contained herein are provided to you "AS IS" without any warranties of any kind. The implied warranties of non-infringement, merchantability and fitness for a particular purpose are expressly disclaimed.
745
For arrays of structs, XPCML uses the <struct_i> XPCML tag to delimit each structParm element. Each <struct_i> tag indicates that the data enclosed within it is one element of type autu0150 struct. The index attribute of the <struct_i> tag specifies the element of the array for the struct. For arrays of simple types, such as arrayOfStringParm, arrayOfIntParm, and so on, the <i> XPCML tag lists array elements.
746
Java code that constructs the ProgramCallDocument object and uses the XPCML to call program QGYOLAUS
system = new AS400(); // Create a ProgramCallDocument into which to parse the file. ProgramCallDocument xpcmlDoc = new ProgramCallDocument(system, "QGYOLAUS.xpcml"); // Call QGYOLAUS boolean rc = xpcmlDoc.callProgram("QGYOLAUS"); // Obtain program call results as XPCML and store them // in file XPCMLOut.xpcml if (rc) // Program was successful xpcmlDoc.generateXPCML("QGYOLAUS","XPCMLOut.xpcml");
Results of the program call, generated as XPCML and stored in file XPCMLOut.xpcml
<?xml version="1.0" ?> <xpcml version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation='xpcml.xsd' > <program name="QGYOLAUS" path="/QSYS.lib/QGY.lib/QGYOLAUS.pgm" parseOrder="listInfo receiver"> <parameterList> <arrayOfStructParm name="receiver" passDirection="out" count="listInfo.rcdsReturned" outputSize="receiverLength" struct="autu0150"> <struct_i index="0"> <stringParm name="name" length="10">JANEDOW</stringParm> <stringParm name="userOrGroup" length="1">0</stringParm> <stringParm name="groupMembers" length="1">0</stringParm> <stringParm name="description" length="50"> Jane Doe</stringParm> </struct_i> <struct_i index="1"> <stringParm name="name" length="10">BOBS</stringParm> <stringParm name="userOrGroup" length="1">0</stringParm> <stringParm name="groupMembers" length="1">0</stringParm> <stringParm name="description" length="50"> Bob Smith</stringParm> </struct_i> <!-- More records here depending on how many users output. --> <!-- In this case 89 user records are listed here. --> </arrayOfStructParm> <!-- End of user array --> <intParm name="receiverLength" passDirection="in"> 16384</intParm> <structParm name="listInfo" passDirection="out" struct="listInfo"> <intParm name="totalRcds">89</intParm> <intParm name="rcdsReturned">89</intParm> <hexBinaryParm name="rqsHandle" totalBytes="4"> 00000001==</hexBinaryParm> <intParm name="rcdLength">62</intParm> <stringParm name="infoComplete" length="1">C</stringParm> <stringParm name="dateCreated" length="7"> 1030321</stringParm> <stringParm name="timeCreated" length="6"> 120927</stringParm> <stringParm name="listStatus" length="1">2</stringParm> <hexBinaryParm totalBytes="1"></hexBinaryParm> <unsignedIntParm name="lengthOfInfo"> 5518</unsignedIntParm> <intParm name="firstRecord">1</intParm> </structParm>
IBM Toolbox for Java
747
<intParm name="rcdsToReturn" passDirection="in">264</intParm> <stringParm name="format" passDirection="in" length="10"> AUTU0150</stringParm> <stringParm name="selection" passDirection="in" length="10"> *USER</stringParm> <stringParm name="member" passDirection="in" length="10"> *NONE</stringParm> <intParm name="errorCode" passDirection="in">0</intParm> </parameterList> </program> </xpcml>
748
749
<program name="prog1" path="/QSYS.LIB/W95LIB.LIB/PROG1.PGM"> <parameterList> <structParm name="s1Ref" struct="s1" passDirection="in" > <stringParm name="s1p1">Value 1</stringParm> <arrayOfStruct name="s1Array" count="2"> <struct_i> <stringParm name="s1Ap1">Value 1</stringParm> </struct_i> <struct_i> <stringParm name="s1Ap1">Value 2</stringParm> </struct_i> </arrayOfStruct> </structParm> <arrayOfStructParm name="s2Ref" struct="s2" count="2" passDirection="in" > <struct_i> <stringParm name="s2p1">Value 1</stringParm> </struct_i> <struct_i> <stringParm name="s2p1">Value 2</stringParm> </struct_i> </arrayOfStructParm> </parameterList> </program> </xpcml>
For example, the following XPCML specifies an array of 3 intParms and sets the first element to 12, the second to 100, and the third to 4:
<?xml version="1.0" ?> <xpcml version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation='xpcml.xsd' > <program name="prog1" path="/QSYS.lib/MYLIG.lib/PROG1.pgm"> <parameterList> <arrayOfIntParm name="intArray" count="3"> <i>12</i> <i>100</i> <i>4</i> </arrayOfIntParm> </parameterList> </program> </xpcml>
Using the index attribute of the <i> and <struct_i> tags to set array values
You can use the index attribute of the <i> and <struct_i> tags to help you set array values. In the following example, the XPCML sets the first element of the array to 4, the second to 100, and the third to 12.
<?xml version="1.0" ?> <xpcml version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation='xpcml.xsd' > <program name="prog1" path="/QSYS.lib/MYLIG.lib/PROG1.pgm"> <parameterList> <arrayOfIntParm name="intArray" count="3"> <i index="2">12</i> <i index="1">100</i> <i index="0">4</i> </arrayOfIntParm> </parameterList> </program> </xpcml>
750
Generated schema
<!-- parm1's XSD definition --> <xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'> <!-- Link back to XPCML.xsd --> <xs:include schemaLocation='xpcml.xsd'/> <xs:element name="parm1_" substitutionGroup="stringParmGroup" > <xs:complexType> <xs:simpleContent> <xs:restriction base="stringParmType"> <!-- Attributes defined for parm1 --> <xs:attribute name="name" type="string50" fixed="parm1" /> <xs:attribute name="length" type="xs:string" fixed="10" /> <xs:attribute name="passMode" type="xs:string" fixed="value" /> <xs:attribute name="ccsid" type="xs:string" fixed="37" /> <xs:attribute name="minvrm" type="xs:string" fixed="V5R2M0" /> </xs:restriction> </xs:simpleContent> </xs:complexType> </xs:element> </schema>
751
</struct> <struct name="jobi0100"> <intParm name="numberOfBytesReturned"/> <intParm name="numberOfBytesAvailable"/> <structParm name="qualifiedJobName" struct="qualifiedJobName"/> <hexBinaryParm name="internalJobIdentifier" totalBytes="16"/> <stringParm name="jobStatus" length="10"/> <stringParm name="jobType" length="1"/> <stringParm name="jobSubtype" length="1"/> <stringParm length="2"/> <intParm name="runPriority"/> <intParm name="timeSlice"/> <intParm name="defaultWait"/> <stringParm name="purge" length="10"/> </struct> <program name="qusrjobi_jobi0100" path="/QSYS.LIB/QUSRJOBI.PGM"> <parameterList> <structParm name="receiverVariable" passDirection="out" outputSize="lengthOfReceiverVariable" struct="jobi0100"/> <intParm name="lengthOfReceiverVariable" passDirection="in">86</intParm> <stringParm name="formatName" passDirection="in" length="8">JOBI0100</stringParm> <structParm name="qualifiedJobName" passDirection="in" struct="qualifiedJobName"/> <hexBinaryParm name="internalJobIdentifier" passDirection="in" totalBytes="16"> </hexBinaryParm> <intParm name="errorCode" passDirection="in">0</intParm> </parameterList> </program> </xpcml>
- "+e.getMessage());
752
<purge_/> </struct> <program name="qusrjobi_jobi0100" path="/QSYS.LIB/QUSRJOBI.PGM"> <parameterList> <structParm name="receiverVariable" passDirection="out" outputSize="lengthOfReceiverVariable" struct="jobi0100"/> <lengthOfReceiverVariable_>86</lengthOfReceiverVariable_> <formatName_>JOBI0100</formatName_> <structParm name="qualifiedJobName" passDirection="in" struct="qualifiedJobName"/> <internalJobIdentifier_> </internalJobIdentifier_> <errorCode_>0</errorCode_> </parameterList> </program> </xpcml>
753
<xs:simpleContent> <xs:restriction base="stringParmType"> <xs:attribute name="name" type="string50" fixed="formatName" /> <xs:attribute name="length" type="xs:string" fixed="8" /> <xs:attribute name="passDirection" type="passDirectionType" fixed="in" /> </xs:restriction> </xs:simpleContent> </xs:complexType> </xs:element> <!-- More type definitions for each newly defined type follow here --> </xs:schema>
Note: The XPCML code that you use to call the program (after creating the ProgramCallDocument object) is the same as the code you would use with PCML.
754
new ProgramCallDocument(system, "myCondensedXPCML.xpcml", new FileInputStream("myXSD.xsd")); boolean rc = xpcmlDoc.callProgram("qusrjobi_jobi0100"); if (rc) // Program was successful { xpcmlDoc.setXsdName("myXSD.xsd"); xpcmlDoc.generateXPCML("qusrjobi_jobi0100","XPCMLOut.xpcml"); }
The following code shows an example of obtaining program call results as condensed XPCML:
<xpcml xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="myXSD.xsd" version="4.0"> <program name="qusrjobi_jobi0100" path="/QSYS.LIB/QUSRJOBI.PGM"> <parameterList> <structParm name="receiverVariable" passDirection="out" outputSize="lengthOfReceiverVariable" struct="jobi0100"/> <numberOfBytesReturned_>100</numberOfBytesReturned_> <numberOfBytesAvailable_>100</numberOfBytesAvailable_> <structParm name="qualifiedJobName" struct="qualifiedJobName"> <jobName_>*</jobName_> <userName_/> <jobNumber_/> </structParm> <internalJobIdentifier_/> <jobStatus_>ACTIVE</jobStatus_> <jobType_>PJ</jobType> <jobSubtype_/> <stringParm length="2"/> <runPriority_>5</runPriority> <timeSlice_/> <defaultWait_>10</defaultWait_> <purge_/> </structParm> <lengthOfReceiverVariable_>86</lengthOfReceiverVariable_> <formatName_>JOBI0100</formatName_> <structParm name="qualifiedJobName" passDirection="in" struct="qualifiedJobName"/> <internalJobIdentifier_> </internalJobIdentifier_> <errorCode_>0</errorCode_> </parameterList> </program> </xpcml>
v IBM Toolbox for Java Frequently Asked Questions (FAQ) performance, troubleshooting, JDBC, and more.
755
v IBM Toolbox for Java and JTOpen forum : Offers an effective way to communicate with the community of Java programmers who use IBM Toolbox for Java and the IBM Toolbox for Java developers themselves.
: Offers information about new wireless technologies, including v IBM alphaWorks Wireless downloads and links to development resources. : Provides additional information about the Java wireless v Sun Java 2 Platform, Micro Edition technologies, including the following: K Virtual Machine (KVM) Connected Limited Device Configuration (CLDC) Mobile Information Device Profile (MIDP) v Java Technology for Wireless, Mobile, and Embedded Devices information for Java wireless application developers. v Wireless application development tools: WebSphere Everyplace Micro Environment Sun Java Wireless Toolkit for CLDC : Offers a wide range of technical
Java
Java is a programming language that allows you to develop portable object-oriented applications and applets. Use the following sites to learn more about Java: : Offers information, education, and tool to help you v IBM developerWorks Java technology zone use Java, IBM products, and other technologies to create business solutions. : Offers information about new Java technologies, including downloads and v IBM alphaWorks Java links to development resources. v The Source for Java Developers technologies. : Offers information about the various uses for Java, including new
756
Servlets
Servlets are small Java programs that run on a server and mediate requests from one or many clients (each of which runs in a browser) to one or more databases. Because servlets are programmed in Java, they can execute requests as multiple threads within a single process, thereby saving system resources. Use the following sites to learn more about servlets: : Provides technical information, instructions, and tools to help you v Java Servlet technology understand and use servlets.
XHTML
XHTML is touted as the successor to HTML 4.0. It is based on HTML 4.0, but incorporates the extensibility of XML. Use following sites to learn more about XHTML: v The Web Developer's Virtual Library links to additional information. v W3C : Offers an introduction to XHTML, including examples and
XML
Extensible Markup Language (XML) is a metalanguage that allows you to describe and organize information in ways that are easily understandable by both humans and computers. A metalanguage allows you to define a document markup language and its structure. Use the following sites to learn more about XML: v : Provides a site dedicated to the work IBM does with XML and IBM developerWorks XML zone how it works to facilitate e-commerce
: Offers information about emerging XML standards and tools, including v IBM alphaWorks XML downloads and links to development resources. v W3C XML v XML.com : Offers technical resources for XML developers. : Offers updated information about XML in the computer industry
: Provides news and information about the XML community, including industry news, v XML.org calendars of events, and more. : Provides a comprehensive online reference work for XML, SGML, and related v XML Cover Pages XML standards, like XSL and XSLT.
Other references
v IBM HTTP Server for i i. v IBM i Access additional sites. : Provides information, resources, and tips about the IBM HTTP Server for
: Offers information about IBM i Access, including downloads, FAQs, and links to
: Provides information about the browser-based emulator that v IBM WebSphere Host On-Demand offers support for S/390, IBM i, and DEC/Unix emulation. v IBM Support and downloads : Offers a portal to IBM hardware and software support.
757
758
Appendix. Notices
This information was developed for products and services offered in the U.S.A. IBM may not offer the products, services, or features discussed in this document in other countries. Consult your local IBM representative for information on the products and services currently available in your area. Any reference to an IBM product, program, or service is not intended to state or imply that only that IBM product, program, or service may be used. Any functionally equivalent product, program, or service that does not infringe any IBM intellectual property right may be used instead. However, it is the user's responsibility to evaluate and verify the operation of any non-IBM product, program, or service. IBM may have patents or pending patent applications covering subject matter described in this document. The furnishing of this document does not grant you any license to these patents. You can send license inquiries, in writing, to: IBM Director of Licensing IBM Corporation North Castle Drive Armonk, NY 10504-1785 U.S.A. For license inquiries regarding double-byte (DBCS) information, contact the IBM Intellectual Property Department in your country or send inquiries, in writing, to: Intellectual Property Licensing Legal and Intellectual Property Law IBM Japan, Ltd. 3-2-12, Roppongi, Minato-ku, Tokyo 106-8711 The following paragraph does not apply to the United Kingdom or any other country where such provisions are inconsistent with local law: INTERNATIONAL BUSINESS MACHINES CORPORATION PROVIDES THIS PUBLICATION AS IS WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Some states do not allow disclaimer of express or implied warranties in certain transactions, therefore, this statement may not apply to you. This information could include technical inaccuracies or typographical errors. Changes are periodically made to the information herein; these changes will be incorporated in new editions of the publication. IBM may make improvements and/or changes in the product(s) and/or the program(s) described in this publication at any time without notice. Any references in this information to non-IBM Web sites are provided for convenience only and do not in any manner serve as an endorsement of those Web sites. The materials at those Web sites are not part of the materials for this IBM product and use of those Web sites is at your own risk. IBM may use or distribute any of the information you supply in any way it believes appropriate without incurring any obligation to you. Licensees of this program who wish to have information about it for the purpose of enabling: (i) the exchange of information between independently created programs and other programs (including this one) and (ii) the mutual use of the information which has been exchanged, should contact: IBM Corporation
Copyright IBM Corp. 1999, 2010
759
Software Interoperability Coordinator, Department YBWA 3605 Highway 52 N Rochester, MN 55901 U.S.A. Such information may be available, subject to appropriate terms and conditions, including in some cases, payment of a fee. The licensed program described in this document and all licensed material available for it are provided by IBM under terms of the IBM Customer Agreement, IBM International Program License Agreement, IBM License Agreement for Machine Code, or any equivalent agreement between us. Any performance data contained herein was determined in a controlled environment. Therefore, the results obtained in other operating environments may vary significantly. Some measurements may have been made on development-level systems and there is no guarantee that these measurements will be the same on generally available systems. Furthermore, some measurements may have been estimated through extrapolation. Actual results may vary. Users of this document should verify the applicable data for their specific environment. Information concerning non-IBM products was obtained from the suppliers of those products, their published announcements or other publicly available sources. IBM has not tested those products and cannot confirm the accuracy of performance, compatibility or any other claims related to non-IBM products. Questions on the capabilities of non-IBM products should be addressed to the suppliers of those products. All statements regarding IBM's future direction or intent are subject to change or withdrawal without notice, and represent goals and objectives only. All IBM prices shown are IBM's suggested retail prices, are current and are subject to change without notice. Dealer prices may vary. This information contains examples of data and reports used in daily business operations. To illustrate them as completely as possible, the examples include the names of individuals, companies, brands, and products. All of these names are fictitious and any similarity to the names and addresses used by an actual business enterprise is entirely coincidental. COPYRIGHT LICENSE: This information contains sample application programs in source language, which illustrate programming techniques on various operating platforms. You may copy, modify, and distribute these sample programs in any form without payment to IBM, for the purposes of developing, using, marketing or distributing application programs conforming to the application programming interface for the operating platform for which the sample programs are written. These examples have not been thoroughly tested under all conditions. IBM, therefore, cannot guarantee or imply reliability, serviceability, or function of these programs. The sample programs are provided "AS IS", without warranty of any kind. IBM shall not be liable for any damages arising out of your use of the sample programs. Each copy or any portion of these sample programs or any derivative work, must include a copyright notice as follows: (your company name) (year). Portions of this code are derived from IBM Corp. Sample Programs. Copyright IBM Corp. _enter the year or years_. If you are viewing this information softcopy, the photographs and color illustrations may not appear.
760
Trademarks
IBM, the IBM logo, and ibm.com are trademarks or registered trademarks of International Business Machines Corp., registered in many jurisdictions worldwide. Other product and service names might be trademarks of IBM or other companies. A current list of IBM trademarks is available on the Web at Copyright and trademark information at www.ibm.com/legal/copytrade.shtml. Adobe, the Adobe logo, PostScript, and the PostScript logo are either registered trademarks or trademarks of Adobe Systems Incorporated in the United States, and/or other countries. Linux is a registered trademark of Linus Torvalds in the United States, other countries, or both. Microsoft, Windows, Windows NT, and the Windows logo are trademarks of Microsoft Corporation in the United States, other countries, or both. UNIX is a registered trademark of The Open Group in the United States and other countries. Java and all Java-based trademarks and logos are trademarks of Sun Microsystems, Inc. in the United States, other countries, or both. Other company, product, or service names may be trademarks or service marks of others.
761
762
Printed in USA