IBM I - IBM Java Development Kit
IBM I - IBM Java Development Kit
7.2
Programming
IBM Developer Kit for Java
IBM
Note
Before using this information and the product it supports, read the information in “Notices” on page
491.
This document may contain references to Licensed Internal Code. Licensed Internal Code is Machine Code and is
licensed to you under the terms of the IBM License Agreement for Machine Code.
© Copyright International Business Machines Corporation 1998, 2013.
US Government Users Restricted Rights – Use, duplication or disclosure restricted by GSA ADP Schedule Contract with
IBM Corp.
Contents
iii
Example: Using JTA to handle a transaction............................................................................ 72
Example: Multiple connections that work on a transaction.....................................................74
Example: Using a connection with multiple transactions........................................................ 76
Example: Suspended ResultSets.............................................................................................. 78
Example: Ending a transaction................................................................................................. 80
Example: Suspending and resuming a transaction.................................................................. 82
Statement types..............................................................................................................................84
Statement objects..................................................................................................................... 84
PreparedStatements................................................................................................................. 87
CallableStatements................................................................................................................... 93
ResultSets..................................................................................................................................... 100
ResultSet characteristics........................................................................................................ 100
Cursor movement....................................................................................................................106
Retrieving ResultSet data....................................................................................................... 108
Changing ResultSets............................................................................................................... 110
Creating ResultSets.................................................................................................................114
Example: ResultSet interface................................................................................................. 116
JDBC object pooling..................................................................................................................... 117
Using DataSource support for object pooling........................................................................ 117
ConnectionPoolDataSource properties.................................................................................. 119
DataSource-based statement pooling....................................................................................121
Building your own connection pooling................................................................................... 123
Batch updates...............................................................................................................................124
Statement batch update......................................................................................................... 124
PreparedStatement batch update.......................................................................................... 125
JDBC BatchUpdateException................................................................................................. 126
Blocked inserts with JDBC......................................................................................................127
Advanced data types.................................................................................................................... 128
Writing code that uses BLOBs.................................................................................................130
Writing code that uses CLOBs.................................................................................................134
Writing code that uses Datalinks............................................................................................ 138
Example: Distinct types.......................................................................................................... 139
JDBC RowSets.............................................................................................................................. 140
RowSet characteristics........................................................................................................... 140
DB2CachedRowSet................................................................................................................. 141
DB2JdbcRowSet..................................................................................................................... 158
Performance tips for the native JDBC driver............................................................................... 162
Accessing databases using DB2 SQLJ support................................................................................. 164
Structured Query Language for Java profiles.............................................................................. 165
The structured query language for Java (SQLJ) translator (sqlj)................................................ 166
Precompiling SQL statements in a profile using the DB2 SQLJ profile customizer, db2profc... 167
Printing the contents of DB2 SQLJ profiles (db2profp and profp).............................................. 171
SQLJ profile auditor installer (profdb)..........................................................................................172
Converting a serialized profile instance to Java class format using the SQLJ profile
conversion tool (profconv)...................................................................................................... 173
Embedding SQL statements in your Java application................................................................. 173
Host variables in Structured Query Language for Java.......................................................... 175
Example: Embedding SQL Statements in your Java application........................................... 175
Compiling and running SQLJ programs........................................................................................177
Java SQL routines...............................................................................................................................179
Using Java SQL routines............................................................................................................... 179
Setting up your system to use SQLJ....................................................................................... 181
Java stored procedures................................................................................................................ 181
JAVA parameter style..............................................................................................................182
DB2GENERAL parameter style............................................................................................... 183
Restrictions on Java stored procedures................................................................................. 185
Java user-defined scalar functions.............................................................................................. 185
Restrictions on Java user-defined functions..........................................................................190
iv
Java user-defined table functions.......................................................................................... 190
SQLJ procedures that manipulate JAR files................................................................................ 192
SQLJ.INSTALL_JAR................................................................................................................. 192
SQLJ.REMOVE_JAR.................................................................................................................193
SQLJ.REPLACE_JAR................................................................................................................194
SQLJ.UPDATEJARINFO........................................................................................................... 196
SQLJ.RECOVERJAR................................................................................................................. 197
SQLJ.REFRESH_CLASSES....................................................................................................... 198
Parameter passing conventions for Java stored procedures and UDFs..................................... 199
Java with other programming languages................................................................................................200
Native methods and the Java Native Interface.................................................................................201
Getting started with Java native methods................................................................................... 201
ILE native methods for Java.........................................................................................................203
Teraspace storage model native methods for Java............................................................... 204
Strings in ILE native methods................................................................................................. 205
Example: ILE native method for Java..................................................................................... 206
PASE for i native methods for Java.............................................................................................. 207
Example: IBM PASE for i native method for Java...................................................................207
Managing native method libraries................................................................................................208
Java native methods and threads considerations....................................................................... 210
Java Invocation API........................................................................................................................... 211
Invocation API functions.............................................................................................................. 212
Support for multiple Java virtual machines................................................................................. 213
Example: Java Invocation API..................................................................................................... 213
Using java.lang.Runtime.exec()......................................................................................................... 216
Example: Calling another Java program with java.lang.Runtime.exec().....................................216
Example: Calling a CL program with java.lang.Runtime.exec()................................................... 217
Example: Calling a CL command with java.lang.Runtime.exec()................................................ 218
Interprocess communications...........................................................................................................219
Using sockets for interprocess communication.......................................................................... 219
Example: Using sockets for interprocess communication.....................................................220
Using input and output streams for interprocess communication..............................................222
Example: Using input and output streams for interprocess communication........................222
Example: Calling Java from ILE C.................................................................................................223
Example: Calling Java from RPG.................................................................................................. 224
Java platform........................................................................................................................................... 224
Java applets and applications........................................................................................................... 225
Java virtual machine.......................................................................................................................... 225
Java JAR and class files..................................................................................................................... 227
Java threads....................................................................................................................................... 228
Java Development Kit........................................................................................................................ 229
Advanced topics...................................................................................................................................... 230
Java classes, packages, and directories............................................................................................230
Java-related files in the IFS............................................................................................................... 232
Java file authorities in the integrated file system............................................................................. 232
Running Java in a batch job............................................................................................................... 233
Running your Java application on a host that does not have a GUI.......................................................234
Native Abstract Windowing Toolkit....................................................................................................234
Selecting an AWT mode............................................................................................................... 234
Using AWT in normal mode with full GUI support................................................................. 235
Verifying your AWT configuration........................................................................................... 240
Java security............................................................................................................................................ 240
Changes to adopted authority in IBM i 7.2........................................................................................241
Examples: Adopted authority alternatives.................................................................................. 242
Java security model........................................................................................................................... 254
Java Cryptography Extension............................................................................................................ 255
Using hardware cryptography...................................................................................................... 256
Key pairs and hardware utilization......................................................................................... 257
v
Java Secure Socket Extension........................................................................................................... 257
Preparing your system for secure sockets layer support............................................................ 258
Changing your Java code to use socket factories........................................................................259
Examples: Changing your Java code to use server socket factories..................................... 259
Examples: Changing your Java code to use client socket factories...................................... 261
Changing your Java code to use secure sockets layer................................................................ 262
Examples: Changing your Java server to use secure sockets layer...................................... 262
Examples: Changing your Java client to use secure sockets layer........................................264
Selecting a digital certificate........................................................................................................ 265
Using the digital certificate when running your Java application............................................... 266
Using Java Secure Socket Extension........................................................................................... 267
Configuring your server to support JSSE ............................................................................... 267
Using the native IBM i JSSE provider..................................................................................... 271
Examples: IBM Java Secure Sockets Extension.................................................................... 283
Java Authentication and Authorization Service................................................................................ 286
Java Authentication and Authorization Service (JAAS) 1.0 ........................................................287
IBM Java Generic Security Service (JGSS)........................................................................................318
JGSS concepts.............................................................................................................................. 319
JGSS principals and credentials............................................................................................. 320
JGSS context establishment...................................................................................................324
JGSS message protection and exchange............................................................................... 324
Resource cleanup and release................................................................................................324
Security mechanisms..............................................................................................................324
Configuring your server to use IBM JGSS.................................................................................... 325
Configuring your IBM i to use JGSS........................................................................................ 325
JGSS providers........................................................................................................................ 325
Using a security manager........................................................................................................326
Running IBM JGSS applications...................................................................................................328
Obtaining Kerberos credentials and creating secret keys..................................................... 328
The kinit and ktab tools...........................................................................................................329
JAAS Kerberos login interface................................................................................................ 330
Configuration and policy files................................................................................................. 332
Developing IBM JGSS applications.............................................................................................. 334
IBM JGSS application programming steps.............................................................................335
Using JAAS with your JGSS application................................................................................. 340
JGSS debugging............................................................................................................................341
Samples: IBM Java Generic Security Service (JGSS).................................................................. 342
Viewing the IBM JGSS samples..............................................................................................343
Samples: Downloading and viewing Javadoc information for the IBM JGSS samples.........347
Samples: Downloading and running the sample JGSS programs......................................... 347
IBM JGSS Javadoc reference information................................................................................... 350
Tuning Java program performance......................................................................................................... 351
Java garbage collection..................................................................................................................... 351
Java Native Method Invocation performance considerations.......................................................... 352
Java exception performance considerations.................................................................................... 353
Java profiling performance tools....................................................................................................... 353
Java Virtual Machine Tool Interface.............................................................................................354
Collecting Java performance data..................................................................................................... 354
Java commands and tools.......................................................................................................................355
Java tools and utilities....................................................................................................................... 355
Standard Java tools and utilities.................................................................................................. 356
IBM Java tools and utilities.......................................................................................................... 359
Java hwkeytool........................................................................................................................359
Additional Java tools and utilities................................................................................................ 359
CL commands that are supported by Java........................................................................................ 359
Debugging Java programs on IBM i........................................................................................................ 360
Debugging Java programs using IBM i Debugger............................................................................. 360
System debugging for IBM Technology for Java..........................................................................361
vi
Debug operations......................................................................................................................... 363
Initial debugging displays for Java programs........................................................................ 364
Setting breakpoints................................................................................................................. 365
Stepping through Java programs............................................................................................366
Evaluating variables in Java programs................................................................................... 366
Debugging Java and native method programs.......................................................................367
Using the QIBM_CHILD_JOB_SNDINQMSG environment variable for debug............................ 367
Debugging Java classes loaded through a custom class loader................................................. 368
Debugging servlets....................................................................................................................... 368
Java Platform Debugger Architecture............................................................................................... 369
Finding memory leaks........................................................................................................................370
Using the Generate JVM Dump command........................................................................................ 370
Java Code examples................................................................................................................................ 371
Troubleshooting Java programs..............................................................................................................484
Limitations..........................................................................................................................................484
Finding job logs for Java problem analysis........................................................................................484
Collecting data for Java problem analysis.........................................................................................485
Applying program temporary fixes.................................................................................................... 486
Getting support for Java on IBM i...................................................................................................... 487
Related information................................................................................................................................. 488
Java Naming and Directory Interface................................................................................................488
JavaMail..............................................................................................................................................488
Java Print Service...............................................................................................................................489
Notices..............................................................................................................491
Programming interface information........................................................................................................ 492
Trademarks.............................................................................................................................................. 492
Terms and conditions.............................................................................................................................. 493
vii
viii
IBM Developer Kit for Java
IBM Developer Kit for Java™ is optimized for use in the IBM® i environment. It uses the compatibility of
Java programming and user interfaces, so you can develop your own IBM i applications.
IBM Developer Kit for Java allows you to create and run Java programs on your IBM i server. IBM
Developer Kit for Java is a compatible implementation of the Oracle America, Inc. Java Technology, so we
assume that you are familiar with their Java Development Kit (JDK) documentation. To make it easier for
you to work with their information and ours, we provide links to Oracle America, Inc.'s information.
If for any reason our links to Oracle America, Inc. Java Development Kit documentation do not work, refer
to their HTML reference documentation for the information that you need. You can find this information on
the World Wide Web at The Source for Java Technology .
Note: Read the “Code license and disclaimer information” on page 489 for important legal information.
Adopted authority
Adopted authority for Java programs is not supported by IBM Technology for Java Virtual Machine.
For more information, see Advanced control of dump agents in the Java Diagnostics Guide.
Migration considerations
When migrating from the Classic JVM, which was the default 64-bit virtual machine that existed in IBM
i 6.1, to the 32-bit version of IBM Technology for Java, consider that there may be limitations when
using the 32-bit environment. For example, the amount of addressable memory is much smaller. In 32-bit
mode, the Java object heap cannot grow much larger than 3 gigabytes. You will also be limited to running
approximately 1000 threads. If your application requires more than 1000 threads or a Java object heap
larger than 3 gigabytes use the 64-bit version of IBM Technology for Java. See “Support for multiple Java
Development Kits (JDKs)” on page 6 for more information.
Table 1 on page 4 shows the levels of Java Developer Kit, which is also referred to as Classic Java, and
the suggested IBM Technology for Java replacement.
Note: IBM recommends Java SE 71 when migrating from Java Developer Kit 1.4 or 5.0.
Table 1. Classic Java levels and the suggested IBM Technology for Java replacement.
Then possible IBM Technology for Java
If you are using classic Java version: replacements include:
Java Developer Kit 1.4 (5761-JV1 option 6) Java SE 8 32 bit (5770-JV1 option 16)
Java SE 8 64 bit (5770-JV1 option 17)
Java SE 71 32 bit (5770-JV1 option 14)
Java SE 71 64 bit (5770-JV1 option 15)
Java SE 7 32 bit (5770-JV1 option 14)
Java SE 7 64 bit (5770-JV1 option 15)
Java Developer Kit 6 (5761-JV1option 10) Java SE 8 32 bit (5770-JV1 option 16)
Java SE 8 64 bit (5770-JV1 option 17)
Java SE 71 32 bit (5770-JV1 option 14)
Java SE 71 64 bit (5770-JV1 option 15)
Java SE 7 32 bit (5770-JV1 option 14)
Java SE 7 64 bit (5770-JV1 option 15)
Related concepts
“Release-to-release compatibility” on page 27
This topic describes considerations when you are moving Java applications from an earlier release to the
most current release.
The default JDK chosen in this multiple JDK environment depends on which 5770-JV1 Options are
installed. The following table gives some examples. You can access IBM Technology for Java JDKs by
setting the JAVA_HOME environment variable, or by specifying a fully qualified path to the Java tool or
utility located in the JDK you want to use.
Note: If you install only one JDK, the default JDK is the one you installed. If you install more than one
JDK, the following order of precedence determines the default JDK:
1. Option 16 - IBM Technology for Java 8.0 32-bit
2. Option 17 - IBM Technology for Java 8.0 64-bit
3. Option 14 - IBM Technology for Java 7.1 32-bit
4. Option 15 - IBM Technology for Java 7.1 64-bit
5. Option 14 - IBM Technology for Java 7.0 32-bit
6. Option 15 - IBM Technology for Java 7.0 64-bit
ADDLNK OBJ('/QIBM/ProdData/Java400/ext/extensionToInstall.jar')
NEWLNK('/QIBM/UserData/Java400/ext/extensionToInstall.jar')
LNKTYPE(*SYMBOLIC)
Where
extensionToInstall.jar
is the name of the ZIP or JAR file that contains the extension that you want to install.
Note: JAR files of extensions not provided by IBM may be placed in the /QIBM/UserData/Java400/ext
directory.
When you create a link or add a file to an extension in the /QIBM/UserData/Java400/ext directory, the list
of files that the extension class loader searches changes for every Java virtual machine that is running on
your server. If you do not want to impact the extension class loaders for other Java virtual machines on
your server, but you still want to create a link to an extension or install an extension not shipped by IBM
with the server, follow these steps:
1. Create a directory to install the extensions. Use either the Make Directory (MKDIR) command from the
IBM i command line or the mkdir command from the Qshell Interpreter.
2. Place the extension JAR file in the directory created.
3. Add the new directory to the java.ext.dirs property. You can add the new directory to the java.ext.dirs
property by using the PROP field of the JAVA command from the IBM i command line.
If the name of your new directory is /home/username/ext, the name of your extension file is
extensionToInstall.jar, and the name of your Java program is Hello, then the commands that you enter
should look like this:
MKDIR DIR('/home/username/ext')
CRTDIR DIR('/mydir')
class HelloWorld {
public static void main (String args[]) {
System.out.println("Hello World");
}
}
On a workstation
You can create a Java source file on a workstation. Then, transfer the file to the integrated file system by
using file transfer protocol (FTP).
To create and edit Java source files on a workstation:
1. Create the ASCII file on the workstation by using the editor of your choice.
2. Connect to your server with FTP.
3. Transfer the source file to your directory in the integrated file system as a binary file, so that the file
remains in ASCII format.
With EDTF
You can edit files from any file system using the Edit File (EDTF) CL command. It is an editor that is similar
to the Source Entry Utility (SEU) for editing stream files or database files. See the Edit File (EDTF) CL
command for information.
If you use the EDTF command to create a new stream file, the file will tagged with an extended binary-
coded decimal interchange code (EBCDIC) coded character set identifier (CCSID). Java files need to be
tagged with an ASCII CCSID. You can use the Qshell utility touch to create an empty stream file with the
an ASCII CCSID and then use the EDTF command to edit the file. For example, to create an empty stream
file /tmp/Test.java with an ASCII CCSID of 819, use the following command:
Java classpath
The Java virtual machine uses the Java classpath to find classes during runtime. Java commands and
tools also use the classpath to locate classes. The default system classpath, the CLASSPATH environment
variable, and the classpath command parameter all determine what directories are searched when
looking for a particular class.
The java.ext.dirs property determines the classpath for the extensions that are loaded. See “Installing
Java extensions” on page 7 for more information.
The default bootstrap classpath is system-defined, and you should not change it. On your server, the
default bootstrap classpath specifies where to find the classes that are part of the IBM Developer Kit for
Java, and other system classes.
The java.endorsed.dirs property is a standard way to override endorsed versions of Java classes by adding
JAR files to the bootstrap classpath. See Java Endorsed Standards Override Mechanism for more
information.
To find any other classes on the system, specify the classpath to search by using the CLASSPATH
environment variable or the classpath parameter. The classpath parameter that is used on a tool or
command overrides the value that is specified in the CLASSPATH environment variable.
You can work with the CLASSPATH environment variable using the Work with Environment Variable
(WRKENVVAR) command. From the WRKENVVAR display, you can add or change the CLASSPATH
environment variable. The Add Environment Variable (ADDENVVAR) command and Change Environment
Variable (CHGENVVAR) command either add or change the CLASSPATH environment variable.
The value of the CLASSPATH environment variable is a list of path names, separated by colons (:), which
are searched to find a particular class. A path name is a sequence of zero or more directory names.
These directory names are followed by the name of the directory, the ZIP file, or the JAR file that is to be
searched in the integrated file system. The components of the path name are separated by the slash (/)
character. Use a period (.) to indicate the current working directory.
You can set the CLASSPATH variable in the Qshell environment by using the export utility that is available
using the Qshell Interpreter.
These commands add the CLASSPATH variable to your Qshell environment and set it to the value ".:/
myclasses.zip:/Product/classes"
• This command sets the CLASSPATH variable in the Qshell environment:
export -s CLASSPATH=.:/myclasses.zip:/Product/classes
• This command sets the CLASSPATH variable from the command line:
The J2SE searches the bootstrap classpath first, then the extension directories, then the classpath. The
search order for J2SE, using the previous example above, is:
1. The bootstrap classpath, which is in the sun.boot.class.path property,
2. The extension directories, which is in the java.ext.dirs property,
3. The current working directory,
4. The myclasses.zip file that is located in the "root" (/) file system,
5. The classes directory in the Product directory in the "root" (/) file system.
Some Java tools and commands contain a classpath parameter in which a list of path names can be
specified. The parameter has the same syntax as the CLASSPATH environment variable. The following list
shows some of the tools and commands for which the classpath parameter can be specified:
• java command in Qshell
• javac tool
• javah tool
• javap tool
• javadoc tool
• rmic tool
• Run Java (RUNJVA) command
For more information about these commands, see “Java commands and tools” on page 355. If you use
the classpath parameter with any of these command or tools, it ignores the CLASSPATH environment
variable.
You can override the CLASSPATH environment variable by using the java.class.path property. You can
change the java.class.path property, as well as other properties, by using the SystemDefault.properties
file. The values in the SystemDefault.properties files override the CLASSPATH environment variable. For
information about the SystemDefault.properties file, see the “SystemDefault.properties file” on page 14.
The -Xbootclasspath option and the java.endorsed.dirs property also affects what directories the system
searches when looking for classes. Using -Xbootclasspath/a:path appends path to the default bootstrap
classpath, /p:path prepends path to the bootstrap classpath, and :path replaces the bootstrap classpath
with path. JAR files located in the directories specified for the java.endorsed.dirs property are prepended
to the bootstrap classpath.
Note: Be careful when you specify -Xbootclasspath because unpredictable results occur when a system
class cannot be found or is incorrectly replaced by a user-defined class. Therefore, you should allow the
system default classpath to be searched before any user-specified classpath.
See “Java system properties” on page 14 for information about how to determine the environment in
which Java programs run.
For more information, see the Program and CL Command APIs or the Integrated file system.
Related concepts
Java system properties
Java system properties determine the environment in which you run your Java programs. They are similar
to system values or environment variables in IBM i.
Internationalization
ADDENVVAR ENVVAR(QIBM_JAVA_PROPERTIES_FILE)
VALUE(/QIBM/userdata/java400/mySystem.properties)
SystemDefault.properties file
The SystemDefault.properties file is a standard Java properties file that enables you to specify default
properties of your Java environment.
This file may be used to send in both JVM properties and JVM options. Previously only JVM properties
were supported. To also allow JVM options, the first line of the file must contain "#AllowOptions" or
else everything will be treated as a JVM property.
The SystemDefault.properties file that resides in your home directory takes priority over the
SystemDefault.properties file that resides in the /QIBM/UserData/Java400 directory.
Properties that you set in the /YourUserHome/SystemDefault.properties file affect only the
following specific Java virtual machines:
#AllowOptions
#Comments start with pound sign
prop1=12345
-Dprop2
-Dprop3=abcd
-Xmx200m
prop4=value
-Xnojit
The Java properties and options above affects the JVM in the following way:
• There are four properties: prop1, prop2, prop3, and prop4.
• The max heap size is 200 MB.
• The JIT will not be used.
If the #AllowOptions line is removed from the example above, then the JVM would contain six
properties: prop1, -Dprop2, -Dprop3, -Xms200m, prop4, and -Xnojit.
Java SE 80 64bit:
• /QOpenSys/QIBM/ProdData/JavaVM/jdk80/64bit/jre/lib/ext
• /QIBM/UserData/Java400/ext
Java SE 71 32bit:
• /QOpenSys/QIBM/ProdData/JavaVM/jdk71/32bit/jre/lib/ext
• /QIBM/UserData/Java400/ext
Java SE 71 64bit:
• /QOpenSys/QIBM/ProdData/JavaVM/jdk71/64bit/jre/lib/ext
• /QIBM/UserData/Java400/ext
Java SE 7 32bit:
• /QOpenSys/QIBM/ProdData/JavaVM/jdk70/32bit/jre/lib/ext
• /QIBM/UserData/Java400/ext
Java SE 7 64bit:
• /QOpenSys/QIBM/ProdData/JavaVM/jdk70/64bit/jre/lib/ext
• /QIBM/UserData/Java400/ext
This property is used for output only. See “Support for multiple Java Development
Kits (JDKs)” on page 6 for details.
java.library.path This property is used for locating native method libraries for the application as well as
internal JVM native libraries. The default value is obtained from the concatenation of
two lists: the IBM i library list and the paths specified for the LIBPATH environment
variable. For more information, see “Managing native method libraries” on page 208.
java.net.preferIPv4Stack • false (no's) - default value
• true
On dual stack machines, system properties are provided for setting the preferred
protocol stack (IPv4 or IPv6) as well as the preferred address family types (inet4
or inet6). IPv6 stack is preferred by default, because on a dual-stack machine IPv6
socket can talk to both IPv4 and IPv6 peers. This setting can be changed with this
property.
os.arch ppc/ppc64
os.name OS/400®
os.version V7R3M0 (default value)
Obtains the IBM i release level from the Retrieve Product Information application
programming interface (API).
os400.certificateContainer Directs Java secure sockets layer (SSL) support to use the specified certificate
container for the Java program that was started and the property that was specified.
If you specify the os400.secureApplication system property, this system
property is ignored. For example, enter -Dos400.certificateContainer=/
home/username/mykeyfile.kdb or any other keyfile in the integrated file system.
os400.certificateLabel You can specify this system property in conjunction with the
os400.certificateContainer system property. This property lets you select
which certificate in the specified container you want secure sockets layer (SSL)
to use. For example, enter -Dos400.certificateLabel=myCert, where myCert
is the label name that you assign to the certificate through the Digital Certificate
Manager (DCM) when you create or import the certificate.
os400.child.stdio.convert Controls the data conversion for stdin, stdout, and stderr in Java. Data conversion
between ASCII data and Extended Binary Coded Decimal Interchange Code (EBCDIC)
data occurs by default in the Java virtual machine. Using this property to turn on
and turn off these conversions only affects child processes that this process starts by
using the Runtime.exec() in which the command being run is a command based on
Java.
This property value becomes the default value for os400.stdio.convert in the
child processes. See “Values for os400.stdio.convert and os400.child.stdio.convert
system properties” on page 19.
os400.display.properties If this value is set to 'true', then all of the Java Virtual Machine properties are printed
to standard out. No other values are recognized.
For more information, see Time zone IDs that can be specified for the user.timezone
property in the WebSphere® Software Information Center.
Related concepts
“Customizing your IBM i server for Java usage” on page 12
Internationalization
You can customize your Java programs for a specific region of the world by creating internationalized Java
program. By using time zones, locales, and character encoding, you can ensure that your Java program
reflects the correct time, place, and language.
Related concepts
Java classpath
The Java virtual machine uses the Java classpath to find classes during runtime. Java commands and
tools also use the classpath to locate classes. The default system classpath, the CLASSPATH environment
variable, and the classpath command parameter all determine what directories are searched when
looking for a particular class.
Java system properties
Java system properties determine the environment in which you run your Java programs. They are similar
to system values or environment variables in IBM i.
IBM i globalization
Java Internationalization
For more information regarding file.encoding support, see Supported encodings by Oracle.
Release-to-release compatibility
This topic describes considerations when you are moving Java applications from an earlier release to the
most current release.
You should take into account the following compatibility issues when running Java applications in the
current release:
• IBM Technology for Java only supports JVMTI interfaces from PASE for i. As a result, JVMTI agents will
need to be ported to PASE for i.
• When using PASE for i native methods, the architecture of the native code needs to match the
architecture of the JVM. That is, object binaries need to be compiled as 32-bit binaries for a 32-bit
JVM, or as 64-bit binaries for a 64-bit JVM. This also applies to agents, such as user-provided JVMTI
agents.
• The Java system property, java.version, is not recognized as an input property for the IBM
Technology for Java JVM. In prior releases, the Classic JVM was available which honored the
java.version Java system property as input for determining which JDK to use. Beginning in IBM i
7.1, the IBM Technology for Java is the only available JVM and it requires the environment variable
JAVA_HOME to be specified to determine which JDK to use.
• In the Classic JVM, the Java method System.getenv() would return the value of the appropriate ILE
environment variable. In IBM Technology for Java, this will instead return the PASE for i environment
variable. This may cause issues where the user sets an environment variable in an ILE native method
and expects a later call to System.getenv() to retrieve it. In general, the user needs to be aware that
ILE and PASE for i have their own disjoint sets of environment variables.
• Support for direct processing stopped in IBM i 6.1. In IBM i 7.1, the Java program commands will
continue to be supported, but only when using them to target a previous release. See the Release-to-
release compatibility section for IBM i 6.1 for additional information. From i 7.2, all java program
commands are no longer supported.
Related concepts
“What's new for IBM i 7.3” on page 1
Read about new or significantly changed information for the IBM Developer Kit for Java topic collection.
Type 1
Type 1 drivers are "bridge" drivers. They use another technology such as Open Database Connectivity
(ODBC) to communicate with a database. This is an advantage because ODBC drivers exist for many
Relational Database Management System (RDBMS) platforms. The Java Native Interface (JNI) is used to
call ODBC functions from the JDBC driver.
A Type 1 driver needs to have the bridge driver installed and configured before JDBC can be used with it.
This can be a serious drawback for a production application. Type 1 drivers cannot be used in an applet
since applets cannot load native code.
Type 2
Type 2 drivers use a native API to communicate with a database system. Java native methods are used to
invoke the API functions that perform database operations. Type 2 drivers are generally faster than Type
1 drivers.
Type 2 drivers need native binary code installed and configured to work. A Type 2 driver also uses the JNI.
You cannot use a Type 2 driver in an applet since applets cannot load native code. A Type 2 JDBC driver
may require some Database Management System (DBMS) networking software to be installed.
The Developer Kit for Java JDBC driver is a Type 2 JDBC driver.
Type 4
A Type 4 driver uses Java to implement a DBMS vendor networking protocol. Since the protocols are
usually proprietary, DBMS vendors are generally the only companies providing a Type 4 JDBC driver.
Type 4 drivers are all Java drivers. This means that there is no client installation or configuration.
However, a Type 4 driver may not be suitable for some applications if the underlying protocol does not
handle issues such as security and network connectivity well.
The IBM Toolbox for Java JDBC driver is a Type 4 JDBC driver, indicating that the API is a pure Java
networking protocol driver.
Related concepts
JDBC requirements
This topic indicates the requirements you need to access Core JDBC and the Java Transaction API (JTA).
Related tasks
JDBC tutorial
The following is a tutorial on writing a Java Database Connectivity (JDBC) program and running it on IBM
i with the native JDBC driver. It is designed to show you the basic steps required for your program to run
JDBC.
Setting up JNDI for the Java examples
DataSources work hand-in-hand with the Java Naming and Directory Interface (JNDI). JNDI is a Java
abstraction layer for directory services just as Java Database Connectivity (JDBC) is an abstraction layer
for databases.
JDBC requirements
This topic indicates the requirements you need to access Core JDBC and the Java Transaction API (JTA).
Before you write and deploy your JDBC applications, you may need to include specific JAR files in your
classpath.
Core JDBC
For core Java Database Connectivity (JDBC) access to the local database, there are no requirements. All
support is built in, preinstalled, and configured.
JDBC compliance
The native JDBC driver is compliant with all relevant JDBC specifications. The compliance level of the
JDBC driver is not dependent on the IBM i release, but on the JDK release you use. The native JDBC
driver's compliance level for the various JDKs is listed as follows:
Related concepts
Types of JDBC drivers
JDBC tutorial
The following is a tutorial on writing a Java Database Connectivity (JDBC) program and running it on IBM
i with the native JDBC driver. It is designed to show you the basic steps required for your program to run
JDBC.
The example creates a table and populates it with some data. The program processes a query to get that
data out of the database and to display it on the screen.
Run the example program
To run the example program, perform the following steps:
1. Copy the program to your workstation.
a) Copy the example and paste it into a file on your workstation.
b) Save the file with the same name as the public class provided and with the .java extension. In this
case, you must name the file BasicJDBC.java on your local workstation.
2. Transfer the file from your workstation to your server. From a command prompt, enter the following
commands:
For these commands to work, you must have a directory in which to put the file. In the example, /
home/cujo is the location, but you can use any location you want.
Note: It is possible that the FTP commands mentioned previously may be different for you based on
how your server is set up, but they should be similar. It does not matter how you transfer the file to
your server as long as you transfer it into the integrated file system.
3. Make sure you set your classpath to the directory where you put the file in so that your Java
commands find the file when you run them. From a CL command line, you can use WRKENVVAR
to see what environment variables are set for your user profile.
• If you see an environment variable named CLASSPATH, you must ensure that the location where you
put the .java file in is in the string of directories listed there or add it if the location has not been
specified.
• If there is no CLASSPATH environment variable, you must add one. This can be accomplished with
the following command:
ADDENVVAR ENVVAR(CLASSPATH)
VALUE('/home/cujo:/QIBM/ProdData/Java400/jdk15/lib/tools.jar')
Note: To compile Java code from the CL command, you must include the tools.jar file. This JAR file
includes the javac command.
cd /home/cujo
javac BasicJDBC.java
QSH automatically ensures that the tools.jar file can be found. As a result, you do not have to add it
to your classpath. The current directory is also in the classpath. By issuing the change directory (cd)
command, the BasicJDBC.java file is also found.
Note: You can also compile the file on your workstation and use FTP to send the class file to your
server in binary mode. This is an example of Java's ability to run on any platform.
Run the program by using the following command from either the CL command line or from QSH:
java BasicJDBC
----------------------
| 1 | Frank Johnson |
| |
| 2 | Neil Schwartz |
| |
| 3 | Ben Rodman |
| |
| 4 | Dan Gloore |
----------------------
There were 4 rows returned.
Output is complete.
Java program completed.
Related concepts
Types of JDBC drivers
This topic defines the Java Database Connectivity (JDBC) driver types. Driver types are used to categorize
the technology used to connect to the database. A JDBC driver vendor uses these types to describe how
their product operates. Some JDBC driver types are better suited for some applications than others.
JDBC requirements
This topic indicates the requirements you need to access Core JDBC and the Java Transaction API (JTA).
Related tasks
Setting up JNDI for the Java examples
DataSources work hand-in-hand with the Java Naming and Directory Interface (JNDI). JNDI is a Java
abstraction layer for directory services just as Java Database Connectivity (JDBC) is an abstraction layer
for databases.
IBM Toolbox for Java JDBC driver Web site
Oracle JDBC documentation
Example: JDBC
This is an example of how to use the BasicJDBC program. This program uses the native JDBC driver for
the IBM Developer Kit for Java to build a simple table and process a query that displays the data in that
table.
Note: By using the code examples, you agree to the terms of the “Code license and disclaimer
information” on page 489.
//////////////////////////////////////////////////////////////////////////////////
//
// BasicJDBC example. This program uses the native JDBC driver for the
// Developer Kit for Java to build a simple table and process a query
// that displays the data in that table.
// Use a try/catch block to catch all exceptions that can come out of the
// following code.
try {
// The DriverManager must be aware that there is a JDBC driver available
// to handle a user connection request. The following line causes the
// native JDBC driver to be loaded and registered with the DriverManager.
Class.forName("com.ibm.db2.jdbc.app.DB2Driver");
// Create the database Connection object that this program uses in all
// the other method calls that are made. The following code specifies
// that a connection is to be established to the local database and that
// that connection should conform to the properties that were set up
// previously (that is, it should use the user ID and password specified).
connection = DriverManager.getConnection("jdbc:db2:*local", properties);
} catch (Exception e) {
// If any of the lines in the try/catch block fail, control transfers to
// the following line of code. A robust application tries to handle the
// problem or provide more details to you. In this program, the error
// message from the exception is displayed and the application allows
// the program to return.
System.out.println("Caught exception: " + e.getMessage());
}
}
/**
Ensures that the qgpl.basicjdbc table looks you want it to at the start of
the test.
try {
// Build the test table from scratch. Process an update statement
// that attempts to delete the table if it currently exists.
s.executeUpdate("drop table qgpl.basicjdbc");
} catch (SQLException e) {
// Do not perform anything if an exception occurred. Assume
// that the problem is that the table that was dropped does not
// exist and that it can be created next.
}
// Use the statement object to populate our table with some data.
s.executeUpdate("insert into qgpl.basicjdbc values(1, 'Frank Johnson')");
s.executeUpdate("insert into qgpl.basicjdbc values(2, 'Neil Schwartz')");
s.executeUpdate("insert into qgpl.basicjdbc values(3, 'Ben Rodman')");
s.executeUpdate("insert into qgpl.basicjdbc values(4, 'Dan Gloore')");
/**
Runs a query against the demonstration table and the results are displayed to
standard out.
**/
public void runQuery() {
// Wrap all the functionality in a try/catch block so an attempts is
// made to handle any errors that might happen within this
// method.
try {
// Create a Statement object.
Statement s = connection.createStatement();
// Display the top of our 'table' and initialize the counter for the
// number of rows returned.
System.out.println("--------------------");
int i = 0;
// Obtain both columns in the table for each row and write a row to
// our on-screen table with the data. Then, increment the count
// of rows that have been processed.
System.out.println("| " + rs.getInt(1) + " | " + rs.getString(2) + "|");
i++;
}
// Place a border at the bottom on the table and display the number of rows
// as output.
System.out.println("--------------------");
System.out.println("There were " + i + " rows returned.");
System.out.println("Output is complete.");
} catch (SQLException e) {
// Display more information about any SQL exceptions that are
// generated as output.
System.out.println("SQLException exception: ");
System.out.println("Message:....." + e.getMessage());
System.out.println("SQLState:...." + e.getSQLState());
System.out.println("Vendor Code:." + e.getErrorCode());
e.printStackTrace();
}
}
/**
The following method ensures that any JDBC resources that are still
allocated are freed.
**/
public void cleanup() {
try {
if (connection != null)
connection.close();
} catch (Exception e) {
System.out.println("Caught exception: ");
e.printStackTrace();
}
1. Download the file system JNDI support from Oracle JNDI site .
2. Transfer (using FTP or another mechanism) fscontext.jar and providerutil.jar to your system and put
them in /QIBM/UserData/Java400/ext. This is the extensions directory and the JAR files that you place
here are found automatically when you run your application (that is, you do not need them in your
classpath).
Once you have support for a service provider for JNDI, you must set up the context information for your
applications. This can be accomplished by putting the required information in a SystemDefault.properties
file. There are several places on the system where you can specify default properties, but the best way is
to create a text file called SystemDefault.properties in your home directory (that is, at /home/).
To create a file, use the following lines or add them to your existing file:
These lines specify that the file system service provider handles JNDI requests and that /DataSources/
jdbc is the root for tasks that use JNDI. You can change this location, but the directory that you specify
must exist. The location that you specify is where the example DataSources are bound and deployed.
Related concepts
Types of JDBC drivers
This topic defines the Java Database Connectivity (JDBC) driver types. Driver types are used to categorize
the technology used to connect to the database. A JDBC driver vendor uses these types to describe how
their product operates. Some JDBC driver types are better suited for some applications than others.
JDBC requirements
This topic indicates the requirements you need to access Core JDBC and the Java Transaction API (JTA).
Related tasks
JDBC tutorial
The following is a tutorial on writing a Java Database Connectivity (JDBC) program and running it on IBM
i with the native JDBC driver. It is designed to show you the basic steps required for your program to run
JDBC.
Connections
The Connection object represents a connection to a data source in Java Database Connectivity (JDBC). It
is through Connection objects that Statement objects are created for processing SQL statements against
Class.forName("com.ibm.db2.jdbc.app.DB2Driver");
JDBC drivers are designed to tell the DriverManager about themselves automatically when their driver
implementation class loads.
In JDBC 4.0, JDBC driver are automatically loaded and the Class.forName call is not necessary.
Once the native JDBC driver is available for the DriverManager with which to work, the following line of
code requests a Connection object using the native JDBC URL:
Example: Request a Connection object
Connection c = DriverManager.getConnection("jdbc:db2:*local");
Connection c =
DriverManager.getConnection("jdbc:db2:rchasmop");
This creates a connection to the rchasmop system. If the system to which you are trying to connect is a
remote system (for example, through the Distributed Relational Database Architecture), the system name
from the relational database directory must be used.
Note: When not specified, the user ID and password currently used to sign in are also used to establish
the connection to the database.
Note: The IBM DB2 JDBC Universal driver also uses the db2 subprotocol. To assure that the native
JDBC driver will handle the URL, applications need to use the jdbc:db2iSeries:xxxx URL instead of the
jdbc:db2:xxxx URL. If the application does not want the native driver to accept URLS with the db2
subprotocol, then the application should load the class com.ibm.db2.jdbc.app.DB2iSeriesDriver, instead
of com.ibm.db2.jdbc.app.DB2Driver. When this class is loaded, the native driver no longer handles URLs
containing the db2 subprotocol.
Properties
The DriverManager.getConnection method takes a single string URL indicated previously and is only one
of the methods on DriverManager to obtain a Connection object. There is also another version of the
DriverManager.getConnection method that takes a user ID and password. The following is an example of
this version:
Example: DriverManager.getConnection method taking a user ID and password
The line of code attempts to connect to the local database as user cujo with password newtiger no matter
who is running the application. There is also a version of the DriverManager.getConnection method that
takes a java.util.Properties object to allow further customization. The following is an example:
Example: DriverManager.getConnection method taking a java.util.Properties object
The code is functionally equivalent to the version previously mentioned that passed the user ID and
password as parameters.
Refer to Connection properties for a complete list of connection properties for the native JDBC driver.
URL properties
Another way to specify properties is to place them in a list on the URL object itself. Each property in the
list is separated by a semi-colon and the list must be of the form property name=property value.
This is just a shortcut and does not significantly change the way processing is performed as the following
example shows:
Example: Specify URL properties
Connection c =
DriverManager.getConnection("jdbc:db2:*local;user=cujo;password=newtiger");
Related concepts
Using DataSources with UDBDataSource
DataSource interfaces allow additional flexibility in using Java Database Connectivity (JDBC) drivers.
Related reference
JDBC driver connection properties
This table contains valid JDBC driver connection properties, their values, and their descriptions.
DataSource properties
For each JDBC driver connection property, there is a corresponding data source method. This table
contains the valid data source properties.
ENDSBS sbs
ADDPJE SBSD(library/sbsd)
PGM(QSYS/QSQSRVR) STRJOBS(*YES) INLJOBS(x)
THRESHOLD(y) ADLJOBS(z) MAXUSE(*NOMAX)
STRSBS sbs
UDBDataSourceBind
The “Example: Creating a UDBDataSource and binding it with JNDI” on page 47 program is an example
of creating a UDBDataSource and getting it bound with JNDI. This program accomplishes all the basic
tasks requested. Namely, it instantiates a UDBDataSource object, sets properties on this object, retrieves
a JNDI context, and binds the object to a name within the JNDI context.
The deployment time code is vendor-specific. The application must import the specific DataSource
implementation that it wants to work with. In the import list, the package-qualified UDBDataSource class
is imported. The most unfamiliar part of this application is the work done with JNDI (for example, the
retrieval of the Context object and the call to bind). For additional information, see JNDI by Oracle.
Once this program has been run and has successfully completed, there is a new entry in a JNDI directory
service called SimpleDS. This entry is at the location specified by the JNDI context. The DataSource
implementation is now deployed. An application program can make use of this DataSource to retrieve
database connections and JDBC-related work.
DataSource properties
For each JDBC driver connection property, there is a corresponding data source method. This table
contains the valid data source properties.
For some properties, you can refer to the corresponding driver connection property for more information.
Related concepts
Java DriverManager class
DriverManager is a static class in the Java 2 Plaform, Standard Edition (J2SE) and Java SE Development
Kit (JDK). DriverManager manages the set of Java Database Connectivity (JDBC) drivers that are available
for an application to use.
Using DataSources with UDBDataSource
DataSource interfaces allow additional flexibility in using Java Database Connectivity (JDBC) drivers.
Related reference
JDBC driver connection properties
This table contains valid JDBC driver connection properties, their values, and their descriptions.
jdbc.db2.trace 1 or error = Trace error information This property turns on tracing for
2 or info = Trace information and the JDBC driver. It should be used
error information 3 or verbose = when reporting a problem.
Trace verbose, information, and
error information 4 or all or true =
Trace all possible information
DatabaseMetaData interface
The DatabaseMetaData interface is implemented by the IBM Developer Kit for Java JDBC driver to
provide information about its underlying data sources. It is used primarily by application servers and
tools to determine how to interact with a given data source. Applications may also use DatabaseMetaData
methods to obtain information about a data source, but this is less typical.
The DatabaseMetaData interface includes over 150 methods that can be categorized according to the
types of information they provide. These are described below. The DatabaseMetaData interface also
contains over 40 fields that are constants used as return values for various DatabaseMetaData methods.
See "Changes in JDBC 3.0" and "Changes in JDBC 4.0" below for information about changes made to
methods in the DatabaseMetaData interface.
Transaction support
A small group of methods provide information about the transaction semantics supported by the data
source. Examples of this category include the following:
• supportsMultipleTransactions
• getDefaultTransactionIsolation
See “Example: Returning a list of tables using the DatabaseMetaData interface” on page 58 for an
example of how to use the DatabaseMetaData interface.
The SQL special registers corresponding to the client info properties are as follows:
The clientInfoProperties may be set using the Connection object's setClientInfo method.
Related concepts
“ResultSets” on page 100
The ResultSet interface provides access to the results generated by running queries. Conceptually, data of
a ResultSet can be thought of as a table with a specific number of columns and a specific number of rows.
By default, the table rows are retrieved in sequence. Within a row, column values can be accessed in any
order.
Related reference
Example: Using metadata ResultSets that have more than one column
This is an example of how to use metadata ResultSets that have more than one column.
Example: Using metadata ResultSets that have more than one column
This is an example of how to use metadata ResultSets that have more than one column.
Note: By using the code examples, you agree to the terms of the “Code license and disclaimer
information” on page 489.
//////////////////////////////////////////////////////////////////////////////////
//
// SafeGetUDTs example. This program demonstrates one way to deal with
// metadata ResultSets that have more columns in JDK 1.4 than they
// had in previous releases.
//
// Command syntax:
// java SafeGetUDTs
//
//////////////////////////////////////////////////////////////////////////////////
//
// This source is an example of the IBM Developer for Java JDBC driver.
// IBM grants you a nonexclusive license to use this as an example
// from which you can generate similar function tailored to
// your own specific needs.
//
// This 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
// merchantability and fitness for a particular purpose are
// expressly disclaimed.
//
// IBM Developer Kit for Java
// (C) Copyright IBM Corp. 2001
// All rights reserved.
// US Government Users Restricted Rights -
// Use, duplication, or disclosure restricted
// by GSA ADP Schedule Contract with IBM Corp.
//
//////////////////////////////////////////////////////////////////////////////////
import java.sql.*;
try {
Class.forName("java.sql.ParameterMetaData");
// Found a JDBC 3.0 interface. Must support JDBC 3.0.
jdbcLevel = 3;
} catch (ClassNotFoundException ez) {
// Could not find the JDBC 3.0 ParameterMetaData class.
// Must be running under a JVM with only JDBC 2.0
// support.
jdbcLevel = 2;
}
try {
// Get the driver registered.
Class.forName("com.ibm.db2.jdbc.app.DB2Driver");
c = DriverManager.getConnection("jdbc:db2:*local");
DatabaseMetaData dmd = c.getMetaData();
if (jdbcLevel == 1) {
System.out.println("No support is provided for getUDTs. Just return.");
System.exit(1);
}
// Fetch all the columns that have been available since the
// JDBC 2.0 release.
System.out.println("TYPE_CAT is " + rs.getString("TYPE_CAT"));
System.out.println("TYPE_SCHEM is " + rs.getString("TYPE_SCHEM"));
System.out.println("TYPE_NAME is " + rs.getString("TYPE_NAME"));
System.out.println("CLASS_NAME is " + rs.getString("CLASS_NAME"));
System.out.println("DATA_TYPE is " + rs.getString("DATA_TYPE"));
System.out.println("REMARKS is " + rs.getString("REMARKS"));
Related reference
Example: Returning a list of tables using the DatabaseMetaData interface
This example shows how to return a list of tables.
Java exceptions
The Java language uses exceptions to provide error-handling capabilities for its programs. An exception is
an event that occurs when you run your program that disrupts the normal flow of instructions.
The Java runtime system and many classes from Java packages throw exceptions in some circumstances
by using the throw statement. You can use the same mechanism to throw exceptions in your Java
programs.
DB2Exception.java
DB2Exception objects are not thrown directly either. This base class is used to hold functionality that
is common to all JDBC exceptions. There are two subclasses of this class that are be the standard
exceptions that JDBC throws. These subclasses are DB2DBException.java and DB2JDBCException.java.
DB2DBExceptions are exceptions that are reported to you that have come directly from the database.
DB2JDBCExceptions are thrown when the JDBC driver finds problems on its own. Splitting the exception
class hierarchy in this manner allows you to handle the two types of exceptions differently.
DB2DBException.java
As stated, DB2DBExceptions are exceptions that come directly from the database. These are encountered
when the JDBC driver make a call to the CLI and gets back an SQLERROR return code. The CLI function
SQLError is called to get the message text, SQLState, and vendor code in these cases. The replacement
text for the SQLMessage is also retrieved and returned to you. The DatabaseException class causes an
error that the database recognizes and reports to the JDBC driver to build the exception object for.
DB2JDBCException.java
DB2JDBCExceptions are generated for error conditions that come from the JDBC driver itself. The
functionality of this exception class is fundamentally different; the JDBC driver itself handles message
language translation of exception and other issues that the operating system and database handle
for exceptions originating within the database. Wherever possible, the JDBC driver adheres to the
SQLStates of the database. The vendor code for exceptions that the JDBC driver throws is always -99999.
DB2DBExceptions that are recognized and returned by the CLI layer often also have the -99999 error
code. The JDBCException class causes an error that the JDBC driver recognizes and builds the exception
for itself. When run during development of the release, the following output was created. Notice that the
top of the stack contains DB2JDBCException. This is an indication that the error is being reported from
the JDBC driver prior to ever making the request to the database.
Related concepts
SQLWarning
Methods in some interfaces generate an SQLWarning object if the methods cause a database access
warning.
DataTruncation and silent truncation
DataTruncation is a subclass of SQLWarning. While SQLWarnings are not thrown, DataTruncation objects
are sometimes thrown and attached like other SQLWarning objects. Silent truncation occurs when the
Example: SQLException
This is an example of catching an SQLException and dumping all the information that it provides.
Note: By using the code examples, you agree to the terms of the “Code license and disclaimer
information” on page 489.
import java.sql.*;
try {
Class.forName("com.ibm.db2.jdbc.app.DB2Driver");
connection = DriverManager.getConnection("jdbc:db2:*local");
Statement s = connection.createStatement();
int count = s.executeUpdate("insert into cujofake.cujofake values(1, 2,3)");
} catch (SQLException e) {
System.out.println("SQLException exception: ");
System.out.println("Message:....." + e.getMessage());
System.out.println("SQLState:...." + e.getSQLState());
System.out.println("Vendor Code:." + e.getErrorCode());
System.out.println("-----------------------------------------------------");
e.printStackTrace();
} catch (Exception ex) {
System.out.println("An exception other than an SQLException was thrown: ");
ex.printStackTrace();
} finally {
try {
if (connection != null) {
connection.close();
}
} catch (SQLException e) {
System.out.println("Exception caught attempting to shutdown...");
}
}
}
}
SQLWarning
Methods in some interfaces generate an SQLWarning object if the methods cause a database access
warning.
Methods in the following interfaces can generate an SQLWarning:
• Connection
• Statement and its subtypes, PreparedStatement and CallableStatement
• ResultSet
When a method generates an SQLWarning object, the caller is not informed that a data access
warning has occurred. The getWarnings method must be called on the appropriate object to retrieve
the SQLWarning object. However, the DataTruncation subclass of SQLWarning may be thrown in some
circumstances. It should be noted that the native JDBC driver opts to ignore some database-generated
warnings for increased efficiency. For example, a warning is generated by the system when you attempt
to retrieve data beyond the end of a ResultSet through the ResultSet.next method. In this case, the next
method is defined to return false instead of true, informing you of the error. It is unnecessary to create an
object to restate this, so the warning is simply ignored.
Data truncation property only affects character and binary-based data types
A couple releases ago, the data truncation property determined whether data truncation exceptions could
be thrown. The data truncation property was put in place to have JDBC applications not worry about a
value getting truncated when the truncation was not important to them. There are few cases where you
would want either the value 00 or 10 stored in the database when applications attempted to insert 100
into a DECIMAL(2,0). Therefore, the JDBC driver's data truncation property was changed to only honor
situations where the parameter is for character-based types such as CHAR, VARCHAR, CHAR FOR BIT
DATA, and VARCHAR FOR BIT DATA.
Silent truncation
The setMaxFieldSize statement method allows a maximum field size to be specified for any column. If
data truncates because its size has exceeded the maximum field size value, no warning or exception
is reported. This method, like the data truncation property previously mentioned, only affects character-
based types such as CHAR, VARCHAR, CHAR FOR BIT DATA, and VARCHAR FOR BIT DATA.
Related concepts
Java SQLException class
JDBC transactions
A transaction is a logical unit of work. To complete a logical unit of work, several actions may need to be
taken against a database.
Transactional support allows applications to ensure the following:
• All the steps to complete a logical unit of work are followed.
• When one of the steps to the unit of work files fails, all the work done as part of that logical unit of work
can be undone and the database can return to its previous state before the transaction began.
Transactions are used to provide data integrity, correct application semantics, and a consistent view of
data during concurrent access. All Java Database Connectivity (JDBC) compliant drivers must support
transactions.
Note: This section only discusses local transactions and the standard JDBC concept of transactions. Java
and the native JDBC driver support the Java Transaction API (JTA), distributed transactions, and the
two-phase commit protocol (2PC).
All transactional work is handled at the Connection object level. When the work for a transaction
completes, it can be finalized by calling the commit method. If the application aborts the transaction,
the rollback method is called.
All Statement objects under a connection are a part of the transaction. This means is that if an application
creates three Statement objects and uses each object to make changes to the database, when a commit
or rollback call happens, the work for all three statements either becomes permanent or is discarded.
The commit and rollback SQL statements are used to finalize transactions when working purely with SQL.
These SQL statements cannot be dynamically prepared and you should not attempt to use them in your
JDBC applications to complete transactions.
If the auto-commit setting is changed in the middle of a transaction, any pending work is automatically
committed. An SQLException is generated if auto-commit is enabled for a connection that is part of a
distributed transaction.
Related concepts
Transaction isolation levels
Database anomalies
Database anomalies are generated results that seem incorrect when looked at from the scope of a single
transaction, but are correct when looked at from the scope of all transactions. The different types of
database anomalies are described as follows:
• Dirty reads occur when:
1. Transaction A inserts a row into a table.
2. Transaction B reads the new row.
3. Transaction A rolls back.
Transaction B may have done work to the system based on the row inserted by transaction A, but that
row never became a permanent part of the database.
• Nonrepeatable reads occur when:
1. Transaction A reads a row.
2. Transaction B changes the row.
3. Transaction A reads the same row a second time and gets the new results.
• Phantom reads occur when:
1. Transaction A reads all rows that satisfy a WHERE clause on an SQL query.
2. Transaction B inserts an additional row that satisfies the WHERE clause.
3. Transaction A re-evaluates the WHERE condition and picks up the additional row.
Note: Db2 for i does not always expose the application to the allowable database anomalies at the
prescribed levels due to its locking strategies.
Considerations
A common misinterpretation is that the JDBC specification defines the five transactional levels previously
mentioned. It is commonly thought that the TRANSACTION_NONE value represents the concept of
running without commitment control. The JDBC specification does not define TRANSACTION_NONE in
the same manner. TRANSACTION_NONE is defined in the JDBC specification as a level where the driver
does not support transactions and is not a JDBC-compliant driver. The NONE level is never reported when
the getTransactionIsolation method is called.
The issue is marginally complicated by the fact that a JDBC driver's default transaction isolation level is
defined by the implementation. The default level of transaction isolation for the native JDBC driver default
transaction isolation level is NONE. This allows the driver to work with files that do not have journals and
you are not required to make any specifications such as files in the QGPL library.
The native JDBC driver allows you to pass JDBC_TRANSACTION_NONE to the setTransactionIsolation
method or specify none as a connection property. However, the getTransactionIsolation method always
reports JDBC_TRANSACTION_READ_UNCOMMITTED when the value is none. It is your application's
responsibility to keep track of what level you are running if it is a requirement in your application.
In past releases, the JDBC driver would handle your specifying true for auto-commit by changing the
transaction isolation level to none because the system did not have a concept of a true auto-commit
mode. This was a close approximation of the functionality, but did not provide the correct results
for all scenarios. This is not done anymore; the database decouples the concept of auto-commit
from the concept of a transaction isolation level. Therefore, it is completely valid to run at the
JDBC_TRANSACTION_SERIALIZABLE level with auto-commit being enabled. The only scenario that is not
valid is to run at the JDBC_TRANSACTION_NONE level and not be in auto-commit mode. Your application
cannot take control over commit boundaries when the system is not running with a transaction isolation
level.
Transaction isolation levels between the JDBC specification and the IBM i platform
The IBM i platform has common names for its transaction isolation levels that do not match those names
provided by the JDBC specification. The following table matches the names used by the IBM i platform,
but are not equivalent to those used by the JDBC specification:
* In this table, the JDBC_TRANSACTION_NONE value is lined up with the IBM i levels *NONE and *NC for
clarity. This is not a direct specification-to-IBM i level match.
Related concepts
JDBC auto-commit mode
Savepoints
Savepoints allow the setting of "staging points" in a transaction. Savepoints are checkpoints that the
application can roll back to without throwing away the entire transaction.
Savepoints are new in JDBC 3.0, meaning that the application must run on Java Development Kit (JDK)
1.4 or a subsequent release to use them. Moreover, savepoints are new to the Developer Kit for Java,
meaning that savepoints are not supported if JDK 1.4 or a subsequent release is not used with previous
releases of the Developer Kit for Java.
Note: The system provides SQL statements for working with savepoints. It is advised that JDBC
applications do not use these statements directly in an application. Doing so may work, but the JDBC
driver loses its ability to track the your savepoints when this is done. At a minimum, mixing the two
models (that is, using your own savepoint SQL statements and using the JDBC API) should be avoided.
Statement s = Connection.createStatement();
s.executeUpdate("insert into table1 values ('FIRST')");
Savepoint pt1 = connection.setSavepoint("FIRST SAVEPOINT");
s.executeUpdate("insert into table1 values ('SECOND')";);
connection.rollback(pt1); // Undoes most recent insert.
s.executeUpdate("insert into table1 values ('THIRD')");
connection.commit();
Although it is unlikely to cause problems to set savepoints while in auto-commit mode, they cannot be
rolled back as their lives end at the end of a transaction.
Releasing a savepoint
Savepoints can be released by the application with the releaseSavepoint method on the Connection
object. Once a savepoint has been released, attempting to roll back to it results in an exception. When a
transaction commits or rolls back, all savepoints automatically release. When a savepoint is rolled back,
other savepoints that follow it are also released.
Related concepts
JDBC auto-commit mode
By default, JDBC uses an operation mode called auto-commit. This means that every update to the
database is immediately made permanent.
Transaction isolation levels
XADataSource properties
In addition to the properties provided by the ConnectionPoolDataSource, the XADataSource interface
provides the following properties:
import java.sql.*;
import javax.sql.*;
import java.util.*;
import javax.transaction.*;
test.setup();
test.run();
}
/**
* Handle the previous cleanup run so that this test can recommence.
*/
public void setup() {
Connection c = null;
Statement s = null;
try {
Class.forName("com.ibm.db2.jdbc.app.DB2Driver");
c = DriverManager.getConnection("jdbc:db2:*local");
s = c.createStatement();
try {
s.executeUpdate("DROP TABLE CUJOSQL.JTATABLE");
} catch (SQLException e) {
// Ignore... does not exist
}
/**
* This test uses JTA support to handle transactions.
*/
public void run() {
Connection c = null;
try {
Context ctx = new InitialContext();
} catch (Exception e) {
System.out.println("Something has gone wrong.");
e.printStackTrace();
} finally {
try {
if (c != null)
c.close();
} catch (SQLException e) {
System.out.println("Note: Cleaup exception.");
e.printStackTrace();
}
}
}
}
Related reference
Example: Multiple connections that work on a transaction
This is an example of how to use multiple connections working on a single transaction.
Example: Using a connection with multiple transactions
This is an example of how to use a single connection with multiple transactions.
Example: Suspended ResultSets
This is an example of the how a Statement object is reprocessed under another transaction to perform
work.
Example: Ending a transaction
This is an example of ending a transaction in your application.
Example: Suspending and resuming a transaction
This is an example of a transaction that is suspended and then is resumed.
import java.sql.*;
import javax.sql.*;
import java.util.*;
import javax.transaction.*;
import javax.transaction.xa.*;
import com.ibm.db2.jdbc.app.*;
public class JTAMultiConn {
public static void main(java.lang.String[] args) {
JTAMultiConn test = new JTAMultiConn();
test.setup();
test.run();
}
/**
* Handle the previous cleanup run so that this test can recommence.
*/
public void setup() {
Connection c = null;
Statement s = null;
try {
Class.forName("com.ibm.db2.jdbc.app.DB2Driver");
c = DriverManager.getConnection("jdbc:db2:*local");
s = c.createStatement();
try {
s.executeUpdate("DROP TABLE CUJOSQL.JTATABLE");
}
catch (SQLException e) {
// Ignore... does not exist
}
xaRes2.start(xid, XAResource.TMJOIN);
int count2 = stmt2.executeUpdate("INSERT INTO " + tableName + "VALUES('Value 1-B')");
xaRes2.end(xid, XAResource.TMNOFLAGS);
xaRes3.start(xid, XAResource.TMJOIN);
int count3 = stmt3.executeUpdate("INSERT INTO " + tableName + "VALUES('Value 1-C')");
xaRes3.end(xid, XAResource.TMSUCCESS);
// When completed, commit the transaction as a single unit.
// A prepare() and commit() or 1 phase commit() is required for
// each separate database (XAResource) that participated in the
// transaction. Since the resources accessed (xaRes1, xaRes2, and xaRes3)
// all refer to the same database, only one prepare or commit is required.
int rc = xaRes.prepare(xid);
xaRes.commit(xid, false);
}
catch (Exception e) {
System.out.println("Something has gone wrong.");
e.printStackTrace();
}
finally {
try {
if (c1 != null) {
c1.close();
}
}
catch (SQLException e) {
System.out.println("Note: Cleaup exception " +
e.getMessage());
}
try {
if (c2 != null) {
c2.close();
}
}
catch (SQLException e) {
System.out.println("Note: Cleaup exception " +
Related reference
Example: Using JTA to handle a transaction
This is an example of how to use the Java Transaction API (JTA) to handle a transaction in an application.
Example: Using a connection with multiple transactions
This is an example of how to use a single connection with multiple transactions.
Example: Suspended ResultSets
This is an example of the how a Statement object is reprocessed under another transaction to perform
work.
Example: Ending a transaction
This is an example of ending a transaction in your application.
Example: Suspending and resuming a transaction
This is an example of a transaction that is suspended and then is resumed.
import java.sql.*;
import javax.sql.*;
import java.util.*;
import javax.transaction.*;
import javax.transaction.xa.*;
import com.ibm.db2.jdbc.app.*;
test.setup();
test.run();
}
/**
* Handle the previous cleanup run so that this test can recommence.
*/
public void setup() {
Connection c = null;
Statement s = null;
try {
Class.forName("com.ibm.db2.jdbc.app.DB2Driver");
c = DriverManager.getConnection("jdbc:db2:*local");
s = c.createStatement();
try {
s.executeUpdate("DROP TABLE CUJOSQL.JTATABLE");
} catch (SQLException e) {
// Ignore... does not exist
}
/**
* This test uses JTA support to handle transactions.
*/
public void run() {
Connection c = null;
try {
Context ctx = new InitialContext();
xaRes.start(xid2, XAResource.TMNOFLAGS);
int count2 = stmt.executeUpdate("INSERT INTO CUJOSQL.JTATABLE VALUES('Value 1-B')");
xaRes.end(xid2, XAResource.TMNOFLAGS);
xaRes.start(xid3, XAResource.TMNOFLAGS);
int count3 = stmt.executeUpdate("INSERT INTO CUJOSQL.JTATABLE VALUES('Value 1-C')");
xaRes.end(xid3, XAResource.TMNOFLAGS);
} catch (Exception e) {
System.out.println("Something has gone wrong.");
e.printStackTrace();
} finally {
try {
if (c != null)
c.close();
} catch (SQLException e) {
System.out.println("Note: Cleaup exception.");
e.printStackTrace();
}
}
}
}
import java.sql.*;
import javax.sql.*;
import java.util.*;
import javax.transaction.*;
import javax.transaction.xa.*;
import com.ibm.db2.jdbc.app.*;
test.setup();
test.run();
}
/**
* Handle the previous cleanup run so that this test can recommence.
*/
public void setup() {
Connection c = null;
Statement s = null;
try {
Class.forName("com.ibm.db2.jdbc.app.DB2Driver");
c = DriverManager.getConnection("jdbc:db2:*local");
s = c.createStatement();
try {
s.executeUpdate("DROP TABLE CUJOSQL.JTATABLE");
} catch (SQLException e) {
// Ignore... does not exist
}
s.close();
} finally {
if (c != null) {
c.close();
}
}
}
/**
* This test uses JTA support to handle transactions.
*/
try {
Context ctx = new InitialContext();
} catch (Exception e) {
System.out.println("Something has gone wrong.");
e.printStackTrace();
} finally {
try {
if (c != null)
c.close();
} catch (SQLException e) {
System.out.println("Note: Cleaup exception.");
e.printStackTrace();
}
}
Related reference
Example: Using JTA to handle a transaction
This is an example of how to use the Java Transaction API (JTA) to handle a transaction in an application.
Example: Multiple connections that work on a transaction
This is an example of how to use multiple connections working on a single transaction.
Example: Using a connection with multiple transactions
This is an example of how to use a single connection with multiple transactions.
Example: Ending a transaction
This is an example of ending a transaction in your application.
Example: Suspending and resuming a transaction
This is an example of a transaction that is suspended and then is resumed.
import java.sql.*;
import javax.sql.*;
import java.util.*;
import javax.transaction.*;
import javax.transaction.xa.*;
import com.ibm.db2.jdbc.app.*;
test.setup();
test.run();
}
/**
* Handle the previous cleanup run so that this test can recommence.
*/
public void setup() {
Connection c = null;
Statement s = null;
try {
Class.forName("com.ibm.db2.jdbc.app.DB2Driver");
c = DriverManager.getConnection("jdbc:db2:*local");
s = c.createStatement();
try {
s.executeUpdate("DROP TABLE CUJOSQL.JTATABLE");
} catch (SQLException e) {
// Ignore... does not exist
}
s.close();
} finally {
if (c != null) {
c.close();
}
}
}
/**
* This test use JTA support to handle transactions.
*/
try {
Context ctx = new InitialContext();
try {
String value = rs.getString(1);
System.out.println("Something failed if you receive this message.");
} catch (SQLException e) {
System.out.println("The expected exception was thrown.");
}
} catch (Exception e) {
System.out.println("Something has gone wrong.");
e.printStackTrace();
} finally {
try {
if (c != null)
c.close();
} catch (SQLException e) {
System.out.println("Note: Cleaup exception.");
e.printStackTrace();
}
}
}
}
Related reference
Example: Using JTA to handle a transaction
This is an example of how to use the Java Transaction API (JTA) to handle a transaction in an application.
Example: Multiple connections that work on a transaction
This is an example of how to use multiple connections working on a single transaction.
Example: Using a connection with multiple transactions
This is an example of how to use a single connection with multiple transactions.
Example: Suspended ResultSets
import java.sql.*;
import javax.sql.*;
import java.util.*;
import javax.transaction.*;
import javax.transaction.xa.*;
import com.ibm.db2.jdbc.app.*;
import javax.naming.InitialContext;
import javax.naming.Context;
test.setup();
test.run();
}
/**
* Handle the previous cleanup run so that this test can recommence.
*/
public void setup() {
Connection c = null;
Statement s = null;
try {
Class.forName("com.ibm.db2.jdbc.app.DB2Driver");
c = DriverManager.getConnection("jdbc:db2:*local");
s = c.createStatement();
try {
s.executeUpdate("DROP TABLE CUJOSQL.JTATABLE");
} catch (SQLException e) {
// Ignore... doesn't exist
}
s.close();
} finally {
if (c != null) {
c.close();
}
}
}
/**
* This test uses JTA support to handle transactions.
*/
public void run() {
Connection c = null;
try {
Context ctx = new InitialContext();
} catch (Exception e) {
System.out.println("Something has gone wrong.");
e.printStackTrace();
} finally {
try {
if (c != null)
c.close();
} catch (SQLException e) {
System.out.println("Note: Cleaup exception.");
e.printStackTrace();
}
}
Related reference
Example: Using JTA to handle a transaction
This is an example of how to use the Java Transaction API (JTA) to handle a transaction in an application.
Example: Multiple connections that work on a transaction
This is an example of how to use multiple connections working on a single transaction.
Example: Using a connection with multiple transactions
This is an example of how to use a single connection with multiple transactions.
Example: Suspended ResultSets
This is an example of the how a Statement object is reprocessed under another transaction to perform
work.
Example: Ending a transaction
This is an example of ending a transaction in your application.
Statement types
The Statement interface and its PreparedStatement and CallableStatement subclasses are used to
process structured query language (SQL) commands against the database. SQL statements cause the
generation of ResultSet objects.
Subclasses of the Statement interface are created with a number of methods on the Connection interface.
A single Connection object can have many Statement objects created under it simultaneously. In past
releases, it was possible to give exact numbers of Statement objects that could be created. It is
impossible to do so in this release because different types of Statement objects take different numbers of
"handles" within the database engine. Therefore, the types of Statement objects you are using influence
the number of statements that can be active under a connection at a single time.
An application calls the Statement.close method to indicate that the application has finished processing a
statement. All Statement objects are closed when the connection that created them is closed. However,
you should not fully rely on this behavior to close Statement objects. For example, if your application
changes so that a connection pool is used instead of explicitly closing the connections, the application
"leaks" statement handles because the connections never close. Closing Statement objects as soon as
they are no longer required allows external database resources that the statement is using to be released
immediately.
The native JDBC driver attempts to detect statement leaks and handles them on you behalf. However,
relying on that support results in poorer performance.
Due to the inheritance hierarchy that CallableStatement extends PreparedStatement which extends
Statement, features of each interface are available in the class that extend the interface. For example,
features of the Statement class are also supported in the PreparedStatement and CallableStatement
classes. The main exception is the executeQuery, executeUpdate, and execute methods on the Statement
class. These methods take in an SQL statement to dynamically process and cause exceptions if you
attempt to use them with PreparedStatement or CallableStatement objects.
Statement objects
A Statement object is used for processing a static SQL statement and obtaining the results produced by it.
Only one ResultSet for each Statement object can be open at a time. All statement methods that process
an SQL statement implicitly close a statement's current ResultSet if an open one exists.
Create statements
Statement objects are created from Connection objects with the createStatement method. For example,
assuming a Connection object named conn already exists, the following line of code creates a Statement
object for passing SQL statements to the database:
Process statements
Processing SQL statements with a Statement object is accomplished with the executeQuery(),
executeUpdate(), and execute() methods.
import java.sql.*;
import java.util.Properties;
Connection c = null;
Statement s = null;
try {
// Create the connection properties.
Properties properties = new Properties ();
properties.put ("user", "userid");
properties.put ("password", "password");
// Run some SQL statements that insert records into the table.
s.executeUpdate("INSERT INTO MYLIBRARY.MYTABLE (NAME, ID) VALUES ('RICH', 123)");
s.executeUpdate("INSERT INTO MYLIBRARY.MYTABLE (NAME, ID) VALUES ('FRED', 456)");
s.executeUpdate("INSERT INTO MYLIBRARY.MYTABLE (NAME, ID) VALUES ('MARK', 789)");
try {
if (c != null) {
c.close();
}
} catch (SQLException e) {
System.out.println("Cleanup failed to close Connection.");
}
}
}
}
PreparedStatements
PreparedStatements extend the Statement interface and provide support for adding parameters to SQL
statements.
SQL statements that are passed to the database go through a two-step process in returning results
to you. They are first prepared and then are processed. With Statement objects, these two phases
appear to be one phase to your applications. PreparedStatements allow these two steps to be broken
apart. The preparation step occurs when the object is created and the processing step occurs when the
executeQuery, executeUpdate, or execute method are called on the PreparedStatement object.
Being able to split the SQL processing into separate phases are meaningless without the addition of
parameter markers. Parameter markers are placed in an application so that it can tell the database that
it does not have a specific value at preparation time, but that it provides one before processing time.
Parameter markers are represented in SQL statements by question marks.
Parameter markers make it possible to make general SQL statements that are used for specific requests.
For example, take the following SQL query statement:
This is a specific SQL statement that returns only one value; that is, information about an employee
named Dettinger. By adding a parameter marker, the statement can become more flexible:
By simply setting the parameter marker to a value, information can be obtained about any employee in
the table.
PreparedStatements provide significant performance improvements over Statements because the
previous Statement example can go through the preparation phase only once and then be processed
repeatedly with different values for the parameter.
Note: Using PreparedStatements is a requirement to support the native JDBC driver's statement pooling.
For more information about using prepared statements, including creating prepared statements,
specifying result set characteristics, working with auto-generated keys, and setting parameter markers,
see the following pages:
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_UPDATEABLE);
Handling parameters
Before a PreparedStatement object can be processed, each of the parameter markers must be set to
some value. The PreparedStatement object provides a number of methods for setting parameters. All
methods are of the form set<Type>, where <Type> is a Java data type. Some examples of these methods
include setInt, setLong, setString, setTimestamp, setNull, and setBlob. Nearly all of these methods take
two parameters:
• The first parameter is the index of the parameter within the statement. Parameter markers are
numbered, starting with 1.
• The second parameter is the value to set the parameter to. There are a couple set<Type> methods that
have additional parameters such as the length parameter on setBinaryStream.
ps.setString(1,'Dettinger');
If an attempt is made to process a PreparedStatement with parameter markers that have not been set, an
SQLException is thrown.
Note: Once set, parameter markers hold the same value between processes unless the following
situations occur:
• The value is changed by another call to a set method.
• The value is removed when the clearParameters method is called.
The clearParameters method flags all parameters as being unset. After the call to clearParameters has
been made, all the parameters must have the set method called again before the next process.
ParameterMetaData support
A new ParameterMetaData interface allows you to retrieve information about a parameter. This support is
the compliment to ResultSetMetaData and is similar. Information such as the precision, scale, data type,
data type name, and whether the parameter allows the null value are all provided.
Related concepts
Processing PreparedStatements
Processing SQL statements with a PreparedStatement object is accomplished with the executeQuery,
executeUpdate, and execute methods like Statement objects are processed. Unlike Statement versions,
no parameters are passed on these methods because the SQL statement was already provided when
the object was created. Because PreparedStatement extends Statement, applications can attempt to call
versions of executeQuery, executeUpdate, and execute methods that take a SQL statement. Doing so
results in an SQLException being thrown.
Related reference
Example: Using PreparedStatement to obtain a ResultSet
This is an example of using a PreparedStatement object's executeQuery method to obtain a ResultSet.
Example: ParameterMetaData
This is an example of using the ParameterMetaData interface to retrieve information about parameters.
Note: By using the code examples, you agree to the terms of the “Code license and disclaimer
information” on page 489.
//////////////////////////////////////////////////////////////////////////////////
//
// ParameterMetaData example. This program demonstrates
// the new support of JDBC 3.0 for learning information
// about parameters to a PreparedStatement.
//
// Command syntax:
// java PMD
//
//////////////////////////////////////////////////////////////////////////////////
//
// This source is an example of the IBM Developer for Java JDBC driver.
// IBM grants you a nonexclusive license to use this as an example
// from which you can generate similar function tailored to
// your own specific needs.
//
// This 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
// merchantability and fitness for a particular purpose are
// expressly disclaimed.
import java.sql.*;
Processing PreparedStatements
Processing SQL statements with a PreparedStatement object is accomplished with the executeQuery,
executeUpdate, and execute methods like Statement objects are processed. Unlike Statement versions,
no parameters are passed on these methods because the SQL statement was already provided when
the object was created. Because PreparedStatement extends Statement, applications can attempt to call
versions of executeQuery, executeUpdate, and execute methods that take a SQL statement. Doing so
results in an SQLException being thrown.
import java.sql.*;
import java.util.Properties;
Connection c = null;
Statement s = null;
ps.setInt(1, 5);
try {
if (c != null) {
c.close();
}
} catch (SQLException e) {
System.out.println("Cleanup failed to close Connection.");
}
Related concepts
Creating and using PreparedStatements
The prepareStatement method is used to create new PreparedStatement objects. Unlike the
createStatement method, the SQL statement must be supplied when the PreparedStatement object is
created. At that time, the SQL statement is precompiled for use.
Processing PreparedStatements
Processing SQL statements with a PreparedStatement object is accomplished with the executeQuery,
executeUpdate, and execute methods like Statement objects are processed. Unlike Statement versions,
no parameters are passed on these methods because the SQL statement was already provided when
the object was created. Because PreparedStatement extends Statement, applications can attempt to call
versions of executeQuery, executeUpdate, and execute methods that take a SQL statement. Doing so
results in an SQLException being thrown.
CallableStatements
The JDBC CallableStatement interface extends PreparedStatement and provides support for output and
input/output parameters. The CallableStatement interface also has support for input parameters that is
provided by the PreparedStatement interface.
The CallableStatement interface allows the use of SQL statements to call stored procedures. Stored
procedures are programs that have a database interface. These programs possess the following:
• They can have input and output parameters, or parameters that are both input and output.
• They can have a return value.
• They have the ability to return multiple ResultSets.
Conceptually in JDBC, a stored procedure call is a single call to the database, but the program associated
with the stored procedure may process hundreds of database requests. The stored procedure program
may also perform a number of other programmatic tasks not typically done with SQL statements.
Because CallableStatements follow the PreparedStatement model of decoupling the preparation and
processing phases, they have the potential for optimized reuse (see “PreparedStatements” on page 87
for details). Since SQL statements of a stored procedure are bound into a program, they are processed as
static SQL and further performance benefits can be gained that way. Encapsulating a lot of database work
in a single, reusable database call is an example of using stored procedures optimally. Only this call goes
over the network to the other system, but the request can accomplish a lot of work on the remote system.
Creating CallableStatements
The prepareCall method is used to create new CallableStatement objects. As with the prepareStatement
method, the SQL statement must be supplied at the time that the CallableStatement object is created.
At that time, the SQL statement is precompiled. For example, assuming a Connection object named conn
already exists, the following creates a CallableStatement object and completes the preparation phase of
getting the SQL statement ready for processing within the database:
The ADDEMPLOYEE stored procedure takes input parameters for a new employee name, his social
security number, and his manager's user ID. From this information, multiple company database tables
may be updated with information about the employee such as his start date, division, department, and so
on. Further, a stored procedure is a program that may generate standard user IDs and e-mail addresses
for that employee. The stored procedure may also send an e-mail to the hiring manager with initial
usernames and passwords; the hiring manager can then provide the information to the employee.
The ADDEMPLOYEE stored procedure is set up to have a return value. The return code may be a success
or failure code that the calling program can use when a failure occurs. The return value may also be
defined as the new employee's company ID number. Finally, the stored procedure program could have
processed queries internally and have left the ResultSets from those queries open and available for the
Handling parameters
As stated, CallableStatement objects may take three types of parameters:
• IN
IN parameters are handled in the same manner as PreparedStatements. The various set methods of the
inherited PreparedStatement class are used to set the parameters.
• OUT
OUT parameters are handled with the registerOutParameter method. The most common form of
registerOutParameter takes an index parameter as the first parameter and an SQL type as the second
parameter. This tells the JDBC driver what to expect for data from the parameter when the statement is
processed. There are two other variations on the registerOutParameter method that can be found in the
java.sql package Javadoc.
• INOUT
INOUT parameters require that the work for both IN parameters and OUT parameters be done. For
each INOUT parameter, you must call a set method and the registerOutParameter method before the
statement can be processed. Failing to set or register any parameter results in an SQLException being
thrown when the statement is processed.
Refer to “Example: Creating a procedure with input and output parameters” on page 98 for more
information.
As with PreparedStatements, CallableStatement parameter values remain the same between processes
unless you call a set method again. The clearParameters method does not affect parameters that are
registered for output. After calling clearParameters, all IN parameters must be set to a value again, but all
OUT parameters do not have to be registered again.
Note: The concept of parameters must not be confused with the index of a parameter marker. A stored
procedure call expects a certain number of parameters that are passed to it. A particular SQL statement
has ? characters (parameter markers) in it to represent values that are supplied at runtime. Consider the
following example to see the difference between the two concepts:
CREATE
PROCEDURE MYLIBRARY.APROC
(IN PARM1 INTEGER)
LANGUAGE SQL SPECIFIC MYLIBRARY.APROC
BODY: BEGIN
<Perform a task here...>
END BODY
There is a single integer parameter with the name PARM1. In JDBC 3.0, there is support for specifying
stored procedure parameters by name as well as by index. The code to set up a CallableStatement for this
procedure is as follows:
Related concepts
Statement objects
A Statement object is used for processing a static SQL statement and obtaining the results produced by it.
Only one ResultSet for each Statement object can be open at a time. All statement methods that process
an SQL statement implicitly close a statement's current ResultSet if an open one exists.
PreparedStatements
PreparedStatements extend the Statement interface and provide support for adding parameters to SQL
statements.
Processing CallableStatements
Processing SQL stored procedure calls with a JDBC CallableStatement object is accomplished with the
same methods that are used with a PreparedStatement object.
? = CALL MYPROC(?, ?, ?)
The return value from a stored procedure call is always an integer type and must be registered like any
other output parameter.
See “Example: Creating a procedure with return values” on page 99 for more information.
Related reference
Example: Creating a procedure with multiple ResultSets
This example shows how to access a database and then create a procedure with multiple ResultSets
using JDBC.
Example: Creating a procedure with input and output parameters
This example shows how to access a database using JDBC and then create a procedure with input and
output parameters.
Example: Creating a procedure with return values
This example shows how to access a database using JDBC and then create a procedure with return
values.
import java.sql.*;
import java.util.Properties;
Statement s = c.createStatement();
try {
s.executeUpdate(sql);
} catch (SQLException e) {
// NOTE: We are ignoring the error here. We are making
// the assumption that the only reason this fails
// is because the procedure already exists. Other
// reasons that it could fail are because the C compiler
// is not found to compile the procedure or because
// collection MYLIBRARY does not exist on the system.
}
s.close();
// Now use JDBC to run the procedure and get the results back. In
// this case we are going to get information about 'MYLIBRARY's stored
// procedures (which is also where we created this procedure, thereby
// ensuring that there is something to get.
CallableStatement cs = c.prepareCall("CALL MYLIBRARY.SQLSPEX1");
ResultSet rs = cs.executeQuery();
// We now have the first ResultSet object that the stored procedure
// left open. Use it.
int i = 1;
while (rs.next()) {
System.out.println("MYLIBRARY stored procedure
" + i + " is " + rs.getString(1) + "." +
rs.getString(2));
i++;
}
System.out.println("");
// Now get the next ResultSet object from the system - the previous
// one is automatically closed.
if (!cs.getMoreResults()) {
System.out.println("Something went wrong. There should have
been another ResultSet, exiting.");
System.exit(0);
}
rs = cs.getResultSet();
// We now have the second ResultSet object that the stored procedure
// left open. Use that one.
i = 1;
while (rs.next()) {
System.out.println("MYLIBRARY procedure " + rs.getString(1)
+ "." + rs.getString(2) +
" parameter: " + rs.getInt(3) + " direction:
" + rs.getString(4) +
" data type: " + rs.getString(5));
i++;
}
if (i == 1) {
System.out.println("None of the stored procedures have any parameters.");
}
if (cs.getMoreResults()) {
System.out.println("Something went wrong,
there should not be another ResultSet.");
System.exit(0);
}
} catch (Exception e) {
System.out.println("Something failed..");
System.out.println("Reason: " + e.getMessage());
e.printStackTrace();
}
}
}
Related concepts
Processing CallableStatements
Processing SQL stored procedure calls with a JDBC CallableStatement object is accomplished with the
same methods that are used with a PreparedStatement object.
Related reference
Example: Creating a procedure with input and output parameters
This example shows how to access a database using JDBC and then create a procedure with input and
output parameters.
Example: Creating a procedure with return values
This example shows how to access a database using JDBC and then create a procedure with return
values.
import java.sql.*;
import java.util.Properties;
Statement s = c.createStatement();
try {
s.executeUpdate(sql);
} catch (SQLException e) {
// NOTE: We are ignoring the error here. We are making
// the assumption that the only reason this fails
// is because the procedure already exists. Other
// reasons that it could fail are because the C compiler
// is not found to compile the procedure or because
// collection MYLIBRARY does not exist on the system.
}
s.close();
// All input parameters must be set and all output parameters must
// be registered. Notice that this means we have two calls to make
// for an input output parameter.
cs.setInt(1, 5);
cs.setInt(3, 10);
cs.registerOutParameter(2, Types.INTEGER);
cs.registerOutParameter(3, Types.INTEGER);
} catch (Exception e) {
System.out.println("Something failed..");
System.out.println("Reason: " + e.getMessage());
e.printStackTrace();
}
}
}
Related concepts
Processing CallableStatements
Processing SQL stored procedure calls with a JDBC CallableStatement object is accomplished with the
same methods that are used with a PreparedStatement object.
Related reference
Example: Creating a procedure with multiple ResultSets
This example shows how to access a database and then create a procedure with multiple ResultSets
using JDBC.
Example: Creating a procedure with return values
This example shows how to access a database using JDBC and then create a procedure with return
values.
import java.sql.*;
import java.util.Properties;
Statement s = c.createStatement();
try {
s.executeUpdate(sql);
} catch (SQLException e) {
// NOTE: The error is ignored here. The assumptions is
// made that the only reason this fails is
// because the procedure already exists. Other
// reasons that it could fail are because the C compiler
// is not found to compile the procedure or because
// collection MYLIBRARY does not exist on the system.
}
s.close();
} catch (Exception e) {
System.out.println("Something failed..");
System.out.println("Reason: " + e.getMessage());
e.printStackTrace();
}
}
}
Related concepts
Processing CallableStatements
Processing SQL stored procedure calls with a JDBC CallableStatement object is accomplished with the
same methods that are used with a PreparedStatement object.
Related reference
Example: Creating a procedure with multiple ResultSets
This example shows how to access a database and then create a procedure with multiple ResultSets
using JDBC.
Example: Creating a procedure with input and output parameters
This example shows how to access a database using JDBC and then create a procedure with input and
output parameters.
ResultSets
The ResultSet interface provides access to the results generated by running queries. Conceptually, data of
a ResultSet can be thought of as a table with a specific number of columns and a specific number of rows.
By default, the table rows are retrieved in sequence. Within a row, column values can be accessed in any
order.
ResultSet characteristics
This topic discusses ResultSet characteristics such ResultSet types, concurrency, ability to close the
ResultSet by committing the connection object, and specification of ResultSet characteristics.
By default, all created ResultSets have a type of forward only, a concurrency of read only,
and cursors are held over commit boundaries. An exception to this is that WebSphere currently
changes the cursor holdability default so that cursors are implicitly closed when committed. These
characteristics are configurable through methods that are accessible on Statement, PreparedStatement,
and CallableStatement objects.
Concurrency
Concurrency determines whether the ResultSet can be updated. The types are again defined by constants
in the ResultSet interface. The available concurrency settings are as follows:
CONCUR_READ_ONLY
A ResultSet that can only be used for reading data out of the database. This is the default setting.
CONCUR_UPDATEABLE
A ResultSet that allows you to make changes to it. These changes can be placed into the underlying
database.
JDBC 1.0 ResultSets are always forward only. Updateable ResultSets were added in JDBC 2.0.
Note: According to the JDBC specification, the JDBC driver is allowed to change the ResultSet type of
the ResultSet concurrency setting if the values cannot be used together. In such cases, the JDBC driver
places a warning on the Connection object.
There is one situation where the application specifies a TYPE_SCROLL_INSENSITIVE,
CONCUR_UPDATEABLE ResultSet. Insensitivity is implemented in the database engine by making a copy
of the data. You are then not allowed to make updates through that copy to the underlying database. If
you specify this combination, the driver changes the sensitivity to TYPE_SCROLL_SENSITIVE and create
the warning indicating that your request has been changed.
Holdability
The holdability characteristic determines whether calling commit on the Connection object closes the
ResultSet. The JDBC API for working with the holdability characteristic is new in version 3.0. However,
the native JDBC driver has provided a connection property for several releases that allows you to specify
that default for all ResultSets created under the connection. The API support overrides any setting for the
connection property. Values for the holdability characteristic are defined by ResultSet constants and are
as follows:
import java.sql.*;
test.setup();
test.run("sensitive");
test.cleanup();
test.setup();
test.run("insensitive");
test.cleanup();
}
try {
Class.forName("com.ibm.db2.jdbc.app.DB2Driver");
connection = DriverManager.getConnection("jdbc:db2:*local");
Statement s = connection.createStatement();
try {
s.executeUpdate("drop table cujosql.sensitive");
} catch (SQLException e) {
// Ignored.
}
} catch (Exception e) {
System.out.println("Caught exception: " + e.getMessage());
if (e instanceof SQLException) {
SQLException another = ((SQLException) e).getNextException();
System.out.println("Another: " + another.getMessage());
}
}
}
} catch (SQLException e) {
System.out.println("SQLException exception: ");
System.out.println("Message:....." + e.getMessage());
System.out.println("SQLState:...." + e.getSQLState());
System.out.println("Vendor Code:." + e.getErrorCode());
System.out.println("-------------------------------------");
e.printStackTrace();
}
catch (Exception ex) {
System.out.println("An exception other than an SQLException was thrown: ");
ex.printStackTrace();
}
}
import java.sql.*;
test.setup();
test.run("sensitive");
test.cleanup();
test.setup();
test.run("insensitive");
test.cleanup();
}
try {
System.out.println("Native JDBC used");
Class.forName("com.ibm.db2.jdbc.app.DB2Driver");
connection = DriverManager.getConnection("jdbc:db2:*local");
Statement s = connection.createStatement();
try {
s.executeUpdate("drop table cujosql.sensitive");
} catch (SQLException e) {
// Ignored.
}
try {
s.executeUpdate("drop table cujosql.sensitive2");
} catch (SQLException e) {
// Ignored.
}
s.close();
} catch (Exception e) {
System.out.println("Caught exception: " + e.getMessage());
if (e instanceof SQLException) {
SQLException another = ((SQLException) e).getNextException();
System.out.println("Another: " + another.getMessage());
}
}
}
Statement s = null;
if (sensitivity.equalsIgnoreCase("insensitive")) {
System.out.println("creating a TYPE_SCROLL_INSENSITIVE cursor");
s = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
} else {
System.out.println("creating a TYPE_SCROLL_SENSITIVE cursor");
s = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_READ_ONLY);
}
rs.next();
System.out.println("value is " + rs.getInt(1));
rs.next();
// Another statement creates a value that does not fit the where clause.
Statement s2 =
connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_UPDATEABLE);
ResultSet rs2 = s2.executeQuery("select *
from cujosql.sensitive where col1 = 5 FOR UPDATE");
rs2.next();
rs2.updateInt(1, -1);
rs2.updateRow();
s2.close();
if (rs.next()) {
System.out.println("There is still a row: " + rs.getInt(1));
} else {
System.out.println("No more rows.");
}
} catch (SQLException e) {
System.out.println("SQLException exception: ");
System.out.println("Message:....." + e.getMessage());
System.out.println("SQLState:...." + e.getSQLState());
System.out.println("Vendor Code:." + e.getErrorCode());
System.out.println("----------------------------");
e.printStackTrace();
}
catch (Exception ex) {
System.out.println("An exception other
than an SQLException was thrown: ");
ex.printStackTrace();
}
}
Cursor movement
The IBM i Java Database Connectivity (JDBC) drivers support scrollable ResultSets. With a scrollable
ResultSet, you can process rows of data in any order using a number of cursor-positioning methods.
The ResultSet.next method is used to move through a ResultSet one row at a time. With Java Database
Connectivity (JDBC) 2.0, the IBM i JDBC drivers support scrollable ResultSets. Scrollable ResultSets allow
processing the rows of data in any order by using the previous, absolute, relative, first, and last methods.
By default, JDBC ResultSets are always forward only, meaning that the only valid cursor-positioning
method to call is next(). You have to explicitly request a scrollable ResultSet. See ResultSet types for more
information.
With a scrollable ResultSet, you can use the following cursor-positioning methods:
Method Description
Next This method moves the cursor forward one row in the ResultSet.
The method returns true if the cursor is positioned on a valid row and false otherwise.
Previous The method moves the cursor backward one row in the ResultSet.
The method returns true if the cursor is positioned on a valid row and false otherwise.
Last The method moves the cursor to the last row in the ResultSet.
The method returns true if the cursor is positioned on the last row and false if the ResultSet
is empty.
BeforeFirst The method moves the cursor immediately before the first row in the ResultSet.
For an empty ResultSet, this method has no effect. There is no return value from this
method.
AfterLast The method moves the cursor immediately after the last row in the ResultSet.
For an empty ResultSet, this method has no effect. There is no return value from this
method.
Relative (int The method moves the cursor relative to its current position.
rows)
• If rows is 0, this method has no effect.
• If rows is positive, the cursor is moved forward that many rows. If there are fewer rows
between the current position and the end of the ResultSet than specified by the input
parameters, this method operates like afterLast.
• If rows is negative, the cursor is moved backward that many rows. If there are fewer rows
between the current position and the end of the ResultSet than specified by the input
parameter, this method operates like beforeFirst.
The method returns true if the cursor in positioned on a valid row and false otherwise.
Absolute (int The method moves the cursor to the row specified by row value.
row)
If row value is positive, the cursor is positioned that many rows from the beginning of the
ResultSet. The first row is numbered 1, the second is 2, and so on. If there are fewer rows
in the ResultSet than specified by the row value, this method operates the same way as
afterLast.
If row value is negative, the cursor is positioned that many rows from the end of the
ResultSet. The last row is numbered -1, the second to last is -2, and so on. If there are fewer
rows in the ResultSet than specified by the row value, this method operates the same way
beforeFirst.
If row value is 0, this method operates the same way as beforeFirst.
The method returns true if the cursor is positioned on a valid row and false otherwise.
Related concepts
ResultSet characteristics
This topic discusses ResultSet characteristics such ResultSet types, concurrency, ability to close the
ResultSet by committing the connection object, and specification of ResultSet characteristics.
Retrieving ResultSet data
The ResultSet object provides several methods for obtaining column data for a row. All are of the form
get<Type>, where <Type> is a Java data type. Some examples of these methods include getInt, getLong,
getString, getTimestamp, and getBlob. Nearly all of these methods take a single parameter that is either
the column index within the ResultSet or the column name.
Creating ResultSets
ResultSetMetaData support
When the getMetaData method is called on a ResultSet object, the method returns a ResultSetMetaData
object describing the columns of that ResultSet object. When the SQL statement being processed is
unknown until runtime, the ResultSetMetaData can be used to determine what get methods should be
used to retrieve the data. The following code example uses ResultSetMetaData to determine each column
type in the result set:
ResultSet rs = stmt.executeQuery(sqlString);
ResultSetMetaData rsmd = rs.getMetaData();
int colType [] = new int[rsmd.getColumnCount()];
for (int idx = 0, int col = 1; idx < colType.length; idx++, col++)
colType[idx] = rsmd.getColumnType(col);
Related concepts
ResultSet characteristics
This topic discusses ResultSet characteristics such ResultSet types, concurrency, ability to close the
ResultSet by committing the connection object, and specification of ResultSet characteristics.
Cursor movement
The IBM i Java Database Connectivity (JDBC) drivers support scrollable ResultSets. With a scrollable
ResultSet, you can process rows of data in any order using a number of cursor-positioning methods.
Creating ResultSets
To create a ResultSet object, you can use executeQuery methods, or other methods. This topic describes
options for creating ResultSets.
Related tasks
Changing ResultSets
With the IBM i JDBC drivers, you can change ResultSets by performing several tasks.
Related reference
Example: ResultSet interface
import java.sql.*;
/**
ResultSetMetaDataExample.java
try {
// Get a database connection and prepare a statement.
Class.forName("com.ibm.db2.jdbc.app.DB2Driver");
con = DriverManager.getConnection("jdbc:db2:*local");
s = con.createStatement();
} catch (Exception e) {
// Handle any errors.
System.out.println("Oops... we have an error... ");
e.printStackTrace();
} finally {
// Ensure we always clean up. If the connection gets closed, the
// statement under it closes as well.
if (con != null) {
try {
con.close();
} catch (SQLException e) {
System.out.println("Critical error - cannot close connection object");
}
}
}
}
}
import java.sql.*;
test.setup();
test.displayTable();
test.run();
test.displayTable();
test.cleanup();
}
/**
Handle all the required setup work.
**/
public void setup() {
try {
// Register the JDBC driver.
Class.forName("com.ibm.db2.jdbc.app.DB2Driver");
connection = DriverManager.getConnection("jdbc:db2:*local");
Statement s = connection.createStatement();
try {
s.executeUpdate("DROP TABLE CUJOSQL.WHERECUREX");
} catch (SQLException e) {
// Ignore problems here.
}
s.close();
} catch (Exception e) {
System.out.println("Caught exception: " + e.getMessage());
e.printStackTrace();
}
}
/**
} catch (Exception e) {
System.out.println("Caught exception: ");
e.printStackTrace();
}
}
/**
In this section, put all clean-up work for testing.
**/
public void cleanup() {
try {
// Close the global connection opened in setup().
connection.close();
} catch (Exception e) {
System.out.println("Caught exception: ");
e.printStackTrace();
}
}
/**
Display the contents of the table.
**/
public void displayTable()
{
try {
Statement s = connection.createStatement();
ResultSet rs = s.executeQuery ("SELECT * FROM CUJOSQL.WHERECUREX");
rs.close ();
s.close();
System.out.println("-----------------------------------------");
} catch (Exception e) {
System.out.println("Caught exception: ");
e.printStackTrace();
}
}
}
import java.sql.*;
test.setup();
test.displayTable();
test.run();
test.displayTable();
test.cleanup();
}
/**
Handle all the required setup work.
**/
public void setup() {
try {
// Register the JDBC driver.
Class.forName("com.ibm.db2.jdbc.app.DB2Driver");
connection = DriverManager.getConnection("jdbc:db2:*local");
Statement s = connection.createStatement();
try {
s.executeUpdate("DROP TABLE CUJOSQL.WHERECUREX");
} catch (SQLException e) {
// Ignore problems here.
}
s.close();
} catch (Exception e) {
System.out.println("Caught exception: " + e.getMessage());
e.printStackTrace();
}
}
/**
In this section, all the code to perform the testing should
be added. If only one connection to the database is required,
the global variable 'connection' can be used.
**/
public void run() {
try {
Statement stmt1 = connection.createStatement();
} catch (Exception e) {
System.out.println("Caught exception: ");
e.printStackTrace();
}
}
/**
In this section, put all clean-up work for testing.
**/
public void cleanup() {
try {
// Close the global connection opened in setup().
connection.close();
} catch (Exception e) {
System.out.println("Caught exception: ");
e.printStackTrace();
}
}
/**
Display the contents of the table.
**/
public void displayTable()
{
try {
Statement s = connection.createStatement();
ResultSet rs = s.executeQuery ("SELECT * FROM CUJOSQL.WHERECUREX");
rs.close ();
s.close();
System.out.println("-----------------------------------------");
} catch (Exception e) {
System.out.println("Caught exception: ");
e.printStackTrace();
}
}
}
Creating ResultSets
To create a ResultSet object, you can use executeQuery methods, or other methods. This topic describes
options for creating ResultSets.
These methods are from the Statement, PreparedStatement, or CallableStatement interfaces. There
are, however, other available methods. For example, DatabaseMetaData methods such as getColumns,
getTables, getUDTs, getPrimaryKeys, and so on, return ResultSets. It is also possible to have a single SQL
statement return multiple ResultSets for processing. You can also use the getResultSet method to retrieve
a ResultSet object after calling the execute method provided by the Statement, PreparedStatement, or
CallableStatement interfaces.
See “Example: Creating a procedure with multiple ResultSets” on page 96 for more information.
import java.sql.*;
/**
ResultSetExample.java
try {
// Get a database connection and prepare a statement.
Class.forName("com.ibm.db2.jdbc.app.DB2Driver");
con = DriverManager.getConnection("jdbc:db2:*local");
s = con.createStatement();
} catch (Exception e) {
// Handle any errors.
System.out.println("Oops... we have an error... ");
e.printStackTrace();
} finally {
// Ensure we always clean up. If the connection gets closed, the
// statement under it closes as well.
if (con != null) {
try {
con.close();
} catch (SQLException e) {
System.out.println("Critical error - cannot close connection object");
}
}
}
}
}
Related concepts
ResultSet characteristics
This topic discusses ResultSet characteristics such ResultSet types, concurrency, ability to close the
ResultSet by committing the connection object, and specification of ResultSet characteristics.
Cursor movement
import java.sql.*;
import javax.naming.*;
import com.ibm.db2.jdbc.app.UDBDataSource;
import com.ibm.db2.jdbc.app.UDBConnectionPoolDataSource;
// Establish a JNDI context and bind the connection pool data source
Context ctx = new InitialContext();
ctx.rebind("ConnectionSupport", cpds);
import java.sql.*;
import javax.naming.*;
import java.util.*;
import javax.sql.*;
startTime = System.currentTimeMillis();
for (int i = 0; i < 100; i++) {
Connection c1 = ds.getConnection();
c1.close();
}
endTime = System.currentTimeMillis();
System.out.println("Time spent: " + (endTime - startTime));
}
}
ConnectionPoolDataSource properties
You can configure the ConnectionPoolDataSource interface by using the set of properties that it provides.
Descriptions of these properties are provided in the following table.
Note: Setting either the maxIdleTime or the propertyCycle time to 0 means that the JDBC driver does not
check for connections to be removed from the pool on its own. The rules specified for initial, min, and max
size are still enforced.
import java.sql.*;
import javax.naming.*;
import java.util.*;
import javax.sql.*;
import com.ibm.db2.jdbc.app.UDBDataSource;
import com.ibm.db2.jdbc.app.UDBConnectionPoolDataSource;
startTime = System.currentTimeMillis();
for (int i = 0; i < 100; i++) {
Connection c1 = ds.getConnection();
PreparedStatement ps = c1.prepareStatement("select * from qsys2.sysprocs");
ResultSet rs = ps.executeQuery();
c1.close();
}
endTime = System.currentTimeMillis();
System.out.println("Time spent: " + (endTime - startTime));
}
// Establish a JNDI context and bind the connection pool data source
Context ctx = new InitialContext();
ctx.rebind("StatementSupport", cpds);
This is the same query, but it uses a different parameter. Both queries can be accomplished with the
following query:
You can then set the parameter marker (denoted by the question mark) to 100000 when processing the
first query and 50000 when processing the second query. This enhances performance for three reasons
beyond what the connection pool can offer:
• Fewer objects are created. A PreparedStatement object is created and reused instead of creating a
Statement object for every request. Therefore, you run fewer constructors.
• The database work to set up the SQL statement (called the prepare) can be reused. Preparing SQL
statements is reasonably expensive as it involves determining what the SQL statement text says and
how the system should accomplish the task requested.
• When removing the additional object creations, there is a benefit that is not often considered. There is
no need to destroy what was not created. This model is easier on the Java garbage collector and also
benefits performance over time with many users.
Considerations
Performance improves through replication. If an item is not reused, then it is wasting resources to pool it.
Most applications contain critical sections of code. Typically, an application uses 80 to 90 percent of its
processing time on only 10 to 20 percent of the code. If there are 10,000 SQL statements potentially used
in an application, not all of them are pooled. The objective is to identify and pool the SQL statements that
are used in the application's critical sections of code.
Batch updates
Batch update support allows any updates to the database to be passed as a single transaction between
the user program and the database. This procedure can significantly improve performance when many
updates must be performed at once.
For example, if a large company requires its newly hired employees to start work on a Monday, this
requirement makes it necessary to process many updates (in this case, insertions) to the employee
database at one time. Creating a batch of updates and submitting them to the database as one unit can
save you processing time.
There are two types of batch updates:
• Batch updates that use Statement objects.
• Batch updates that use PreparedStatement objects.
connection.setAutoCommit(false);
Statement statement = connection.createStatement();
statement.addBatch("INSERT INTO TABLEX VALUES(1, 'Cujo')");
statement.addBatch("INSERT INTO TABLEX VALUES(2, 'Fred')");
statement.addBatch("INSERT INTO TABLEX VALUES(3, 'Mark')");
int [] counts = statement.executeBatch();
connection.commit();
In this example, an array of integers is returned from the executeBatch method. This array has one integer
value for each statement that is processed in the batch. If values are being inserted into the database, the
value for each statement is 1 (that is, assuming successful processing). However, some of the statements
may be update statements that affect multiple rows. If you put any statements in the batch other than
INSERT, UPDATE, or DELETE, an exception occurs.
Related concepts
JDBC BatchUpdateException
An important consideration of batch updates is what action to take when a call to the executeBatch
method fails. In this case, a new type of exception, called BatchUpdateException, is thrown. The
BatchUpdateException is a subclass of SQLException and it allows you to call all the same methods
you have always called to receive the message, the SQLState, and vendor code.
Blocked inserts with JDBC
You can use a blocked insert operation to insert several rows into a database table at a time.
Related reference
PreparedStatement batch update
A preparedStatement batch is similar to the Statement batch; however, a preparedStatement batch
always works off the same prepared statement, and you only change the parameters to that statement.
connection.setAutoCommit(false);
PreparedStatement statement =
connection.prepareStatement("INSERT INTO TABLEX VALUES(?, ?)");
statement.setInt(1, 1);
statement.setString(2, "Cujo");
statement.addBatch();
statement.setInt(1, 2);
statement.setString(2, "Fred");
statement.addBatch();
statement.setInt(1, 3);
statement.setString(2, "Mark");
statement.addBatch();
int [] counts = statement.executeBatch();
connection.commit();
Related concepts
JDBC BatchUpdateException
An important consideration of batch updates is what action to take when a call to the executeBatch
method fails. In this case, a new type of exception, called BatchUpdateException, is thrown. The
BatchUpdateException is a subclass of SQLException and it allows you to call all the same methods
you have always called to receive the message, the SQLState, and vendor code.
Blocked inserts with JDBC
JDBC BatchUpdateException
An important consideration of batch updates is what action to take when a call to the executeBatch
method fails. In this case, a new type of exception, called BatchUpdateException, is thrown. The
BatchUpdateException is a subclass of SQLException and it allows you to call all the same methods
you have always called to receive the message, the SQLState, and vendor code.
BatchUpdateException also provides the getUpdateCounts method that returns an integer array. The
integer array contains update counts from all the statements in the batch that were processed up to
the point where the failure occurred. The array length tells you which statement in the batch failed. For
example, if the array returned in the exception has a length of three, the fourth statement in the batch
failed. Therefore, from the single BatchUpdateException object that is returned, you can determine the
update counts for all the statements that were successful, which statement failed, and all the information
about the failure.
The standard performance of processing batched updates is equivalent to the performance of processing
each statement independently. You can refer to Blocked insert support for more information about
optimized support for batch updates. You should still use the new model when coding and take advantage
of future performance optimizations.
Note: In the JDBC 2.1 specification, a different option is provided for how exception conditions for batch
updates are handled. JDBC 2.1 introduces a model where the processing batch continues after a batch
entry fails. A special update count is placed in the array of update count integers that is returned for each
entry that fails. This allows large batches to continue processing even though one of their entries fails.
See the JDBC 2.1 or JDBC 3.0 specification for details on these two modes of operation. By default, the
native JDBC driver uses the JDBC 2.0 definition. The driver provides a Connection property that is used
when using DriverManager to establish connections. The driver also provides a DataSource property that
is used when using DataSources to establish connections. These properties allow applications to choose
how they want batch operations to handle failures.
Related concepts
Blocked inserts with JDBC
You can use a blocked insert operation to insert several rows into a database table at a time.
Related reference
Statement batch update
To perform a Statement batch update, you must turn off auto-commit. In Java Database Connectivity
(JDBC), auto-commit is on by default. Auto-commit means any updates to the database are committed
after each SQL statement is processed. If you want to treat a group of statements being handed to the
database as one functional group, you do not want the database committing each statement individually.
If you do not turn off auto-commit and a statement in the middle of the batch fails, you cannot roll
back the entire batch and try it again because half of the statements have been made final. Further, the
additional work of committing each statement in a batch creates a lot of overhead.
PreparedStatement batch update
// Start timing...
for (int i = 1; i <= 10000; i++) {
ps.setInt(1, i); // Set all the parameters for a row
ps.setBigDecimal(2, bd);
ps.setBigDecimal(3, bd);
ps.setBigDecimal(4, bd);
ps.addBatch(); //Add the parameters to the batch
}
// End timing...
Distinct types
The distinct type is a user-defined type that is based on a standard database type. For example, you
can define a Social Security Number type, SSN, that is a CHAR(9) internally. The following SQL statement
creates such a DISTINCT type.
A distinct type always maps to a built-in data type. For more information about how and when to use
distinct types in the context of SQL, consult the SQL reference manuals.
To use distinct types in JDBC, you access them the same way that you access an underlying type. The
getUDTs method is a new method that allows you to query what distinct types are available on the
system. The Example: Distinct types program shows the following:
• The creation of a distinct type.
• The creation of a table that uses it.
• The use of a PreparedStatement to set a distinct type parameter.
• The use of a ResultSet to return a distinct type.
• The use of the metadata Application Programming Interface (API) call to getUDTs to learn about a
distinct type.
For more information, see the Example: Distinct types subtopic that shows various commons tasks you
can perform by using distinct types.
Datalinks
Datalinks are encapsulated values that contain a logical reference from the database to a file stored
outside the database. Datalinks are represented and used from a JDBC perspective in two different ways,
depending on whether you are using JDBC 2.0 or earlier, or you are using JDBC 3.0 or later.
Read BLOBs from the database and insert BLOBs into the database
With the JDBC API, there are ways to get BLOBs out of the database and ways to put BLOBs into the
database. However, there is no standardized way to create a Blob object. This is not a problem if your
database is already full of BLOBs, but it poses a problem if you want to work with BLOBs from scratch
through JDBC. Instead of defining a constructor for the Blob and Clob interfaces of the JDBC API, support
is provided for placing BLOBs into the database and getting them out of the database directly as other
types. For example, the setBinaryStream method can work with a database column of type Blob. The
Example: Blobs topic shows some of the common ways that a BLOB can be put into the database or
retrieved from the database.
Example: BLOB
This is an example of how a BLOB can be put into the database or retrieved from the database.
Note: By using the code examples, you agree to the terms of the “Code license and disclaimer
information” on page 489.
/////////////////////////////////////////
// PutGetBlobs is an example application
// that shows how to work with the JDBC
// API to obtain and put BLOBs to and from
// database columns.
//
// Process a query and obtain the BLOB that was just inserted out
// of the database as a Blob object.
ResultSet rs = s.executeQuery("SELECT * FROM CUJOSQL.BLOBTABLE");
rs.next();
Blob blob = rs.getBlob(1);
Related reference
Example: Updating BLOBs
This is an example of how to update BLOBs in your Java applications.
Example: Using BLOBs
/////////////////////////////////////////
// UpdateBlobs is an example application
// that shows some of the APIs providing
// support for changing Blob objects
// and reflecting those changes to the
// database.
//
// This program must be run after
// the PutGetBlobs program has completed.
/////////////////////////////////////////
import java.sql.*;
Connection c = DriverManager.getConnection("jdbc:db2:*local");
Statement s = c.createStatement();
rs.next();
Blob blob1 = rs.getBlob(1);
rs.next();
Blob blob2 = rs.getBlob(1);
// Truncate a BLOB.
blob1.truncate((long) 150000);
System.out.println("Blob1's new length is " + blob1.length());
Related reference
Example: BLOB
This is an example of how a BLOB can be put into the database or retrieved from the database.
Example: Using BLOBs
/////////////////////////////////////////
// UseBlobs is an example application
// that shows some of the APIs associated
// with Blob objects.
//
// This program must be run after
// the PutGetBlobs program has completed.
/////////////////////////////////////////
import java.sql.*;
Connection c = DriverManager.getConnection("jdbc:db2:*local");
Statement s = c.createStatement();
rs.next();
Blob blob1 = rs.getBlob(1);
rs.next();
Blob blob2 = rs.getBlob(1);
Related reference
Example: BLOB
This is an example of how a BLOB can be put into the database or retrieved from the database.
Example: Updating BLOBs
Read CLOBs from the database and insert CLOBs into the database
With the JDBC API, there are ways to get CLOBs out of the database and ways to put CLOBs into the
database. However, there is no standardized way to create a Clob object. This is not a problem if your
database is already full of CLOBs, but it poses a problem if you want to work with CLOBs from scratch
through JDBC. Instead of defining a constructor for the Blob and Clob interfaces of the JDBC API, support
is provided for placing CLOBs into the database and getting them out of the database directly as other
types. For example, the setCharacterStream method can work with a database column of type Clob. The
Example: CLOB topic shows some of the common ways that a CLOB can be put into the database or
retrieved from the database.
Example: CLOB
This is an example of how a CLOB can be put into the database or retrieved from the database.
Note: By using the code examples, you agree to the terms of the “Code license and disclaimer
information” on page 489.
/////////////////////////////////////////
// PutGetClobs is an example application
// Process a query and get the CLOB that was just inserted out of the
// database as a Clob object.
ResultSet rs = s.executeQuery("SELECT * FROM CUJOSQL.CLOBTABLE");
rs.next();
Clob clob = rs.getClob(1);
Related reference
Example: Updating CLOBs
/////////////////////////////////////////
// UpdateClobs is an example application
// that shows some of the APIs providing
// support for changing Clob objects
// and reflecting those changes to the
// database.
//
// This program must be run after
// the PutGetClobs program has completed.
/////////////////////////////////////////
import java.sql.*;
Connection c = DriverManager.getConnection("jdbc:db2:*local");
Statement s = c.createStatement();
rs.next();
Clob clob1 = rs.getClob(1);
rs.next();
Clob clob2 = rs.getClob(1);
// Truncate a CLOB.
clob1.truncate((long) 150000);
System.out.println("Clob1's new length is " + clob1.length());
Related reference
Example: CLOB
This is an example of how a CLOB can be put into the database or retrieved from the database.
Example: Using CLOBs
/////////////////////////////////////////
// UpdateClobs is an example application
// that shows some of the APIs providing
// support for changing Clob objects
// and reflecting those changes to the
// database.
//
// This program must be run after
// the PutGetClobs program has completed.
/////////////////////////////////////////
import java.sql.*;
Connection c = DriverManager.getConnection("jdbc:db2:*local");
Statement s = c.createStatement();
rs.next();
Clob clob1 = rs.getClob(1);
rs.next();
Clob clob2 = rs.getClob(1);
Related reference
Example: CLOB
This is an example of how a CLOB can be put into the database or retrieved from the database.
Example: Updating CLOBs
Example: Datalink
This example application shows how to use the JDBC API to handle datalink database columns.
Note: By using the code examples, you agree to the terms of the “Code license and disclaimer
information” on page 489.
/////////////////////////////////////////
// PutGetDatalinks is an example application
// that shows how to use the JDBC
// API to handle datalink database columns.
/////////////////////////////////////////
import java.sql.*;
import java.net.URL;
import java.net.MalformedURLException;
// Process a query and obtain the CLOB that was just inserted out of the
// database as a Clob object.
ResultSet rs = s.executeQuery("SELECT * FROM CUJOSQL.DLTABLE");
rs.next();
String datalink = rs.getString(1);
/////////////////////////////////////////
// This example program shows examples of
// various common tasks that can be done
// with distinct types.
/////////////////////////////////////////
import java.sql.*;
Connection c = DriverManager.getConnection("jdbc:db2:*local");
Statement s = c.createStatement();
try {
s.executeUpdate("DROP DISTINCT TYPE CUJOSQL.SSN");
} catch (SQLException e) {
// Ignore it and assume the table did not exist.
}
// You can obtain details about the types available with new metadata in
// JDBC 2.0
DatabaseMetaData dmd = c.getMetaData();
Related concepts
Writing code that uses BLOBs
There are a number of tasks that can be accomplished with database Binary Large Object (BLOB) columns
through the Java Database Connectivity (JDBC) Application Programming Interface (API). The following
topics briefly discuss these tasks and include examples on how to accomplish them.
Writing code that uses CLOBs
There are a number of tasks that can be performed with database CLOB and DBCLOB columns through
the Java Database Connectivity (JDBC) Application Programming Interface (API). The following topics
briefly discuss these tasks and include examples on how to accomplish them.
Writing code that uses Datalinks
How you work with Datalinks is dependent on what release you are working with. In JDBC 3.0, there is
support to work directly with Datalink columns using the getURL and putURL methods.
JDBC RowSets
RowSets were originally added to the Java Database Connectivity (JDBC) 2.0 Optional Package. Unlike
some of the better-known interfaces of the JDBC specification, the RowSet specification is designed
to be more of a framework than an actual implementation. The RowSet interfaces define a set of core
functionality that all RowSets have. RowSet implementation providers have considerable freedom to
define the functionality that is needed to fit their needs in a specific problem space.
RowSet characteristics
You can request certain properties to be satisfied by the rowsets. Common properties include the set of
interfaces to be supported by the resulting rowset.
DB2CachedRowSet
The DB2CachedRowSet object is a disconnected RowSet, meaning that it can be used without being
connected to the database. Its implementation adheres closely to the description of a CachedRowSet.
The DB2CachedRowSet is a container for rows of data from a ResultSet. The DB2CachedRowSet holds
all its own data so it does not need to maintain a connection to the database other than explicitly while
reading or writing data to the database.
Related concepts
RowSet characteristics
You can request certain properties to be satisfied by the rowsets. Common properties include the set of
interfaces to be supported by the resulting rowset.
DB2JdbcRowSet
The DB2JdbcRowSet is a connected RowSet, meaning that it can only be used with the support of
an underlying Connection object, PreparedStatement object, or ResultSet object. Its implementation
adheres closely to the description of a JdbcRowSet.
Using DB2CachedRowSet
Because the DB2CachedRowSet object can be disconnected and serialized, it is useful in environments
where it is not always practical to run a full JDBC driver (for example, on Personal Digital Assistants
(PDAs) and Java-enabled cell phones).
Since the DB2CachedRowSet object is contained in memory and its data is always known, it can serve
as a highly optimized form of a scrollable ResultSet for applications. Whereas DB2ResultSets that are
scrollable typically pay a performance penalty because their random movements interfere with the JDBC
driver's ability to cache rows of data, RowSets do not have this issue.
crs.close();
Related concepts
Using DB2CachedRowSet
import java.sql.*;
import javax.sql.*;
import com.ibm.db2.jdbc.app.*;
import java.io.*;
import java.math.*;
try {
Connection conn = DriverManager.getConnection("jdbc:db2:*local");
stmt.execute("insert into cujosql.test_table values (null, null, null, null, null, null,
null, null,
null, null, null, null, null)");
System.out.println("Rows inserted");
conn.close();
System.out.println("RowSet is detached...");
crs.close();
}
catch (Exception ex) {
System.out.println("SQLException: " + ex.getMessage());
ex.printStackTrace();
}
}
}
import java.sql.*;
import javax.sql.*;
import com.ibm.db2.jdbc.app.DB2CachedRowSet;
try {
Connection conn = DriverManager.getConnection("jdbc:db2:*local");
conn.close();
System.out.println("RowSet is detached...");
System.out.println("Use next()");
while (crs.next()) {
System.out.println("v1 is " + crs.getShort(1));
}
System.out.println("Use previous()");
while (crs.previous()) {
System.out.println("value is " + crs.getShort(1));
}
System.out.println("Use relative()");
crs.next();
crs.relative(9);
System.out.println("value is " + crs.getShort(1));
crs.relative(-9);
System.out.println("value is " + crs.getShort(1));
System.out.println("Test beforeFirst()");
crs.beforeFirst();
System.out.println("isBeforeFirst is " + crs.isBeforeFirst());
crs.next();
System.out.println("move one... isFirst is " + crs.isFirst());
System.out.println("Test afterLast()");
crs.afterLast();
System.out.println("isAfterLast is " + crs.isAfterLast());
crs.previous();
System.out.println("move one... isLast is " + crs.isLast());
System.out.println("Test getRow()");
crs.absolute(7);
System.out.println("row should be (7) and is " + crs.getRow() +
" value should be (6) and is " + crs.getShort(1));
crs.close();
}
catch (SQLException ex) {
System.out.println("SQLException: " + ex.getMessage());
}
}
}
Related concepts
Using DB2CachedRowSet
Because the DB2CachedRowSet object can be disconnected and serialized, it is useful in environments
where it is not always practical to run a full JDBC driver (for example, on Personal Digital Assistants
(PDAs) and Java-enabled cell phones).
DB2CachedRowSet features
In addition to working like a ResultSet, the DB2CachedRowSet class has some additional functionality
that makes it more flexible to use. Methods are provided for turning either the entire Java Database
Connectivity (JDBC) RowSet or just a portion of it into a Java collection. Moreover, because of their
disconnected nature, DB2CachedRowSets do not have a strict one-to-one relationship with ResultSets.
Related reference
Creating and populating a DB2CachedRowSet
There are several ways to place data into a DB2CachedRowSet: the populate method,
DB2CachedRowSet properties with DataSources, DB2CachedRowSet properties and JDBC URLs, the
setConnection(Connection) method , the execute(Connection) method, and the execute(int) method.
Changing DB2CachedRowSet data and reflecting changes back to the data source
This topic provides information about making changes to rows in a DB2CachedRowSet and then updating
the underlying database.
Changing DB2CachedRowSet data and reflecting changes back to the data source
This topic provides information about making changes to rows in a DB2CachedRowSet and then updating
the underlying database.
The DB2CachedRowSet uses the same methods as the standard ResultSet interface for making changes
to the data in the RowSet object. There is no difference at the application level between changing the data
of a RowSet and changing the data of a ResultSet. The DB2CachedRowSet provides the acceptChanges
method that is used to reflect changes to the RowSet back to the database where the data came from.
import java.sql.*;
import javax.sql.*;
import com.ibm.db2.jdbc.app.DB2CachedRowSet;
try {
Connection conn = DriverManager.getConnection("jdbc:db2:*local");
conn.close();
System.out.println("RowSet is detached...");
crs.beforeFirst();
System.out.println("Insert the value -10 into the RowSet");
crs.setShowDeleted(true);
crs.cancelRowInsert();
crs.setShowDeleted(false);
crs.close();
import java.sql.*;
import javax.sql.*;
import com.ibm.db2.jdbc.app.DB2CachedRowSet;
try {
Connection conn = DriverManager.getConnection("jdbc:db2:*local");
conn.close();
System.out.println("RowSet is detached...");
crs.beforeFirst();
System.out.println("Insert the value -10 into the RowSet");
crs.moveToInsertRow();
crs.updateShort(1, (short)-10);
crs.insertRow();
crs.moveToCurrentRow();
crs.setUrl("jdbc:db2:*local");
crs.setTableName("cujosql.test_table");
crs.acceptChanges();
crs.close();
conn.close();
}
catch (SQLException ex) {
System.out.println("SQLException: " + ex.getMessage());
}
}
}
Related concepts
Using DB2CachedRowSet
Because the DB2CachedRowSet object can be disconnected and serialized, it is useful in environments
where it is not always practical to run a full JDBC driver (for example, on Personal Digital Assistants
(PDAs) and Java-enabled cell phones).
DB2CachedRowSet features
In addition to working like a ResultSet, the DB2CachedRowSet class has some additional functionality
that makes it more flexible to use. Methods are provided for turning either the entire Java Database
Connectivity (JDBC) RowSet or just a portion of it into a Java collection. Moreover, because of their
disconnected nature, DB2CachedRowSets do not have a strict one-to-one relationship with ResultSets.
Related reference
Creating and populating a DB2CachedRowSet
There are several ways to place data into a DB2CachedRowSet: the populate method,
DB2CachedRowSet properties with DataSources, DB2CachedRowSet properties and JDBC URLs, the
setConnection(Connection) method , the execute(Connection) method, and the execute(int) method.
Accessing DB2CachedRowSet data and cursor manipulation
This topic provides information about accessing DB2CachedRowSet data and various cursor manipulation
functions.
DB2CachedRowSet features
In addition to working like a ResultSet, the DB2CachedRowSet class has some additional functionality
that makes it more flexible to use. Methods are provided for turning either the entire Java Database
Connectivity (JDBC) RowSet or just a portion of it into a Java collection. Moreover, because of their
disconnected nature, DB2CachedRowSets do not have a strict one-to-one relationship with ResultSets.
In addition to working like a ResultSet as several examples have shown, the DB2CachedRowSet class
has some additional functionality that makes it more flexible to use. Methods are provided for turning
either the entire Java Database Connectivity (JDBC) RowSet or just a portion of it into a Java collection.
Moreover, because of their disconnected nature, DB2CachedRowSets do not have a strict one-to-one
relationship with ResultSets.
With the methods provided by DB2CachedRowSet, you can perform the following tasks:
import java.sql.*;
import javax.sql.*;
import com.ibm.db2.jdbc.app.DB2CachedRowSet;
import java.util.*;
try {
Connection conn = DriverManager.getConnection("jdbc:db2:*local");
Statement stmt = conn.createStatement();
conn.close();
System.out.println("RowSet is detached...");
iter = vector.iterator();
while (iter.hasNext()) {
System.out.println("Iter: Value is " + iter.next());
}
import java.sql.*;
import javax.sql.*;
import com.ibm.db2.jdbc.app.*;
import java.io.*;
try {
Connection conn = DriverManager.getConnection("jdbc:db2:*local");
conn.close();
System.out.println("RowSet is detached...");
crs.beforeFirst();
crs2.beforeFirst();
crs3.beforeFirst();
System.out.println("Now look at all three of them again");
while (crs.next()) {
crs2.next();
crs3.next();
System.out.println("Values: crs: " + crs.getShort(1) + ", crs2: " + crs2.getShort(1) +
", crs3: " + crs3.getShort(1));
}
}
catch (Exception ex) {
System.out.println("SQLException: " + ex.getMessage());
ex.printStackTrace();
}
import java.sql.*;
import javax.sql.*;
import com.ibm.db2.jdbc.app.*;
import java.io.*;
try {
Connection conn = DriverManager.getConnection("jdbc:db2:*local");
conn.close();
System.out.println("RowSet is detached...");
crs.beforeFirst();
crs2.afterLast();
while (crs.next()) {
crs2.previous();
crs3.next();
System.out.println("Values: crs: " + crs.getShort(1) + ", crs2: " + crs2.getShort(1) +
", crs3: " + crs3.getShort(1));
}
crs.close();
crs2.close();
crs3.close();
}
catch (Exception ex) {
System.out.println("SQLException: " + ex.getMessage());
ex.printStackTrace();
}
}
}
DB2JdbcRowSet
The DB2JdbcRowSet is a connected RowSet, meaning that it can only be used with the support of
an underlying Connection object, PreparedStatement object, or ResultSet object. Its implementation
adheres closely to the description of a JdbcRowSet.
Use DB2JdbcRowSet
Because the DB2JdbcRowSet object supports events described in the Java Database Connectivity (JDBC)
3.0 specification for all RowSets, it can serve as an intermediate object between a local database and
other objects that must be notified about changes to the database data.
As an example, assume that you are working in an environment where you have a main database and
several Personal Digital Assistants (PDAs) that use a wireless protocol to connect to it. A DB2JdbcRowSet
object can be used to move to a row and update it by using a master application that is running on the
server. The row update causes an event to be generated by the RowSet component. If there is a service
running that is responsible for sending out updates to the PDAs, it can register itself as a "listener" of the
RowSet. Each time that it receives a RowSet event, it can generate the appropriate update and send it out
to the wireless devices.
Refer to Example: DB2JdbcRowSet events for more information.
Create JDBCRowSets
There are several methods provided for creating a DB2JDBCRowSet object. Each is outlined as follows.
Use DB2JdbcRowSet properties and DataSources
DB2JdbcRowSets have properties that accept an SQL query and a DataSource name. The
DB2JdbcRowSets are then ready to be used. The following is an example of this approach. The reference
to the DataSource named BaseDataSource is assumed to be a valid DataSource that has been previously
set up.
Example: Use DB2JdbcRowSet properties and DataSources
Note: Read the Code example disclaimer for important legal information.
DB2JdbcRowSet events
All RowSet implementations support event handling for situations that are of interest to other
components. This support allows application components to "talk" to each other when events happen
to them. For example, updating a database row through a RowSet can cause a Graphical User Interface
(GUI) table shown to you to update itself.
In the following example, the main method does the update to the RowSet and is your core application.
The listener is part of your wireless server used by your disconnected clients in the field. It is possible to
tie these two aspects of a business together without getting the code for the two processes intermingled.
While the event support of RowSets was designed primarily for updating GUIs with database data, it
works perfectly for this type of application problem.
Example: DB2JdbcRowSet events
Note: Read the Code example disclaimer for important legal information.
import java.sql.*;
import javax.sql.*;
import com.ibm.db2.jdbc.app.DB2JdbcRowSet;
try {
// Obtain the JDBC Connection and Statement needed to set
// up this example.
Connection conn = DriverManager.getConnection("jdbc:db2:*local");
Statement stmt = conn.createStatement();
// Cause a few cursor change events. These events cause the cursorMoved
// method in the listener object to get control.
jrs.next();
jrs.next();
jrs.next();
// Cause a row change event to occur. This event causes the rowChanged method
// in the listener object to get control.
jrs.updateShort(1, (short)6);
jrs.updateRow();
/**
* This is an example of a listener. This example prints messages that show
* how control flow moves through the application and offers some
* suggestions about what might be done if the application were fully implemented.
*/
class MyListener
implements RowSetListener {
public void cursorMoved(RowSetEvent rse) {
System.out.println("Event to do: Cursor position changed.");
System.out.println(" For the remote system, do nothing ");
System.out.println(" when this event happened. The remote view of the data");
System.out.println(" could be controlled separately from the local view.");
try {
DB2JdbcRowSet rs = (DB2JdbcRowSet) rse.getSource();
System.out.println("row is " + rs.getRow() + ". \n\n");
} catch (SQLException e) {
System.out.println("To do: Properly handle possible problems.");
}
}
SQLJ setup
Before you can use SQLJ in Java applications on your server, you need to prepare your server to use SQLJ.
For more information, see the SQLJ setup topic.
SQLJ tools
The following tools are also included in the SQLJ support provided by the IBM Developer Kit for Java:
• The SQLJ translator, sqlj, replaces embedded SQL statements in the SQLJ program with Java source
statements and generates a serialized profile that contains information about the SQLJ operations that
are found in the SQLJ program.
• The DB2 SQLJ Profile Customizer, db2profc, precompiles the SQL statements stored in the generated
profile and generates a package in the DB2 database.
• The DB2 SQLJ Profile Printer, db2profp, prints the contents of a DB2 customized profile in plain text.
• The SQLJ profile auditor installer, profdb, installs and uninstalls debugging class-auditors into an
existing set of binary profiles.
• The SQLJ profile conversion tool, profconv, converts a serialized profile instance to Java class format.
Note: These tools must be run in the Qshell Interpreter.
db2profc MyClass_SJProfile0.ser
"jdbc:db2:systemName"
For more information, see “Accessing your IBM i database with the Java JDBC driver” on page 27.
-user=<username>
Where username is your username. The default value is the user ID of the current user that is signed
on for local connection.
-commitctrl=<commitment_control>
Where commitment_control is the level of commitment control you want. Commitment control can
have any one of the following character values:
Value Definition
C *CHG. Dirty reads, nonrepeatable reads and phantom
reads are possible.
S *CS. Dirty reads are not possible, but non-repeatable
reads and phantom reads are possible.
A *ALL. Dirty reads and nonrepeatable reads are not
possible, but phantom reads are possible.
N *NONE. Dirty reads, nonrepeatable reads, and
phantom reads are not possible. This is the default.
-datefmt=<date_format>
Where date_format is the type of date formatting you want. Date format can have any one of the
following values:
Value Definition
USA IBM USA standard (mm.dd.yyyy,hh:mm a.m., hh:mm
p.m.)
ISO International Standards Organization (yyyy-mm-dd,
hh.mm.ss) This is the default.
EUR IBM European Standard (dd.mm.yyyy, hh.mm.ss)
JIS Japanese Industrial Standard Christian Era (yyyy-mm-
dd, hh:mm:ss)
MDY Month/Day/Year (mm/d/yy)
DMY Day/Month/Year (dd/mm/yy)
YMD Year/Month/Day (yy/mm/dd)
Date format is used when accessing date result columns. All output date fields are returned in the
specified format. For input date strings, the specified value is used to determine whether the date is
specified Inc valid format. The default value is ISO.
-datesep=<date_separator>
Where date_separator is the type of separator you want to use. Date separator is used when accessing
date result columns. Date separator can be any of the following values:
Value Definition
/ A slash is used.
. A period is used.
, A comma is used.
- A dash is used. This is the default.
blank A space is used.
-timefmt=<time_format>
Where time_format is the format you want to use to display time fields. Time format is used when
accessing time result columns. For input time strings, the specified value is used to determine
whether the time is specified in a valid format. Time format can be any one of the following values:
Value Definition
USA IBM USA standard (mm.dd.yyyy,hh:mm a.m., hh:mm
p.m.)
ISO International Standards Organization (yyyy-mm-dd,
hh.mm.ss) This is the default.
EUR IBM European Standard (dd.mm.yyyy, hh.mm.ss)
JIS Japanese Industrial Standard Christian Era (yyyy-mm-
dd, hh:mm:ss)
HMS Hour/Minute/Second (hh:mm:ss)
-timesep=<time_separator>
Where time_separator is the character you want to use to access your time result columns. Time
separator can be any one of the following values:
Value Definition
: A colon is used.
. A period is used. This is the default.
, A comma is used.
blank A space is used.
-decimalpt=<decimal_point>
Where decimal_point is the decimal point you want to use. The decimal point is used for numeric
constants in SQL statements. Decimal point can be any one of the following values:
Value Definition
. A period is used. This is the default.
-stmtCCSID=<CCSID>
Where CCSID is the coded character set identifier for the SQL statements that are prepared into the
package. The value of the job during customization time is the default value.
-sorttbl=<library_name/sort_sequence_table_name>
Where library_name/sort_sequence_table_name is the location and table name of the sort sequence
table you want to use. The sort sequence table is used for string comparisons in SQL statements. The
library name and sort sequence table name each have limits of 10 characters. The default value is
taken from the job during customization time.
-langID=<language_identifier>
Where language identifier is the language identifier you want to use. The default value for the language
identifier is taken from the current job during customization time. The language identifier is used in
conjunction with the sort sequence table.
Related concepts
Structured Query Language for Java profiles
Profiles are generated by the SQLJ Translator, sqlj, when you translate the SQLJ source file. Profiles
are serialized binary files. That is why these files have a .ser extension. These files contain the SQL
statements from the associated SQLJ source file.
The structured query language for Java (SQLJ) translator (sqlj)
The SQLJ translator, sqlj, generates a serialized profile containing information about the SQL operations
found in the SQLJ program. The SQLJ translator uses the /QIBM/ProdData/Java400/ext/translator.zip file.
Printing the contents of DB2 SQLJ profiles (db2profp and profp)
The DB2 SQLJ Profile Printer, db2profp, prints the contents of a DB2 customized profile in plain text. The
Profile Printer, profp, prints the contents of profiles generated by the SQLJ translator in plain text.
SQLJ profile auditor installer (profdb)
The SQLJ profile auditor installer (profdb) installs and uninstalls debugging class-auditors. The debugging
class-auditors are installed into an existing set of binary profiles. Once the debugging class-auditors are
installed, all RTStatement and RTResultSet calls made during application run time are logged. They
can be logged to a file or standard output. The logs can then be inspected to verify the behavior
and trace errors of the application. Note that only the calls made to the underlying RTStatement and
RTResultSetcall interface at run time are audited.
Embedding SQL statements in your Java application
Static SQL statements in SQLJ are in SQLJ clauses. SQLJ clauses begin with #sql and end with a
semicolon (;) character.
Related tasks
Converting a serialized profile instance to Java class format using the SQLJ profile conversion tool
(profconv)
The SQLJ profile conversion tool (profconv) converts a serialized profile instance to Java class format.
The profconv tool is needed because some browsers do not support loading a serialized object from a
resource file that is associated with an applet. Run the profconv utility to perform the conversion.
Compiling and running SQLJ programs
If your Java program has embedded SQLJ statements, you need to follow a special procedure to compile
and run it.
Related information
SQL Programming
profp MyClass_SJProfile0.ser
db2profp MyClass_SJProfile0.ser
Where SQLJ_profile_name is the name of the profile to be printed and options is the list of options you
want.
The options available for db2profp are the following:
-URL=<JDBC_URL>
Where JDBC_URL is the URL you want to connect to. For more information, see “Accessing your IBM i
database with the Java JDBC driver” on page 27.
-user=<username>
Where username is the user name is your user profile.
-password=<password>
Where password is the password of your user profile.
Related concepts
Structured Query Language for Java profiles
Profiles are generated by the SQLJ Translator, sqlj, when you translate the SQLJ source file. Profiles
are serialized binary files. That is why these files have a .ser extension. These files contain the SQL
statements from the associated SQLJ source file.
The structured query language for Java (SQLJ) translator (sqlj)
The SQLJ translator, sqlj, generates a serialized profile containing information about the SQL operations
found in the SQLJ program. The SQLJ translator uses the /QIBM/ProdData/Java400/ext/translator.zip file.
Precompiling SQL statements in a profile using the DB2 SQLJ profile customizer, db2profc
You can use the DB2 SQLJ Profile Customizer, db2profc, to make your Java application work more
efficiently with your database.
SQLJ profile auditor installer (profdb)
The SQLJ profile auditor installer (profdb) installs and uninstalls debugging class-auditors. The debugging
class-auditors are installed into an existing set of binary profiles. Once the debugging class-auditors are
installed, all RTStatement and RTResultSet calls made during application run time are logged. They
can be logged to a file or standard output. The logs can then be inspected to verify the behavior
and trace errors of the application. Note that only the calls made to the underlying RTStatement and
RTResultSetcall interface at run time are audited.
Embedding SQL statements in your Java application
profdb MyClass_SJProfile0.ser
Where MyClass_SJProfile0.ser is the name of the profile that was generated by the SQLJ Translator.
To uninstall debugging class-auditors, enter the following at the Qshell command prompt:
profdb -Cuninstall MyClass_SJProfile.ser
Where MyClass_SJProfile0.ser is the name of the profile that was generated by the SQLJ Translator.
Related concepts
Structured Query Language for Java profiles
Profiles are generated by the SQLJ Translator, sqlj, when you translate the SQLJ source file. Profiles
are serialized binary files. That is why these files have a .ser extension. These files contain the SQL
statements from the associated SQLJ source file.
The structured query language for Java (SQLJ) translator (sqlj)
The SQLJ translator, sqlj, generates a serialized profile containing information about the SQL operations
found in the SQLJ program. The SQLJ translator uses the /QIBM/ProdData/Java400/ext/translator.zip file.
Precompiling SQL statements in a profile using the DB2 SQLJ profile customizer, db2profc
You can use the DB2 SQLJ Profile Customizer, db2profc, to make your Java application work more
efficiently with your database.
Printing the contents of DB2 SQLJ profiles (db2profp and profp)
The DB2 SQLJ Profile Printer, db2profp, prints the contents of a DB2 customized profile in plain text. The
Profile Printer, profp, prints the contents of profiles generated by the SQLJ translator in plain text.
Embedding SQL statements in your Java application
Static SQL statements in SQLJ are in SQLJ clauses. SQLJ clauses begin with #sql and end with a
semicolon (;) character.
Related tasks
Converting a serialized profile instance to Java class format using the SQLJ profile conversion tool
(profconv)
The SQLJ profile conversion tool (profconv) converts a serialized profile instance to Java class format.
The profconv tool is needed because some browsers do not support loading a serialized object from a
resource file that is associated with an applet. Run the profconv utility to perform the conversion.
Compiling and running SQLJ programs
Converting a serialized profile instance to Java class format using the SQLJ
profile conversion tool (profconv)
The SQLJ profile conversion tool (profconv) converts a serialized profile instance to Java class format.
The profconv tool is needed because some browsers do not support loading a serialized object from a
resource file that is associated with an applet. Run the profconv utility to perform the conversion.
• To run the profconv utility, type the following on the Qshell command line:
profconv MyApp_SJProfile0.ser
The previous example deletes all the rows in the table named TAB.
In an SQLJ process clause, the tokens that appear inside the braces are either SQL tokens or host
variables. All host variables are distinguished by the colon (:) character. SQL tokens never occur outside
the braces of an SQLJ process clause. For example, the following Java method inserts its arguments into
an SQL table:
The method body consists of an SQLJ process clause containing the host variables x, y, and z.
In general, SQL tokens are case insensitive (except for identifiers delimited by double quotation marks),
and can be written in upper, lower, or mixed case. Java tokens, however, are case sensitive. For clarity
in examples, case insensitive SQL tokens are uppercase, and Java tokens are lowercase or mixed case.
Throughout this topic, the lowercase null is used to represent the Java "null" value, and the uppercase
NULL is used to represent the SQL "null" value.
The following types of SQL constructs may appear in SQLJ programs:
• Queries For example, SELECT statements and expressions.
• SQL Data Change statements (DML) For example, INSERT, UPDATE, DELETE.
• Data statements For example, FETCH, SELECT..INTO.
• Transaction Control statements For example, COMMIT, ROLLBACK, etc.
• Data Definition Language (DDL, also known as Schema Manipulation Language) statements For
example, CREATE, DROP, ALTER.
• Calls to stored procedures For example, CALL MYPROC(:x, :y, :z)
• Invocations of stored functions For example, VALUES( MYFUN(:x) )
Related concepts
Structured Query Language for Java profiles
Profiles are generated by the SQLJ Translator, sqlj, when you translate the SQLJ source file. Profiles
are serialized binary files. That is why these files have a .ser extension. These files contain the SQL
statements from the associated SQLJ source file.
The structured query language for Java (SQLJ) translator (sqlj)
The SQLJ translator, sqlj, generates a serialized profile containing information about the SQL operations
found in the SQLJ program. The SQLJ translator uses the /QIBM/ProdData/Java400/ext/translator.zip file.
Precompiling SQL statements in a profile using the DB2 SQLJ profile customizer, db2profc
You can use the DB2 SQLJ Profile Customizer, db2profc, to make your Java application work more
efficiently with your database.
Printing the contents of DB2 SQLJ profiles (db2profp and profp)
The DB2 SQLJ Profile Printer, db2profp, prints the contents of a DB2 customized profile in plain text. The
Profile Printer, profp, prints the contents of profiles generated by the SQLJ translator in plain text.
SQLJ profile auditor installer (profdb)
The SQLJ profile auditor installer (profdb) installs and uninstalls debugging class-auditors. The debugging
class-auditors are installed into an existing set of binary profiles. Once the debugging class-auditors are
installed, all RTStatement and RTResultSet calls made during application run time are logged. They
can be logged to a file or standard output. The logs can then be inspected to verify the behavior
import java.sql.*;
import sqlj.runtime.*;
import sqlj.runtime.ref.*;
class App
{
/**********************
** Register Driver **
**********************/
static
{
try
{
Class.forName("com.ibm.db2.jdbc.app.DB2Driver").newInstance();
}
catch (Exception e)
{
e.printStackTrace();
}
}
/********************
// URL is jdbc:db2:dbname
String url = "jdbc:db2:sample";
sqlj MyClass.sqlj
db2profc MyClass_SJProfile0.ser
where MyClass_SJProfile0.ser is the name of the profile on which the DB2 SQLJ Customizer is run.
Note: This step is optional but is recommended to increase runtime performance.
4. Run the Java class file just like any other Java class file.
For example, type in the command:
java MyClass
javac -DCLASSPATH=/QIBM/ProdData/Java400/ext/db2routines_classes.jar
source.java
4. Make the compiled classes accessible to the Java virtual machine (JVM) used by the database
The user-defined classes used by the database JVM can either reside in the /QIBM/UserData/OS400/
SQLLib/Function directory or in a JAR file registered to the database.
The /QIBM/UserData/OS400/SQLLib/Function is the IBM i equivalent of /sqllib/function, the directory
where Db2 for i stores Java stored procedures and Java UDFs on other platforms. If the class is part
of a Java package, it must reside in the appropriate subdirectory. For example, if the runit class is
created as part of the foo.bar package, the file runnit.class should be in the integrated file system
directory, /QIBM/ProdData/OS400/SQLLib/Function/foo/bar.
The class file may also be placed in a JAR file that is registered to the database. The JAR file is
registered using the SQLJ.INSTALL_JAR stored procedure. This stored procedure is used to assign a
JAR ID to a JAR file. This JAR ID is used to identify the JAR file in which the class file resides. See SQLJ
procedures that manipulate JAR files for more information on SQLJ.INSTALL_JAR as well as other
stored procedures to manipulate JAR files.
5. Register the routine with the database.
Java SQL routines is registered with the database using the CREATE PROCEDURE and CREATE
FUNCTION SQL statements. These statements contain the following elements:
ADDLNK OBJ('/QIBM/ProdData/Os400/Java400/ext/runtime.zip')
NEWLNK('/QIBM/UserData/Java400/ext/runtime.zip')
For more information about installing extensions, see the following page:
Install extensions for the IBM Developer Kit for Java
connection=DriverManager.getConnection("jdbc:default:connection");
package mystuff;
import java.sql.*;
public class sample2 {
public static void donut(String query, int[] rowCount,
String[] sqlstate) throws Exception {
try {
Connection c=DriverManager.getConnection("jdbc:default:connection");
Statement s=c.createStatement();
ResultSet r=s.executeQuery(query);
int counter=0;
while(r.next()){
counter++;
}
In the SQLj standard, to return a result set in routines that use the JAVA parameter style, the result
set must be set explicitly. When a procedure is created that returns result sets, additional result set
parameters are added to the end of the parameter list. For example, the statement
would call a Java method with the signature public static void
returnTwoResultSets(ResultSet[] rs1, ResultSet[] rs2).
The output parameters of the result sets must be explicitly set as illustrated in the following example. As
in the DB2GENERAL style, the result sets and corresponding statements should not be closed.
Example: Stored procedure that returns two result sets
Note: By using the code examples, you agree to the terms of the “Code license and disclaimer
information” on page 489.
import java.sql.*;
public class javaClass {
/**
* Java stored procedure, with JAVA style parameters,
* that processes two predefined sentences
* and returns two result sets
*
* @param ResultSet[] rs1 first ResultSet
* @param ResultSet[] rs2 second ResultSet
*/
public static void returnTwoResultSets (ResultSet[] rs1, ResultSet[] rs2) throws Exception
{
//get caller's connection to the database; inherited from StoredProc
Connection con = DriverManager.getConnection("jdbc:default:connection");
On the server, the additional result set parameters are not examined to determine the ordering of the
results sets. The results sets on the server are returned in the order in which they were opened. To ensure
compatibility with the SQLj standard, the result should be assigned in the order that they are opened, as
previously shown.
package mystuff;
import com.ibm.db2.app.*;
import java.sql.*;
public class sample2 extends StoredProc {
public void donut(String query, int rowCount,
String sqlstate) throws Exception {
try {
Statement s=getConnection().createStatement();
ResultSet r=s.executeQuery(query);
int counter=0;
while(r.next()){
counter++;
}
r.close(); s.close();
set(2, counter);
}catch(SQLException x){
set(3, x.getSQLState());
}
}
}
To return a result set in procedures that use the DB2GENERAL parameter style, the result set and the
responding statement must be left open at the end of the procedure. The result set that is returned must
be closed by the client application. If multiple results sets are returned, they are returned in the order in
which they were opened. For example, the following stored procedure returns two results sets.
Example: Stored procedure that returns two results sets
Note: By using the code examples, you agree to the terms of the “Code license and disclaimer
information” on page 489.
import com.ibm.db2.app.*;
public class sample {
public static int test3(String arg1, Blob arg2, Date arg3) { ... }
}
where:
• name is the method name
• T1 through T4 are the Java types that correspond to SQL types t1 through t4.
• a, b, and c are arbitrary variable names for the input arguments.
The correlation between SQL types and Java types is found in Parameter passing conventions for stored
procedures and UDFs.
SQL NULL values are represented by Java variables that are not initialized. These variables have a Java
null value if they are object types. If an SQL NULL is passed to a Java scalar data type, such as int, then an
exception condition is raised.
To return a result from a Java UDF when using the JAVA parameter style, simply return the result from the
method.
{ ....
return value;
}
Like C modules used in UDFs and stored procedures, you cannot use the Java standard I/O streams
(System.in, System.out, and System.err) in Java UDFs.
import com.ibm.db2.app.*;
public class sample extends UDF {
public void test3(String arg1, Blob arg2, String arg3, int result) { ... }
}
The parameters of a Java method must be SQL types. For example, if a UDF is declared as taking
arguments of SQL types t1, t2, and t3, returning type t4, it is called as a Java method with the expected
Java signature:
where:
{ ....
if (isNull(1)) { /* argument #1 was a SQL NULL */ }
else { /* not NULL */ }
}
In the previous example, the argument numbers start at one. The isNull() function, like the other functions
that follow, are inherited from the com.ibm.db2.app.UDF class. To return a result from a Java UDF when
using the DB2GENERAL parameter style, use the set() method in the UDF, as follows:
{ ....
set(2, value);
}
Where 2 is the index of an output argument, and value is a literal or variable of a compatible type. The
argument number is the index in the argument list of the selected output. In the first example in this
section, the int result variable has an index of 4. An output argument that is not set before the UDF returns
has a NULL value.
Like C modules used in UDFs and stored procedures, you cannot use the Java standard I/O streams
(System.in, System.out, and System.err) in Java UDFs.
Typically, DB2 calls a UDF many times, once for each row of an input or result set in a query. If
SCRATCHPAD is specified in the CREATE FUNCTION statement of the UDF, DB2 recognizes that some
"continuity" is needed between successive invocations of the UDF, and therefore, for DB2GENERAL
parameter style functions, the implementing Java class is not instantiated for each call, but generally
speaking once per UDF reference per statement. If, however, NO SCRATCHPAD is specified for a UDF, then
a clean instance is instantiated for each call to the UDF, by means of a call to the class constructor.
A scratchpad may be useful for saving information across calls to a UDF. Java UDFs can either use
instance variables or set the scratchpad to achieve continuity between calls. Java UDFs access the
scratchpad with the getScratchPad and setScratchPad methods available in com.ibm.db2.app.UDF. At
the end of a query, if you specify the FINAL CALL option on the CREATE FUNCTION statement, the
object's public void close() method is called (for DB2GENERAL parameter style functions). If you do not
define this method, a stub function takes over and the event is ignored. The com.ibm.db2.app.UDF class
contains useful variables and methods that you can use within a DB2GENERAL parameter style UDF.
These variables and methods are explained in the following table.
• public static final int SQLUDF_FIRST_CALL = -1; For scalar UDFs, these are constants to determine if
the call is a first call or a normal call. For table UDFs,
• public static final int SQLUDF_NORMAL_CALL = 0; these are constants to determine if the call is a first
• public static final int SQLUDF_TF_FIRST = -2; call, open call, fetch call, close call, or final call.
• public static final int SQLUDF_TF_OPEN = -1;
• public static final int SQLUDF_TF_FETCH = 0;
• public static final int SQLUDF_TF_CLOSE = 1;
• public static final int SQLUDF_TF_FINAL = 2;
• public void set(int i, short s); These methods set an output argument to the given
value. An exception is thrown if anything goes wrong,
• public void set(int i, int j); including the following:
• public void set(int i, long j);
• UDF call is not in progress
• public void set(int i, double d);
• Index does not refer to valid output argument
• public void set(int i, float f);
• Data type does not match
• public void set(int i, BigDecimal bigDecimal);
• Data length does not match
• public void set(int i, String string);
• Code page conversion error occurs
• public void set(int i, Blob blob);
• public void set(int i, Clob clob);
• public boolean needToSet(int i);
public void setSQLstate(String string); This method may be called from a UDF to set the
SQLSTATE to be returned from this call. If the string
is not acceptable as an SQLSTATE, an exception
is thrown. The user may set the SQLSTATE in the
external program to return an error or warning from
the function. In this case, the SQLSTATE must contain
one of the following:
• '00000' to indicate success
• '01Hxx', where xx is any two digits or uppercase
letters, to indicate a warning
• '38yxx', where y is an uppercase letter between 'I'
and 'Z' and xx is any two digits or uppercase letters,
to indicate an error
public void setSQLmessage(String string); This method is similar to the setSQLstate method.
It sets the SQL message result. If the string is not
acceptable (for example, longer than 70 characters),
an exception is thrown.
public String getFunctionName(); This method returns the name of the processing UDF.
public String getSpecificName(); This method returns the specific name of the
processing UDF.
public byte[] getDBinfo(); This method returns a raw, unprocessed DBINFO
structure for the processing UDF, as a byte array.
The UDF must have been registered (using CREATE
FUNCTION) with the DBINFO option.
• public String getDBname(); These methods return the value of the appropriate
field from the DBINFO structure of the processing
• public String getDBauthid(); UDF. The UDF must have been registered
• public String getDBver_rel(); (using CREATE FUNCTION) with the DBINFO
• public String getDBplatform(); option. The getDBtbschema(), getDBtbname(), and
getDBcolname() methods only return meaningful
• public String getDBapplid(); information if a user-defined function is specified on
• public String getDBapplid(); the right side of a SET clause in an UPDATE statement.
• public String getDBtbschema();
• public String getDBtbname();
• public String getDBcolname();
public int getCCSID(); This method returns the CCSID of the job.
public byte[] getScratchpad(); This method returns a copy of the scratchpad of the
currently processing UDF. You must first declare the
UDF with the SCRATCHPAD option.
public void setScratchpad(byte ab[]); This method overwrites the scratchpad of the
currently processing UDF with the contents of the
given byte array. You must first declare the UDF with
the SCRATCHPAD option. The byte array must have the
same size as getScratchpad() returns.
public int getCallType(); This method returns the type of call that is currently
being made. These values correspond to the C values
defined in sqludf.h. Possible return values include the
following:
• SQLUDF_FIRST_CALL
• SQLUDF_NORMAL_CALL
• SQLUDF_TF_FIRST
• SQLUDF_TF_OPEN
• SQLUDF_TF_FETCH
• SQLUDF_TF_CLOSE
• SQLUDF_TF_FINAL
Related concepts
Java stored procedures
When using Java to write stored procedures, you can use two possible parameter passing styles.
SQLJ procedures that manipulate JAR files
Both Java stored procedures and Java UDFs can use Java classes that are stored in Java JAR files.
Parameter passing conventions for Java stored procedures and UDFs
The following table lists how SQL data types are represented in Java stored procedures and UDFs.
Related tasks
Using Java SQL routines
Point in scan time NO FINAL CALL LANGUAGE JAVA FINAL CALL LANGUAGE JAVA
SCRATCHPAD SCRATCHPAD
Before the first OPEN of the table No calls Class constructor is called (means
function new scratchpad). UDF method is
called with FIRST call.
At each OPEN of the table function. Class constructor is called (means UDF method is called with OPEN
new scratchpad). UDF method is call.
called with OPEN all.
import com.ibm.db2.app.*;
import java.util.*;
After the table function is compiled, and its class file copied to /QIBM/UserData/OS400/SQLLib/Function,
the function can be registered to the database by using the following SQL statement.
After the function has been registered, it can be used as part of an SQL statement. For example, the
following SELECT statement returns the table generated by the table function.
SQLJ.INSTALL_JAR
The SQLJ.INSTALL_JAR stored procedure installs a JAR file into the database system. This JAR file can be
used in subsequent CREATE FUNCTION and CREATE PROCEDURE statements.
Authorization
The privilege held by the authorization ID of the CALL statement must include at least one of the following
for the SYSJAROBJECTS and SYSJARCONTENTS catalog tables:
• The following system authorities:
– The INSERT and SELECT privileges on the table
– The system authority *EXECUTE on library QSYS2
• Administrative authority
The privilege held by the authorization ID of the CALL statement must also have the following authorities:
• Read (*R) access to the JAR file specified in the jar-url parameter being installed.
• Write, Execute, and Read (*RWX) access to the directory where the JAR file is installed. This directory
is /QIBM/UserData/OS400/SQLLib/Function/jar/schema, where schema is the schema of the jar-id.
Adopted authority cannot be used for these authorities.
SQL syntax
>>-CALL--SQLJ.INSTALL_JAR-- (--'jar-url'--,--'jar-id'--,--deploy--)-->
>--------------------------------------------------------------><
Description
jar-url
The URL containing the JAR file to be installed or replaced. The only URL scheme supported is 'file:'.
Usage notes
When a JAR file is installed, Db2 for i registers the JAR file in the SYSJAROBJECTS system catalog.
It also extracts the names of the Java class files from the JAR file and registers each class in the
SYSJARCONTENTS system catalog. Db2 for i copies the JAR file to a jar/schema subdirectory of the /
QIBM/UserData/OS400/SQLLib/Function directory. Db2 for i gives the new copy of the JAR file the name
given in the jar-id clause. A JAR file that has been installed by Db2 for i into a subdirectory of /QIBM/
UserData/OS400/SQLLib/Function/jar should not be changed. Instead, the CALL SQLJ.REMOVE_JAR and
CALL SQLJ.REPLACE_JAR SQL commands should be used to remove or replace an installed JAR file.
Example
The following command is issued from an SQL interactive session.
The Proc.jar file located in the file:/home/db2inst/classes/ directory is installed into Db2 for i with the
name myproc_jar. Subsequent SQL commands that use the Procedure.jar file refer to it with the name
myproc_jar.
Related reference
SQLJ.REMOVE_JAR
The SQLJ.REMOVE_JAR stored procedure removes a JAR file from the database system.
SQLJ.REPLACE_JAR
The SQLJ.REPLACE_JAR stored procedure replaces a JAR file into the database system.
SQLJ.UPDATEJARINFO
The SQLJ.UPDATEJARINFO updates the CLASS_SOURCE column of the SYSJARCONTENTS catalog table.
This procedure is not part of the SQLJ standard but is used by the Db2 for i stored procedure builder.
SQLJ.RECOVERJAR
The SQLJ.RECOVERJAR procedure takes the JAR file that is stored in the SYSJAROBJECTS catalog and
restores it to the /QIBM/UserData/OS400/SQLLib/Function/jar/jarschema/jar_id.jar file.
SQLJ.REFRESH_CLASSES
The SQLJ.REFRESH_CLASSES stored procedure causes the reloading of user defined classes used by Java
stored procedures or Java UDFs in the current database connection. This stored procedure must be called
by existing database connections to obtain changes made by a call to the SQLJ.REPLACE_JAR stored
procedure.
SQLJ.REMOVE_JAR
The SQLJ.REMOVE_JAR stored procedure removes a JAR file from the database system.
Authorization
The privilege held by the authorization ID of the CALL statement must include at least one of the following
for the SYSJARCONTENTS and SYSJAROBJECTS catalog tables:
• The following system authorities:
– The SELECT and DELETE privileges on the table
Syntax
>>-CALL--SQLJ.REMOVE_JAR--(--'jar-id'--,--undeploy--)----------><
Description
jar-id
The JAR identifier of the JAR file that is to be removed from the database.
undeploy
The value used to describe the remove_action of the deployment descriptor file. If this integer is a
non-zero value, then the remove_actions of a deployment descriptor file should be run at the end of
the install_jar procedure. The current version of Db2 for i only supports a value of zero.
Example
The following command is issued from an SQL interactive session:
CALL SQLJ.REMOVE_JAR('myProc_jar', 0)
SQLJ.REPLACE_JAR
The SQLJ.REPLACE_JAR stored procedure replaces a JAR file into the database system.
Authorization
The privilege held by the authorization ID of the CALL statement must include at least one of the following
for the SYSJAROBJECTS and SYSJARCONTENTS catalog tables:
Syntax
>>-CALL--SQLJ.REPLACE_JAR--(--'jar-url'--,--'jar-id'--)--------><
Description
jar-url
The URL containing the JAR file to be replaced. The only URL scheme supported is 'file:'.
jar-id
The JAR identifier in the database to be associated with the file specified by the jar-url. The jar-id uses
SQL naming and the JAR file is installed in the schema or library specified by the implicit or explicit
qualifier.
Usage notes
The SQLJ.REPLACE_JAR stored procedure replaces a JAR file that was previously installed in the
database using SQLJ.INSTALL_JAR.
Example
The following command is issued from an SQL interactive session:
The current JAR file referred to by the jar-id myproc_jar is replaced with the Proc.jar file located in the
file:/home/db2inst/classes/ directory.
Related reference
SQLJ.INSTALL_JAR
The SQLJ.INSTALL_JAR stored procedure installs a JAR file into the database system. This JAR file can be
used in subsequent CREATE FUNCTION and CREATE PROCEDURE statements.
SQLJ.REMOVE_JAR
The SQLJ.REMOVE_JAR stored procedure removes a JAR file from the database system.
SQLJ.UPDATEJARINFO
The SQLJ.UPDATEJARINFO updates the CLASS_SOURCE column of the SYSJARCONTENTS catalog table.
This procedure is not part of the SQLJ standard but is used by the Db2 for i stored procedure builder.
SQLJ.RECOVERJAR
The SQLJ.RECOVERJAR procedure takes the JAR file that is stored in the SYSJAROBJECTS catalog and
restores it to the /QIBM/UserData/OS400/SQLLib/Function/jar/jarschema/jar_id.jar file.
SQLJ.REFRESH_CLASSES
The SQLJ.REFRESH_CLASSES stored procedure causes the reloading of user defined classes used by Java
stored procedures or Java UDFs in the current database connection. This stored procedure must be called
SQLJ.UPDATEJARINFO
The SQLJ.UPDATEJARINFO updates the CLASS_SOURCE column of the SYSJARCONTENTS catalog table.
This procedure is not part of the SQLJ standard but is used by the Db2 for i stored procedure builder.
Authorization
The privilege held by the authorization ID of the CALL statement must include at least one of the following
for the SYSJARCONTENTS catalog table:
• The following system authorities:
– The SELECT and UPDATEINSERT privileges on the table
– The system authority *EXECUTE on library QSYS2
• Administrative authority
The user running the CALL statement must also have the following authorities:
• Read (*R) access to the JAR file specified in the jar-url parameter. Read (*R) access to the JAR file being
installed.
• Write, Execute, and Read (*RWX) access to the directory where the JAR file is installed. This directory
is /QIBM/UserData/OS400/SQLLib/Function/jar/schema, where schema is the schema of the jar-id.
Adopted authority cannot be used for these authorities.
Syntax
>>-CALL--SQLJ.UPDATEJARINFO--(--'jar-id'--,--'class-id'--,--'jar-url'--)-->
>--------------------------------------------------------------><
Description
jar-id
The JAR identifier in the database that is to be updated.
class-id
The package qualified class name of the class to be updated.
jar-url
The URL containing the classfile to update the JAR file with. The only URL scheme supported is 'file:'.
Example
The following command is issued from an SQL interactive session:
The JAR file associated with the jar-id myproc_jar, is updated with a new version of the
mypackage.myclass class. The new version of the class is obtained from the file /home/user/mypackage/
myclass.class.
Related reference
SQLJ.INSTALL_JAR
The SQLJ.INSTALL_JAR stored procedure installs a JAR file into the database system. This JAR file can be
used in subsequent CREATE FUNCTION and CREATE PROCEDURE statements.
SQLJ.REMOVE_JAR
SQLJ.RECOVERJAR
The SQLJ.RECOVERJAR procedure takes the JAR file that is stored in the SYSJAROBJECTS catalog and
restores it to the /QIBM/UserData/OS400/SQLLib/Function/jar/jarschema/jar_id.jar file.
Authorization
The privilege held by the authorization ID of the CALL statement must include at least one of the following
for the SYSJAROBJECTS catalog table:
• The following system authorities:
– The SELECT and UPDATEINSERT privileges on the table
– The system authority *EXECUTE on library QSYS2
• Administrative authority
The user running the CALL statement must also have the following authorities:
• Write, Execute, and Read (*RWX) access to the directory where the JAR file is installed. This directory
is /QIBM/UserData/OS400/SQLLib/Function/jar/schema, where schema is the schema of the jar-id.
• *OBJMGT authority to the JAR file being removed. The JAR file is named /QIBM/UserData/OS400/
SQLLib/Function/jar/schema/jarfile.
Syntax
>>-CALL--SQLJ.RECOVERJAR--(--'jar-id'--)-----------------------><
Description
jar-id
The JAR identifier in the database that is to be recovered.
Example
The following command is issued from a SQL interactive session:
CALL SQLJ.UPDATEJARINFO('myproc_jar')
The JAR file associated with the myproc_jar is updated with the contents from SYSJARCONTENT table.
The file is copied to /QIBM/UserData/OS400/SQLLib/Function/jar/jar_schema myproc_jar.jar.
Related reference
SQLJ.INSTALL_JAR
The SQLJ.INSTALL_JAR stored procedure installs a JAR file into the database system. This JAR file can be
used in subsequent CREATE FUNCTION and CREATE PROCEDURE statements.
SQLJ.REMOVE_JAR
SQLJ.REFRESH_CLASSES
The SQLJ.REFRESH_CLASSES stored procedure causes the reloading of user defined classes used by Java
stored procedures or Java UDFs in the current database connection. This stored procedure must be called
by existing database connections to obtain changes made by a call to the SQLJ.REPLACE_JAR stored
procedure.
Authorization
NONE
Syntax
>>-CALL--SQLJ.REFRESH_CLASSES-- ()-->
>--------------------------------------------------------------><
Example
Call a Java stored procedure, MYPROCEDURE, that uses a class in a JAR file registered with the MYJAR
jarid:
CALL MYPROCEDURE()
In order for subsequence calls to the MYPROCEDURE stored procedure to use the updated JAR file,
SQLJ.REFRESH_CLASSES must be called:
CALL SQLJ.REFRESH_CLASSES()
Call the stored procedure again. The updated class files are used when the procedure is called.
CALL MYPROCEDURE()
Related reference
SQLJ.INSTALL_JAR
The SQLJ.INSTALL_JAR stored procedure installs a JAR file into the database system. This JAR file can be
used in subsequent CREATE FUNCTION and CREATE PROCEDURE statements.
SQLJ.REMOVE_JAR
The SQLJ.REMOVE_JAR stored procedure removes a JAR file from the database system.
SQLJ.REPLACE_JAR
SQL data type Java parameter style JAVA Java parameter style
DB2GENERAL
SMALLINT short short
INTEGER int int
BIGINT long long
DECIMAL(p,s) BigDecimal BigDecimal
NUMERIC(p,s) BigDecimal BigDecimal
REAL or FLOAT(p) float float
DOUBLE PRECISION or FLOAT or double double
FLOAT(p)
CHARACTER(n) String String
CHARACTER(n) FOR BIT DATA byte[] com.ibm.db2.app.Blob
VARCHAR(n) String String
VARCHAR(n) FOR BIT DATA byte[] com.ibm.db2.app.Blob
GRAPHIC(n) String String
VARGRAPHIC(n) String String
DATE Date String
TIME Time String
TIMESTAMP Timestamp String
Indicator Variable - -
CLOB java.sql.Clob com.ibm.db2.app.Clob
BLOB java.sql.Blob com.ibm.db2.app.Blob
DBCLOB java.sql.Clob com.ibm.db2.app.Clob
DataLink - -
ARRAY java.sql.Array -
Related concepts
Java stored procedures
When using Java to write stored procedures, you can use two possible parameter passing styles.
Java user-defined scalar functions
ILE Java
Members that are part of the library or file structure on Stream files in the integrated file system contain
an IBM i server store source codes. source code.
American Standard Code for Information Interchange
Source entry utility (SEU) edits extended binary-coded
(ASCII) source files are usually edited using a
decimal interchange code (EBCDIC) source files.
workstation editor.
Source files compile into object code modules, which Source code compiles into class files, which the
are stored in libraries on an IBM i server. integrated file system stores.
Object modules are statically bound together in Classes are dynamically loaded, as needed, at
programs or service programs. runtime.
You can directly call to functions that are written in Java Native Interface must be used to call other
other ILE programming languages. languages from Java.
ILE languages are always compiled and run as
Java programs can be interpreted or compiled.
machine instructions.
Note: If portability is a concern, avoid using a solution that is not "pure" Java.
Related concepts
“Java Invocation API” on page 211
The Invocation API, which is part of the Java Native Interface (JNI), allows non-Java code to create a Java
virtual machine, and load and use Java classes. This function lets a multithreaded program make use of
Java classes that are running in a single Java virtual machine in multiple threads.
“Using sockets for interprocess communication” on page 219
Sockets streams communicate between programs that are running in separate processes.
“Using input and output streams for interprocess communication” on page 222
Input and output streams communicate between programs that are running in separate processes.
Related reference
“Example: Calling Java from ILE C” on page 223
This is an example of an integrated language environment (ILE) C program that uses the system()
function to call the Java Hello program.
“Example: Calling Java from RPG” on page 224
This is an example of an RPG program that uses the QCMDEXC API to call the Java Hello program.
Related information
IBM Toolbox for Java
System.loadLibrary("Sample");
System.load("/qsys.lib/mylib.lib/Sample.srvpgm");
Note: A symbolic link to a service program can be used in these library loading methods.
• If the native methods are PASE for i native methods and the Java code loads a library named
Sample, the corresponding executable file must be an AIX library named either libSample.a or
libSample.so. The following shows how you would load the PASE for i native library:
System.loadLibrary("Sample");
System.load("/somedir/libSample.so");
2. Use the javac tool to compile the Java source into a class file.
3. Use the javah tool to create the header file (.h). This header file contains the exact prototypes for
creating the native method implementations. The -d option specifies the directory where you should
create the header file.
4. Write the C implementation code for the native method. See the “Java native methods and threads
considerations” on page 210 topic for details about the languages and functions that are used for
native methods.
a) Include the header file that was created in the previous steps.
b) Match the prototypes in the header file exactly.
c) If your native method must interact with the Java virtual machine, use the functions that are
provided with JNI.
d) For ILE native methods only, convert strings to American Standard Code for Information
Interchange (ASCII) if the strings are to be passed to the Java virtual machine. For more
information, see “Strings in ILE native methods” on page 205.
5. Compile your C implementation code for the native method into a native library.
• For ILE native methods, use the Create C Module (CRTCMOD) command to compile source files into
module objects. Then bind one or more module objects into a service program by using the Create
Service Program (CRTSRVPGM) command. The name of this service program must match the name
that you supplied in your Java code that is in the System.load() or System.loadLibrary()
Java method calls.
Note: The implementation code for the native method must be compiled with teraspace storage
enabled. For more information about teraspace and native methods, see “Teraspace storage model
native methods for Java” on page 204.
• For PASE for i native methods, use the xlc or xlc_r commands to compile and build an AIX library.
For more information about compiling and building libraries for PASE for i, see Compiling your AIX
source topic.
6. If you used the System.loadLibrary() call in your Java code to load the native library, perform one
of the following tasks:
• Include the list of the native library paths that you need in the LIBPATH environment variable. You
can change the LIBPATH environment variable in QShell and from the IBM i command line.
– From the Qshell command prompt, type in:
TERASPACE(*YES *TSIFC)
Note: If you do not use DTAMDL(*LLP64) when using teraspace storage model Java native methods,
calling a native method throws a runtime exception.
Creating teraspace storage model service programs that implement native methods
In order to create a teraspace storage model service program, use the following option on the Create
Service Program (CRTSRVPGM) control language (CL) command:
CRTSRVPGM STGMDL(*TERASPACE)
In addition, you should use the ACTGRP(*CALLER) option, which allows the JVM to activate all teraspace
storage model native method service programs into the same teraspace activation group. Using a
teraspace activation group this way can be important for native methods to efficiently handle exceptions.
For additional details on program activation and activation groups, see Chapter 3 of ILE Concepts.
Literal strings
If the string can be represented in ASCII, as most are, then the string can be bracketed by pragma
statements that change the current codepage of the compiler. Then, the compiler stores the string
internally in the UTF-8 form that is required by the JNI. If the string cannot be represented in ASCII, it is
easier to treat the original extended binary-coded decimal interchange code (EBCDIC) string as a dynamic
string, and process it using iconv() before passing it to the JNI.
#pragma convert(819)
myClass = (*env)->FindClass(env,"java/lang/String");
#pragma convert(0)
The first pragma, with the number 819, informs the compiler to store all subsequent double-quoted
strings (literal strings) in ASCII. The second pragma, with the number 0, tells the compiler to revert to the
default code page of the compiler for double-quoted strings, which is usually the EBCDIC code page 37.
So, by bracketing this call with these pragmas, we satisfy the JNI requirement that string parameters are
encoded in UTF-8.
Caution: Be careful with text substitutions. For example, if your code looks like this:
#pragma convert(819)
#define MyString "java/lang/String"
#pragma convert(0)
myClass = (*env)->FindClass(env,MyString);
Then, the resulting string is EBCDIC, because the value of MyString is substituted into the
FindClass() call during compilation. At the time of this substitution, the pragma, number 819, is not in
effect. Thus, literal strings are not stored in ASCII.
cd /ileexample
java NativeHello
Related concepts
Teraspace storage model native methods for Java
The IBM i Java virtual machine (JVM) supports the use of teraspace storage model native methods. The
teraspace storage model provides a large, process-local address environment for ILE programs. Using the
teraspace storage model allows you to port native method code from other operating systems to IBM i
with little or no source code changes.
Strings in ILE native methods
Many Java Native Interface (JNI) functions accept C language-style strings as parameters. For example,
the FindClass() JNI function accepts a string parameter that specifies the fully-qualified name of a
class file. If the class file is found, it is loaded by FindClass(), and a reference to it is returned to the
caller of FindClass().
cd /home/example
java PaseExample1
LIBPATH
/home/user1/lib32
/samples/lib32
Note: Uppercase and lowercase characters are significant only in the /QOpenSys path.
In order to search for library Sample2, the Java library loader searches for file candidates in the following
order:
1. /qsys.lib/sample2.srvpgm
2. /qsys.lib/libSample2.a
3. /qsys.lib/libSample2.so
4. /qsys.lib/qsys2.lib/sample2.srvpgm
5. /qsys.lib/qsys2.lib/libSample2.a
6. /qsys.lib/qsys2.lib/libSample2.so
7. /qsys.lib/qgpl.lib/sample2.srvpgm
8. /qsys.lib/qgpl.lib/libSample2.a
9. /qsys.lib/qgpl.lib/libSample2.so
10. /qsys.lib/qtemp.lib/sample2.srvpgm
11. /qsys.lib/qtemp.lib/libSample2.a
12. /qsys.lib/qtemp.lib/libSample2.so
13. /home/user1/lib32/sample2.srvpgm
14. /home/user1/lib32/libSample2.a
15. /home/user1/lib32/libSample2.so
16. /samples/lib32/sample2.srvpgm
17. /samples/lib32/libSample2.a
18. /samples/lib32/libSample2.so
IBM i loads the first candidate in the list that actually exists into the JVM as a native method library.
The IBM Developer Kit for Java supports the Java Invocation API for the following types of callers:
• An ILE program or service program that is enabled to work with teraspace storage. The storage model
can either be single-level storage or teraspace storage. For more information about JNI and teraspace
storage, see “Teraspace storage model native methods for Java” on page 204.
• An PASE for i executable created for either 32-bit or 64-bit AIX.
Note: The LIBPATH and LDR_CNTRL environment variables may need to be set appropriately when
running PASE for i executables.
The application controls the Java virtual machine. The application can create the Java virtual machine,
call Java methods (similar to the way in which an application calls subroutines), and destroy the Java
virtual machine. Once you create the Java virtual machine, it remains ready to run within the process until
the application explicitly destroys it. While being destroyed, the Java virtual machine performs clean-up,
such as running finalizers, ending Java virtual machine threads, and releasing Java virtual machine
resources.
With a Java virtual machine that is ready to run, an application written in ILE languages, such as C and
RPG, can call into the Java virtual machine to perform any function. It also can return from the Java virtual
machine to the C application, call into the Java virtual machine again, and so on. The Java virtual machine
is created once and does not have to be recreated before calling into the Java virtual machine to run a
little or a lot of Java code.
When using the Invocation API to run Java programs, the destination for STDOUT and STDERR
is controlled by the use of an environment variable called QIBM_USE_DESCRIPTOR_STDIO. If this
environment variable is set to Y or I (for example, QIBM_USE_DESCRIPTOR_STDIO=Y), the Java virtual
machine uses file descriptors for STDIN (fd 0), STDOUT (fd 1), and STDERR (fd 2). In this case, the
program must set these file descriptors to valid values by opening them as the first three files or pipes
in this job. The first file opened in the job is given fd of 0, the second fd of 1, and third is fd of 2. For
jobs initiated with the spawn API, these descriptors can be preassigned using a file descriptor map (see
documentation on Spawn API). If the environment variable QIBM_USE_DESCRIPTOR_STDIO is not set or
is set to any other value, file descriptors are not used for STDIN, STDOUT, or STDERR. Instead, STDOUT
and STDERR are routed to a spooled file that is owned by the current job, and use of STDIN results in an
IO exception.
Note: Message CPFB9C8 (File descriptors 0, 1, and 2 must be open to run the PASE
for i program.) will be issued if it is determined that the file descriptors for STDIN, STDOUT, and
STDERR are not set but are required to be set.
Related concepts
Native methods and the Java Native Interface
Native methods are Java methods that start in a language other than Java. Native methods can access
system-specific functions and APIs that are not available directly in Java.
Using java.lang.Runtime.exec()
Use the java.lang.Runtime.exec() method to call programs or commands from within your Java
program. Using java.lang.Runtime.exec() method creates one or more additional thread-enabled
jobs. The additional jobs process the command string that you pass on the method.
Interprocess communications
vmBuf is an output area whose size is determined by bufLen, which is the number of pointers. Each Java
virtual machine has an associated JavaVM structure that is defined in java.h. This API stores a pointer
to the JavaVM structure that is associated with each created Java virtual machine into vmBuf, unless
vmBuf is 0. Pointers to JavaVM structures are stored in the order of the corresponding Java virtual
machines that are created. nVMs returns the number of virtual machines that are currently created. Your
server supports the creation of more than one Java virtual machine, so you may expect a value higher
than one. This information, along with the size of the vmBuf, determines whether pointers to JavaVM
structures for each created Java virtual machine are returned.
• JNI_CreateJavaVM
Allows you to create a Java virtual machine and subsequently use it in an application.
Signature:
p_vm is the address of a JavaVM pointer for the newly created Java virtual machine. Several other
JNI Invocation APIs use p_vm to identify the Java virtual machine. p_env is the address of a JNI
Environment pointer for the newly created Java virtual machine. It points to a table of JNI functions that
start those functions. vm_args is a structure that contains Java virtual machine initialization parameters.
If you start a Run Java (RUNJVA) command or JAVA command and specify a property that has an
equivalent command parameter, then the command parameter takes precedence. The property is
ignored.
For a list of unique properties that are supported by the JNI_CreateJavaVM API, see “Java system
properties” on page 14.
Note: Java on IBM i supports creating only one Java virtual machine (JVM) within a single job or
process. For more information, see “Support for multiple Java virtual machines” on page 213
• DestroyJavaVM
Destroys the Java virtual machine.
Signature:
When the Java virtual machine is created, vm is the JavaVM pointer that is returned.
• AttachCurrentThread
The JavaVM pointer, vm, identifies the Java virtual machine to which the thread is being attached. p_env
is the pointer to the location where the JNI Interface pointer of the current thread is placed. thr_args
contains VM specific thread attachment arguments.
• DetachCurrentThread
Signature:
vm identifies the Java virtual machine from which the thread is being detached.
Java Native Interface by Oracle.
Any job that creates a Java virtual machine must be multithread-capable. The output from the main
program, as well as any output from the program, ends up in QPRINT spooled files. These spooled files
#define OS400_JVM_12
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <jni.h>
#pragma convert(819)
/* Procedure: Oops
*
* Description: Helper routine that is called when a JNI function
* returns a zero value, indicating a serious error.
* This routine reports the exception to stderr and
* ends the JVM abruptly with a call to FatalError.
*
* Parameters: env -- JNIEnv* to use for JNI calls
* msg -- char* pointing to error description in UTF-8
*
* Note: Control does not return after the call to FatalError
* and it does not return from this procedure.
*/
/* Set the version field of the initialization arguments for JNI v1.4. */
initArgs.version = 0x00010004;
/* Now, you want to specify the directory for the class to run in the classpath.
* with Java2, classpath is passed in as an option.
* Note: You must specify the directory name in UTF-8 format. So, you wrap
* blocks of code in #pragma convert statements.
*/
options[0].optionString="-Djava.class.path=/CrtJvmExample";
/* Now, get the method identifier for the 'main' entry point
* of the class.
* Note: The signature of 'main' is always the same for any
* class called by the following java command:
* "main" , "([Ljava/lang/String;)V"
*/
mainID = (*myEnv)->GetStaticMethodID(myEnv,myClass,"main",
"([Ljava/lang/String;)V");
if (! mainID) {
Oops(myEnv, "Failed to find jmethodID of 'main'");
}
/* Now, you have the methodID of main and the class, so you can
* call the main method.
*/
(*myEnv)->CallStaticVoidMethod(myEnv,myClass,mainID,args);
/* All done. */
return 0;
}
Related concepts
Native methods and the Java Native Interface
Native methods are Java methods that start in a language other than Java. Native methods can access
system-specific functions and APIs that are not available directly in Java.
Java Invocation API
The Invocation API, which is part of the Java Native Interface (JNI), allows non-Java code to create a Java
virtual machine, and load and use Java classes. This function lets a multithreaded program make use of
Java classes that are running in a single Java virtual machine in multiple threads.
Interprocess communications
When communicating with programs that are running in another process, there are a number of options.
import java.io.*;
System.out.println("CallHelloPgm.main() invoked");
Related reference
Example: Calling a CL program with java.lang.Runtime.exec()
This example shows how to run CL programs from within a Java program. In this example, the Java class
CallCLPgm runs a CL program.
Example: Calling a CL command with java.lang.Runtime.exec()
This example shows how to run a control language (CL) command from within a Java program.
import java.io.*;
PGM
DSPJVMJOB OUTPUT(*PRINT)
ENDPGM
Runtime.getRuntime().exec("system CLCOMMAND");
import java.io.*;
Related concepts
“Using java.lang.Runtime.exec()” on page 216
Use the java.lang.Runtime.exec() method to call programs or commands from within your Java
program. Using java.lang.Runtime.exec() method creates one or more additional thread-enabled
jobs. The additional jobs process the command string that you pass on the method.
“List of Java system properties” on page 15
Java system properties determine the environment in which the Java programs run. They are like system
values or environment variables in IBM i.
Related reference
Example: Calling another Java program with java.lang.Runtime.exec()
This example shows how to call another Java program with java.lang.Runtime.exec(). This class
calls the Hello program that is shipped as part of the IBM Developer Kit for Java. When the Hello class
writes to System.out, this program gets a handle to the stream and can read from it.
Example: Calling a CL program with java.lang.Runtime.exec()
Interprocess communications
When communicating with programs that are running in another process, there are a number of options.
One option is to use sockets for interprocess communication. One program can act as the server program
that listens on a socket connection for input from the client program. The client program connects to
the server with a socket. Once the socket connection is established, either program can send or receive
information.
Another option is to use stream files for communication between programs. To do this, use the System.in,
System.out, and System.err classes.
A third option is to use the IBM Toolbox for Java, which provides data queues and IBM i message objects.
You can also call Java from other languages, as demonstrated in the examples below.
Related concepts
Native methods and the Java Native Interface
Native methods are Java methods that start in a language other than Java. Native methods can access
system-specific functions and APIs that are not available directly in Java.
Java Invocation API
The Invocation API, which is part of the Java Native Interface (JNI), allows non-Java code to create a Java
virtual machine, and load and use Java classes. This function lets a multithreaded program make use of
Java classes that are running in a single Java virtual machine in multiple threads.
Using java.lang.Runtime.exec()
Use the java.lang.Runtime.exec() method to call programs or commands from within your Java
program. Using java.lang.Runtime.exec() method creates one or more additional thread-enabled
jobs. The additional jobs process the command string that you pass on the method.
Related information
IBM Toolbox for Java
import java.net.*;
import java.io.*;
class TalkToC
{
private String host = null;
private int port = -999;
private Socket socket = null;
private BufferedReader inStream = null;
try
{
socket = new Socket(host, port);
inStream = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
}
catch(UnknownHostException e)
{
System.err.println("Cannot find host called: " + host);
e.printStackTrace();
System.exit(-1);
}
catch(IOException e)
{
System.err.println("Could not establish connection for " + host);
e.printStackTrace();
System.exit(-1);
}
}
SockServ.C starts by passing in a parameter for the port number. For example, CALL SockServ '2001'.
Source code for SockServ.C server program
Note: Read the Code example disclaimer for important legal information.
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <unistd.h>
#include <sys/time.h>
memset(&local_Address,0x00,sizeof(local_Address));
local_Address.sin_family = AF_INET;
local_Address.sin_port = htons(portNum);
local_Address.sin_addr.s_addr = htonl(INADDR_ANY);
/* allocate socket */
if((server = socket(AF_INET, SOCK_STREAM, 0))<0)
{
printf("failure on socket allocation\n");
perror(NULL);
exit(-1);
}
/* do bind */
if((bndrc=bind(server,(struct sockaddr*)&local_Address, address_len))<0)
{
printf("Bind failed\n");
perror(NULL);
/* invoke listen */
listen(server, 1);
close(client);
close(server);
}
import java.io.*;
System.out.println("CallPgm.main() invoked");
#include <stdio.h>
#include <stdlib.h>
fflush(stdout);
}
#include <stdlib.h>
int main(void)
{
int result;
Related concepts
Using sockets for interprocess communication
Sockets streams communicate between programs that are running in separate processes.
Using input and output streams for interprocess communication
Input and output streams communicate between programs that are running in separate processes.
Related reference
Example: Calling Java from RPG
This is an example of an RPG program that uses the QCMDEXC API to call the Java Hello program.
Related concepts
Using sockets for interprocess communication
Sockets streams communicate between programs that are running in separate processes.
Using input and output streams for interprocess communication
Input and output streams communicate between programs that are running in separate processes.
Related reference
Example: Calling Java from ILE C
This is an example of an integrated language environment (ILE) C program that uses the system()
function to call the Java Hello program.
Java platform
The Java platform is the environment for developing and managing Java applets and applications. It
consists of three primary components: the Java language, the Java packages, and the Java virtual
machine.
The Java language and packages are similar to C++ and its class libraries. The Java packages contain
classes, which are available in any compliant Java implementation. The application programming
interface (API) should be the same on any system that supports Java.
Java differs from a traditional language, like C++, in the way it compiles and runs. In a traditional
programming environment, you write and compile source code of a program into object code for a specific
hardware and operating system. The object code binds to other object code modules to create a running
program. The code is specific for a particular set of computer hardware and does not run on other systems
without being changed. This figure illustrates the traditional language deployment environment.
For more information, see Writing Applets , Oracle's tutorial for Java applets. It includes an overview of
applets, directions for writing applets, and some common applet problems.
Applications are stand-alone programs that do not require the use of a browser. Java applications run by
starting the Java interpreter from the command line and by specifying the file that contains the compiled
application. Applications usually reside on the system on which they are deployed. Applications access
resources on the system, and are restricted by the Java security model.
Related concepts
Java virtual machine
The Java virtual machine is a runtime environment that you can add into a web browser or any operating
system, such as IBM i. The Java virtual machine runs instructions that a Java compiler generates.
It consists of a bytecode interpreter and runtime that allow Java class files to run on any platform,
regardless of the platform on which they were originally developed.
Java JAR and class files
A Java ARchive (JAR) file is a file format that combines many files into one. The Java environment differs
from other programming environments in that the Java compiler does not generate machine code for a
hardware-specific instruction set. Instead, the Java compiler converts Java source code into Java virtual
machine instructions, which Java class files store. You can use JAR files to store class files. The class file
does not target a specific hardware platform, but instead targets the Java virtual machine architecture.
Java threads
A thread is a single independent stream that runs within a program. Java is a multithreaded programming
language, so more than one thread may be running within the Java virtual machine at one time. Java
threads provide a way for a Java program to perform multiple tasks at the same time. A thread is
essentially a flow of control in a program.
Java Development Kit
The Java Development Kit (JDK) is software for Java developers. It includes the Java interpreter, Java
classes, and Java development tools: compiler, debugger, disassembler, appletviewer, stub file generator,
and documentation generator.
It is also possible to start the Java runtime environment by using the java command in Qshell from the
Qshell Interpreter. In this environment, the Qshell Interpreter is running in a BCI job that is associated
with an interactive job. The Java runtime environment starts in the job that is running the Qshell
Interpreter.
Figure 2: The Java environment when using the java command in Qshell
Java interpreter
The Java interpreter is the part of the Java virtual machine that interprets Java class files for a particular
hardware platform. The Java interpreter decodes each bytecode and performs the corresponding
operation.
Related concepts
Java applets and applications
An applet is a Java program designed to be included in an HTML Web document. You can write your Java
applet and include it in an HTML page, much in the same way an image is included. When you use a
Java-enabled browser to view an HTML page that contains an applet, the applet's code is transferred to
your system and is run by the browser's Java virtual machine.
Java JAR and class files
A Java ARchive (JAR) file is a file format that combines many files into one. The Java environment differs
from other programming environments in that the Java compiler does not generate machine code for a
hardware-specific instruction set. Instead, the Java compiler converts Java source code into Java virtual
machine instructions, which Java class files store. You can use JAR files to store class files. The class file
does not target a specific hardware platform, but instead targets the Java virtual machine architecture.
Java threads
A thread is a single independent stream that runs within a program. Java is a multithreaded programming
language, so more than one thread may be running within the Java virtual machine at one time. Java
threads provide a way for a Java program to perform multiple tasks at the same time. A thread is
essentially a flow of control in a program.
Java Development Kit
The Java Development Kit (JDK) is software for Java developers. It includes the Java interpreter, Java
classes, and Java development tools: compiler, debugger, disassembler, appletviewer, stub file generator,
and documentation generator.
Running an PASE for i program with QP2TERM()
“Invocation API functions” on page 212
The IBM Developer Kit for Java supports these Invocation API functions.
Java threads
A thread is a single independent stream that runs within a program. Java is a multithreaded programming
language, so more than one thread may be running within the Java virtual machine at one time. Java
threads provide a way for a Java program to perform multiple tasks at the same time. A thread is
essentially a flow of control in a program.
Threads are a modern programming construct that are used to support concurrent programs and
to improve the performance and scalability of applications. Most programming languages support
threads through the use of add-in programming libraries. Java supports threads as built-in application
programming interfaces (APIs).
Note: The use of threads provides the support to increase the interactivity, meaning a shorter wait at the
keyboard because more tasks are running in parallel. But, the program is not necessarily more interactive
just because it has threads.
Threads are the mechanism for waiting on long running interactions, while still allowing the program to
handle other work. Threads have the ability to support multiple flows through the same code stream.
They are sometimes called lightweight processes. The Java language includes direct support for threads.
But, by design, it does not support asynchronous non-blocking input and output with interrupts or
multiple wait.
Threads allow the development of parallel programs that scale well in an environment where a machine
has multiple processors. If properly constructed, they also provide a model for handling multiple
transactions and users.
You can use threads in a Java program for a number of situations. Some programs must be able to engage
in multiple activities and still be able to respond to additional input from the user. For example, a Web
browser should be able to respond to user input while playing a sound.
Threads can also use asynchronous methods. When you call a second method, you do not have to wait for
the first method to complete before the second method continues with its own activity.
There are also many reasons not to use threads. If a program uses inherently sequential logic, one thread
can accomplish the entire sequence. Using multiple threads in such a case results in a complex program
with no benefits. There is considerable work in creating and starting a thread. If an operation involves only
a few statements, it is faster to handle it in a single thread. This can be true even when the operation
is conceptually asynchronous. When multiple threads share objects, the objects must synchronize to
Then, look for the same version of Oracle. JDK at The Source for Java Technology for specific
documentation. The IBM Developer Kit for Java is a compatible implementation of the Oracle Java
Technology, so you should be familiar with their JDK documentation.
Java packages
A Java package is a way of grouping related classes and interfaces in Java. Java packages are similar to
class libraries that are available in other languages.
The Java packages, which provide the Java APIs, are available as part of Oracle Java Development Kit
(JDK). For a complete list of Java packages and information on Java APIs, see Java 2 Platform Packages.
Advanced topics
This topic provides instructions on how to run Java in a batch job and describes the Java file authorities
required in the integrated file system to display, run, or debug a Java program.
package classes.geometry;
import java.awt.Dimension;
Dimension metrics;
// The implementation for the Shape class would be coded here ...
The package statement in the previous code indicates that the Shape class is part of the classes.geometry
package. For the Java runtime to find the Shape class, store the Shape class in the relative directory
structure classes/geometry.
Note: The package name corresponds to the relative directory name in which the class resides. The Java
virtual machine class loader finds the class by appending the relative path name to each directory that
you specify in the classpath. The Java virtual machine class loader can also find the class by searching the
ZIP files or JAR files that you specify in the classpath.
For example, when you store the Shape class in the /Product/classes/geometry directory in the "root" (/)
file system, you need to specify /Product in the classpath.
Figure 1: Example directory structure for Java classes of the same name in different packages
Note: Multiple versions of the Shape class can exist in the directory structure. To use the Beta version
of the Shape class, place /Beta/myclasses in the classpath before any other directories or ZIP files that
contain the Shape class.
Running your Java application on a host that does not have a GUI
If you want to run your Java application on a host that does not have a graphical user interface (GUI), such
as an IBM i server, you can use the Native Abstract Windowing Toolkit (NAWT).
Use NAWT to provide your Java applications and servlets with the full capability of the Java 2 Platform,
Standard Edition (J2SE) AWT graphics functionality.
Normal Mode
Normal mode must be used if your application uses the Java AWT API to display windows, frames, dialog
boxes, or similar heavyweight components. Use normal mode if you expect your application to receive
mouse operation events or keyboard input. Normal mode is the default mode and nothing needs to be
specified to enable it.
Headless mode
Headless mode can be used if your Java application does not interact directly with a user. This means
that your Java application does not display windows or dialog boxes, does not accept keyboard or mouse
input, and does not use any heavyweight AWT components. This mode is selected by specifying Java
property java.awt.headless=true on the Java invocation. By using headless mode, you avoid the need for a
VNC/X-server.
Examples of applications that can use headless mode include:
• Servlets or other server based programs that only use the AWT API to create images to be included in a
data stream returned to a remote user
• Any program that only creates or manipulates images or image files without actually displaying them
using heavyweight AWT components
The default value for the Java property java.awt.headless is false.
Using AWT in normal mode with full graphical user interface support
In order to support a graphical user interface, a windowing system is required. The supported choice for
IBM i Java is the Virtual Network Computing (VNC) server. The VNC server is well-suited to the system
because it does not require a dedicated mouse, keyboard, and graphics-capable monitor. IBM provides a
version of the VNC server that runs in PASE for i. Follow these instructions to ensure that VNC is installed,
started, and your Java session is configured to use it.
Before you can test or begin using AWT, perform the following required and optional steps:
• Create a VNC password. This is required one time for each user profile that will be used to start a VNC
server.
• Start the VNC server, typically after each system IPL.
• Configure AWT environment variables, once in each session before the first time you run Java and use
the AWT API.
• Configure Java system properties. This must be done each time you run Java.
• Optional, for interactive use: Configure the iceWM window manager
• Optional, for direct interaction with a user: Use a VNC viewer or web browser to connect to VNC
• Optional: Verify your AWT configuration
where systemname is the host name or IP address of your system and n is the display number of the VNC
server to be used.
STRPTL CLIENT(IGNORE)
The IGNORE value functions as a placeholder that ensures the command activates only the
configuration features of STRPTL that NAWT requires.
2. Type the following command and press ENTER to sign off:
SIGNOFF
Signing off ensures that any session-specific results of the STRPTL command do not affect subsequent
actions that you perform to use or configure NAWT.
Note: Run the STRPTL command only once for each profile that starts a VNC server. NAWT does not
require any of the available optional arguments for the command. These statements override any setup
instructions for STRPTL associated with the 5799-PTL IBM i Tools For Developers PRPQ.
Disabling iceWM
Starting the VNC server creates or modifies an existing script file called xstartup_java that contains
the command to run iceWM. The xstartup_java script file resides in the following integrated file system
directory:
/home/VNCprofile/.vnc/
where VNCprofile is the name of the profile that started the VNC server.
To completely disable iceWM, use a text editor to either comment out or remove the line in the script that
starts iceWM. To comment out the line, insert a pound sign character (#) at the beginning of the line.
• VNC viewers are available for most platforms from the RealVNC Web site
http://systemname:58nn
where:
• systemname is the name or IP address of the system that is running the VNC server
• nn is the 2-digit representation of the VNC server display number
For example, when the system name is system_one and the display number is 2, the URL is:
http://system_one:5802
2. Successfully accessing the URL displays a prompt for the VNC server password. At the password
prompt, type the VNC password to gain access to the VNC server display.
where:
• systemname is the host name or IP address of the system where VNC is running
• n is the numeric value that represents the display number that you want to start
Note: The example assumes that you are not already running display :n and that you have successfully
created the required VNC password file. For more information about creating a password file, see Creating
a VNC password file.
where n is the numeric value that represents the display number that you want to terminate.
CALL QP2TERM
The resulting output from this command will reveal running VNC servers in the following format:
Where:
• The first column is the profile which started the server.
• The second column is the process ID of the server.
• The information starting with /QOpensys/ is the command that started the VNC server (including
arguments). The display number typically is the first item in the argument list for the Xvnc command.
Note: The Xvnc process, shown in the previous example output, is the name of the actual VNC server
program. You start Xvnc when you run the vncserver_java script, which prepares the environment and
parameters for Xvnc and then starts Xvnc.
where VNCprofile and WASprofile are the appropriate profiles under which you are running the VNC
server and WebSphere Application Server.
Note: You should only follow these steps when the VNCprofile and WASprofile are different profiles.
Following these steps when VNCprofile and WASprofile are the same profile can cause VNC to not
function correctly.
3. From the WebSphere Application Server administrative console, define the DISPLAY and XAUTHORITY
environment variables for your application:
• For DISPLAY, use either: system:n or localhost:n
where system is the name or IP address of your system and n is the display number that you used to
start the VNC server.
• For XAUTHORITY, use: /home/VNCprofile/.Xauthority
where VNCprofile is the profile that started the VNC server.
4. Pick up the configuration changes by restarting WebSphere Application Server.
WebSphere Application Server for IBM i
Or
The test program creates a JPEG-encoded image and saves it to the following path in the integrated file
system:
/tmp/NAWTtest.jpg
After you run the test program, check to ensure that the test program created the file and produced no
Java exceptions. To display the image, use binary mode to upload the image file to a graphics-capable
system and display it with a browser, paint program, or similar tool.
Java security
This topic provides details on adopted authority and explains how you can use SSL to make socket
streams secure in your Java application.
Java applications are subject to the same security restrictions as any other program on the IBM i platform.
To run a Java program on a IBM i server, you must have authority to the class file in the integrated file
system. Once the program starts, it runs under the user's authority.
The majority of the Java programs that run on a IBM i server are applications, not applets, so the
"sandbox" security model does not restrict them.
The output from the tool can help you determine what Java applications on your system are using
adopted authority. Using this information, you may need to do the following:
• If the usage is in code that you have purchased, contact the vendor to find out what their plans are
relative to adopted authority.
• If the usage is in your code, read through the solutions outlined in this document, and see if you are
willing and able to modify your code to no longer use adopted authority.
In this example, IBM Java method J is contained in a Java program, which adopts user profile P and
directly calls native method X. Native method X calls ILE method Y, which requires the adopted authority.
JA61Example1.java
static {
System.loadLibrary("EX1");
}
}
JA61Example1.h
#ifndef _Included_JA61Example1
#define _Included_JA61Example1
#ifdef __cplusplus
}
#endif
#endif
JA61Example1.c
/* This contains the source code for native method Java_JA61Example1_X. This
module is bound into service program JADOPT61/EX1. */
#include "JA61Example1.h"
#include "JA61ModuleY.h"
/*
* Class: JA61Example1
* Method: X
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_JA61Example1_X(JNIEnv* env, jclass klass) {
return methodY();
}
JA61ModuleY.h
JA61ModuleY.c
#include <except.h>
#include <stdio.h>
#include "JA61ModuleY.h"
#include <xxdtaa.h>
#define START 1
#define LENGTH 8
ChangeCompleted:
printf("Successfully updated data area\n");
returnValue = 1;
goto TestComplete;
TestComplete:
printf("methodY completed\n");
return returnValue;
}
One way to preserve authority adoption is to separate native method X into a new service program. That
new service program may then adopt user profile P, which was previously adopted by Java method J.
JA61Alternative1A.java
static {
System.loadLibrary("ALT1A");
}
}
JA61Alternative1A.h
#ifndef _Included_JA61Alternative1A
#define _Included_JA61Alternative1A
#ifdef __cplusplus
}
#endif
#endif
JA61Alternative1A.c
/* This contains the source code for native method Java_JA61Alternative1A_X. This
module is bound into service program JADOPT61/ALT1A.*/
#include "JA61Alternative1A.h"
#include "JA61ModuleY.h"
/*
* Class: JA61Alternative1A
* Method: X
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_JA61Alternative1A_X(JNIEnv* env, jclass klass) {
return methodY();
}
Another way to preserve user profile adoption is to create an entirely new native method N contained in a
service program which adopts user profile P. This new method is called by Java method J and calls native
method X. Java method J would need to be changed to call N instead of X, but native method X would not
need to be changed or repackaged.
JA61Alternative1B.java
static {
System.loadLibrary("ALT1B");
}
}
#ifndef _Included_JA61Alternative1B
#define _Included_JA61Alternative1B
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: JA61Alternative1B
* Method: N
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_JA61Alternative1B_N
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif
JA61Alternative1B.c
/* This contains the source code for native method Java_JA61Alternative1B_N. This
module is bound into service program JADOPT61/ALT1B. */
#include "JA61Alternative1B.h"
#include "JA61Example1.h"
/*
* Class: JA61Alternative1B
* Method: N
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_JA61Alternative1B_N(JNIEnv* env, jclass klass) {
return Java_JA61Example1_X(env, klass); /* from JA61Example1.h */
}
In this example, an IBM Java method J1 is contained in a Java program which adopts user profile P. J1
and calls Java method J2, which calls J3, which then calls native method X. Native method X calls ILE
method Y, which requires the adopted authority.
JA61Example2.java
static {
System.loadLibrary("EX2ALLOW");
}
}
JA61Example2Allow.h
#ifndef _Included_JA61Example2Allow
#define _Included_JA61Example2Allow
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: JA61Example2Allow
* Method: X
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_JA61Example2Allow_X
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif
JA61Example2Allow.c
/* This contains the source code for native method Java_JA61Example2Allow_X. This
module is bound into service program JADOPT61/EX2ALLOW. */
#include "JA61Example2Allow.h"
#include "JA61ModuleY.h"
/*
* Class: JA61Example2Allow
* Method: X
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_JA61Example2Allow_X(JNIEnv* env, jclass klass) {
return methodY();
}
In order to preserve adopted authority in this case, a new native method N may be created. This native
method would be contained in a service program that adopts user profile P.
Native method N would then use JNI to call Java method J2, which is unchanged. Java method J1 would
need to be changed to call native method N instead of Java method J2.
JA61Alternative2.java
static {
System.loadLibrary("ALT2");
}
JA61Alternative2.h
#ifndef _Included_JA61Alternative2
#define _Included_JA61Alternative2
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: JA61Alternative2
* Method: N
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_JA61Alternative2_N
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif
JA61Alternative2.C
include "JA61Alternative2.h"
/*
* Class: JA61Alternative2
* Method: N
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_JA61Alternative2_N(JNIEnv* env, jclass klass) {
#pragma convert(819)
char* className = "JA61Example2Allow";
char* methodName = "J2";
char* methodSig = "()I";
#pragma convert(0)
> cd /home/javatests/adoptup/v6r1mig
> javac -g *.java
From CL:
Create “Example 1: Java method adopts authority immediately before calling a native method” on page
243:
Create “Example 2: Java method adopts authority and calls other Java methods before calling a native
method” on page 249
For a general overview of JCE, see Oracle's documentation of JCE . The documents at this Web site
contain links to many other Web-based information sources.
IBM provides the following JCE providers on IBM i:
IBMJCE
The default JCE provider.
IBMJCEFIPS
A JCE provider implementation evaluated against FIPS 140. For more information about the
IBMJCEFIPS JCE provider, see "Security information" on the IBM developerWorks® Web site.
IBMJCECCAI5OS
A JCE provider implementation that extends JCE to use cryptographic hardware via the IBM Common
Cryptographic Architecture Interface. For more information about the IBMJCECCAI5OS JCE provider,
see “Using hardware cryptography” on page 256.
Related concepts
Changes to adopted authority in IBM i 7.2
Support for adopted user profile authority through Java programs is not supported in IBM i 7.2. This
topic describes how to determine if your applications are using adopted authority and how to modify your
applications to accommodate this change.
Java security model
You can download Java applets from any system; thus, security mechanisms exist within the Java virtual
machine to protect against malicious applets. The Java runtime system verifies the bytecodes as the Java
virtual machine loads them. This ensures that they are valid bytecodes and that the code does not violate
any of the restrictions that the Java virtual machine places on Java applets.
Java Secure Socket Extension
Java Secure Socket Extension (JSSE) is like a framework that abstracts the underlying mechanisms
of both Secure Sockets Layer (SSL) and Transport Layer Security (TLS). By abstracting the complexity
and peculiarities of the underlying protocols, JSSE enables programmers to use secure encrypted
communications while at the same time minimizing possible security vulnerabilities. Java Secure
Socket Extension (JSSE) uses both the SSL protocol and the TLS protocol to provide secure encrypted
communications between your clients and servers.
Java Authentication and Authorization Service
The Java Authentication and Authorization Service (JAAS) is a standard extension to the Java 2 Platform,
Standard Edition (J2SE). J2SE provides access controls that are based on where the code originated
and who signed the code (code source-based access controls). It lacks, however, the ability to enforce
additional access controls based on who runs the code. JAAS provides a framework that adds this support
to the Java 2 security model.
IBM Java Generic Security Service (JGSS)
The IBMJCECCAI5OS provider also includes a strong Pseudo Random Number Generator (PRNG), key
generation via key factories, key/certificate generation and key/certificate management via a keytool
application.
The hardware cryptographic access provider is available using the hwkeytool application.
Note: The IBMJCECCAI5OS provider cannot be added to the JVM by using the insertProviderAt() and the
addProviderAt() methods.
import javax.net.*;
SocketFactory socketFactory
3. Initialize the SocketFactory instance by setting it equal to the method SocketFactory.getDefault(). For
example:
socketFactory = SocketFactory.getDefault();
4. Initialize your existing sockets. Call the SocketFactory method createSocket(host,port) on your socket
factory for each socket you declare.
Your socket declarations should now look like this:
Socket s = socketFactory.createSocket(host,port);
Where:
• s is the socket that is being created.
• socketFactory is the SocketFactory that was created in step 2.
• host is a string variable that represents the name of a host server.
• port is an integer variable that represents the port number of the socket connection.
When you have completed all of these steps, your code uses socket factories. You do not need to make
any other changes to your code. All of the methods that you call and all the syntax with your sockets still
work.
/* File simpleSocketServer.java*/
import java.net.*;
import java.io.*;
if (args.length < 1) {
System.out.println("java simpleSocketServer serverPort");
System.out.println("Defaulting to port 3000 since serverPort not specified.");
}
else
serverPort = new Integer(args[0]).intValue();
ServerSocket serverSocket =
new ServerSocket(serverPort);
// a real server would handle more than just one client like this...
Socket s = serverSocket.accept();
BufferedInputStream is = new BufferedInputStream(s.getInputStream());
BufferedOutputStream os = new BufferedOutputStream(s.getOutputStream());
int bytesRead;
s.close();
serverSocket.close();
} // end main()
/* File factorySocketServer.java */
if (args.length < 1) {
System.out.println("java simpleSocketServer serverPort");
System.out.println("Defaulting to port 3000 since serverPort not specified.");
}
else
serverPort = new Integer(args[0]).intValue();
// a real server would handle more than just one client like this...
Socket s = serverSocket.accept();
BufferedInputStream is = new BufferedInputStream(s.getInputStream());
BufferedOutputStream os = new BufferedOutputStream(s.getOutputStream());
int bytesRead;
s.close();
serverSocket.close();
}
Related reference
Examples: Changing your Java code to use client socket factories
These examples show you how to change a simple socket class, named simpleSocketClient, so that it
uses socket factories to create all of the sockets. The first example shows you the simpleSocketClient
class without socket factories. The second example shows you the simpleSocketClient class with socket
factories. In the second example, simpleSocketClient is renamed to factorySocketClient.
import java.net.*;
import java.io.*;
if (args.length < 1) {
System.out.println("java simpleSocketClient serverHost serverPort");
System.out.println("serverPort defaults to 3000 if not specified.");
return;
}
if (args.length == 2)
serverPort = new Integer(args[1]).intValue();
if (args.length < 1) {
System.out.println("java factorySocketClient serverHost serverPort");
System.out.println("serverPort defaults to 3000 if not specified.");
return;
}
if (args.length == 2)
serverPort = new Integer(args[1]).intValue();
// Now the factory creates the socket. This is the last change
// to the original simpleSocketClient program.
Related reference
Examples: Changing your Java code to use server socket factories
These examples show you how to change a simple socket class, named simpleSocketServer, so that it
uses socket factories to create all of the sockets. The first example shows you the simpleSocketServer
class without socket factories. The second example shows you the simpleSocketServer class with socket
factories. In the second example, simpleSocketServer is renamed to factorySocketServer.
import javax.net.ssl.*;
3. Use your new SocketFactory to initialize your sockets the same way that you used your old
SocketFactory:
Your code now uses SSL support. You do not need to make any other changes to your code.
/* File factorySocketServer.java */
// need to import javax.net to pick up the ServerSocketFactory class
import javax.net.*;
import java.net.*;
import java.io.*;
if (args.length < 1) {
System.out.println("java simpleSocketServer serverPort");
System.out.println("Defaulting to port 3000 since serverPort not specified.");
}
else
serverPort = new Integer(args[0]).intValue();
// a real server would handle more than just one client like this...
Socket s = serverSocket.accept();
BufferedInputStream is = new BufferedInputStream(s.getInputStream());
BufferedOutputStream os = new BufferedOutputStream(s.getOutputStream());
int bytesRead;
s.close();
serverSocket.close();
}
}
/* File factorySocketServer.java */
if (args.length < 1) {
System.out.println("java simpleSocketServer serverPort");
System.out.println("Defaulting to port 3000 since serverPort not specified.");
}
else
serverPort = new Integer(args[0]).intValue();
// a real server would handle more than just one client like this...
Socket s = serverSocket.accept();
BufferedInputStream is = new BufferedInputStream(s.getInputStream());
BufferedOutputStream os = new BufferedOutputStream(s.getOutputStream());
int bytesRead;
s.close();
serverSocket.close();
}
}
Related reference
Examples: Changing your Java client to use secure sockets layer
These examples show you how to change one class, named factorySocketClient, to use secure sockets
layer (SSL). The first example shows you the factorySocketClient class not using SSL. The second example
shows you the same class, renamed factorySSLSocketClient, using SSL.
import javax.net.*;
import java.net.*;
import java.io.*;
if (args.length < 1) {
System.out.println("java factorySocketClient serverHost serverPort");
System.out.println("serverPort defaults to 3000 if not specified.");
return;
}
if (args.length == 2)
serverPort = new Integer(args[1]).intValue();
if (args.length < 1) {
System.out.println("java factorySSLSocketClient serverHost serverPort");
System.out.println("serverPort defaults to 3000 if not specified.");
return;
}
if (args.length == 2)
serverPort = new Integer(args[1]).intValue();
Related reference
Examples: Changing your Java server to use secure sockets layer
These examples show you how to change one class, named factorySocketServer, to use secure sockets
layer (SSL).
java -Dos400.certificateContainer=YOURDCC
-Dos400.certificateLabel=MYCERTIFICATE MyClass
If you have not already decided which digital certificate to use, see “Selecting a digital certificate” on page
265. You may also decide to use your system's default certificate, which is stored in the system's default
certificate container.
To use your system's default digital certificate, you do not need to specify a certificate or a certificate
container anywhere. Your Java application uses your system's default digital certificate automatically.
os400.certificateLabel=
For example, if the name of the certificate you want to use is MYCERTIFICATE, then the java command
you enter would look like this:
In this example, the Java application MyClass would use the certificate MYCERTIFICATE. MYCERTIFICATE
would need to be in the system's default certificate container to be used by MyClass.
os400.certificateContainer=
For example, if the name of the certificate container that contains the digital certificate you want to use is
named MYDCC, then the java command you enter would look like this:
In this example, the Java application, named MyClass.class, would run on the system by using the default
digital certificate that is in the digital certificate container named MYDCC. Any sockets that you create in
the application use the default certificate that is in MYDCC to identify themselves and make all of their
communications secure.
If you wanted to use the digital certificate MYCERTIFICATE in the digital certificate container, then the
java command that you would enter would look like this:
java -Dos400.certificateContainer=MYDCC
-Dos400.certificateLabel=MYCERTIFICATE MyClass
Related information
Digital Certificate Manager
Security managers
If you are running your JSSE application with a Java security manager enabled, you may need to set the
available network permissions. For more information, see SSL Permission in Permissions in the Java 2
SDK .
JSSE providers
IBM JSSE includes a native IBM i JSSE provider and an IBM pure Java JSSE provider. The provider that
you choose to use depends on the needs of your application.
All providers adhere to the JSSE interface specification. They can communicate with each other and with
any other SSL or TLS implementation, even non-Java implementations.
security.provider.5=com.ibm.i5os.jsse.JSSEProvider
security.provider.6=com.ibm.jsse2.IBMJSSEProvider2
ssl.KeyManagerFactory.algorithm
Specifies the default KeyManagerFactory algorithm. For the native IBM i JSSE provider, use the
following:
ssl.KeyManagerFactory.algorithm=IbmISeriesX509
ssl.KeyManagerFactory.algorithm=IbmX509
For the Oracle America, Inc. pure Java JSSE provider, use the following:
ssl.KeyManagerFactory.algorithm=SunX509
ssl.TrustManagerFactory.algorithm=IbmISeriesX509
For the IBM pure Java JSSE provider, use the following:
ssl.TrustManagerFactory.algorithm=IbmX509
ssl.SocketFactory.provider=com.ibm.i5os.jsse.JSSESocketFactory
For the IBM pure Java JSSE provider, use the following:
ssl.SocketFactory.provider=com.ibm.jsse2.SSLSocketFactoryImpl
ssl.ServerSocketFactory.provider=com.ibm.i5os.jsse.JSSEServerSocketFactory
ssl.ServerSocketFactory.provider=com.ibm.jsse2.SSLServerSocketFactoryImpl
Properties that work for the native IBM i JSSE provider only
The following properties apply to the native IBM i JSSE provider only.
os400.secureApplication
The application identifier. JSSE uses this property only when you do not specify any of the
following properties:
• javax.net.ssl.keyStore
• javax.net.ssl.keyStorePassword
• javax.net.ssl.keyStoreType
• javax.net.ssl.trustStore
• javax.net.ssl.trustStorePassword
• javax.ssl.net.trustStoreType
os400.certificateContainer
The name of the keyring that you want to use. JSSE uses this property only when you do not
specify any of the following properties:
• javax.net.ssl.keyStore
• javax.net.ssl.keyStorePassword
• javax.net.ssl.keyStoreType
• javax.net.ssl.trustStore
• javax.net.ssl.trustStorePassword
• javax.ssl.net.trustStoreType
• os400.secureApplication
java.lang.Object
|
+--com.ibm.i5os.keystore.i5OSLoadStoreParameter
This class creates a KeyStore.ProtectionParameter object that can be used to load/store i5OS certificate
stores. Once created, this class provides information about the certificate store to be accessed and the
password used to protect that certificate store.
An example use of this class would be:
Since:
SDK 1.5
-------------------------------------------------
Constructor Summary
i5OSLoadStoreParameter(java.io.File ksFile, char[] password)
Creates a ProtectionParameter instance from the KeyStore file and the password to be used for loading/
storing an i5OS certificate store.
i5OSLoadStoreParameter(java.io.File ksFile,
java.security.KeyStore.PasswordProtection pwdProtParam)
Creates a ProtectionParameter instance from the KeyStore file and PasswordProtection to be used for
loading/storing an i5OS certificate store.
-------------------------------------------------
-------------------------------------------------
Constructor detail
i5OSLoadStoreParameter
Creates a ProtectionParameter instance from the KeyStore file and the password to be used for loading/
storing an i5OS certificate store.
Parameters:
ksFile - The File object of the KeyStore.
If keystore.load() was used with an i5OSLoadStoreParameter(ksFile = null,
password), then a new keystore is created.
If keystore.store() was used with an i5OSLoadStoreParameter(ksFile = null,
password), then an IllegalArgumentException is thrown.
password - The password to access the i5OS certificate store. It cannot be null nor empty.
Throws:
java.lang.IllegalArgumentException - If password is null or empty
-------------------------------------------------
Creates a ProtectionParameter instance from the KeyStore file and PasswordProtection to be used for
loading/storing an i5OS certificate store.
If keystore.load() was used with an i5OSLoadStoreParameter(ksFile = null,
password), then a new keystore is created.
If keystore.store() was used with an i5OSLoadStoreParameter(ksFile = null,
password), then an IllegalArgumentException is thrown.
Parameters:
ksFile - The File object of the KeyStore.
pwdProtParam - PasswordProtection instance which will be used to acquire the password. It cannot
be null.
Throws:
java.lang.IllegalArgumentException - If KeyStore.PasswordProtection is null, or if the
password contained in pwdProtParam is either null or empty.
-------------------------------------------------
Method detail
-------------------------------------------------
getProtectionParameter
Returns:
An instance that implements KeyStore.KeyStoreParameter interface
See Also:
java.security.KeyStore.ProtectionParameter#getProtectionParameter()
java.lang.Object
java.io.File
com.ibm.i5os.keystore.i5OSSystemCertificateStoreFile
This class provides a new File implementation which points to the *SYSTEM certificate store file. It
provides a mechanism for the user to load the *SYSTEM certificate store without forcing them to know the
actual path to the store.
To load the *SYSTEM certificate store into a keystore, first create an i5OSSystemCertificateStoreFile.
From here, the keystore can be loaded in 2 ways:
• Using an i5OSLoadStoreParameter:
//create an i5OSSystemCertificateStoreFile
File starSystemFile = new i5OSSystemCertificateStoreFile();
• Using a FileInputStream:
//create an i5OSSystemCertificateStoreFile
File starSystemFile = new i5OSSystemCertificateStoreFile();
Since:
SDK 1.5
See also:
Serialized Form
-------------------------------------------------
Field Summary
Fields inherited from class java.io.File
pathSeparator, pathSeparatorChar, separator, separatorChar
Constructor Summary
i5OSSystemCertificateStoreFile()
Creates a File() pointing to the *System certificate store file.
Method Summary
Methods inherited from class java.io.File
canRead, canWrite, compareTo, createNewFile, createTempFile, createTempFile,
delete, deleteOnExit, equals, exists, getAbsoluteFile, getAbsolutePath,
getCanonicalFile, getCanonicalPath, getName, getParent, getParentFile,
getPath, hashCode, isAbsolute, isDirectory, isFile, isHidden, lastModified,
length, list, list, listFiles, listFiles, listFiles, listRoots, mkdir,
mkdirs, renameTo, setLastModified, setReadOnly, toString, toURI, toURL
Constructor detail
i5OSSystemCertificateStoreFile
public i5OSSystemCertificateStoreFile()
java.lang.Object
|
+--com.ibm.i5os.jsse.SSLConfiguration
This class provides for the specification of the configuration needed by the native IBM i JSSE
implementation.
The native IBM i JSSE implementation works the most efficiently using a KeyStore object of type
"IbmISeriesKeyStore". This type of KeyStore object contains key entries and trusted certificate entries
based either on an application identifier registered with the Digital Certificate Manager (DCM) or on a
keyring file (digital certificate container). A KeyStore object of this type can then be used to initialize
an X509KeyManger and an X509TrustManager object from the "IBMi5OSJSSEProvider" Provider.
The X509KeyManager and X509TrustManager objects can then be used to initialize an SSLContext
object from the "IBMi5OSJSSEProvider". The SSLContext object then provides access to the native IBM
i JSSE implementation based on the configuration information specified for the KeyStore object. Each
time a load is performed for an "IbmISeriesKeyStore" KeyStore, the KeyStore is initialized based on
the current configuration specified by the application identifier or keyring file.
This class can also be used to generate a KeyStore object of any valid type. The KeyStore is initialized
based on the current configuration specified by the application identifier or keyring file. Any change made
to the configuration specified by an application identifier or keyring file would require the KeyStore
object to be regenerated to pick up the change. Note that a keyring password must be specified (for the
*SYSTEM certificate store when using an application ID) to be able to successfully create a KeyStore
of a type other than "IbmISeriesKeyStore". The keyring password must be specified to successfully gain
access to any private key for any KeyStore of type "IbmISeriesKeyStore" which is created.
Since:
SDK 1.5
See Also:
KeyStore, X509KeyManager, X509TrustManager, SSLContext
-------------------------------------------------
“clear” on page 281() Clears all information in the object so that all of
void the get methods return null.
java.lang.Object “clone” on page 282() Generates a new copy of this SSL configuration.
boolean “equals” on page 282(java.lang.Objectobj) Indicates whether some
other object is "equal to" this one.
protected void “finalize” on page 281() Called by the garbage collector on an object
when garbage collection determines that there are no more references
to the object.
java.lang.String “getApplicationId” on page 280() Returns the application ID.
java.lang.String “getKeyringLabel” on page 280() Returns the keyring label.
java.lang.String “getKeyringName” on page 280() Returns the keyring name.
char[] “getKeyringPassword” on page 280() Returns the keyring password.
java.security.KeyStore “getKeyStore” on page 282(char[]password) Returns a keystore of type
"IbmISeriesKeyStore" using the given password.
java.security.KeyStore “getKeyStore” on page 283(java.lang.Stringtype, char[]password)
Returns a keystore of the requested type using the given password.
int “hashCode” on page 282() Returns a hash code value for the object.
staticvoid (java.lang.String[]args) Executes SSLConfiguration functions.
void (java.lang.String[]args, java.io.PrintStreamout) Executes
SSLConfiguration functions.
void “setApplicationId” on page 281(java.lang.StringapplicationId) Sets the
application ID.
void “setApplicationId” on page 281(java.lang.StringapplicationId,
char[]password) Sets the application ID and the keyring password.
void “setKeyring” on page 281(java.lang.Stringname,java.lang.Stringlabel,
char[]password) Sets the keyring information.
-------------------------------------------------
-------------------------------------------------
Constructor detail
SSLConfiguration
public SSLConfiguration()
-------------------------------------------------
Method detail
-------------------------------------------------
main
Executes SSLConfiguration functions. There are four commands that can be performed: -help, -create,
-display, and -update. The command must be the first parameter specified.
The following are the options which may be specified (in any order):
-keystore keystore-file-name
Specifies the name of the keystore file to be created, updated or displayed. This option is required for
all commands.
-storepass keystore-file-password
Specifies the password associated with the keystore file to be created, updated, or displayed. This
option is required for all commands.
-storetype keystore-type
Specifies the type of keystore file to be created, updated, or displayed. This option may be specified
for any command. If this option is not specified, then a value of "IbmISeriesKeyStore" is used.
-appid application-identifier
Specifies the application identifier to be used to initialize a keystore file being created or updated.
This option is optional for the -create and -update commands. Only one of the -appid, keyring, and
-systemdefault options may be specified.
-keyring keyring-file-name
Specifies the keyring file name to be used to initialize a keystore file being created or updated.
This option is optional for the -create and -update commands. Only one of the -appid, keyring, and
-systemdefault options may be specified.
-keyringpass keyring-file-password
Specifies the keyring file password to be used to initialize a keystore file being created or updated.
This option may be specified for the -create and -update commands and is required when a keystore
type other than "IbmISeriesKeyStore" is specified. If this option is not specified, then the stashed
keyring password is used.
-keyringlabel keyring-file-label
Specifies the keyring file label to be used to initialize a keystore file being created or updated. This
option may only be specified when the -keyring option is also specified. If this option is not specified
when the keyring option is specified, then the default label in the keyring is used.
-help
The create command creates a new keystore file. There are three variations of the create command. One
variation to create a keystore based on a particular application identifier, another variation to create a
keystore based on a keyring name, label, and password, and a third variation to create a keystore based
on the system default configuration.
To create a keystore based on a particular application identifier, the -appid option must be specified.
The following parameters would create a keystore file of type "IbmISeriesKeyStore" named "keystore.file"
with a password of "keypass" which is initialized based on the application identifier "APPID":
To create a keystore based on a particular keyring file, the -keyring option must be specified. The
-keyringpass and keyringlabel options may also be specified. The following parameters would create a
keystore file of type "IbmISeriesKeyStore" named "keystore.file" with a password of "keypass" which is
initialized based on the keyring file named "keyring.file", keyring password "ringpass", and keyring label
"keylabel":
To create a keystore based on the system default configuration, the -systemdefault option must be
specified. The following parameters would create a keystore file of type "IbmISeriesKeyStore" named
"keystore.file" with a password of "keypass" which is initialized based on the system default configuration:
The update command updates an existing keystore file of type "IbmISeriesKeyStore". There are three
variations of the update command which are identical to the variations of the create command. The
options for the update command are identical to the options used for the create command. The display
command displays the configuration specified for an existing keystore file. The following parameters
would display the configuration specified by a keystore file of type "IbmISeriesKeyStore" named
"keystore.file" with a password of "keypass":
Parameters:
args - the command line arguments
-------------------------------------------------
Executes SSLConfiguration functions. The parameters and functionality of this method are identical to the
main() method.
Parameters:
args - the command arguments
out - output stream to which results are to be written
See Also:com.ibm.i5os.jsse.SSLConfiguration.main()
-------------------------------------------------
getApplicationId
-------------------------------------------------
getKeyringName
-------------------------------------------------
getKeyringLabel
-------------------------------------------------
getKeyringPassword
-------------------------------------------------
Called by the garbage collector on an object when garbage collection determines that there are no more
references to the object.
Overrides:
finalize in class java.lang.Object
Throws:
java.lang.Throwable - the exception raised by this method.
-------------------------------------------------
clear
Clears all information in the object so that all of the get methods return null.
-------------------------------------------------
setKeyring
-------------------------------------------------
setApplicationId
-------------------------------------------------
setApplicationId
Sets the application ID and the keyring password. Specifying the keyring password allows any keystore
which is created to allow access to the private key.
-------------------------------------------------
equals
-------------------------------------------------
hashCode
-------------------------------------------------
clone
Generate a new copy of this SSL configuration. Subsequent changes to the components of this SSL
configuration will not affect the new copy, and vice versa.
Overrides:
clone in class java.lang.Object
Returns:
a copy of this SSL configuration
-------------------------------------------------
getKeyStore
Returns a keystore of type "IbmISeriesKeyStore" using the given password. The keystore is intialized
based on the configuration information currently stored in the object.
-------------------------------------------------
getKeyStore
Returns a keystore of the requested type using the given password. The keystore is initialized based on
the configuration information currently stored in the object.
Parameters:
type - type of keystore to be returned
password - used to initialize the keystore
Returns:
KeyStore keystore initialized based on the configuration information currently stored in the object
Throws:
java.security.KeyStoreException - if the keystore could not be created
//////////////////////////////////////////////////////////////////////////////////
//
// This example client program utilizes an SSLContext object, which it initializes
// to use the "MY_CLIENT_APP" application ID.
//
// The example uses the native JSSE provider, regardless of the
// properties specified by the java.security file.
//
// Command syntax:
// java SslClient
//
//////////////////////////////////////////////////////////////////////////////////
import java.io.*;
import javax.net.ssl.*;
import java.security.*;
import com.ibm.i5os.jsse.SSLConfiguration;
/**
* SSL Client Program.
/**
* SslClient main method.
*
* @param args the command line arguments (not used)
*/
public static void main(String args[]) {
/*
* Set up to catch any exceptions thrown.
*/
try {
/*
* Initialize an SSLConfiguration object to specify an application
* ID. "MY_CLIENT_APP" must be registered and configured
* correctly with the Digital Certificate Manager (DCM).
*/
SSLConfiguration config = new SSLConfiguration();
config.setApplicationId("MY_CLIENT_APP");
/*
* Get a KeyStore object from the SSLConfiguration object.
*/
char[] password = "password".toCharArray();
KeyStore ks = config.getKeyStore(password);
/*
* Allocate and initialize a KeyManagerFactory.
*/
KeyManagerFactory kmf =
KeyManagerFactory.getInstance("IbmISeriesX509");
kmf.init(ks, password);
/*
* Allocate and initialize a TrustManagerFactory.
*/
TrustManagerFactory tmf =
TrustManagerFactory.getInstance("IbmISeriesX509");
tmf.init(ks);
/*
* Allocate and initialize an SSLContext.
*/
SSLContext c =
SSLContext.getInstance("SSL", "IBMi5OSJSSEProvider");
c.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
/*
* Get the an SSLSocketFactory from the SSLContext.
*/
SSLSocketFactory sf = c.getSocketFactory();
/*
* Create an SSLSocket.
*
* Change the hard-coded IP address to the IP address or host name
* of the server.
*/
SSLSocket s = (SSLSocket) sf.createSocket("1.1.1.1", 13333);
/*
* Send a message to the server using the secure session.
*/
String sent = "Test of java SSL write";
OutputStream os = s.getOutputStream();
os.write(sent.getBytes());
/*
* Write results to screen.
*/
System.out.println("Wrote " + sent.length() + " bytes...");
System.out.println(sent);
/*
* Receive a message from the server using the secure session.
*/
InputStream is = s.getInputStream();
byte[] buffer = new byte[1024];
int bytesRead = is.read(buffer);
if (bytesRead == -1)
throw new IOException("Unexpected End-of-file Received");
String received = new String(buffer, 0, bytesRead);
/*
* Write results to screen.
*/
System.out.println("Read " + received.length() + " bytes...");
System.out.println(received);
} catch (Exception e) {
System.out.println("Unexpected exception caught: " +
e.getMessage());
//////////////////////////////////////////////////////////////////////////////////
//
// The following server program utilizes an SSLContext object that it
// initializes with a previously created keystore file.
//
// The keystore file has the following name and keystore password:
// File name: /home/keystore.file
// Password: password
//
// The example program needs the keystore file in order to create an
// IbmISeriesKeyStore object. The KeyStore object must specify MY_SERVER_APP as
// the application identifier.
//
// To create the keystore file, you can use the following Qshell command:
//
// java com.ibm.i5os.SSLConfiguration -create -keystore /home/keystore.file
// -storepass password -appid MY_SERVER_APP
//
// Command syntax:
// java JavaSslServer
//
// You can also create the keystore file by entering this command at an CL command prompt:
//
// RUNJVA CLASS(com.ibm.i5os.SSLConfiguration) PARM('-create' '-keystore'
// '/home/keystore.file' '-storepass' 'password' '-appid' 'MY_SERVER_APP')
//
/////////////////////////////////////////////////////////////////////////////////
import java.io.*;
import javax.net.ssl.*;
import java.security.*;
/**
* Java SSL Server Program using Application ID.
*/
public class JavaSslServer {
/**
* JavaSslServer main method.
*
* @param args the command line arguments (not used)
*/
public static void main(String args[]) {
/*
* Set up to catch any exceptions thrown.
*/
try {
/*
* Allocate and initialize a KeyStore object.
*/
char[] password = "password".toCharArray();
KeyStore ks = KeyStore.getInstance("IbmISeriesKeyStore");
FileInputStream fis = new FileInputStream("/home/keystore.file");
ks.load(fis, password);
/*
* Allocate and initialize a KeyManagerFactory.
*/
KeyManagerFactory kmf =
KeyManagerFactory.getInstance("IbmISeriesX509");
kmf.init(ks, password);
/*
* Allocate and initialize a TrustManagerFactory.
*/
TrustManagerFactory tmf =
TrustManagerFactory.getInstance("IbmISeriesX509");
Developer's Guide
• Overview
• Who Should Read This Document
• Related Documentation
• Introduction
• Core Classes
• Common Classes
– Subject
– Principals
– Credentials
• Authentication Classes
• LoginContext
• LoginModule
• CallbackHandler
• Callback
• Authorization Classes
• Policy
References
• Implementation
• "Hello World", JAAS style!
• Appendix A: JAAS Settings in the java.security Security Properties File
• Appendix B: Login Configuration File
• Appendix C: Authorization Policy File
Overview
The Java Authentication and Authorization Service (JAAS) is a standard extension to the Java 2 Software
Development Kit, version 1.3. Currently, Java 2 provides codesource-based access controls (access
controls based on where the code originated from and who signed the code). It lacks, however, the ability
to additionally enforce access controls based on who runs the code. JAAS provides a framework that
augments the Java 2 security model with such support.
Related Documentation
This document assumes you have already read the following documentation:
• Java 2 Software Development Kit API Specification
• JAAS API Specification
• Security and the Java platform
A supplement to this guide is the LoginModule Developer's Guide that is supplied by Oracle Corporation.
Introduction
The JAAS infrastructure can be divided into two main components: an authentication component and
an authorization component. The JAAS authentication component provides the ability to reliably and
securely determine who is currently processing Java code, regardless of whether the code is running
as an application, an applet, a bean, or a servlet. The JAAS authorization component supplements the
existing Java 2 security framework by providing the means to restrict the processing Java code from
performing sensitive tasks, depending on its codesource (as is done in Java 2) and depending on who was
authenticated.
JAAS authentication is performed in a pluggable fashion. This permits Java applications to remain
independent from underlying authentication technologies. Therefore new or updated authentication
technologies can be plugged under an application without requiring modifications to the application itself.
Applications enable the authentication process by instantiating a
LoginContext
Configuration
, to be used in performing the authentication. Typical LoginModules may prompt for and verify a username
and password. Others may read and verify a voice or fingerprint sample.
Once the user processing the code has been authenticated, the JAAS authorization component works in
conjunction with the existing Java 2 access control model to protect access to sensitive resources. Unlike
in Java 2, where access control decisions are based solely on code location and code signers (a
CodeSource
), in JAAS access control decisions are based both on the processing code's
CodeSource
Subject
. Note that the JAAS policy merely extends the Java 2 policy with the relevant Subject-based information.
Therefore permissions recognized and understood in Java 2 (
java.io.FilePermission
and
java.net.SocketPermission
, for example) are also understood and recognized by JAAS. Furthermore, although the JAAS security
policy is physically separate from the existing Java 2 security policy, the two policies, together, form one
logical policy.
Core Classes
The JAAS core classes can be broken into 3 categories: Common, Authentication, and Authorization.
• Common Classes
– Subject, Principals, Credentials
• Authentication Classes
– LoginContext, LoginModule, CallbackHandler, Callback
• Authorization Classes
– Policy, AuthPermission, PrivateCredentialPermission
Common Classes
Common classes are shared within both the JAAS authentication and authorization components.
The key JAAS class is
Subject
, which represents a grouping of related information for a single entity such as a person. It encompasses
the entity's Principals, public credentials, and private credentials.
java.security.Principal
interface to represent a Principal. Also note that JAAS does not introduce a separate credential interface
or class. A credential, as defined by JAAS, may be any Object.
Subject
To authorize access to resources, applications first need to authenticate the source of the request. The
JAAS framework defines the term, Subject, to represent the source of a request. A Subject may be any
entity, such as a person or service. Once authenticated, a Subject is populated with associated identities,
or Principals. A Subject may have many Principals. For example, a person may have a name Principal
("John Doe") and a SSN Principal ("123-45-6789") which distinguishes it from other Subjects.
A
Subject
may also own security-related attributes, which are referred to as credentials. Sensitive credentials that
require special protection, such as private cryptographic keys, are stored within a private credential
Set
. Credentials intended to be shared, such as public key certificates or Kerberos tickets are stored within a
public credential
Set
. Different permissions are required to access and modify the different credential Sets.
Subjects are created using these constructors:
public Subject();
The first constructor creates a Subject with empty (non-null) Sets of Principals and credentials. The
second constructor creates a Subject with the specified Sets of Principals and credentials. It also has a
boolean argument which can create a read-only Subject (immutable Principal and credential Sets).
An alternative way to obtain a reference to an authenticated Subject without using these constructors will
be shown in the LoginContext section.
If a Subject was not instantiated to be in a read-only state, it can be set to a read-only state by calling this
method:
An
AuthPermission("setReadOnly")
is required to invoke this method. Once in a read-only state, any attempt to add or remove Principals or
credentials will result in an
IllegalStateException
To retrieve the Principals associated with a Subject, two methods are available:
The first method returns all Principals contained in the Subject, while the second method only returns
those Principals that are an instance of the specified Class c, or an instance of a subclass of Class c. An
empty set will be returned if the Subject does not have any associated Principals.
To retrieve the public credentials associated with a Subject, these methods are available:
getPrincipals
method.
To access private credentials associated with a Subject, the following methods are available:
getPrincipals
and
getPublicCredentials
methods.
To modify or operate upon a Subject's Principal Set, public credential Set, or private credential Set, callers
use the methods defined in the
java.util.Set
Subject subject;
Principal principal;
Object credential;
Note that an
AuthPermission("modifyPrincipals")
AuthPermission("modifyPublicCredentials")
, or
AuthPermission("modifyPrivateCredentials")
is required to modify the respective Sets. Also note that only the sets returned via the
getPrincipals
getPublicCredentials
, and
getPrivateCredentials
methods are backed by the Subject's respective internal sets. Therefore any modification to the returned
set affects the internal sets as well. The sets returned via the
getPrincipals(Class c)
getPublicCredentials(Class c)
, and
getPrivateCredentials(Class c)
methods are not backed by the Subject's respective internal sets. A new set is created and returned
for each method invocation. Modifications to these sets will not affect the Subject's internal sets. The
following method returns the Subject associated with the specified
AccessControlContext
AccessControlContext
An
AuthPermission("getSubject")
is required to call
Subject.getSubject
java.lang.Object
The following static methods may be called to perform work as a particular Subject:
Both methods first associate the specified subject with the current Thread's
AccessControlContext
, and then process the action. This achieves the effect of having the action run as the subject. The first
method can throw runtime exceptions but normal processing has it returning an Object from the run()
method of its action argument. The second method behaves similarly except that it can throw a checked
exception from its
PrivilegedExceptionAction
run() method. An
AuthPermission("doAs")
doAs
methods.
Here are two examples utilizing the first
doAs
Subject
com.ibm.security.Principal
LoginContext
Subject.doAs Example 1
Subject bob;
...
During processing,
ExampleAction
f.exists()
. However, since
ExampleAction
is running as "BOB", and because the JAAS policy (above) grants the necessary
FilePermission
to "BOB", the
ExampleAction
Subject bob;
...
SecurityException
if the example permission grant statement is altered incorrectly, such as adding an incorrect CodeBase or
changing the Principal to "MOE". Removing the Principal field from the grant block and then moving it to a
Java 2 policy file will not cause a
SecurityException
to be thrown because the permission is more general now (available to all Principals).
Since both examples perform the same function, there must be a reason to write code one way over the
other. Example 1 may be easier to read for some programmers unfamiliar with anonymous classes. Also,
the action class could be placed in a separate file with a unique CodeBase and then the permission grant
could utilize this information. Example 2 is more compact and the action to be performed is easier to find
since it is right there in the
doAs
call.
The following methods also perform work as a particular Subject. However, the
doAsPrivileged
methods will have security checks based on the supplied action and subject. The supplied context will be
tied to the specified subject and action. A null context object will disregard the current
AccessControlContext
altogether.
The
doAs
methods: the subject is associated with the context acc, an action is performed, and runtime exceptions
or checked exceptions may be thrown. However, the
doAsPrivileged
AccessControlContext
before associating the subject with the supplied context, and before invoking the action. A null acc
argument has the effect of causing access control decisions (invoked while the action processes) to be
based solely upon the subject and action. An
AuthPermission("doAsPrivileged")
doAsPrivileged
methods.
Principals
As mentioned previously, Principals may be associated with a Subject. Principals represent Subject
identities, and must implement the
java.security.Principal
and
java.io.Serializable
interfaces. The Subject section describes ways to update the Principals associated with a Subject.
Credentials
Public and private credential classes are not part of the core JAAS class library. Any java class, therefore,
can represent a credential. However, developers may elect to have their credential classes implement two
interfaces related to credentials: Refreshable and Destroyable.
Refreshable
This interface provides the capability for a credential to refresh itself. For example, a credential with a
particular time-restricted lifespan may implement this interface to allow callers to refresh the time period
for which it is valid. The interface has two abstract methods:
boolean isCurrent();
Updates or extends the validity of the credential. This method implementation performs an
AuthPermission("refreshCredential")
security check to ensure the caller has permission to refresh the credential.
Destroyable
This interface provides the capability of destroying the contents within a credential. The interface has two
abstract methods:
boolean isDestroyed();
Destroys and clears the information associated with this credential. Subsequent calls to certain methods
on this credential will result in an
IllegalStateException
AuthPermission("destroyCredential")
security check to ensure the caller has permission to destroy the credential.
Authentication Classes
To authenticate a
Subject
LoginContext
.
2. The
LoginContext
consults a configuration to load all of the LoginModules configured for that application.
3. The application invokes the LoginContext's login method.
4. The login method invokes all of the loaded LoginModules. Each
LoginModule
. Upon success, LoginModules associate relevant Principals and credentials with the
Subject
.
5. The
LoginContext
Subject
from the
LoginContext
LoginContext
The
LoginContext
class provides the basic methods used to authenticate Subjects, and provides a way to develop an
application independent of the underlying authentication technology. The
LoginContext
consults a configuration
Configuration
LoginContext
LoginContext
Subject
Subject
AuthPermission("createLoginContext")
to instantiate a
LoginContext
.
Actual authentication occurs with a call to the following method:
When login is invoked, all of the configured LoginModules' respective login methods are invoked to
perform the authentication. If the authentication succeeded, the authenticated
Subject
(which may now hold Principals, public credentials, and private credentials) can be retrieved by using the
following method:
To logout a
Subject
and remove its authenticated Principals and credentials, the following method is provided:
The following snippet of code in an application will authenticate a Subject called "bob" after accessing a
configuration file with a configuration entry named "moduleFoo":
If the authentication failed, then getSubject returns null. Also, there isn't an
AuthPermission("getSubject")
Subject.getSubject
LoginModule
The LoginModule interface gives developers the ability to implement different kinds of authentication
technologies that can be plugged under an application. For example, one type of
LoginModule
LoginModule
,a
LoginContext
expects each
LoginModule
LoginModule
LoginContext
initialize
An example method implementation may prompt the user for a username and password, and then
verify the information against the data stored in a naming service such as NIS or LDAP. Alternative
implementations might interface smart cards and biometric devices, or may simply extract user
information from the underlying operating system. This is considered phase 1 of the JAAS authentication
process.
The following method completes and finalizes the authentication process:
If phase 1 of the authentication process was successful, then this method continues with phase 2:
associating Principals, public credentials, and private credentials with the Subject. If phase 1 failed,
then the commit method removes any previously stored authentication state, such as usernames and
passwords.
The following method halts the authentication process if phase 1 was unsuccessful:
Typical implementations of this method clean up previously stored authentication state, such as
usernames or passwords. The following method logs out a Subject:
This method removes the Principals and credentials originally associated with the
Subject
during the
commit
CallbackHandler
In some cases a LoginModule must communicate with the user to obtain authentication information.
LoginModules use a CallbackHandler for this purpose. Applications implement the CallbackHandler
interface and pass it to the LoginContext, which forwards it directly to the underlying LoginModules.
LoginModules use the CallbackHandler both to gather input from users (such as a password or smart card
pin number) or to supply information to users (such as status information). By allowing the application
to specify the CallbackHandler, underlying LoginModules can remain independent of the different ways
applications interact with users. For example, the implementation of a CallbackHandler for a GUI
application might display a Window to solicit input from a user. The implementation of a CallbackHandler
for a non-GUI tool might prompt the user for input directly from the command line.
CallbackHandler
Callback
The javax.security.auth.callback package contains the Callback interface as well as several
implementations. LoginModules may pass an array of Callbacks directly to the handle method of a
CallbackHandler.
Consult the various Callback APIs for more information on their use.
Authorization Classes
Upon successful authentication of a
Subject
Subject
Subject
Policy
Policy
This is an abstract class for representing the system-wide JAAS access control. As a default, JAAS
provides a file-based subclass implementation, PolicyFile. Each
Policy
The
getPermissions
Subject
and
. The
refresh
Policy
with any modifications made since the last time it was loaded from its permanent store (a file or database,
for example). The
refresh
method requires an
AuthPermission("refreshPolicy")
.
The following method retrieves the current runtime
Policy
object, and is protected with a security check that requires the caller to have an
AuthPermission("getPolicy")
Policy
object can be queried for the set of permissions granted to the specified
Subject
and
CodeSource
policy = Policy.getPolicy();
PermissionCollection perms = policy.getPermissions(subject, codeSource);
To set a new
Policy
Policy.setPolicy
AuthPermission("setPolicy")
Policy
Subject
Principal
Subject
Policy
grant entry, a parsing exception will be thrown. However, grant entries that already exist in the regular
Java 2 codesource-based policy file (and therefore have no Principal information) are still valid. In those
cases, the Principal information is implied to be '*' (the grant entries applies to all Principals).
Policy
. If they are not present, then any codebase will match, and any signer (including unsigned code) will
match.
In the example above, the grant entry specifies that code downloaded from "http://griffin.ibm.com",
signed by "davis", and running as the NT user "kent", has one
Permission
. This
Permission
permits the processing code to read and write files in the directory "c:\kent\files".
Multiple Principals may be listed within one grant entry. The current
Subject
running the code must have all of the specified Principals in its
Principal
This entry grants any code running as both the NT user "kent" with the NT group identification number
"S-1-1-0", permission to read and write files in "c:\user\kent", as well as permission to make socket
connections to "griffin.ibm.com".
AuthPermission
This class encapsulates the basic permissions required for JAAS. An AuthPermission contains a name
(also referred to as a "target name") but no actions list; you either have the named permission or you
don't. In addition to inherited methods (from the
Permission
class), an
AuthPermission
Policy
object to instantiate new Permission objects. For most code, the first constructor is appropriate.
The AuthPermission object is used to guard access to the Policy, Subject, LoginContext, and Configuration
objects. Refer to the AuthPermission Javadoc for the list of valid names that are supported.
PrivateCredentialPermission
This class protects access to a Subject's private credentials and provides one public constructor:
Refer to the PrivateCredentialPermission Javadoc for more detailed information on this class.
Implementation
Note: Appendix A contains a sample java.security file that includes the static properties mentioned here.
Because there exists default values for JAAS providers and policy files, users need not statically (in the
java.security file) nor dynamically (command line -D option) list their values in order to implement JAAS.
Also, the default configuration and policy file providers may be replaced by a user-developed provider.
Therefore this section is an attempt to explain the JAAS default providers and policy files as well as the
properties that enable alternative providers.
Read the Default Policy File API and Default Configuration File API for more information than is
summarized here.
Authentication Provider
The authentication provider, or configuration class, is statically set with
login.configuration.provider=[class]
Configuration
object.
For example:
login.configuration.provider=com.foo.Config
login.configuration.provider
is not found in java.security, then JAAS will set it to the default value:
com.ibm.security.auth.login.ConfigFile
Configuration
is created, then an
AuthPermission("getLoginConfiguration")
login.config.url.n=[URL]
, where n is a consecutively number integer starting with 1. The format is identical to the format for Java
security policy files (policy.url.n=[URL]).
If the Security property
policy.allowSystemProperty
is set to "true" in java.security, then users can dynamically set policy files on the command line utilizing
the -D option with this property:
java.security.auth.login.config
Note: using double equal signs (==) on the command line allows a user to override all other policy files
found.
If no configuration files can be found statically or dynamically, JAAS will try to load the configuration file
from this default location:
${user.home}\.java.login.config
auth.policy.provider=[class]
Policy
object.
auth.policy.provider=com.foo.Policy
auth.policy.provider
is not found in java.security, then JAAS will set it to the default value:
com.ibm.security.auth.PolicyFile
.
If a security manager is set before the
Configuration
is created, then an
AuthPermission("getPolicy")
auth.policy.url.n=[URL]
, where n is a consecutively number integer starting with 1. The format is identical to the format for Java
security policy files (policy.url.n=[URL]).
If the Security property
policy.allowSystemProperty
is set to "true" in java.security, then users can dynamically set policy files on the command line utilizing
the -D option with this property:
java.security.auth.policy
Note: using double equal signs (==) on the command line allows a user to override all other policy files
found.
There is not a default location to load an authorization policy from.
The classpath needs the classes directory (.\classes) added to it in order to compile the classes.
Note:
HWLoginModule
and
HWPrincipal
are in the
com.ibm.security
helloWorld {
com.ibm.security.HWLoginModule required debug=true;
};
Only one
is supplied with the test case. When processing the HelloWorld application, experiment by changing the
LoginModuleControlFlag
(required, requisite, sufficient, optional) and deleting the debug flag. If more LoginModules are available
for testing, then feel free to alter this configuration and experiment with multiple LoginModules.
HWLoginModule
grant {
permission javax.security.auth.AuthPermission "createLoginContext";
permission javax.security.auth.AuthPermission "modifyPrincipals";
permission javax.security.auth.AuthPermission "doAsPrivileged";
};
The three permissions are required because the HelloWorld application (1) creates a LoginContext object,
(2) modifies the Principals of the the authenticated
Subject
Subject
class.
The JAAS policy file, jaas.policy, also contains one permission block:
HWPrincipal
Subject
Here's the action code from HelloWorld with the three system calls (the reason for the required
permissions) in bold:
try {
Thread.currentThread().sleep(2000);
} catch (Exception e) {
// ignore
}
System.out.println("\n\nHello World!\n");
return null;
}
}, null);
When running the HelloWorld program, use various usernames and alter jaas.policy accordingly. There is
no need to alter java2.policy. Also, create a file called foo.txt in the test directory to test the last system
call.
Examine Source Files The LoginModule,
HWLoginModule
, authenticates any user who enters the correct password (case sensitive): Go JAAS.
The HelloWorld application permits users three attempts to do so. When Go JAAS is correctly entered, an
HWPrincipal
Subject
.
The Principal class,
HWPrincipal
, represents a Principal based on the username entered. It is this name that is important when granting
permissions to authenticated Subjects.
The main application,
HelloWorld
, first creates a
LoginContext
based on a configuration entry with the name helloWorld. The configuration file has already been
discussed. Callbacks are used to retrieve user input. Look at the
MyCallbackHandler
LoginContext lc = null;
try {
lc = new LoginContext("helloWorld", new MyCallbackHandler());
The user enters a username/password (up to three times) and if Go JAAS is entered as the password,
then the Subject is authenticated (
HWLoginModule
adds a
HWPrincipal
to the Subject).
As mentioned previously, work is then performed as the authenticated Subject.
Run HelloWorld Test
To run the HelloWorld program, first change to the test directory. The configuration and policy files will
need to be loaded. See Implementation for the correct properties to set either in java.security or on the
command line. The latter method will be discussed here.
The following command has been broken up into several lines for clarity. Enter as one continuous
command.
java -Djava.security.manager=
-Djava.security.auth.login.config=.\jaas.config
-Djava.security.policy=.\java2.policy
-Djava.security.auth.policy=.\jaas.policy
HelloWorld
Note: the use of ".\filename" for the policy files is necessary because each user's test directory canonical
path will vary. If desired, substitute "." with the path to the test directory. For example, if the test directory
is "c:\test\hello", then the first file is changed to:
-Djava.security.auth.login.config=c:\test\hello\jaas.config
SecurityException
will be thrown. Otherwise, information concerning your java.home and user.home properties will be
displayed. Also, the existence of a file called foo.txt in your test directory will be checked. Finally, the
ubiquitous "Hello World" message is displayed.
Having Fun With HelloWorld
Rerun HelloWorld as many times as you like. It has already been suggested to vary the username/
passwords entered, change the configuration file entries, change the policy file permissions, and to even
add (stack) additional LoginModules to the helloWorld configuration entry. You could add codebase fields
to the policy files too.
Finally, try running the program without a SecurityManager to see how it works if you run into problems.
java.security
lib/security
lib\security
on Windows) directory of the Java 2 runtime. Thus, if the Java 2 runtime is installed in a directory called
jdk1.3
, the file is
•
jdk1.3/lib/security/java.security
(Unix)
•
jdk1.3\lib\security\java.security
(Windows)
JAAS adds four new properties to
java.security
:
• Authentication Properties
–
login.configuration.provider
–
login.policy.url.n
• Authorization Properties
–
auth.policy.provider
–
auth.policy.url.n
The new JAAS properties are located at the end of this file:
#
# This is the "master security properties file".
#
# In this file, various security properties are set for use by
# java.security classes. This is where users can statically register
# Cryptography Package Providers ("providers" for short). The term
# "provider" refers to a package or set of packages that supply a
# concrete implementation of a subset of the cryptography aspects of
# the Java Security API. A provider may, for example, implement one or
# more digital signature algorithms or message digest algorithms.
#
# Each provider must implement a subclass of the Provider class.
# To register a provider in this master security properties file,
# specify the Provider subclass name and priority in the format
#
# security.provider.n=className
#
# This declares a provider, and specifies its preference
#
# List of providers and their preference orders (see above):
#
security.provider.1=sun.security.provider.Sun
#
# Class to instantiate as the system Policy. This is the name of the class
# that will be used as the Policy object.
#
policy.provider=sun.security.provider.PolicyFile
#
# Default keystore type.
#
keystore.type=jks
#
# Class to instantiate as the system scope:
#
system.scope=sun.security.provider.IdentityDatabase
##############################################################################
#
# Java Authentication and Authorization Service (JAAS)
# properties and policy files:
#
LoginContext
Application {
LoginModule Flag ModuleOptions;
> more LoginModule entries <
LoginModule Flag ModuleOptions;
};
login.config.url.n
java.security
file. For more information about this property and the location of the
java.security
LoginModule
is required to succeed. If it succeeds or fails, authentication still continues to proceed down the
LoginModule
list.
2. Requisite The
LoginModule
LoginModule
LoginModule
list).
3. Sufficient The
LoginModule
is not required to succeed. If it does succeed, control immediately returns to the application
(authentication does not proceed down the
LoginModule
LoginModule
list.
4. Optional The
LoginModule
is not required to succeed. If it succeeds or fails, authentication still continues to proceed down the
LoginModule
list.
The overall authentication succeeds only if all Required and Requisite LoginModules succeed. If a
Sufficient
LoginModule
is configured and succeeds, then only the Required and Requisite LoginModules prior to that Sufficient
LoginModule
need to have succeeded for the overall authentication to succeed. If no Required or Requisite
LoginModules are configured for an application, then at least one Sufficient or Optional
LoginModule
must succeed.
Sample Configuration File:
Login1 {
com.ibm.security.auth.module.SampleLoginModule required debug=true;
};
Login2 {
com.ibm.security.auth.module.SampleLoginModule required;
com.ibm.security.auth.module.NTLoginModule sufficient;
ibm.loginModules.SmartCard requisite debug=true;
Note: the Flags are not case sensitive. REQUISITE = requisite = Requisite.
Login1 only has one LoginModule which is an instance of the class
com.ibm.security.auth.module.SampleLoginModule
. Therefore, a
LoginContext
associated with Login1 will have a successful authentication if and only if its lone module successfully
authenticates. The Required flag is trivial in this example; flag values have a relevant effect on
authentication when two or more modules are present.
Login2 is easier to explain with a table.
* = trivial value due to control returning to the application because a previous REQUISITE module failed or
a previous SUFFICIENT module succeeded.
// The following permissions are granted to Principal 'Pooh' and all codesource:
JGSS concepts
JGSS operations consist of four distinct stages, as standardized by the Generic Security Service
Application Programming Interface (GSS-API).
The stages are as follows:
1. Gathering of credentials for principals.
2. Creating and establishing a security context between the communicating peer principals.
3. Exchanging secure messages between the peers.
4. Cleaning up and releasing resources.
Additionally, JGSS leverages the Java Cryptographic Architecture to offer seamless pluggability of
different security mechanisms.
Use the following links to read high-level descriptions of these important JGSS concepts.
Related concepts
Configuring your server to use IBM JGSS
How you configure your server to use JGSS depends on which version of the Java Platform, Standard
Edition (J2SE) that you run on your system.
Running IBM JGSS applications
The IBM Java Generic Security Service (JGSS) API 1.0 shields secure applications from the complexities
and peculiarities of the different underlying security mechanisms. JGSS uses features provided by Java
Authentication and Authorization Service (JAAS) and IBM Java Cryptography Extension (JCE).
Developing IBM JGSS applications
Use JGSS to develop secure applications. Learn about generating transport tokens, creating JGSS objects,
establishing context, and more.
JGSS debugging
When you are trying to identify JGSS problems, use the JGSS debugging capability to produce helpful
categorized messages.
Samples: IBM Java Generic Security Service (JGSS)
The IBM Java Generic Security Service (JGSS) sample files include client and server programs,
configuration files, policy files, and Javadoc reference information. Use the sample programs to test and
verify your JGSS setup.
Related reference
IBM JGSS Javadoc reference information
java.lang.Object
|
+--com.ibm.security.krb5.internal.tools.Klist
This class can execute as a command-line tool to list entries in credential cache and key tab.
Constructor summary
Klist()
Method summary
static void main(java.lang.String[] args)
The main program that can be invoked at command line.
Method detail
main
public static void main(java.lang.String[] args)
The main program that can be invoked at command line.
Usage: java com.ibm.security.krb5.tools.Klist [[-c] [-f] [-e] [-a]] [-k [-t] [-K]] [name]
Available options for credential caches:
• -f shows credentials flags
• -e shows the encryption type
• -a displays the address list
Available options for keytabs:
• -t shows keytab entry timestamps
• -K shows keytab entry DES keys
java.lang.Object
|
+--com.ibm.security.krb5.internal.tools.Kinit
Constructor summary
Kinit(java.lang.String[] args)
Constructs a new Kinit object.
Method summary
static void
main(java.lang.String[] args)
The main method is used to accept user command line input for ticket
request.
Constructor detail
Kinit
Method detail
main
public static void main(java.lang.String[] args)
The main method is used to accept user command line input for ticket request.
Usage: java com.ibm.security.krb5.tools.Kinit [-f] [-F] [-p] [-P] [-k] [-c cache name] [principal] [password]
• -f forwardable
• -F not forwardable
• -p proxiable
• -P not proxiable
• -c cache name (i.e., FILE:d:\temp\mykrb5cc)
• -k use keytab
• -t keytab file name
• principal the principal name (i.e., qwedf [email protected])
• password the principal's Kerberos password
Use java com.ibm.security.krb5.tools.Kinit -help to bring up help menu.
We currently only support file-based credentials cache. By default, a cache file named
krb5cc_{user.name} would be generated at {user.home} directory to store the ticket obtained from KDC.
For instance, on Windows NT, it could be c:\winnt\profiles\qwedf\krb5cc_qwedf, in which qwedf is the
{user.name}, and c:\winnt\profile\qwedf is the {user.home}. {user.home} is obtained by Kerberos from
Java system property "user.home". If in some case {user.home} is null (which barely happens), the cache
file would be stored in the current directory that the program is running from. {user.name} is operating
system's login username. It could be different from user's principal name. One user could have multiple
principal names, but the primary principal of the credentials cache could only be one, which means one
cache file could only store tickets for one specific user principal. If the user switches the principal name at
the next Kinit, the cache file generated for the new ticket would overwrite the old cache file by default. To
avoid overwriting, you need to specify a different directory or different cache file name when you request
a new ticket.
Cache file location
There are several ways to define user specific cache file name and location, they are listed as follows in
the order that Kerberos searches for:
1. -c option. Use java com.ibm.security.krb5.tools.Kinit -c FILE:<user specific directory and file name>.
"FILE:" is the prefix to identify the credentials cache type. The default is file-based type.
2. Set Java system property "KRB5CCNAME" by using -DKRB5CCNAME=FILE:<user specific directory
and file name> during runtime.
3. Set environment variable "KRB5CCNAME" at command prompt before the runtime. Different
operating system has different way to set environment variables. For example, Windows
uses set KRB5CCNAME=FILE:<user specific directory and file name>, while UNIX uses export
KRB5CCNAME=FILE:<user specific directory and file name>. Note that Kerberos relies on system
specific command to retrieve environment variable. The command used on UNIX is "/usr/bin/env".
java.lang.Object
|
+--com.ibm.security.krb5.internal.tools.Ktab
This class can execute as a command-line tool to help the user manage entires in the key table. Available
functions include list/add/update/delete service key(s).
Constructor summary
Ktab()
Method summary
static void
main(java.lang.String[] args)
The main program that can be invoked at command line.
Constructor detail
Ktab
public Ktab()
Method detail
main
public static void main(java.lang.String[] args)
The main program that can be invoked at command line.
Usage: java com.ibm.security.krb5.tools.Ktab <options>
Available options to Ktab:
Security mechanisms
The GSS-API consists of an abstract framework over one or more underlying security mechanisms. How
the framework interacts with the underlying security mechanisms is implementation specific.
Such implementations exist in two general categories:
• At one extreme, a monolithic implementation tightly binds the framework to a single mechanism. This
kind of implementation precludes the use of other mechanisms or even different implementations of
the same mechanism.
• At the other end of the spectrum, a highly modular implementation offers ease of use and flexibility.
This kind of implementation offers the ability to seamlessly and easily plug different security
mechanisms and their implementations into the framework.
IBM JGSS falls into the latter category. As a modular implementation, IBM JGSS leverages the provider
framework defined by the Java Cryptographic Architecture (JCA) and treats any underlying mechanism as
a (JCA) provider. A JGSS provider supplies a concrete implementation of a JGSS security mechanism. An
application can instantiate and use multiple mechanisms.
It is possible for a provider to support multiple mechanisms, and JGSS makes it easy to use different
security mechanisms. However, the GSS-API does not provide a means for two communicating peers to
choose a mechanism when multiple mechanisms are available. One way to choose a mechanism is to
start with the Simple And Protected GSS-API Negotiating Mechanism (SPNEGO), a pseudo-mechanism
that negotiates an actual mechanism between the two peers. IBM JGSS does not include a SPNEGO
mechanism.
Security managers
If you are running your JGSS application with a Java security manager enabled, see Using a security
manager.
JGSS providers
IBM JGSS includes a native IBM i JGSS provider and a pure Java JGSS provider. The provider that you
choose to use depends on the needs of your application.
The pure Java JGSS provider offers the following features:
• Ensures the greatest level of portability for your application.
• Works with the optional JAAS Kerberos login interface.
• Compatible with the Java Kerberos credential management tools.
The native IBM i JGSS provider offers the following features:
JVM permissions
In addition to the access control checks performed by JGSS, the Java virtual machine (JVM) performs
authorization checks when accessing a variety of resources, including files, Java properties, packages,
and sockets.
The following list identifies the permissions required when you use the JAAS features of JGSS or use JGSS
with a security manager:
• javax.security.auth.AuthPermission "modifyPrincipals"
• javax.security.auth.AuthPermission "modifyPrivateCredentials"
• javax.security.auth.AuthPermission "getSubject"
• javax.security.auth.PrivateCredentialPermission "javax.security.auth.kerberos.KerberosKey
javax.security.auth.kerberos.KerberosPrincipal \"*\"", "read"
• javax.security.auth.PrivateCredentialPermission "javax.security.auth.kerberos.KerberosTicket
javax.security.auth.kerberos.KerberosPrincipal \"*\"", "read"
• java.util.PropertyPermission "com.ibm.security.jgss.debug", "read"
• java.util.PropertyPermission "DEBUG", "read"
• java.util.PropertyPermission "java.home", "read"
• java.util.PropertyPermission "java.security.krb5.conf", "read"
• java.util.PropertyPermission "java.security.krb5.kdc", "read"
• java.util.PropertyPermission "java.security.krb5.realm", "read"
• java.util.PropertyPermission "javax.security.auth.useSubjectCredsOnly", "read"
• java.util.PropertyPermission "user.dir", "read"
• java.util.PropertyPermission "user.home", "read"
• java.lang.RuntimePermission "accessClassInPackage.sun.security.action"
• java.security.SecurityPermission "putProviderProperty.IBMJGSSProvider"
Related concepts
JAAS permission checks
DelegationPermission check
The DelegationPermission allows the security policy to control the use of the ticket forwarding and
proxying features of Kerberos. Using these features, a client can allow a service to act on behalf of the
client.
DelegationPermission takes two arguments, in the following order:
1. The subordinate principal, which is the name of the service principal that acts on behalf of, and under
the authority of, the client.
2. The name of the service that the client wants to allow the subordinate principal to use.
Example: Using the DelegationPermission check
In the following example, superSecureServer is the subordinate principal and krbtgt/
[email protected] is the service that we want to allow superSecureServer to use on
behalf of the client. In this case, the service is the ticket-granting ticket for the client, which means that
superSecureServer can get a ticket for any service on behalf of the client.
permission javax.security.auth.kerberos.DelegationPermission
"\"superSecureServer/[email protected]\"
\"krbtgt/[email protected]\"";
In the previous example, DelegationPermission grants the client permission to get a new ticket-granting
ticket from the Key Distribution Center (KDC) that only superSecureServer can use. After the client has
sent the new ticket-granting ticket to superSecureServer, superSecureServer has the ability to act on
behalf of the client.
The following example enables the client to get a new ticket that allows superSecureServer to access only
the ftp service on behalf of the client:
permission javax.security.auth.kerberos.DelegationPermission
"\"superSecureServer/[email protected]\"
\"ftp/[email protected]\"";
ServicePermission check
ServicePermission checks restrict the use of credentials for context initiation and acceptance. A context
initiator must have permission to initiate a context. Likewise, a context acceptor must have permission to
accept a context.
Example: Using the ServicePermission check
permission javax.security.auth.kerberos.ServicePermission
"ftp/[email protected]", "initiate";
The following example allows the server side to access and use the secret key for the ftp service by
granting permission to the server:
permission javax.security.auth.kerberos.ServicePermission
"ftp/[email protected]", "accept";
Related concepts
JVM permissions
In addition to the access control checks performed by JGSS, the Java virtual machine (JVM) performs
authorization checks when accessing a variety of resources, including files, Java properties, packages,
and sockets.
Related information
Oracle Corporation documentation
useCcache <URL> Don't use ccache Retrieve TGT from the specified credential cache
useKeytab <URL> Don't use key table Retrieve secret key from the specified key table
useDefaultCcache true|false Don't use default ccache Retrieve TGT from default credential cache
useDefaultKeytab true|false Don't use default key Retrieve secret key from the specified key table
table
For a simple example of using Krb5LoginModule, see the Sample JAAS login configuration file.
Option incompatabilities
Some Krb5LoginModule options, excluding principal name, are incompatible with each other, meaning
that you cannot specify them together. The following table represents compatible and incompatible login
module options.
Indicators in the table describe the relationship between the two associated options:
• X = Incompatible
• N/A = Inapplicable combination
• Blank = Compatible
forwardable X X X X X
proxiable X X X X X
useCcache X X X X X X
useKeytab X X X X X X
useDefaultCcache X X X X X X
useDefaultKeytab X X X X X X
_ (underscore)
: (colon)
/ (forward slash)
\ (back slash)
security.provider.1=sun.security.provider.Sun
security.provider.2=com.ibm.crypto.provider.IBMJCE
policy.provider=sun.security.provider.PolicyFile
policy.url.<integer>: URLs of policy files. To use the sample policy file, include an entry such as:
policy.url.1=file:/home/user/jgss/config/java.policy
login.configuration.provider=com.ibm.security.auth.login.ConfigFile
auth.policy.provider: JAAS principal-based access control policy handler class, for example:
auth.policy.provider=com.ibm.security.auth.PolicyFile
login.config.url.<integer>: URLs for JAAS login configuration files. To use the sample configuration file,
include an entry similar to:
login.config.url.1=file:/home/user/jgss/config/jaas.conf
auth.policy.url.1=file:/home/user/jgss/config/jaas.policy
Creating a GSSManager
The GSSManager abstract class serves as a factory for creating JGSS objects.
GSSManager abstract class creates the following:
• GSSName
• GSSCredential
• GSSContext
Creating a GSSName
GSSName represents the identity of a GSS-API principal. A GSSName may contain many representations
of the principal, one for each supported underlying mechanism. A GSSName that contains only one name
representation is called a Mechanism Name (MN).
GSSManager has several overloaded methods for creating a GSSName from a string or a contiguous array
of bytes. The methods interpret the string or byte array according to a specified name type. Typically, you
use the GSSName byte-array methods to reconstitute an exported name. The exported name is usually
a mechanism name of type GSSName.NT_EXPORT_NAME. Some of these methods allow you to specify a
security mechanism with which to create the name.
Creating a GSSCredential
A GSSCredential contains all the cryptographic information necessary to create a context on behalf of a
principal and can contain credential information for multiple mechanisms.
GSSManager has three credential creation methods. Two of the methods take for parameters a GSSName,
the lifetime of the credential, one or more mechanisms from which to get credentials, and the credential
usage type. The third method takes only a usage type and uses the default values for other parameters.
Specifying a null mechanism also uses the default mechanism. Specifying a null array of mechanisms
causes the method to return credentials for the default set of mechanisms.
Note: Because IBM JGSS supports only the Kerberos V5 mechanism, that is the default mechanism.
Your application can create only one of the three credentials types (initiate, accept, or initiate and accept)
at a time.
• A context initiator creates initiate credentials
• An acceptor creates accept credentials
• An acceptor that also behaves as an initiator creates initiate and accept credentials.
Examples: Obtaining credentials
The following example obtains the default credentials for an initiator:
Creating GSSContext
IBM JGSS supports two methods provided by GSSManager for creating a context. These methods are a
method used by the context initiator and a method used by the acceptor.
Note: GSSManager provides a third method for creating a context that involves recreating previously
exported contexts. However, because IBM JGSS Kerberos V5 mechanism does not support the use of
exported contexts, IBM JGSS does not support this method.
Your application cannot use an initiator context for context acceptance, nor can it use an acceptor context
for context initiation. Both supported methods for creating a context require a credential as input. When
the value of the credential is null, JGSS uses the default credential.
Examples: Using GSSContext
The following example creates a context with which the principal (foo) can initiate a context with
the peer (superSecureServer) on the host (securityCentral). The example specifies the peer as
superSecureServer@securityCentral. The created context is valid for the default period:
The following example creates a context for superSecureServer in order to accept contexts initiated by
any peer:
Note that your application can create and simultaneously use both types of contexts.
fooContext.requestMutualAuth(true);
fooContext.requestCredDeleg(true);
byte array[] inToken = null; // The input token is null for the first call
int inTokenLen = 0;
do {
byte[] outToken = fooContext.initSecContext(inToken, 0, inTokenLen);
if (outToken != null) {
send(outToken); // transport token to acceptor
}
if( !fooContext.isEstablished()) {
inToken = receive(); // receive token from acceptor
inTokenLen = inToken.length;
}
} while (!fooContext.isEstablished());
if (outToken != null) {
send(outToken); // transport token to initiator
}
} while (!serverAcceptorContext.isEstablished());
Sending messages
IBM JGSS provides two sets of methods for securing messages: wrap() and getMIC().
byte[] mic =
serverAcceptorContext.getMIC(message, 0, message.length, mprop);
send(mic);
// send the MIC to foo. foo also needs the original message to verify the MIC
Receiving messages
The receiver of a wrapped message uses unwrap() to decode the message. The unwrap method performs
the following actions:
• Verifies the cryptographic MIC embedded in the message
• Returns the original message over which the sender computed the MIC
If the sender encrypted the message, unwrap() decrypts the message before verifying the MIC and then
returns the original plaintext message. The receiver of an MIC token uses verifyMIC() to verify the MIC
over a given a message.
The peer applications use their own protocol to deliver JGSS context and message tokens to each other.
Peer applications also need to define a protocol for determining whether the token is an MIC or a wrapped
message. For example, part of such a protocol may be as simple (and rigid) as that used by Simple
Authentication and Security Layer (SASL) applications. The SASL protocol specifies that the context
acceptor is always the first peer to send a per-message (wrapped) token following context establishment.
For more information, see Simple Authentication and Security Layer (SASL).
Example: Using per-message services to receive a message
byte[] plaintextFromFoo =
serverAcceptorContext.unwrap(wrappedTokenFromFoo, 0,
wrappedTokenFromFoo.length, mprop);
// foo can now examine mprop to determine the message properties applied by
Related concepts
IBM JGSS application programming steps
There are multiple steps required to develop a JGSS application, including using transport tokens,
creating the necessary JGSS objects, establishing and deleting context, and using per-message services.
JGSS debugging
When you are trying to identify JGSS problems, use the JGSS debugging capability to produce helpful
categorized messages.
You can turn on one or more categories by setting the appropriate values for the Java property
com.ibm.security.jgss.debug. Activate multiple categories by using a comma to separate the category
names.
Debugging categories include the following:
Category Description
help List debug catgories
all Turn on debugging for all categories
off Turn off debugging completely
app Application debugging (default)
ctx Context operations debugging
cred Credentials (including name) operations
marsh Marshaling of tokens
mic MIC operations
prov Provider operations
qop QOP operations
unmarsh Unmarshaling of tokens
unwrap Unwrap operations
wrap Wrap operations
import com.ibm.security.jgss.debug;
if (debug.on(Debug.OPTS_CAT_APPLICATION)) {
// Fill someBuffer with data.
debug.out(Debug.OPTS_CAT_APPLICATION, someBuffer);
// someBuffer may be a byte array or a String.
Related concepts
JGSS concepts
JGSS operations consist of four distinct stages, as standardized by the Generic Security Service
Application Programming Interface (GSS-API).
Configuring your server to use IBM JGSS
How you configure your server to use JGSS depends on which version of the Java Platform, Standard
Edition (J2SE) that you run on your system.
Running IBM JGSS applications
The IBM Java Generic Security Service (JGSS) API 1.0 shields secure applications from the complexities
and peculiarities of the different underlying security mechanisms. JGSS uses features provided by Java
Authentication and Authorization Service (JAAS) and IBM Java Cryptography Extension (JCE).
Developing IBM JGSS applications
Use JGSS to develop secure applications. Learn about generating transport tokens, creating JGSS objects,
establishing context, and more.
Samples: IBM Java Generic Security Service (JGSS)
The IBM Java Generic Security Service (JGSS) sample files include client and server programs,
configuration files, policy files, and Javadoc reference information. Use the sample programs to test and
verify your JGSS setup.
Related reference
IBM JGSS Javadoc reference information
The Javadoc reference information for IBM JGSS includes classes and methods in the org.ietf.jgss api
package and the Java versions of some Kerberos credential management tools.
# ---------------------------------------------------------------------------------
# Kerberos configuration file for running the JGSS sample applications.
# Modify the entries to suit your environment.
#----------------------------------------------------------------------------------
[libdefaults]
default_keytab_name = /QIBM/UserData/OS400/NetworkAuthentication/keytab/krb5.keytab
default_realm = REALM.IBM.COM
default_tkt_enctypes = des-cbc-crc
default_tgs_enctypes = des-cbc-crc
default_checksum = rsa-md5
kdc_timesync = 0
kdc_default_options = 0x40000010
clockskew = 300
check_delegate = 1
ccache_type = 3
kdc_timeout = 60000
[realms]
REALM.IBM.COM = {
kdc = kdc.ibm.com:88
}
[domain_realm]
.ibm.com = REALM.IBM.COM
/**
* ---------------------------------------------------------------------------------
* JAAS Login Configuration for the JGSS samples.
* ---------------------------------------------------------------------------------
*
* 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.
JAASClient {
com.ibm.security.auth.module.Krb5LoginModule required
useDefaultCcache=true;
};
JAASServer {
com.ibm.security.auth.module.Krb5LoginModule required
credsType=acceptor useDefaultKeytab=true
principal=gss_service/[email protected];
};
// ----------------------------------------------------------------------------
// JAAS policy file for running the JGSS sample applications.
// Modify these permissions to suit your environment.
// Not recommended for use for any purpose other than that stated above.
// In particular, do not use this policy file or its
// contents to protect resources in a production environment.
//
// 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.
//
// ----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Permissions for client only
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Permissions for the server only
//-----------------------------------------------------------------------------
// The server acts as a client when communicating with the secondary (backup) server
// This permission allows the server to initiate a context with the secondary server
permission javax.security.auth.kerberos.ServicePermission
"gss_service2/[email protected]", "initiate";
};
//-----------------------------------------------------------------------------
// Permissions for the secondary server
//-----------------------------------------------------------------------------
// -----------------------------------------------------------------
// Java policy file for running the JGSS sample applications on
// the server.
// Modify these permissions to suit your environment.
// Not recommended for use for any purpose other than that stated above.
// In particular, do not use this policy file or its
// contents to protect resources in a production environment.
//
// 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.
//
//---------------------------------------------------------------------
// Access to the Kerberos key table so we can get our server key.
permission java.io.FilePermission
"/QIBM/UserData/OS400/NetworkAuthentication/keytab/krb5.keytab", "read";
Samples: Downloading and viewing Javadoc information for the IBM JGSS samples
To download and view the documentation for the IBM JGSS sample programs, complete the following
steps.
1. Choose an existing directory (or create a new one) where you want to store the Javadoc information.
2. Download the Javadoc information (jgsssampledoc.zip) into the directory.
3. Extract the files from jgsssampledoc.zip into the directory.
4. Use your browser to access the index.htm file.
Related concepts
Viewing the IBM JGSS samples
The IBM Java Generic Security Service (JGSS) sample files include client and server programs,
configuration files, policy files, and Javadoc reference information. Use the following links to view HTML
versions of the JGSS samples.
Related tasks
Samples: Downloading and running the sample JGSS programs
This topic contains instructions for downloading and running the sample Javadoc information.
where
• [-DpropertyN=valueN] is one or more optional Java properties, including the names of the configuration
and policy files, JGSS debug options, and the security manager. For more information, see the following
example and Running JGSS applications.
• <program> is a required parameter that specifies the sample program that you want to run (either
Client, Server, JAASClient, or JAASServer).
• [options] is an optional parameter for the sample program that you want to run. To display a list of
supported options, use the following command:
java com.ibm.security.jgss.test.<program> -?
Note: Turn off the JAAS features in a JGSS-enabled sample by setting the Java property
javax.security.auth.useSubjectCredsOnly to false. Of course, the default value of the JAAS-enabled
samples is to turn on JAAS, meaning that the property value is true. The non-JAAS client and server
programs set the property to false, unless you have explicitly set the property value.
Related information
You may want to read about related tasks or look at an example:
• “Samples: Preparing to run the JGSS sample programs” on page 348
• “Samples: Downloading the IBM JGSS samples” on page 348
• “Example: Running the non-JAAS sample” on page 349
Related concepts
Java garbage collection
Garbage collection is the process of freeing storage that is used by objects that are no longer referred
to by a program. With garbage collection, programmers no longer have to write error prone code to
explicitly "free" or "delete" their objects. This code frequently results in "memory leak" program errors.
The garbage collector automatically detects an object or group of objects that the user program can no
longer reach. It does this because there are no references to that object in any program structure. Once
the object has been collected, you can allocate the space for other uses.
Java Native Method Invocation performance considerations
Related concepts
“Support for multiple Java Development Kits (JDKs)” on page 6
Java hwkeytool
The hwkeytool application enables you to use the cryptography capabilities of the model 4764
Cryptographic Coprocessor with the Java Cryptography Extension (JCE) and Java Cryptography
Architecture (JCA).
The hwkeytool application for hardware uses the same syntax and commands as the keytool
application with the exception of two commands and the default keystore. The hardware keytool provides
additional parameters to the -genkey and delete commands.
On the -genkey command, the following additional parameters are available:
-KeyLabel
Allows you to set a specific label for the hardware key.
-hardwaretype
Determine the type of key pair: Public key data set (PKDS) or RETAINED.
-hardwareusage
Set the usage of the key pair being generated, either a signature-only key or a signature and key
management key.
On the delete command, an additional parameter of -hardwarekey , which deletes the key pair from the
keystore and from the hardware, is available.
The default keystore name is .HWkeystore. You can change this using the -keystore parameter.
4764 Cryptographic Coprocessor
If the batch job is started in some other way, then the JAVA_TOOL_OPTIONS environment variable may be
used to start the debug agent. The JAVA_TOOL_OPTIONS environment variable is automatically queried
by the JVM during startup. If it is set to -agentlib:d9ti, then the debug agent will be started for the JVM.
For example:
If the batch job does not automatically inherit all environment variables, then the JAVA_TOOL_OPTIONS
environment variable will need to be set system-wide. For example:
Note: When you set the JAVA_TOOL_OPTIONS environment variable system-wide, all IBM Technology
for Java JVMs started on the system are started with debug enabled. This may result in a significant
performance degradation.
Enabling Java debug for a JVM created with the Java Invocation API
When using the JNI_CreateJavaVM API to create a JVM, or when calling a Java method from RPG using
the EXTPROC(*JAVA) support, you can enable debug using any one of the following methods:
• Set the JAVA_TOOL_OPTIONS environment variable to -agentlib:d9ti.
• Add the -debug parameter to the options parameter list passed to the JNI_CreateJavaVM API.
• Add the -agentlib:d9ti parameter to the options parameter list passed to the JNI_CreateJavaVM
API.
• Add "-debug" or "-agentlib:d9ti" to the QIBM_RPG_JAVA_OPTIONS environment variable if you are
starting the JVM by calling a Java method from RPG.
Debugging must be done from another job.
In addition, in order to see the Java source code for the classes being debugged, the DEBUGSOURCEPATH
environment variable may need to be set to the base directory location of the Java source code.
Starting the IBM Technology for Java JVM from the IBM i Debugger graphical user
interface
In order to start an IBM Technology for Java JVM from the IBM i Debugger graphical user interface, the
JAVA_HOME environment variable must be set when starting the JVM job. You can set this environment
variable using the Initialization Command display when starting the JVM. This display is located in the
Start Debug window of the IBM i Debugger interface.
For example, in order to start a 32-bit JDK 7.0 JVM, add the following to the Initialization Command
display:
Debug operations
You can use the interactive display of your server to use the *DEBUG option to view the source code
before running the program. Then, you can set breakpoints, or step over or into a program to analyze
errors while the program is running.
+--------------------------------------------------------------------------------+
| Display Module Source |
| |
| Class file name: HELLOD |
| 1 import java.lang.*; |
| 2 |
| 3 public class Hellod extends Object |
| 4 { |
| 5 int k; |
| 6 int l; |
| 7 int m; |
| 8 int n; |
| 9 int o; |
| 10 int p; |
| 11 String myString; |
| 12 Hellod myHellod; |
| 13 int myArray[]; |
| 14 |
| 15 public Hellod() |
| More... |
+--------------------------------------------------------------------------------+
| Work with Module List |
| System: AS400 |
| Type options, press enter. |
| 1=Add program 4=Remove program 5=Display module source |
| 8=Work with module breakpoints |
| |
| Opt Program/module Library Type |
| *LIBL *SRVPGM |
| HELLOD *CLASS Selected |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| Bottom |
| Command |
| ===> |
| F3=Exit F4=Prompt F5=Refresh F9=Retrieve F12=Cancel |
| F22=Display class file name |
| |
+--------------------------------------------------------------------------------+
• When adding a class to debug, you may need to enter a package-qualified class name that is longer than
the Program/module input field. To enter a longer name, follow these steps:
1. Enter Option 1 (Add program).
2. Leave the Program/module field blank.
3. Leave the library field as *LIBL.
4. Enter *CLASS for Type.
5. Press Enter.
6. A pop up window is displayed where you have more room to enter the package-qualified class file
name. For example: pkgname1.pkgname2.classname
Setting breakpoints
You can control the running of a program with breakpoints. Breakpoints stop a running program at a
specific statement.
To set breakpoints, perform the following steps:
1. Place the cursor on the line of code where you would like to set a breakpoint.
2. Press F6 (Add/Clear breakpoint) to set the breakpoint.
3. Press F12 (Resume) to run the program.
Note: Just before the line of code runs, where the breakpoint is set, the program source is displayed
indicating that the breakpoint was hit.
+--------------------------------------------------------------------------------+
| Display Module Source |
| |
|Current thread: 00000019 Stopped thread: 00000019 |
|Class file name: Hellod |
Once a breakpoint is encountered or a step is completed, you can use the TBREAK command to set a
breakpoint that only applies to the current thread.
+--------------------------------------------------------------------------------+
| Display Module Source |
| |
|Current thread: 00000019 Stopped thread: 00000019 |
|Class file name: Hellod |
|35 public static void main(String[] args) |
|36 { |
|37 int i,j,h,B[],D[][]; |
|38 Hellod A=new Hellod(); |
|39 A.myHellod = A; |
|40 Hellod C[]; |
|41 C = new Hellod[5]; |
|42 for (int counter=0; counter<2; counter++) { |
|43 C[counter] = new Hellod(); |
|44 C[counter].myHellod = C[counter]; |
|45 } |
|46 C[2] = A; |
|47 C[0].myString = null; |
|48 C[0].myHellod = null; |
|49 A.method1(); |
|Debug . . . |
| |
|F3=End program F6=Add/Clear breakpoint F10=Step F11=Display variable |
|F12=Resume F17=Watch variable F18=Work with watch F24=More key |
|Step completed at line 42 in thread 00000019 |
+--------------------------------------------------------------------------------+
2. Add the class to the debug view from the Display Module Source screen.
If the class has already been loaded into the Java virtual machine (JVM), just add the *CLASS as usual
and display the source code to debug.
For example, to view the source for pkg1/test14.class, enter the following:
If the class has not been loaded into the JVM, perform the same steps to add the *CLASS as previously
indicated. The Java class file not available message then displays. At this point, you may resume
program processing. The JVM automatically stops when any method of the class matching the given
name is entered. The source code for the class is displayed and can be debugged.
Debugging servlets
Debugging servlets is a special case of debugging classes loaded through a custom class loader. Servlets
run in the Java runtime of an application server such as IBM WebSphere Application Server for IBM i or
the IBM Integrated Web Application Server for i. You have several options to debug servlets.
You can debug servlets by following the instructions for classes loaded through a custom class loader.
You can also use the interactive display of your server to debug a servlet by completing the following
steps:
1. Use the javac -g command in the Qshell Interpreter to compile your servlet.
2. Copy the source code (.java file) and compiled code (.class file) to a directory in your classpath.
3. Start the server.
4. Run the Start Service Job (STRSRVJOB) command on the job where the servlet runs.
5. Enter STRDBG CLASS(myServlet), where myServlet is the name of your servlet. The source should be
displayed.
6. Set a breakpoint in the servlet and press F12.
7. Run your servlet. When the servlet hits the breakpoint, you can continue debugging.
Another way to debug Java programs and servlets that run on your system is to use the IBM i Debugger.
The IBM i Debugger provides a graphical user interface that enables you to more easily use the debugging
capabilities of your system.
Related information
IBM i Debugger
For more information about using JVMTI, see the JVMTI Reference page at the Oracle America, Inc.
Web site.
In this example, JDWP listens for connections from remote debuggers on TCP/IP port 8000, but you can
use any port number you want; dt_socket is the name of the SRVPGM that handles the JDWP transport
and does not change.
For additional options that you can use with -agentlib, see Sun VM Invocation Options by Oracle
America, Inc.
For more information on JDPA, see Java Platform Debugger Architecture by Oracle America, Inc.
Related concepts
Debugging Java programs using IBM i Debugger
Related concepts
Debugging Java programs using IBM i Debugger
The easiest way to debug Java programs that run on your system is to use the IBM i Debugger. The
IBM i Debugger provides a graphical user interface that enables you to more easily use the debugging
capabilities of your system.
Java Platform Debugger Architecture
The Java Platform Debugger Architecture (JPDA) consists of the JVM Debug Interface/JVM Tool Interface,
the Java Debug Wire Protocol, and the Java Debug Interface. All these parts of the JPDA enable any front
end of a debugger that uses the JDWP to perform debugging operations. The debugger front end can
either run remotely or run as a IBM i application.
Using the Generate JVM Dump command
The Generate JVM Dump (GENJVMDMP) CL command can be used to generate Java, system, and heap
dumps.
//************************
// File: DateExample.java
//************************
import java.text.*;
import java.util.*;
import java.util.Date;
//**************************
// File: NumberExample.java
//**************************
//*********************************
// File: ResourceBundleExample.java
//*********************************
import java.util.*;
// Default locale
rb = ResourceBundle.getBundle(resourceName);
System.out.println("Default : " + rb.getString("Hello" + ".text"));
// No property file for China in this example... use default, which is now fr_FR.
rb = ResourceBundle.getBundle(resourceName, Locale.CHINA);
System.out.println("Chinese : " + rb.getString("Hello" + ".text"));
}
}
test.setup();
test.run();
test.cleanup();
}
/**
Set up the DataSource used in the testing.
**/
public void setup()
throws Exception
{
Class.forName("com.ibm.db2.jdbc.app.DB2Driver");
connection = DriverManager.getConnection(url);
Statement s = connection.createStatement();
try {
s.executeUpdate("DROP TABLE CUJOSQL.TEMP");
} catch (SQLException e) { // Ignore it - it doesn't exist
}
try {
String sql = "CREATE PROCEDURE CUJOSQL.TEMP "
+ " LANGUAGE SQL SPECIFIC CUJOSQL.TEMP "
+ " MYPROC: BEGIN"
+ " RETURN 11;"
+ " END MYPROC";
s.executeUpdate(sql);
} catch (SQLException e) {
// Ignore it - it exists.
}
s.executeUpdate("create table cujosql.temp (col1 char(10))");
s.executeUpdate("insert into cujosql.temp values ('compare')");
s.close();
}
rs.next();
if (rs.getString(1).equals("compare "))
return true;
return false;
} catch (SQLException e) {
// System.out.println("Exception: SQLState(" +
// e.getSQLState() + ") " + e + " (" + e.getErrorCode() + ")");
return false;
} finally {
if (s != null) {
try {
s.close();
} catch (Exception e) {
// Ignore it.
}
}
}
}
return true;
} catch (SQLException e) {
//System.out.println("Exception: SQLState(" +
// e.getSQLState() + ") " + e + " (" + e.getErrorCode() + ")");
return false;
} finally {
if (s != null) {
try {
s.close();
} catch (Exception e) {
// Ignore it.
}
}
}
}
return true;
} catch (SQLException e) {
//System.out.println("Exception: SQLState(" +
// e.getSQLState() + ") " + e + " (" + e.getErrorCode() + ")");
Example: BLOB
This is an example of how a BLOB can be put into the database or retrieved from the database.
Note: By using the code examples, you agree to the terms of the “Code license and disclaimer
information” on page 489.
/////////////////////////////////////////
// PutGetBlobs is an example application
// that shows how to work with the JDBC
// API to obtain and put BLOBs to and from
// database columns.
//
// The results of running this program
// are that there are two BLOB values
// in a new table. Both are identical
// and contain 500k of random byte
// data.
/////////////////////////////////////////
import java.sql.*;
import java.util.Random;
// Process a query and obtain the BLOB that was just inserted out
// of the database as a Blob object.
ResultSet rs = s.executeQuery("SELECT * FROM CUJOSQL.BLOBTABLE");
rs.next();
Blob blob = rs.getBlob(1);
Related reference
Example: Updating BLOBs
This is an example of how to update BLOBs in your Java applications.
Example: Using BLOBs
This is an example of how to use BLOBs in your Java applications.
“CallableStatements” on page 93
The JDBC CallableStatement interface extends PreparedStatement and provides support for output and
input/output parameters. The CallableStatement interface also has support for input parameters that is
provided by the PreparedStatement interface.
import java.sql.*;
test.setup();
test.displayTable();
test.run();
test.displayTable();
test.cleanup();
}
/**
Handle all the required setup work.
**/
public void setup() {
try {
// Register the JDBC driver.
Class.forName("com.ibm.db2.jdbc.app.DB2Driver");
connection = DriverManager.getConnection("jdbc:db2:*local");
Statement s = connection.createStatement();
try {
s.executeUpdate("DROP TABLE CUJOSQL.WHERECUREX");
} catch (SQLException e) {
// Ignore problems here.
}
s.close();
} catch (Exception e) {
/**
In this section, all the code to perform the testing should
be added. If only one connection to the database is needed,
the global variable 'connection' can be used.
**/
public void run() {
try {
Statement stmt1 = connection.createStatement();
} catch (Exception e) {
System.out.println("Caught exception: ");
e.printStackTrace();
}
}
/**
In this section, put all clean-up work for testing.
**/
public void cleanup() {
try {
// Close the global connection opened in setup().
connection.close();
} catch (Exception e) {
System.out.println("Caught exception: ");
e.printStackTrace();
}
}
/**
Display the contents of the table.
**/
public void displayTable()
{
try {
Statement s = connection.createStatement();
ResultSet rs = s.executeQuery ("SELECT * FROM CUJOSQL.WHERECUREX");
rs.close ();
s.close();
System.out.println("-----------------------------------------");
} catch (Exception e) {
System.out.println("Caught exception: ");
Example: CLOB
This is an example of how a CLOB can be put into the database or retrieved from the database.
Note: By using the code examples, you agree to the terms of the “Code license and disclaimer
information” on page 489.
/////////////////////////////////////////
// PutGetClobs is an example application
// that shows how to work with the JDBC
// API to obtain and put CLOBs to and from
// database columns.
//
// The results of running this program
// are that there are two CLOB values
// in a new table. Both are identical
// and contain about 500k of repeating
// text data.
/////////////////////////////////////////
import java.sql.*;
// Process a query and get the CLOB that was just inserted out of the
// database as a Clob object.
ResultSet rs = s.executeQuery("SELECT * FROM CUJOSQL.CLOBTABLE");
rs.next();
Clob clob = rs.getClob(1);
Related reference
Example: Updating CLOBs
This is an example of how to update CLOBs in your Java applications.
Example: Using CLOBs
This is an example of how to use CLOBs in your Java applications.
Related reference
Example: Using metadata ResultSets that have more than one column
This is an example of how to use metadata ResultSets that have more than one column.
Example: Datalink
This example application shows how to use the JDBC API to handle datalink database columns.
Note: By using the code examples, you agree to the terms of the “Code license and disclaimer
information” on page 489.
/////////////////////////////////////////
// PutGetDatalinks is an example application
// that shows how to use the JDBC
// API to handle datalink database columns.
/////////////////////////////////////////
import java.sql.*;
import java.net.URL;
import java.net.MalformedURLException;
// Process a query and obtain the CLOB that was just inserted out of the
// database as a Clob object.
ResultSet rs = s.executeQuery("SELECT * FROM CUJOSQL.DLTABLE");
rs.next();
String datalink = rs.getString(1);
/////////////////////////////////////////
// This example program shows examples of
// various common tasks that can be done
// with distinct types.
/////////////////////////////////////////
import java.sql.*;
Connection c = DriverManager.getConnection("jdbc:db2:*local");
Statement s = c.createStatement();
try {
s.executeUpdate("DROP DISTINCT TYPE CUJOSQL.SSN");
} catch (SQLException e) {
// Ignore it and assume the table did not exist.
}
// You can obtain details about the types available with new metadata in
// JDBC 2.0
DatabaseMetaData dmd = c.getMetaData();
Related concepts
Writing code that uses BLOBs
There are a number of tasks that can be accomplished with database Binary Large Object (BLOB) columns
through the Java Database Connectivity (JDBC) Application Programming Interface (API). The following
topics briefly discuss these tasks and include examples on how to accomplish them.
Writing code that uses CLOBs
There are a number of tasks that can be performed with database CLOB and DBCLOB columns through
the Java Database Connectivity (JDBC) Application Programming Interface (API). The following topics
briefly discuss these tasks and include examples on how to accomplish them.
Writing code that uses Datalinks
import java.sql.*;
import sqlj.runtime.*;
import sqlj.runtime.ref.*;
class App
{
/**********************
** Register Driver **
**********************/
static
{
try
{
Class.forName("com.ibm.db2.jdbc.app.DB2Driver").newInstance();
}
catch (Exception e)
{
e.printStackTrace();
}
}
/********************
** Main **
********************/
// URL is jdbc:db2:dbname
String url = "jdbc:db2:sample";
import java.sql.*;
import javax.sql.*;
import java.util.*;
import javax.transaction.*;
import javax.transaction.xa.*;
import com.ibm.db2.jdbc.app.*;
test.setup();
test.run();
}
/**
* Handle the previous cleanup run so that this test can recommence.
*/
public void setup() {
Connection c = null;
Statement s = null;
try {
Class.forName("com.ibm.db2.jdbc.app.DB2Driver");
c = DriverManager.getConnection("jdbc:db2:*local");
s = c.createStatement();
try {
s.executeUpdate("DROP TABLE CUJOSQL.JTATABLE");
} catch (SQLException e) {
// Ignore... does not exist
}
s.close();
} finally {
if (c != null) {
c.close();
}
}
}
/**
* This test use JTA support to handle transactions.
*/
public void run() {
Connection c = null;
try {
try {
String value = rs.getString(1);
System.out.println("Something failed if you receive this message.");
} catch (SQLException e) {
System.out.println("The expected exception was thrown.");
}
} catch (Exception e) {
System.out.println("Something has gone wrong.");
e.printStackTrace();
} finally {
try {
if (c != null)
c.close();
} catch (SQLException e) {
System.out.println("Note: Cleaup exception.");
e.printStackTrace();
}
}
}
}
Related reference
Example: Using JTA to handle a transaction
This is an example of how to use the Java Transaction API (JTA) to handle a transaction in an application.
Example: Multiple connections that work on a transaction
This is an example of how to use multiple connections working on a single transaction.
Example: Using a connection with multiple transactions
This is an example of how to use a single connection with multiple transactions.
Example: Suspended ResultSets
This is an example of the how a Statement object is reprocessed under another transaction to perform
work.
Example: Suspending and resuming a transaction
Example: JDBC
This is an example of how to use the BasicJDBC program. This program uses the native JDBC driver for
the IBM Developer Kit for Java to build a simple table and process a query that displays the data in that
table.
Note: By using the code examples, you agree to the terms of the “Code license and disclaimer
information” on page 489.
//////////////////////////////////////////////////////////////////////////////////
//
// BasicJDBC example. This program uses the native JDBC driver for the
// Developer Kit for Java to build a simple table and process a query
// that displays the data in that table.
//
// Command syntax:
// BasicJDBC
//
//////////////////////////////////////////////////////////////////////////////////
//
// This source is an example of the native JDBC driver.
// IBM grants you a nonexclusive license to use this as an example
// from which you can generate similar function tailored to
// your own specific needs.
//
// This 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
// merchantability and fitness for a particular purpose are
// expressly disclaimed.
//
// IBM Developer Kit for Java
// (C) Copyright IBM Corp. 2001
// All rights reserved.
// US Government Users Restricted Rights -
// Use, duplication, or disclosure restricted
// by GSA ADP Schedule Contract with IBM Corp.
//
//////////////////////////////////////////////////////////////////////////////////
/**
This is the constructor for the basic JDBC test. It creates a database
connection that is stored in an instance variable to be used in later
method calls.
**/
public BasicJDBC() {
// Use a try/catch block to catch all exceptions that can come out of the
// following code.
try {
// The DriverManager must be aware that there is a JDBC driver available
// to handle a user connection request. The following line causes the
// native JDBC driver to be loaded and registered with the DriverManager.
Class.forName("com.ibm.db2.jdbc.app.DB2Driver");
// Create the database Connection object that this program uses in all
// the other method calls that are made. The following code specifies
// that a connection is to be established to the local database and that
// that connection should conform to the properties that were set up
// previously (that is, it should use the user ID and password specified).
connection = DriverManager.getConnection("jdbc:db2:*local", properties);
} catch (Exception e) {
// If any of the lines in the try/catch block fail, control transfers to
// the following line of code. A robust application tries to handle the
// problem or provide more details to you. In this program, the error
// message from the exception is displayed and the application allows
// the program to return.
System.out.println("Caught exception: " + e.getMessage());
}
}
/**
Ensures that the qgpl.basicjdbc table looks you want it to at the start of
the test.
try {
// Build the test table from scratch. Process an update statement
// that attempts to delete the table if it currently exists.
s.executeUpdate("drop table qgpl.basicjdbc");
} catch (SQLException e) {
// Do not perform anything if an exception occurred. Assume
// that the problem is that the table that was dropped does not
// exist and that it can be created next.
}
// Use the statement object to populate our table with some data.
s.executeUpdate("insert into qgpl.basicjdbc values(1, 'Frank Johnson')");
s.executeUpdate("insert into qgpl.basicjdbc values(2, 'Neil Schwartz')");
s.executeUpdate("insert into qgpl.basicjdbc values(3, 'Ben Rodman')");
s.executeUpdate("insert into qgpl.basicjdbc values(4, 'Dan Gloore')");
/**
Runs a query against the demonstration table and the results are displayed to
standard out.
**/
public void runQuery() {
// Wrap all the functionality in a try/catch block so an attempts is
// made to handle any errors that might happen within this
// method.
try {
// Create a Statement object.
Statement s = connection.createStatement();
// Display the top of our 'table' and initialize the counter for the
// number of rows returned.
System.out.println("--------------------");
int i = 0;
// Obtain both columns in the table for each row and write a row to
// our on-screen table with the data. Then, increment the count
// of rows that have been processed.
System.out.println("| " + rs.getInt(1) + " | " + rs.getString(2) + "|");
i++;
}
// Place a border at the bottom on the table and display the number of rows
// as output.
System.out.println("--------------------");
System.out.println("There were " + i + " rows returned.");
} catch (SQLException e) {
// Display more information about any SQL exceptions that are
// generated as output.
System.out.println("SQLException exception: ");
System.out.println("Message:....." + e.getMessage());
System.out.println("SQLState:...." + e.getSQLState());
System.out.println("Vendor Code:." + e.getErrorCode());
e.printStackTrace();
}
}
/**
The following method ensures that any JDBC resources that are still
allocated are freed.
**/
public void cleanup() {
try {
if (connection != null)
connection.close();
} catch (Exception e) {
System.out.println("Caught exception: ");
e.printStackTrace();
}
}
}
import java.sql.*;
import javax.sql.*;
import java.util.*;
import javax.transaction.*;
import javax.transaction.xa.*;
import com.ibm.db2.jdbc.app.*;
public class JTAMultiConn {
public static void main(java.lang.String[] args) {
JTAMultiConn test = new JTAMultiConn();
test.setup();
test.run();
}
/**
* Handle the previous cleanup run so that this test can recommence.
*/
public void setup() {
Connection c = null;
Statement s = null;
try {
Class.forName("com.ibm.db2.jdbc.app.DB2Driver");
c = DriverManager.getConnection("jdbc:db2:*local");
s = c.createStatement();
try {
s.executeUpdate("DROP TABLE CUJOSQL.JTATABLE");
}
catch (SQLException e) {
// Ignore... does not exist
}
s.executeUpdate("CREATE TABLE CUJOSQL.JTATABLE (COL1 CHAR
(50))");
s.close();
}
finally {
if (c != null) {
c.close();
}
}
}
/**
* This test uses JTA support to handle transactions.
*/
public void run() {
Connection c1 = null;
xaRes2.start(xid, XAResource.TMJOIN);
int count2 = stmt2.executeUpdate("INSERT INTO " + tableName + "VALUES('Value 1-B')");
xaRes2.end(xid, XAResource.TMNOFLAGS);
xaRes3.start(xid, XAResource.TMJOIN);
int count3 = stmt3.executeUpdate("INSERT INTO " + tableName + "VALUES('Value 1-C')");
xaRes3.end(xid, XAResource.TMSUCCESS);
// When completed, commit the transaction as a single unit.
// A prepare() and commit() or 1 phase commit() is required for
// each separate database (XAResource) that participated in the
// transaction. Since the resources accessed (xaRes1, xaRes2, and xaRes3)
// all refer to the same database, only one prepare or commit is required.
int rc = xaRes.prepare(xid);
xaRes.commit(xid, false);
}
catch (Exception e) {
System.out.println("Something has gone wrong.");
e.printStackTrace();
}
finally {
try {
if (c1 != null) {
c1.close();
}
}
catch (SQLException e) {
System.out.println("Note: Cleaup exception " +
e.getMessage());
}
try {
if (c2 != null) {
c2.close();
}
}
catch (SQLException e) {
System.out.println("Note: Cleaup exception " +
e.getMessage());
}
try {
if (c3 != null) {
c3.close();
}
}
catch (SQLException e) {
System.out.println("Note: Cleaup exception " +
e.getMessage());
}
}
}
}
Example: ParameterMetaData
This is an example of using the ParameterMetaData interface to retrieve information about parameters.
Note: By using the code examples, you agree to the terms of the “Code license and disclaimer
information” on page 489.
//////////////////////////////////////////////////////////////////////////////////
//
// ParameterMetaData example. This program demonstrates
// the new support of JDBC 3.0 for learning information
// about parameters to a PreparedStatement.
//
// Command syntax:
// java PMD
//
//////////////////////////////////////////////////////////////////////////////////
//
// This source is an example of the IBM Developer for Java JDBC driver.
// IBM grants you a nonexclusive license to use this as an example
// from which you can generate similar function tailored to
// your own specific needs.
//
// This 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
// merchantability and fitness for a particular purpose are
// expressly disclaimed.
//
// IBM Developer Kit for Java
// (C) Copyright IBM Corp. 2001
// All rights reserved.
// US Government Users Restricted Rights -
// Use, duplication, or disclosure restricted
// by GSA ADP Schedule Contract with IBM Corp.
//
//////////////////////////////////////////////////////////////////////////////////
import java.sql.*;
import java.sql.*;
test.setup();
test.displayTable();
test.run();
test.displayTable();
test.cleanup();
}
/**
Handle all the required setup work.
**/
public void setup() {
try {
// Register the JDBC driver.
Class.forName("com.ibm.db2.jdbc.app.DB2Driver");
connection = DriverManager.getConnection("jdbc:db2:*local");
Statement s = connection.createStatement();
try {
s.executeUpdate("DROP TABLE CUJOSQL.WHERECUREX");
} catch (SQLException e) {
// Ignore problems here.
}
s.close();
} catch (Exception e) {
System.out.println("Caught exception: " + e.getMessage());
e.printStackTrace();
}
}
/**
In this section, all the code to perform the testing should
be added. If only one connection to the database is required,
the global variable 'connection' can be used.
**/
} catch (Exception e) {
System.out.println("Caught exception: ");
e.printStackTrace();
}
}
/**
In this section, put all clean-up work for testing.
**/
public void cleanup() {
try {
// Close the global connection opened in setup().
connection.close();
} catch (Exception e) {
System.out.println("Caught exception: ");
e.printStackTrace();
}
}
/**
Display the contents of the table.
**/
public void displayTable()
{
try {
Statement s = connection.createStatement();
ResultSet rs = s.executeQuery ("SELECT * FROM CUJOSQL.WHERECUREX");
rs.close ();
s.close();
System.out.println("-----------------------------------------");
} catch (Exception e) {
System.out.println("Caught exception: ");
e.printStackTrace();
}
}
}
import java.sql.*;
/**
ResultSetExample.java
try {
// Get a database connection and prepare a statement.
Class.forName("com.ibm.db2.jdbc.app.DB2Driver");
con = DriverManager.getConnection("jdbc:db2:*local");
s = con.createStatement();
} catch (Exception e) {
// Handle any errors.
System.out.println("Oops... we have an error... ");
e.printStackTrace();
} finally {
// Ensure we always clean up. If the connection gets closed, the
// statement under it closes as well.
if (con != null) {
try {
con.close();
} catch (SQLException e) {
System.out.println("Critical error - cannot close connection object");
}
}
}
}
}
Related concepts
ResultSet characteristics
This topic discusses ResultSet characteristics such ResultSet types, concurrency, ability to close the
ResultSet by committing the connection object, and specification of ResultSet characteristics.
Cursor movement
import java.sql.*;
test.setup();
test.run("sensitive");
test.cleanup();
test.setup();
test.run("insensitive");
test.cleanup();
}
try {
System.out.println("Native JDBC used");
Class.forName("com.ibm.db2.jdbc.app.DB2Driver");
connection = DriverManager.getConnection("jdbc:db2:*local");
Statement s = connection.createStatement();
try {
s.executeUpdate("drop table cujosql.sensitive");
} catch (SQLException e) {
// Ignored.
}
try {
s.executeUpdate("drop table cujosql.sensitive2");
} catch (SQLException e) {
// Ignored.
}
s.close();
} catch (Exception e) {
System.out.println("Caught exception: " + e.getMessage());
if (e instanceof SQLException) {
SQLException another = ((SQLException) e).getNextException();
System.out.println("Another: " + another.getMessage());
}
}
}
Statement s = null;
if (sensitivity.equalsIgnoreCase("insensitive")) {
System.out.println("creating a TYPE_SCROLL_INSENSITIVE cursor");
s = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
} else {
System.out.println("creating a TYPE_SCROLL_SENSITIVE cursor");
s = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_READ_ONLY);
}
rs.next();
System.out.println("value is " + rs.getInt(1));
rs.next();
System.out.println("value is " + rs.getInt(1));
rs.next();
System.out.println("value is " + rs.getInt(1));
rs.next();
System.out.println("value is " + rs.getInt(1));
// Another statement creates a value that does not fit the where clause.
Statement s2 =
connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_UPDATEABLE);
ResultSet rs2 = s2.executeQuery("select *
from cujosql.sensitive where col1 = 5 FOR UPDATE");
rs2.next();
rs2.updateInt(1, -1);
rs2.updateRow();
s2.close();
if (rs.next()) {
System.out.println("There is still a row: " + rs.getInt(1));
} else {
System.out.println("No more rows.");
}
} catch (SQLException e) {
System.out.println("SQLException exception: ");
System.out.println("Message:....." + e.getMessage());
System.out.println("SQLState:...." + e.getSQLState());
System.out.println("Vendor Code:." + e.getErrorCode());
System.out.println("----------------------------");
e.printStackTrace();
}
catch (Exception ex) {
System.out.println("An exception other
than an SQLException was thrown: ");
ex.printStackTrace();
}
}
import java.sql.*;
test.setup();
test.run("sensitive");
test.cleanup();
test.setup();
test.run("insensitive");
test.cleanup();
}
try {
Class.forName("com.ibm.db2.jdbc.app.DB2Driver");
connection = DriverManager.getConnection("jdbc:db2:*local");
Statement s = connection.createStatement();
try {
s.executeUpdate("drop table cujosql.sensitive");
} catch (SQLException e) {
// Ignored.
}
} catch (Exception e) {
System.out.println("Caught exception: " + e.getMessage());
if (e instanceof SQLException) {
SQLException another = ((SQLException) e).getNextException();
System.out.println("Another: " + another.getMessage());
}
}
}
} catch (SQLException e) {
System.out.println("SQLException exception: ");
System.out.println("Message:....." + e.getMessage());
System.out.println("SQLState:...." + e.getSQLState());
System.out.println("Vendor Code:." + e.getErrorCode());
System.out.println("-------------------------------------");
e.printStackTrace();
}
catch (Exception ex) {
System.out.println("An exception other than an SQLException was thrown: ");
ex.printStackTrace();
}
}
import java.sql.*;
import javax.naming.*;
import com.ibm.db2.jdbc.app.UDBDataSource;
import com.ibm.db2.jdbc.app.UDBConnectionPoolDataSource;
// Establish a JNDI context and bind the connection pool data source
Context ctx = new InitialContext();
ctx.rebind("ConnectionSupport", cpds);
Example: SQLException
This is an example of catching an SQLException and dumping all the information that it provides.
Note: By using the code examples, you agree to the terms of the “Code license and disclaimer
information” on page 489.
import java.sql.*;
try {
Class.forName("com.ibm.db2.jdbc.app.DB2Driver");
connection = DriverManager.getConnection("jdbc:db2:*local");
Statement s = connection.createStatement();
int count = s.executeUpdate("insert into cujofake.cujofake values(1, 2,3)");
} catch (SQLException e) {
System.out.println("SQLException exception: ");
System.out.println("Message:....." + e.getMessage());
System.out.println("SQLState:...." + e.getSQLState());
System.out.println("Vendor Code:." + e.getErrorCode());
System.out.println("-----------------------------------------------------");
e.printStackTrace();
} catch (Exception ex) {
System.out.println("An exception other than an SQLException was thrown: ");
ex.printStackTrace();
} finally {
try {
if (connection != null) {
connection.close();
}
} catch (SQLException e) {
System.out.println("Exception caught attempting to shutdown...");
}
}
}
}
import java.sql.*;
import javax.sql.*;
import java.util.*;
test.setup();
test.run();
}
/**
* Handle the previous cleanup run so that this test can recommence.
*/
public void setup() {
Connection c = null;
Statement s = null;
try {
Class.forName("com.ibm.db2.jdbc.app.DB2Driver");
c = DriverManager.getConnection("jdbc:db2:*local");
s = c.createStatement();
try {
s.executeUpdate("DROP TABLE CUJOSQL.JTATABLE");
} catch (SQLException e) {
// Ignore... doesn't exist
}
s.close();
} finally {
if (c != null) {
c.close();
}
}
}
/**
* This test uses JTA support to handle transactions.
*/
public void run() {
Connection c = null;
try {
Context ctx = new InitialContext();
} catch (Exception e) {
System.out.println("Something has gone wrong.");
e.printStackTrace();
} finally {
try {
if (c != null)
c.close();
} catch (SQLException e) {
System.out.println("Note: Cleaup exception.");
e.printStackTrace();
}
}
}
}
Related reference
Example: Using JTA to handle a transaction
This is an example of how to use the Java Transaction API (JTA) to handle a transaction in an application.
Example: Multiple connections that work on a transaction
This is an example of how to use multiple connections working on a single transaction.
Example: Using a connection with multiple transactions
This is an example of how to use a single connection with multiple transactions.
Example: Suspended ResultSets
This is an example of the how a Statement object is reprocessed under another transaction to perform
work.
Example: Ending a transaction
import java.sql.*;
import javax.sql.*;
import java.util.*;
import javax.transaction.*;
import javax.transaction.xa.*;
import com.ibm.db2.jdbc.app.*;
test.setup();
test.run();
}
/**
* Handle the previous cleanup run so that this test can recommence.
*/
public void setup() {
Connection c = null;
Statement s = null;
try {
Class.forName("com.ibm.db2.jdbc.app.DB2Driver");
c = DriverManager.getConnection("jdbc:db2:*local");
s = c.createStatement();
try {
s.executeUpdate("DROP TABLE CUJOSQL.JTATABLE");
} catch (SQLException e) {
// Ignore... does not exist
}
s.close();
} finally {
if (c != null) {
c.close();
}
}
}
/**
* This test uses JTA support to handle transactions.
*/
public void run() {
Connection c = null;
try {
Context ctx = new InitialContext();
} catch (Exception e) {
System.out.println("Something has gone wrong.");
e.printStackTrace();
} finally {
try {
if (c != null)
c.close();
} catch (SQLException e) {
System.out.println("Note: Cleaup exception.");
e.printStackTrace();
}
}
}
}
Related reference
Example: Using JTA to handle a transaction
This is an example of how to use the Java Transaction API (JTA) to handle a transaction in an application.
Example: Multiple connections that work on a transaction
This is an example of how to use multiple connections working on a single transaction.
Example: Using a connection with multiple transactions
This is an example of how to use a single connection with multiple transactions.
Example: Ending a transaction
import java.sql.*;
import javax.naming.*;
import java.util.*;
import javax.sql.*;
startTime = System.currentTimeMillis();
for (int i = 0; i < 100; i++) {
Connection c1 = ds.getConnection();
c1.close();
}
endTime = System.currentTimeMillis();
System.out.println("Time spent: " + (endTime - startTime));
}
}
import java.sql.*;
import javax.naming.*;
import java.util.*;
import javax.sql.*;
import com.ibm.db2.jdbc.app.UDBDataSource;
import com.ibm.db2.jdbc.app.UDBConnectionPoolDataSource;
startTime = System.currentTimeMillis();
for (int i = 0; i < 100; i++) {
Connection c1 = ds.getConnection();
PreparedStatement ps = c1.prepareStatement("select * from qsys2.sysprocs");
ResultSet rs = ps.executeQuery();
c1.close();
}
endTime = System.currentTimeMillis();
System.out.println("Time spent: " + (endTime - startTime));
}
// Establish a JNDI context and bind the connection pool data source
Context ctx = new InitialContext();
ctx.rebind("StatementSupport", cpds);
}
}
/////////////////////////////////////////
// UpdateBlobs is an example application
// that shows some of the APIs providing
// support for changing Blob objects
// and reflecting those changes to the
// database.
//
// This program must be run after
// the PutGetBlobs program has completed.
/////////////////////////////////////////
import java.sql.*;
Connection c = DriverManager.getConnection("jdbc:db2:*local");
Statement s = c.createStatement();
rs.next();
Blob blob1 = rs.getBlob(1);
rs.next();
Blob blob2 = rs.getBlob(1);
// Truncate a BLOB.
blob1.truncate((long) 150000);
System.out.println("Blob1's new length is " + blob1.length());
Related reference
Example: BLOB
This is an example of how a BLOB can be put into the database or retrieved from the database.
Example: Using BLOBs
This is an example of how to use BLOBs in your Java applications.
/////////////////////////////////////////
// UpdateClobs is an example application
// that shows some of the APIs providing
// support for changing Clob objects
// and reflecting those changes to the
// database.
//
// This program must be run after
// the PutGetClobs program has completed.
/////////////////////////////////////////
import java.sql.*;
Connection c = DriverManager.getConnection("jdbc:db2:*local");
Statement s = c.createStatement();
rs.next();
Clob clob1 = rs.getClob(1);
rs.next();
Clob clob2 = rs.getClob(1);
// Truncate a CLOB.
clob1.truncate((long) 150000);
System.out.println("Clob1's new length is " + clob1.length());
Related reference
Example: CLOB
This is an example of how a CLOB can be put into the database or retrieved from the database.
Example: Using CLOBs
This is an example of how to use CLOBs in your Java applications.
import java.sql.*;
import javax.sql.*;
import java.util.*;
import javax.transaction.*;
import javax.transaction.xa.*;
import com.ibm.db2.jdbc.app.*;
test.setup();
test.run();
}
/**
* Handle the previous cleanup run so that this test can recommence.
*/
public void setup() {
Connection c = null;
Statement s = null;
try {
Class.forName("com.ibm.db2.jdbc.app.DB2Driver");
c = DriverManager.getConnection("jdbc:db2:*local");
s = c.createStatement();
try {
s.executeUpdate("DROP TABLE CUJOSQL.JTATABLE");
s.close();
} finally {
if (c != null) {
c.close();
}
}
}
/**
* This test uses JTA support to handle transactions.
*/
public void run() {
Connection c = null;
try {
Context ctx = new InitialContext();
xaRes.start(xid2, XAResource.TMNOFLAGS);
int count2 = stmt.executeUpdate("INSERT INTO CUJOSQL.JTATABLE VALUES('Value 1-B')");
xaRes.end(xid2, XAResource.TMNOFLAGS);
xaRes.start(xid3, XAResource.TMNOFLAGS);
int count3 = stmt.executeUpdate("INSERT INTO CUJOSQL.JTATABLE VALUES('Value 1-C')");
xaRes.end(xid3, XAResource.TMNOFLAGS);
} catch (Exception e) {
System.out.println("Something has gone wrong.");
e.printStackTrace();
} finally {
try {
if (c != null)
c.close();
} catch (SQLException e) {
System.out.println("Note: Cleaup exception.");
e.printStackTrace();
}
}
Related reference
Example: Using JTA to handle a transaction
This is an example of how to use the Java Transaction API (JTA) to handle a transaction in an application.
Example: Multiple connections that work on a transaction
This is an example of how to use multiple connections working on a single transaction.
Example: Suspended ResultSets
This is an example of the how a Statement object is reprocessed under another transaction to perform
work.
Example: Ending a transaction
This is an example of ending a transaction in your application.
Example: Suspending and resuming a transaction
This is an example of a transaction that is suspended and then is resumed.
/////////////////////////////////////////
// UseBlobs is an example application
// that shows some of the APIs associated
// with Blob objects.
//
// This program must be run after
// the PutGetBlobs program has completed.
/////////////////////////////////////////
import java.sql.*;
Connection c = DriverManager.getConnection("jdbc:db2:*local");
Statement s = c.createStatement();
rs.next();
Blob blob1 = rs.getBlob(1);
rs.next();
Blob blob2 = rs.getBlob(1);
Related reference
Example: BLOB
This is an example of how a BLOB can be put into the database or retrieved from the database.
Example: Updating BLOBs
This is an example of how to update BLOBs in your Java applications.
/////////////////////////////////////////
// UpdateClobs is an example application
// that shows some of the APIs providing
// support for changing Clob objects
// and reflecting those changes to the
// database.
//
// This program must be run after
// the PutGetClobs program has completed.
/////////////////////////////////////////
import java.sql.*;
Connection c = DriverManager.getConnection("jdbc:db2:*local");
Statement s = c.createStatement();
rs.next();
Clob clob1 = rs.getClob(1);
rs.next();
Clob clob2 = rs.getClob(1);
Related reference
Example: CLOB
This is an example of how a CLOB can be put into the database or retrieved from the database.
Example: Updating CLOBs
This is an example of how to update CLOBs in your Java applications.
import java.sql.*;
import javax.sql.*;
import java.util.*;
import javax.transaction.*;
import javax.transaction.xa.*;
import com.ibm.db2.jdbc.app.*;
test.setup();
test.run();
}
/**
* Handle the previous cleanup run so that this test can recommence.
*/
public void setup() {
Connection c = null;
Statement s = null;
try {
Class.forName("com.ibm.db2.jdbc.app.DB2Driver");
c = DriverManager.getConnection("jdbc:db2:*local");
s = c.createStatement();
try {
s.executeUpdate("DROP TABLE CUJOSQL.JTATABLE");
} catch (SQLException e) {
// Ignore... does not exist
}
/**
* This test uses JTA support to handle transactions.
*/
public void run() {
Connection c = null;
try {
Context ctx = new InitialContext();
} catch (Exception e) {
System.out.println("Something has gone wrong.");
e.printStackTrace();
} finally {
try {
if (c != null)
c.close();
} catch (SQLException e) {
System.out.println("Note: Cleaup exception.");
e.printStackTrace();
}
}
}
}
Related reference
Example: Multiple connections that work on a transaction
This is an example of how to use multiple connections working on a single transaction.
Example: Using a connection with multiple transactions
This is an example of how to use a single connection with multiple transactions.
Example: Suspended ResultSets
This is an example of the how a Statement object is reprocessed under another transaction to perform
work.
Example: Ending a transaction
This is an example of ending a transaction in your application.
Example: Suspending and resuming a transaction
Example: Using metadata ResultSets that have more than one column
This is an example of how to use metadata ResultSets that have more than one column.
Note: By using the code examples, you agree to the terms of the “Code license and disclaimer
information” on page 489.
//////////////////////////////////////////////////////////////////////////////////
//
// SafeGetUDTs example. This program demonstrates one way to deal with
// metadata ResultSets that have more columns in JDK 1.4 than they
// had in previous releases.
//
// Command syntax:
// java SafeGetUDTs
//
//////////////////////////////////////////////////////////////////////////////////
//
// This source is an example of the IBM Developer for Java JDBC driver.
// IBM grants you a nonexclusive license to use this as an example
// from which you can generate similar function tailored to
// your own specific needs.
//
// This 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
// merchantability and fitness for a particular purpose are
// expressly disclaimed.
//
// IBM Developer Kit for Java
// (C) Copyright IBM Corp. 2001
// All rights reserved.
// US Government Users Restricted Rights -
// Use, duplication, or disclosure restricted
// by GSA ADP Schedule Contract with IBM Corp.
//
//////////////////////////////////////////////////////////////////////////////////
import java.sql.*;
try {
Class.forName("java.sql.ParameterMetaData");
// Found a JDBC 3.0 interface. Must support JDBC 3.0.
jdbcLevel = 3;
} catch (ClassNotFoundException ez) {
// Could not find the JDBC 3.0 ParameterMetaData class.
// Must be running under a JVM with only JDBC 2.0
// support.
jdbcLevel = 2;
}
c = DriverManager.getConnection("jdbc:db2:*local");
DatabaseMetaData dmd = c.getMetaData();
if (jdbcLevel == 1) {
System.out.println("No support is provided for getUDTs. Just return.");
System.exit(1);
}
// Fetch all the columns that have been available since the
// JDBC 2.0 release.
System.out.println("TYPE_CAT is " + rs.getString("TYPE_CAT"));
System.out.println("TYPE_SCHEM is " + rs.getString("TYPE_SCHEM"));
System.out.println("TYPE_NAME is " + rs.getString("TYPE_NAME"));
System.out.println("CLASS_NAME is " + rs.getString("CLASS_NAME"));
System.out.println("DATA_TYPE is " + rs.getString("DATA_TYPE"));
System.out.println("REMARKS is " + rs.getString("REMARKS"));
Related reference
Example: Returning a list of tables using the DatabaseMetaData interface
This example shows how to return a list of tables.
Example: Using native JDBC and IBM Toolbox for Java JDBC concurrently
This is an example of how to use the native JDBC connection and the IBM Toolbox for Java JDBC
connection in a program.
Note: By using the code examples, you agree to the terms of the “Code license and disclaimer
information” on page 489.
//////////////////////////////////////////////////////////////////////////////////
//
// GetConnections example.
//
// This program demonstrates being able to use both JDBC drivers at
// once in a program. Two Connection objects are created in this
// program. One is a native JDBC connection and one is a IBM Toolbox for Java
// JDBC connection.
//
// This technique is convenient because it allows you to use different
// JDBC drivers for different tasks concurrently. For example, the
// IBM Toolbox for Java JDBC driver is ideal for connecting to a remote IBM i
// server and the native JDBC driver is faster for local connections.
// You can use the strengths of each driver concurrently in your
// application by writing code similar to this example.
//
//////////////////////////////////////////////////////////////////////////////////
//
// This source is an example of the IBM Developer for Java JDBC driver.
// IBM grants you a nonexclusive license to use this as an example
// from which you can generate similar function tailored to
try {
// Obtain a connection with each driver.
Connection conn1 = DriverManager.getConnection("jdbc:db2://localhost", args[0],
args[1]);
Connection conn2 = DriverManager.getConnection("jdbc:as400://localhost", args[0],
args[1]);
conn1.close();
conn2.close();
} catch (SQLException e) {
System.out.println("ERROR: " + e.getMessage());
}
}
}
import java.sql.*;
import java.util.Properties;
Connection c = null;
Statement s = null;
ps.setInt(1, 5);
try {
if (c != null) {
c.close();
}
} catch (SQLException e) {
System.out.println("Cleanup failed to close Connection.");
}
}
}
}
Related concepts
Creating and using PreparedStatements
The prepareStatement method is used to create new PreparedStatement objects. Unlike the
createStatement method, the SQL statement must be supplied when the PreparedStatement object is
created. At that time, the SQL statement is precompiled for use.
Processing PreparedStatements
Processing SQL statements with a PreparedStatement object is accomplished with the executeQuery,
executeUpdate, and execute methods like Statement objects are processed. Unlike Statement versions,
no parameters are passed on these methods because the SQL statement was already provided when
the object was created. Because PreparedStatement extends Statement, applications can attempt to call
import java.sql.*;
import java.util.Properties;
Connection c = null;
Statement s = null;
try {
// Create the connection properties.
Properties properties = new Properties ();
properties.put ("user", "userid");
properties.put ("password", "password");
// Run some SQL statements that insert records into the table.
s.executeUpdate("INSERT INTO MYLIBRARY.MYTABLE (NAME, ID) VALUES ('RICH', 123)");
s.executeUpdate("INSERT INTO MYLIBRARY.MYTABLE (NAME, ID) VALUES ('FRED', 456)");
s.executeUpdate("INSERT INTO MYLIBRARY.MYTABLE (NAME, ID) VALUES ('MARK', 789)");
try {
if (c != null) {
c.close();
}
} catch (SQLException e) {
System.out.println("Cleanup failed to close Connection.");
}
}
}
}
HelloWorld.java
Here is the source for the file HelloWorld.java.
Note: By using the code examples, you agree to the terms of the “Code license and disclaimer
information” on page 489.
/*
* ===========================================================================
* Licensed Materials - Property of IBM
*
* (C) Copyright IBM Corp. 2000 All Rights Reserved.
*
* US Government Users Restricted Rights - Use, duplication or
* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
* ===========================================================================
*
* File: HelloWorld.java
*/
import java.io.*;
import java.util.*;
import java.security.Principal;
import java.security.PrivilegedAction;
import javax.security.auth.*;
import javax.security.auth.callback.*;
import javax.security.auth.login.*;
import javax.security.auth.spi.*;
/**
* This SampleLogin application attempts to authenticate a user.
*
* If the user successfully authenticates itself,
* the user name and number of Credentials is displayed.
*
* @version 1.1, 09/14/99
*/
public class HelloWorld {
/**
* Attempt to authenticate the user.
*/
public static void main(String[] args) {
// use the configured LoginModules for the "helloWorld" entry
LoginContext lc = null;
try {
lc = new LoginContext("helloWorld", new MyCallbackHandler());
} catch (LoginException le) {
le.printStackTrace();
System.exit(-1);
}
// attempt authentication
lc.login();
System.out.println("Authentication Failed");
try {
Thread.currentThread().sleep(3000);
} catch (Exception e) {
// ignore
}
} catch (Exception e) {
try {
Thread.currentThread().sleep(2000);
} catch (Exception e) {
// ignore
}
System.out.println("\n\nHello World!\n");
return null;
}
}, null);
System.exit(0);
}
}
/**
* The application must implement the CallbackHandler.
*
/**
* Invoke an array of Callbacks.
*
*
* @param callbacks an array of Callback objects which contain
* the information requested by an underlying security
* service to be retrieved or displayed.
*
* @exception java.io.IOException if an input or output error occurs.
*
* @exception UnsupportedCallbackException if the implementation of this
* method does not support one or more of the Callbacks
* specified in the callbacks parameter.
*/
public void handle(Callback[] callbacks)
throws IOException, UnsupportedCallbackException {
} else {
throw new UnsupportedCallbackException
(callbacks[i], "Unrecognized Callback");
}
}
}
char[] lineBuffer;
char[] buf;
int i;
case '\r':
int c2 = in.read();
if ((c2 != '\n') && (c2 != -1)) {
if (!(in instanceof PushbackInputStream)) {
in = new PushbackInputStream(in);
}
((PushbackInputStream)in).unread(c2);
} else
break loop;
default:
if (--room < 0) {
buf = new char[offset + 128];
room = buf.length - offset - 1;
System.arraycopy(lineBuffer, 0, buf, 0, offset);
Arrays.fill(lineBuffer, ' ');
lineBuffer = buf;
}
buf[offset++] = (char) c;
break;
}
}
if (offset == 0) {
return null;
}
return ret;
}
}
HWLoginModule.java
Here is the source for HWLoginModule.java.
Note: Read the Code example disclaimer for important legal information.
/*
* ===========================================================================
* Licensed Materials - Property of IBM
*
* (C) Copyright IBM Corp. 2000 All Rights Reserved.
*
* US Government Users Restricted Rights - Use, duplication or
* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
* ===========================================================================
*
* File: HWLoginModule.java
*/
package com.ibm.security;
import java.util.*;
import java.io.IOException;
import javax.security.auth.*;
import javax.security.auth.callback.*;
import javax.security.auth.login.*;
import javax.security.auth.spi.*;
import com.ibm.security.HWPrincipal;
/**
* This LoginModule authenticates users with a password.
*
* This LoginModule only recognizes any user who enters
* the required password: Go JAAS
*
* If the user successfully authenticates itself,
* a HWPrincipal with the user name
* is added to the Subject.
// initial state
private Subject subject;
private CallbackHandler callbackHandler;
private Map sharedState;
private Map options;
// configurable option
private boolean debug = false;
/**
* Initialize this LoginModule.
*
* @param subject the Subject to be authenticated.
*
* @param callbackHandler a CallbackHandler for communicating
* with the end user (prompting for user names and
* passwords, for example).
*
* @param sharedState shared LoginModule state.
*
* @param options options specified in the login
* Configuration for this particular
* LoginModule.
*/
public void initialize(Subject subject, CallbackHandler callbackHandler,
Map sharedState, Map options) {
this.subject = subject;
this.callbackHandler = callbackHandler;
this.sharedState = sharedState;
this.options = options;
/**
* Authenticate the user by prompting for a user name and password.
*
*
* @return true in all cases since this LoginModule
* should not be ignored.
*
* @exception FailedLoginException if the authentication fails.
*
* @exception LoginException if this LoginModule
* is unable to perform the authentication.
*/
public boolean login() throws LoginException {
try {
callbackHandler.handle(callbacks);
user name = ((NameCallback)callbacks[0]).getName();
char[] tmpPassword = ((PasswordCallback)callbacks[1]).getPassword();
// authentication succeeded!!!
if (debug)
System.out.println("\n\t[HWLoginModule] " +
"authentication succeeded");
succeeded = true;
return true;
} else {
/**
* This method is called if the overall authentication of LoginContext
* succeeded
* (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules
* succeeded).
*
* If this LoginModule authentication attempt
* succeeded (checked by retrieving the private state saved by the
* login method), then this method associates a
* SolarisPrincipal
* with the Subject located in the
* LoginModule. If this LoginModule
* authentication attempt failed, then this method removes
* any state that was originally saved.
*
* @exception LoginException if the commit fails.
*
* @return true if the login and commit LoginModule
* attempts succeeded, or false otherwise.
*/
public boolean commit() throws LoginException {
if (succeeded == false) {
if (debug) {
System.out.println("\t[HWLoginModule] " +
"added HWPrincipal to Subject");
}
commitSucceeded = true;
return true;
}
}
/**
* This method is called if the overall authentication of LoginContext
* failed.
* (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules
* did not succeed).
*
* If this authentication attempt of LoginModule
* succeeded (checked by retrieving the private state saved by the
* login and commit methods),
* then this method cleans up any state that was originally saved.
*
* @exception LoginException if the abort fails.
*
* @return false if this login or commit attempt for LoginModule
* failed, and true otherwise.
*/
public boolean abort() throws LoginException {
if (succeeded == false) {
return false;
} else if (succeeded == true && commitSucceeded == false) {
// login succeeded but overall authentication failed
succeeded = false;
user name = null;
if (password != null) {
for (int i = 0; i > password.length; i++)
password[i] = ' ';
password = null;
}
userPrincipal = null;
} else {
// overall authentication succeeded and commit succeeded,
// but another commit failed
logout();
}
return true;
}
/**
* Logout the user.
*
* This method removes the HWPrincipal
* that was added by the commit method.
*
* @exception LoginException if the logout fails.
*
* @return true in all cases since this LoginModule
* should not be ignored.
*/
succeeded = false;
succeeded = commitSucceeded;
user name = null;
if (password != null) {
for (int i = 0; i > password.length; i++)
password[i] = ' ';
password = null;
}
userPrincipal = null;
return true;
}
}
HWPrincipal.java
Here is the source for HWPrincipal.java.
Note: Read the Code example disclaimer for important legal information.
/*
* ===========================================================================
* Licensed Materials - Property of IBM
*
* (C) Copyright IBM Corp. 2000 All Rights Reserved.
*
* US Government Users Restricted Rights - Use, duplication or
* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
* ===========================================================================
*
* File: HWPrincipal.java
*/
package com.ibm.security;
import java.security.Principal;
/**
* This class implements the Principal interface
* and represents a HelloWorld tester.
*
* @version 1.1, 09/10/99
* @author D. Kent Soper
*/
public class HWPrincipal implements Principal, java.io.Serializable {
/*
* Create a HWPrincipal with the supplied name.
*/
public HWPrincipal(String name) {
if (name == null)
throw new NullPointerException("illegal null input");
this.name = name;
}
/*
* Return the name for the HWPrincipal.
*/
public String getName() {
return name;
}
/*
* Return a string representation of the HWPrincipal.
*/
/*
* Compares the specified Object with the HWPrincipal for equality.
* Returns true if the given object is also a HWPrincipal and the
* two HWPrincipals have the same user name.
*/
public boolean equals(Object o) {
if (o == null)
return false;
if (this == o)
return true;
if (this.getName().equals(that.getName()))
return true;
return false;
}
/*
* Return a hash code for the HWPrincipal.
*/
public int hashCode() {
return name.hashCode();
}
}
//////////////////////////////////////////////////////////////////////
//
// File Name: SampleThreadSubjectLogin.java
//
// Class: SampleThreadSubjectLogin
//
/////////////////////////////////////////////////////////////////////
//
// CHANGE ACTIVITY:
//
//
// END CHANGE ACTIVITY
//
////////////////////////////////////////////////////////////////////
import com.ibm.security.auth.ThreadSubject;
import com.ibm.as400.access.*;
import java.io.*;
import java.util.*;
import java.security.Principal;
import javax.security.auth.*;
import javax.security.auth.callback.*;
import javax.security.auth.login.*;
/**
* This SampleThreadSubjectLogin application authenticates a single
* user, swaps the OS thread identity to the authenticated user,
* and then writes "Hello World" into a privately authorized
* file, thread.txt, in the user's test directory.
*
* The user is requested to enter the user id and password to
4) Change the current directory to your test directory and compile the
java source code.
Enter -
strqsh
cd 'yourTestDir'
ADDLNK OBJ('/QIBM/ProdData/OS400/Java400/ext/jaas14.jar')
NEWLNK('/QIBM/ProdData/Java400/jdk14/lib/ext/jaas14.jar')
7) If not already done to run this sample, add the symbolic link to the extension
directory for the jt400.jar and jt400ntv.jar files. This causes these
files to be loaded by the extension class loader. The application class loader
can also load these files by including them in the CLASSPATH.
If these files are loaded from the class path directory,
do not add the symbolic link to the extension directory.
The jaas14.jar file requires these JAR files for the credential
implementation classes which are part of the IBM Toolbox
for Java Licensed Program Product.
(See the IBM Toolbox for Java topic for documentation
on the credential classes found in the left frame
under Security Classes => Authentication. Select the link to the
ProfileTokenCredential class. At the top select 'This Package' for the
entire com/ibm/as400/security/auth Java package. Javadoc for the
authentication classes can also be found by selecting 'Javadoc' =>
'Access Classes' on the left frame. Select 'All Packages' at the top
and look for the com.ibm.as400.security.* packages)
ADDLNK OBJ('/QIBM/ProdData/HTTP/Public/jt400/lib/jt400.jar')
NEWLNK('/QIBM/ProdData/Java400/jdk14/lib/ext/jt400.jar')
ADDLNK OBJ('/QIBM/ProdData/OS400/jt400/lib/jt400Native.jar')
NEWLNK('/QIBM/ProdData/Java400/jdk14/lib/ext/jt400Native.jar')
/////////////////////////////////////
IMPORTANT NOTES -
/////////////////////////////////////
CHGCURDIR DIR('yourTestDir')
JAVA CLASS(SampleThreadSubjectLogin)
CLASSPATH('yourTestDir/classes')
PROP(((java.security.manager)
(java.security.auth.login.config
'yourTestDir/threadLogin.config')
(java.security.policy
'yourTestDir/threadJava2.policy')
(java.security.auth.policy
'yourTestDir/threadJaas.policy'))
*
**/
// attempt authentication
lc.login();
System.out.println("Authentication Failed");
try {
Thread.currentThread().sleep(3000);
} catch (Exception e) {
// ignore
}
} catch (Exception e) {
System.out.println("Principals:");
while (itr.hasNext())
System.out.println(itr.next());
itr = lc.getSubject().getPrivateCredentials().iterator();
while (itr.hasNext())
System.out.println(itr.next());
itr = lc.getSubject().getPublicCredentials().iterator();
while (itr.hasNext())
System.out.println(itr.next());
try {
// write "Hello World number x" into thread.txt
PrintStream ps = new PrintStream(new FileOutputStream("thread.txt", true), true);
System.exit(0);
// Returns the current OS identity for the main thread of the application.
// (This routine uses classes from IBM Toolbox for Java)
// Note - Applications running on a secondary thread cannot use this API to determine the
current user.
static public String getCurrentUser() {
try {
AS400 localSys = new AS400("localhost", "*CURRENT", "*CURRENT");
return ((String)(uidText.toObject(uidBytes))).trim();
}
catch (Exception e) {
e.printStackTrace();
}
return "";
}
/**
* A CallbackHandler is passed to underlying security
* services so that they may interact with the application
* to retrieve specific authentication data,
* such as user names and passwords, or to display certain
* information, such as error and warning messages.
*
* CallbackHandlers are implemented in an application
* and platform-dependent fashion. The implementation decides
* how to retrieve and display information depending on the
* Callbacks passed to it.
*
* This class provides a sample CallbackHandler. However, it is
* not intended to fulfill the requirements of production applications.
* As indicated, the CallbackHandler is ultimately considered to
* be application-dependent, as individual applications have
* unique error checking, data handling, and user
* interface requirements.
*
* The following callbacks are handled:
*
*
* For simplicity, prompting is handled interactively through
* standard input and output. However, it is worth noting
* that when standard input is provided by the console, this
* approach allows passwords to be viewed as they are
* typed. This should be avoided in production
* applications.
*
* This CallbackHandler also allows a name and password
* to be acquired through an alternative mechanism
* and set directly on the handler to bypass the need for
* user interaction on the respective Callbacks.
*
*/
class SampleCBHandler implements CallbackHandler {
private String name_ = null;
private String password_ = null;
/**
* Constructs a new SampleCBHandler.
*
*/
public SampleCBHandler() {
this(null, null);
}
/**
* Constructs a new SampleCBHandler.
*
* A name and password can optionally be specified in
* order to bypass the need to prompt for information
* on the respective Callbacks.
*
* @param name
* The default value for name callbacks. A null
* value indicates that the user should be
* prompted for this information. A non-null value
* cannot be zero length or exceed 10 characters.
*
* @param password
* The default value for password callbacks. A null
* value indicates that the user should be
* prompted for this information. A non-null value
* cannot be zero length or exceed 10 characters.
*/
public SampleCBHandler(String name, String password) {
if (name != null)
if ((name.length()==0) || (name.length()>10))
throw new IllegalArgumentException("name");
name_ = name;
if (password != null)
if ((password.length()==0) || (password.length()>10))
throw new IllegalArgumentException("password");
password_ = password;
}
/**
* Handle the given name callback.
*
* First check to see if a name has been passed in
* on the constructor. If so, assign it to the
* callback and bypass the prompt.
*
* If a value has not been preset, attempt to prompt
* for the name using standard input and output.
*
* @param c
* The NameCallback.
*
* @exception java.io.IOException
* If an input or output error occurs.
*
*/
private void handleNameCallback(NameCallback c) throws IOException {
}
}
/**
* Handle the given text output callback.
*
* If the text is informational or a warning,
* text is written to standard output. If the
* callback defines an error message, text is
* written to standard error.
*
* @param c
* The TextOutputCallback.
*
* @exception java.io.IOException
* If an input or output error occurs.
*
*/
private void handleTextOutputCallback(TextOutputCallback c) throws IOException {
if (c.getMessageType() == TextOutputCallback.ERROR)
System.err.println(c.getMessage());
else
System.out.println(c.getMessage());
}
/**
* Retrieve or display the information requested in the
* provided Callbacks.
*
* The handle method implementation
* checks the instance(s) of the Callback
* object(s) passed in to retrieve or display the
* requested information.
*
* @param callbacks
* An array of Callback objects provided
* by an underlying security service which contains
* the information requested to be retrieved or displayed.
*
if (c instanceof NameCallback)
handleNameCallback((NameCallback)c);
else if (c instanceof PasswordCallback)
handlePasswordCallback((PasswordCallback)c);
else if (c instanceof TextOutputCallback)
handleTextOutputCallback((TextOutputCallback)c);
else
throw new UnsupportedCallbackException
(callbacks[i]);
}
}
/**
* Displays the given string using standard output,
* followed by a space to separate from subsequent
* input.
*
* @param prompt
* The text to display.
*
* @exception IOException
* If an input or output error occurs.
*
*/
private void stdIOPrompt(String prompt) throws IOException {
System.out.print(prompt + ' ');
System.out.flush();
}
/**
* Reads a String from standard input, stopped at
* maxLength or by a newline.
*
* @param prompt
* The text to display to standard output immediately
* prior to reading the requested value.
*
* @param maxLength
* Maximum length of the String to return.
*
* @return
* The entered string. The value returned does
* not contain leading or trailing whitespace
* and is converted to uppercase.
*
* @exception IOException
* If an input or output error occurs.
*
*/
private String stdIOReadName(String prompt, int maxLength) throws IOException {
stdIOPrompt(prompt);
String s =
(new BufferedReader
(new InputStreamReader(System.in))).readLine().trim();
if (s.length() < maxLength)
s = s.substring(0,maxLength);
return s.toUpperCase();
}
package com.ibm.security.jgss.test;
import org.ietf.jgss.*;
import com.ibm.security.jgss.Debug;
import java.io.*;
import java.net.*;
import java.util.*;
/**
* A JGSS sample client;
* to be used in conjunction with the JGSS sample server.
* The client first establishes a context with the server
* and then sends wrapped message followed by a MIC to the server.
* The MIC is calculated over the plain text that was wrapped.
* The client requires to server to authenticate itself
* (mutual authentication) during context establishment.
* It also delegates its credentials to the server.
*
* It sets the JAVA variable
* javax.security.auth.useSubjectCredsOnly to false
* so that JGSS will not acquire credentials through JAAS.
*
* The client takes input parameters, and complements it
* with information from the jgss.ini file; any required input not
* supplied on the command line is taking from the jgss.ini file.
*
* Usage: Client [options]
*
* The -? option produces a help message including supported options.
*
* This sample client does not use JAAS.
* The client can be run against the JAAS sample client and server.
* See {@link JAASClient JAASClient} for a sample client that uses JAAS.
*/
class Client
{
private Util testUtil = null;
private String myName = null;
private GSSName gssName = null;
private String serverName = null;
private int servicePort = 0;
private GSSManager mgr = GSSManager.getInstance();
private GSSName service = null;
private GSSContext context = null;
private String program = "Client";
private String debugPrefix = "Client: ";
private TCPComms tcp = null;
private String data = null;
private byte[] dataBytes = null;
private String serviceHostname= null;
private GSSCredential gssCred = null;
if (myCred != null)
{
gssCred = myCred;
}
else
{
throw new GSSException(GSSException.NO_CRED, 0,
"Null input credential");
}
if (temp == null)
{
debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix
+ "setting useSubjectCredsOnly property to "
+ useSubjectCredsOnly);
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction() {
public Object run() {
System.setProperty(property, subjectOnly);
return null;
}
});
}
else
{
debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix
+ "useSubjectCredsOnly property already set "
+ "in JVM to " + temp);
}
}
// peer's host
if (serverHostname != null)
{
this.serviceHostname = serverHostname;
}
else
{
this.serviceHostname = testUtil.getDefaultServiceHostname();
}
// peer's port
if (serverPort > 0)
{
this.servicePort = serverPort;
}
else
{
this.servicePort = testUtil.getDefaultServicePort();
}
this.dataBytes = this.data.getBytes();
if (gssCred == null)
{
if (myName != null)
{
debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix
+ "creating GSSName USER_NAME for "
+ myName);
gssName = mgr.createName(
myName,
GSSName.NT_USER_NAME,
krb5MechanismOid);
debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix
+ "Canonicalized GSSName=" + gssName);
}
else
gssName = null; // for default credentials
gssCred = mgr.createCredential(
myName = gssName.toString();
debug.out(Debug.OPTS_CAT_APPLICATION,
debugPrefix + "default credential principal=" + myName);
}
}
debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix
+ "creating canonicalized GSSName for serverName " + serverName);
service = mgr.createName(serverName,
GSSName.NT_HOSTBASED_SERVICE,
krb5MechanismOid);
debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix
+ "Canonicalized server name = " + service);
debug.out(Debug.OPTS_CAT_APPLICATION,
debugPrefix + "Raw data=" + data);
}
debug.out(Debug.OPTS_CAT_APPLICATION,
debugPrefix + "creating GSScontext");
if (flags != null)
{
if (flags.get(Util.CONTEXT_OPTS_MUTUAL))
{
debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix
+ "requesting mutualAuthn");
context.requestMutualAuth(true);
}
if (flags.get(Util.CONTEXT_OPTS_INTEG))
{
debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix
+ "requesting integrity");
context.requestInteg(true);
}
if (flags.get(Util.CONTEXT_OPTS_CONF))
{
context.requestConf(true);
debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix
+ "requesting confidentiality");
}
if (flags.get(Util.CONTEXT_OPTS_DELEG))
{
context.requestCredDeleg(true);
debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix
+ "requesting delegation");
}
if (flags.get(Util.CONTEXT_OPTS_REPLAY))
{
context.requestReplayDet(true);
debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix
+ "requesting replay detection");
}
if (request != null)
{
debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix
+ "Sending initial context token");
tcp.send(request);
}
done = context.isEstablished();
if (!done)
{
debug.out(Debug.OPTS_CAT_APPLICATION,
debugPrefix + "Receiving response token");
debug.out(Debug.OPTS_CAT_APPLICATION,
debugPrefix + "context established with acceptor");
if (mic != null)
{
debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix + "sending MIC");
tcp.send(mic);
}
else
debug.out(Debug.OPTS_CAT_APPLICATION,
debugPrefix + "getMIC Failed");
}
if (wrapped != null)
{
debug.out(Debug.OPTS_CAT_APPLICATION,
debugPrefix + "sending wrapped message");
tcp.send(wrapped);
}
else
debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix + "wrap Failed");
}
case 'h':
if (sHost == null)
{
sHost = options.optArgGet();
int p = sHost.indexOf(':');
if (p != -1)
{
String temp1 = sHost.substring(0, p);
if (port == null)
port = sHost.substring(p+1, sHost.length()).trim();
sHost = temp1;
}
}
continue;
case 'p':
if (port == null)
port = options.optArgGet();
continue;
case 'm':
if (msg == null)
msg = options.optArgGet();
continue;
case 'n':
if (myName == null)
myName = options.optArgGet();
continue;
case 's':
if (serverName == null)
serverName = options.optArgGet();
continue;
}
}
if (p != -1)
servicePort = p;
}
package com.ibm.security.jgss.test;
import org.ietf.jgss.*;
import com.ibm.security.jgss.Debug;
import java.io.*;
import java.net.*;
import java.util.*;
/**
* A JGSS sample server; to be used in conjunction with a JGSS sample client.
*
* It continuously listens for client connections,
static {
try {
testUtil = new Util();
} catch (Exception exc) {
exc.printStackTrace();
System.exit(1);
}
}
if (temp == null)
{
debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix
+ "setting useSubjectCredsOnly property to "
+ (useSubjectCredsOnly ? "true" : "false"));
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction() {
public Object run() {
System.setProperty(property, subjectOnly);
return null;
}
});
}
else
{
debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix
+ "useSubjectCredsOnly property already set "
+ "in JVM to " + temp);
}
}
myName = myNameWithoutRealm;
// my port
if (port > 0)
{
myPort = port;
}
else if (primary)
{
myPort = testUtil.getDefaultServicePort();
}
else
{
myPort = testUtil.getDefaultService2Port();
}
if (primary)
{
///// peer's name
if (serverNameWithoutRealm != null)
{
serviceNameNoRealm = serverNameWithoutRealm;
}
else
{
serviceNameNoRealm =
testUtil.getDefaultService2PrincipalWithoutRealm();
}
// peer's host
if (serverHostname != null)
{
if (serverHostname.equalsIgnoreCase("localHost"))
{
serverHostname = InetAddress.getLocalHost().getHostName();
}
serviceHost = serverHostname;
}
else
{
serviceHost = testUtil.getDefaultService2Hostname();
}
// peer's port
if (serverPort > 0)
{
servicePort = serverPort;
}
else
{
servicePort = testUtil.getDefaultService2Port();
}
debug.out(Debug.OPTS_CAT_APPLICATION, temp);
}
mgr = GSSManager.getInstance();
if (myName != null)
{
debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix
+ "creating GSSName for " + myName);
gssName = mgr.createName(myName,
GSSName.NT_HOSTBASED_SERVICE);
debug.out(Debug.OPTS_CAT_APPLICATION,
debugPrefix + "Canonicalized GSSName=" + gssName);
}
else
gssName = null;
gssCred = mgr.createCredential(
gssName, GSSCredential.DEFAULT_LIFETIME,
(Oid)null, usage);
if (gssName == null)
{
gssName = gssCred.getName();
myName = gssName.toString();
debug.out(Debug.OPTS_CAT_APPLICATION,
debugPrefix + "default credential principal=" + myName);
}
}
case '#':
if (status == null)
status = options.optArgGet();
continue;
case 'p':
if (port == null)
port = options.optArgGet();
continue;
case 'n':
if (name == null)
name = options.optArgGet();
continue;
case 'b':
clientServer = true;
continue;
case 'P':
if (sport == null)
sport = options.optArgGet();
continue;
case 'm':
if (smessage == null)
smessage = options.optArgGet();
continue;
case 's':
if (sname == null)
sname = options.optArgGet();
continue;
case 'h':
if (shost == null)
{
shost = options.optArgGet();
int p = shost.indexOf(':');
if (p != -1)
{
String temp1 = shost.substring(0, p);
if (sport == null)
sport = shost.substring
(p+1, shost.length()).trim();
shost = temp1;
}
}
continue;
}
}
if (status != null)
{
int p = -1;
try {
p = Integer.parseInt(status);
} catch (Exception exc) {
System.out.println( "Bad status input: "+status);
}
if (p != -1)
{
primary = (p == 1);
}
if (port != null)
{
int p = -1;
try {
p = Integer.parseInt(port);
} catch (Exception exc) {
System.out.println( "Bad port input: "+port);
}
if (p != -1)
iport = p;
}
if (sport != null)
{
int p = -1;
try {
p = Integer.parseInt(sport);
} catch (Exception exc) {
System.out.println( "Bad server port input: "+port);
}
if (p != -1)
isport = p;
}
debug.out(Debug.OPTS_CAT_APPLICATION,
debugPrefix + "incoming connection on " + csocket);
void dispose()
{
try {
if (tcp != null)
{
tcp.close();
tcp = null;
}
} catch (Exception exc) {}
}
debug.out(Debug.OPTS_CAT_APPLICATION,
debugPrefix + "establishing context");
do {
request = tcp.receive();
if (request == null || request.length == 0)
{
debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix
+ "Received no data; perhaps client disconnected");
return false;
}
debug.out(Debug.OPTS_CAT_APPLICATION,
debugPrefix + "context established - " + context);
return true;
}
debug.out(Debug.OPTS_CAT_APPLICATION,
debugPrefix + "unwrapped msg is:");
debug.out(Debug.OPTS_CAT_APPLICATION, unwrappedMsg);
return unwrappedMsg;
}
void verifyMIC (GSSContext context, byte[] mic, byte[] raw) throws Exception
{
debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix + "verifying MIC");
debug.out(Debug.OPTS_CAT_APPLICATION,
debugPrefix + "successfully verified MIC");
}
}
}
else
{
debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix +
"ERROR: null delegated cred");
}
try {
Thread currentThread = Thread.currentThread();
String threadName = currentThread.getName();
debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix
+ "servicing client ...");
debug.out(Debug.OPTS_CAT_APPLICATION,
debugPrefix + "creating GSSContext");
context = mgr.createContext(gssCred);
do {
debug.out(Debug.OPTS_CAT_APPLICATION,
debugPrefix + "receiving per-message request");
request = tcp.receive();
if (request == null || request.length == 0)
{
debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix
+ "Received no data; perhaps client disconnected");
return;
}
// Followed by a MIC.
verifyMIC(context, request, response);
debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix
+ "clientServer=" + clientServer
+ ", beenInitiator=" + beenInitiator);
} while(true);
debug.out(Debug.OPTS_CAT_APPLICATION, debugPrefix +
"About to run as initiator with own creds ...");
//thread.sleep(30*1000, 0);
runAsInitiator();
}
}
client.initialize();
client.interactWithAcceptor(flags);
exc.printStackTrace();
} finally {
try {
client.dispose();
} catch (Exception exc) {}
}
}
void runAsInitiator()
{
if (clientServer)
{
debug.out(Debug.OPTS_CAT_APPLICATION,
debugPrefix + "running as initiator with own creds");
void printUsage()
{
System.out.println(program + usageString);
}
package com.ibm.security.jgss.test;
import com.ibm.security.jgss.Debug;
import com.ibm.security.auth.callback.Krb5CallbackHandler;
import javax.security.auth.Subject;
import javax.security.auth.login.LoginContext;
import java.security.PrivilegedExceptionAction;
/**
* A Java GSS sample client that uses JAAS.
*
* It does a JAAS login and operates within the JAAS login context so created.
*
* It does not set the JAVA variable
* javax.security.auth.useSubjectCredsOnly, leaving
* the variable to default to true
* so that Java GSS acquires credentials from the JAAS Subject
* associated with login context (created by the client).
*
* The JAASClient is equivalent to its superclass {@link Client Client}
* in all other respects, and it
* can be run against the non-JAAS sample clients and servers.
*/
System.out.println(dbg.toString()); // XXXXXXX
try {
client = new JAASClient(programName);//use Subject creds
client.processArgs(args);
loginCtxt.login();
dbg.out(Debug.OPTS_CAT_APPLICATION,
programName + ": Kerberos login OK");
PrivilegedExceptionAction jaasClientAction
= new JAASClientAction(client);
dbg.out(Debug.OPTS_CAT_APPLICATION,
programName + ": Done ...");
}
}
package com.ibm.security.jgss.test;
import com.ibm.security.jgss.Debug;
import com.ibm.security.auth.callback.Krb5CallbackHandler;
import javax.security.auth.Subject;
import javax.security.auth.login.LoginContext;
import java.security.PrivilegedExceptionAction;
/**
* A Java GSS sample server that uses JAAS.
*
* It does a JAAS login and operates within the JAAS login context so created.
*
* It does not set the JAVA variable
* javax.security.auth.useSubjectCredsOnly, leaving
* the variable to default to true
* so that Java GSS acquires credentials from the JAAS Subject
JAASServerAction(JAASServer server)
{
this.server = server;
}
return null;
}
}
System.out.println(dbg.toString()); // XXXXXXX
try {
// Do not set useSubjectCredsOnly.
// useSubjectCredsOnly defaults to "true" if not set.
server.processArgs(args);
loginCtxt.login();
dbg.out(Debug.OPTS_CAT_APPLICATION, programName +
": Login successful");
import java.io.*;
PGM
DSPJVMJOB OUTPUT(*PRINT)
ENDPGM
Related reference
Example: Calling another Java program with java.lang.Runtime.exec()
This example shows how to call another Java program with java.lang.Runtime.exec(). This class
calls the Hello program that is shipped as part of the IBM Developer Kit for Java. When the Hello class
writes to System.out, this program gets a handle to the stream and can read from it.
Example: Calling a CL command with java.lang.Runtime.exec()
This example shows how to run a control language (CL) command from within a Java program.
Runtime.getRuntime().exec("system CLCOMMAND");
import java.io.*;
Related concepts
“Using java.lang.Runtime.exec()” on page 216
Use the java.lang.Runtime.exec() method to call programs or commands from within your Java
program. Using java.lang.Runtime.exec() method creates one or more additional thread-enabled
jobs. The additional jobs process the command string that you pass on the method.
“List of Java system properties” on page 15
Java system properties determine the environment in which the Java programs run. They are like system
values or environment variables in IBM i.
Related reference
Example: Calling another Java program with java.lang.Runtime.exec()
This example shows how to call another Java program with java.lang.Runtime.exec(). This class
calls the Hello program that is shipped as part of the IBM Developer Kit for Java. When the Hello class
writes to System.out, this program gets a handle to the stream and can read from it.
Example: Calling a CL program with java.lang.Runtime.exec()
This example shows how to run CL programs from within a Java program. In this example, the Java class
CallCLPgm runs a CL program.
import java.io.*;
System.out.println("CallHelloPgm.main() invoked");
Related reference
Example: Calling a CL program with java.lang.Runtime.exec()
This example shows how to run CL programs from within a Java program. In this example, the Java class
CallCLPgm runs a CL program.
Example: Calling a CL command with java.lang.Runtime.exec()
This example shows how to run a control language (CL) command from within a Java program.
#include <stdlib.h>
int main(void)
{
int result;
Related concepts
Using sockets for interprocess communication
Sockets streams communicate between programs that are running in separate processes.
Using input and output streams for interprocess communication
Input and output streams communicate between programs that are running in separate processes.
Related reference
Example: Calling Java from RPG
Related concepts
Using sockets for interprocess communication
Sockets streams communicate between programs that are running in separate processes.
Using input and output streams for interprocess communication
Input and output streams communicate between programs that are running in separate processes.
Related reference
Example: Calling Java from ILE C
This is an example of an integrated language environment (ILE) C program that uses the system()
function to call the Java Hello program.
import java.io.*;
System.out.println("CallPgm.main() invoked");
#include <stdio.h>
#include <stdlib.h>
fflush(stdout);
}
Any job that creates a Java virtual machine must be multithread-capable. The output from the main
program, as well as any output from the program, ends up in QPRINT spooled files. These spooled files
are visible when you use the Work with Submitted Jobs (WRKSBMJOB) control language (CL) command
and view the job that you started by using the Submit Job (SBMJOB) CL command.
#define OS400_JVM_12
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <jni.h>
#pragma convert(819)
/* Procedure: Oops
*
* Description: Helper routine that is called when a JNI function
* returns a zero value, indicating a serious error.
* This routine reports the exception to stderr and
* ends the JVM abruptly with a call to FatalError.
*
* Parameters: env -- JNIEnv* to use for JNI calls
* msg -- char* pointing to error description in UTF-8
*
* Note: Control does not return after the call to FatalError
* and it does not return from this procedure.
*/
/* Set the version field of the initialization arguments for JNI v1.4. */
initArgs.version = 0x00010004;
/* Now, you want to specify the directory for the class to run in the classpath.
* with Java2, classpath is passed in as an option.
* Note: You must specify the directory name in UTF-8 format. So, you wrap
* blocks of code in #pragma convert statements.
*/
options[0].optionString="-Djava.class.path=/CrtJvmExample";
/* Now, get the method identifier for the 'main' entry point
* of the class.
* Note: The signature of 'main' is always the same for any
* class called by the following java command:
* "main" , "([Ljava/lang/String;)V"
*/
mainID = (*myEnv)->GetStaticMethodID(myEnv,myClass,"main",
"([Ljava/lang/String;)V");
if (! mainID) {
Oops(myEnv, "Failed to find jmethodID of 'main'");
}
/* Now, you have the methodID of main and the class, so you can
* call the main method.
*/
(*myEnv)->CallStaticVoidMethod(myEnv,myClass,mainID,args);
/* All done. */
return 0;
}
cd /home/example
java PaseExample1
Example: PaseExample1.java
This example program loads the native method library 'PaseExample1'. The source code for the native
method is contained in PaseExample1.c. The printString method in this Java program uses a native
method, getStringNative to retrieve the value of the String. The native method simply calls back into the
getStringCallback method of this class.
Note: Read the Code example disclaimer for important legal information.
//////////////////////////////////////////////////////////////////////////////////
//
// This example program loads the native method library 'PaseExample1'.
// The source code for the native method is contained in PaseExample1.c
// The printString method in this Java program uses a native method,
// getStringNative to retrieve the value of the String. The native method
// simply calls back into the getStringCallback method of this class.
//
//////////////////////////////////////////////////////////////////////////////////
String str;
PaseExample1(String s) {
str = s;
}
//-----------------------------------------------------------------
public void printString() {
String result = getStringNative();
System.out.println("Value of str is '" + result + "'");
}
//-----------------------------------------------------------------
static {
System.loadLibrary("PaseExample1");
}
Example: PaseExample1.c
This native method implements the getStringNative method of class PaseExample1. It uses the JNI
function CallObjectMethod to call back to the getStringCallback method of class PaseExample1.
Note: Read the Code example disclaimer for important legal information.
/*
*
#include "PaseExample1.h"
#include <stdlib.h>
/*
* Class: PaseExample1
* Method: getStringNative
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_PaseExample1_getStringNative(JNIEnv* env, jobject obj) {
char* methodName = "getStringCallback";
char* methodSig = "()Ljava/lang/String;";
jclass clazz = (*env)->GetObjectClass(env, obj);
jmethodID methodID = (*env)->GetMethodID(env, clazz, methodName, methodSig);
return (*env)->CallObjectMethod(env, obj, methodID);
}
javac PaseExample1.java
2. Use the following command to create a C include file that contains the native method prototypes:
The new C include file (PaseExample1.h) contains a function prototype for the getStringNative method.
The example C source code (PaseExample1.c) already includes the information you would copy and
modify from the C include file to use the getStringNative method. For more information about using
JNI, see the Java Native Interface on the Oracle Web site.
3. Use the following command to compile the C source code and create a shared library object.
The new shared library object file (libPaseExample1.so) contains the native method library
"PaseExample1" that the example uses.
Note: You may need to change the -I option to point to the directory that contains the correct Java
native method include files (for example, jni.h) for your AIX system.
For more information about the PASE for i native method for Java example, see the following topics:
“Example: IBM PASE for i native method for Java” on page 207
The PASE for i native method for Java example calls an instance of a native C method that then uses
Java Native Interface (JNI) to call back into Java code. Rather than accessing the string directly from Java
code, the example calls a native method that then calls back into Java through JNI to get the string value.
“Example: Downloading the example source code to your AIX workstation” on page 465
Before you can run the PASE for i native method for Java example, you need to download a compressed
file that contains the source code. To download the compressed file to your AIX workstation, complete the
following steps.
“Example: Preparing your IBM i server to run the PASE for i native method for Java example” on page 467
Example: Preparing your IBM i server to run the PASE for i native method for
Java example
Before running the PASE for i native method for Java example, you need to prepare your server to run
the example. Preparing the server requires copying the files to the server and adding the necessary
environment variables to run the example.
To prepare your server, complete the following steps:
1. Create the following integrated file system directory on the server that you want to contain the
example files. For example, use the following control language (CL) command to create the directory
named /home/example:
mkdir '/home/example'
Note: When using PASE native methods from an PASE for i terminal session, a 32-bit PASE for i
environment is already started. In this case, set only PASE_THREAD_ATTACH to Y and. LIBPATH to the
path for the PASE for i native method libraries.
For more information about the PASE for i native method for Java example, see the following topics:
“Example: IBM PASE for i native method for Java” on page 207
The PASE for i native method for Java example calls an instance of a native C method that then uses
Java Native Interface (JNI) to call back into Java code. Rather than accessing the string directly from Java
code, the example calls a native method that then calls back into Java through JNI to get the string value.
“Example: Downloading the example source code to your AIX workstation” on page 465
Before you can run the PASE for i native method for Java example, you need to download a compressed
file that contains the source code. To download the compressed file to your AIX workstation, complete the
following steps.
“Example: Preparing the example source code” on page 466
Before moving the PASE for i native method for Java example to your server, you need to compile the
source code, create a C include file, and create a shared library object.
cd /ileexample
java NativeHello
Related concepts
Teraspace storage model native methods for Java
The IBM i Java virtual machine (JVM) supports the use of teraspace storage model native methods. The
teraspace storage model provides a large, process-local address environment for ILE programs. Using the
teraspace storage model allows you to port native method code from other operating systems to IBM i
with little or no source code changes.
Strings in ILE native methods
Many Java Native Interface (JNI) functions accept C language-style strings as parameters. For example,
the FindClass() JNI function accepts a string parameter that specifies the fully-qualified name of a
class file. If the class file is found, it is loaded by FindClass(), and a reference to it is returned to the
caller of FindClass().
Example: NativeHello.java
The Java source code is used in the integrated language environment (ILE) native method for Java
example.
The NativeHello.java source code shows the Java code that is used to demonstrate ILE native
methods for Java. The native method setTheString() is called by the Java code from within the
main() method. The result of the call is that the function Java_NativeHello_setTheString(),
defined in the C implementation code, gets control and uses Java Native Interface (JNI) to call back into
the Java code to set the value of the Java string variable theString. Control is then returned to the Java
code, and the string variable is written to stdout.
Note: By using the code examples, you agree to the terms of the “Code license and disclaimer
information” on page 489.
try {
// System.load takes the full integrated file system form path.
System.load ("/qsys.lib/ileexample.lib/nathello.srvpgm");
}
catch (UnsatisfiedLinkError e2) {
// If you get to this point, then you are done! Write the message
// and exit.
System.out.println
("<sigh> I did not find NATHELLO *SRVPGM anywhere. Goodbye");
System.exit(1);
}
}
}
// Here is the 'main' code of this class. This is what runs when you
// enter 'java NativeHello' on the command line.
public static void main(String argv[]){
// Echo location.
System.out.println("(Java) Instantiated NativeHello object");
System.out.println("(Java) string field is '" + nh.theString + "'");
System.out.println("(Java) Calling native method to set the string");
Example: NativeHello.c
The C source code is used in the integrated language environment (ILE) native method for Java example.
The NativeHello.c source code shows the implementation of the native method in C. When the Java
native method setTheString(), defined in the Java code, is called by the Java code the C function
Java_NativeHello_setTheString() gets control and uses Java Native Interface (JNI) to call back
into the Java code to set the value of the Java string variable theString. Control is then returned to the
Java code, and the string variable is written to stdout out by the Java code.
This example shows how to link Java to native methods. However, it points out complications that arise
from the fact that the IBM i is internally an extended binary-coded decimal interchange code (EBCDIC)
machine. It also shows complications from the current lack of true internationalization elements in the
JNI.
These reasons, although they are not new with the JNI, cause some unique IBM i server-specific
differences in the C code that you write. You must remember that if you are writing to stdout or stderr or
reading from stdin, your data is probably encoded in EBCDIC form.
In C code, you can easily convert most literal strings, those that contain 7-bit characters only, into the
UTF-8 form that is required by the JNI. To do this, bracket the literal strings with the codepage conversion
pragma statement. However, because you may write information directly to stdout or stderr from your C
code, you might allow some literals to remain in EBCDIC.
Note: The #pragma convert(0) statements convert character data to EBCDIC. The #pragma
convert(819) statements convert character data to American Standard Code for Information
Interchange (ASCII). These statements convert character data in the C program at compile time.
/* get the class of the 'this' object, required to get the fieldID */
if (! (thisClass = (*env)->GetObjectClass(env,javaThis)))
{
/* A null class returned from GetObjectClass indicates that there
* was a problem. Instead of handling this problem, simply return and
* know that the return to Java automatically 'throws' the stored Java
* exception.
*/
return;
}
/* Check to see if the update was successful. If not, report the error. */
if ((*env)->ExceptionOccurred(env)) {
len = strlen(str);
/* Make local copies of the input and output sizes that are initialized
* to the size of the input string. The iconv() requires the
* length parameters to be passed by address (that is as int*).
*/
originalLen = sStrLen = tStrLen = strlen(sourceStr);
mkdir '/ileexample'
2. Create two empty stream files named NativeHello.java and NativeHello.c in the directory
created in step 1. For example, use the following CL commands to create the files:
3. Copy the Java source code shown in “Example: NativeHello.java” on page 468 to the file created in
step 2 named NativeHello.java.
4. Copy the C source code shown in “Example: NativeHello.c” on page 469 to the file created in step 2
named NativeHello.c.
5. Create a library named ileexample that will contain the service program containing the C
implementation code for the Java native method. For example, use the following CL command to
create the library:
crtlib ileexample
cd '/ileexample'
2. Compile the Java source file. For example, use the following command to compile the Java source
code from the command line:
3. Use the following command to create a C include file that contains the native method prototypes:
The new C include file (NativeHello.h) contains a function prototype for the setTheString()
method. The example C source code NativeHello.c already includes the include file.
4. Use the following commands to compile the C source code and create a service program.
The new service program (NATHELLO) contains the native method setTheString() that the example
uses.
“Example: ILE native method for Java” on page 206
The integrated language environment (ILE) native method for Java example calls an instance of a native
C method that then uses Java Native Interface (JNI) to call back into Java code to set the value of a Java
string variable. The Java string variable is then written to standard out by the Java code.
“Example: NativeHello.java” on page 468
The Java source code is used in the integrated language environment (ILE) native method for Java
example.
“Example: NativeHello.c” on page 469
The C source code is used in the integrated language environment (ILE) native method for Java example.
“Example: Preparing the ILE native method source code” on page 472
import java.net.*;
import java.io.*;
class TalkToC
{
private String host = null;
private int port = -999;
private Socket socket = null;
private BufferedReader inStream = null;
try
{
socket = new Socket(host, port);
inStream = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
}
catch(UnknownHostException e)
{
System.err.println("Cannot find host called: " + host);
e.printStackTrace();
System.exit(-1);
}
catch(IOException e)
{
System.err.println("Could not establish connection for " + host);
e.printStackTrace();
System.exit(-1);
}
}
SockServ.C starts by passing in a parameter for the port number. For example, CALL SockServ '2001'.
Source code for SockServ.C server program
Note: Read the Code example disclaimer for important legal information.
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <unistd.h>
#include <sys/time.h>
memset(&local_Address,0x00,sizeof(local_Address));
local_Address.sin_family = AF_INET;
local_Address.sin_port = htons(portNum);
local_Address.sin_addr.s_addr = htonl(INADDR_ANY);
/* allocate socket */
if((server = socket(AF_INET, SOCK_STREAM, 0))<0)
{
printf("failure on socket allocation\n");
perror(NULL);
exit(-1);
}
/* do bind */
if((bndrc=bind(server,(struct sockaddr*)&local_Address, address_len))<0)
{
printf("Bind failed\n");
perror(NULL);
exit(-1);
/* invoke listen */
listen(server, 1);
close(client);
close(server);
}
import java.sql.*;
import sqlj.runtime.*;
import sqlj.runtime.ref.*;
class App
{
/**********************
** Register Driver **
**********************/
static
{
try
{
Class.forName("com.ibm.db2.jdbc.app.DB2Driver").newInstance();
}
catch (Exception e)
{
e.printStackTrace();
}
}
/********************
** Main **
********************/
// URL is jdbc:db2:dbname
String url = "jdbc:db2:sample";
import java.net.*;
import java.io.*;
if (args.length < 1) {
System.out.println("java simpleSocketClient serverHost serverPort");
System.out.println("serverPort defaults to 3000 if not specified.");
return;
}
if (args.length == 2)
serverPort = new Integer(args[1]).intValue();
if (args.length < 1) {
System.out.println("java factorySocketClient serverHost serverPort");
System.out.println("serverPort defaults to 3000 if not specified.");
return;
}
if (args.length == 2)
serverPort = new Integer(args[1]).intValue();
// Now the factory creates the socket. This is the last change
// to the original simpleSocketClient program.
Related reference
Examples: Changing your Java code to use server socket factories
These examples show you how to change a simple socket class, named simpleSocketServer, so that it
uses socket factories to create all of the sockets. The first example shows you the simpleSocketServer
class without socket factories. The second example shows you the simpleSocketServer class with socket
factories. In the second example, simpleSocketServer is renamed to factorySocketServer.
/* File simpleSocketServer.java*/
import java.net.*;
import java.io.*;
if (args.length < 1) {
System.out.println("java simpleSocketServer serverPort");
ServerSocket serverSocket =
new ServerSocket(serverPort);
// a real server would handle more than just one client like this...
Socket s = serverSocket.accept();
BufferedInputStream is = new BufferedInputStream(s.getInputStream());
BufferedOutputStream os = new BufferedOutputStream(s.getOutputStream());
int bytesRead;
s.close();
serverSocket.close();
} // end main()
/* File factorySocketServer.java */
if (args.length < 1) {
System.out.println("java simpleSocketServer serverPort");
System.out.println("Defaulting to port 3000 since serverPort not specified.");
}
else
serverPort = new Integer(args[0]).intValue();
// a real server would handle more than just one client like this...
Socket s = serverSocket.accept();
BufferedInputStream is = new BufferedInputStream(s.getInputStream());
BufferedOutputStream os = new BufferedOutputStream(s.getOutputStream());
int bytesRead;
s.close();
serverSocket.close();
}
Related reference
Examples: Changing your Java code to use client socket factories
These examples show you how to change a simple socket class, named simpleSocketClient, so that it
uses socket factories to create all of the sockets. The first example shows you the simpleSocketClient
class without socket factories. The second example shows you the simpleSocketClient class with socket
factories. In the second example, simpleSocketClient is renamed to factorySocketClient.
import javax.net.*;
import java.net.*;
import java.io.*;
if (args.length < 1) {
System.out.println("java factorySocketClient serverHost serverPort");
System.out.println("serverPort defaults to 3000 if not specified.");
return;
}
if (args.length == 2)
serverPort = new Integer(args[1]).intValue();
if (args.length < 1) {
System.out.println("java factorySSLSocketClient serverHost serverPort");
Related reference
Examples: Changing your Java server to use secure sockets layer
These examples show you how to change one class, named factorySocketServer, to use secure sockets
layer (SSL).
/* File factorySocketServer.java */
// need to import javax.net to pick up the ServerSocketFactory class
import javax.net.*;
import java.net.*;
import java.io.*;
if (args.length < 1) {
System.out.println("java simpleSocketServer serverPort");
System.out.println("Defaulting to port 3000 since serverPort not specified.");
}
else
serverPort = new Integer(args[0]).intValue();
// a real server would handle more than just one client like this...
Socket s = serverSocket.accept();
BufferedInputStream is = new BufferedInputStream(s.getInputStream());
BufferedOutputStream os = new BufferedOutputStream(s.getOutputStream());
s.close();
serverSocket.close();
}
}
/* File factorySocketServer.java */
if (args.length < 1) {
System.out.println("java simpleSocketServer serverPort");
System.out.println("Defaulting to port 3000 since serverPort not specified.");
}
else
serverPort = new Integer(args[0]).intValue();
// a real server would handle more than just one client like this...
Socket s = serverSocket.accept();
BufferedInputStream is = new BufferedInputStream(s.getInputStream());
BufferedOutputStream os = new BufferedOutputStream(s.getOutputStream());
int bytesRead;
s.close();
serverSocket.close();
}
}
Related reference
Examples: Changing your Java client to use secure sockets layer
Limitations
This list identifies any known limitations, restrictions, or unique behaviors in Java on the IBM i server.
• The java.net backlog parameter on the IBM i may behave differently than on other platforms. For
example:
– Listen backlogs 0, 1
- Listen(0) means to allow one pending connection; it does not disable a socket.
- Listen(1) means to allow one pending connection, and means the same as Listen(0).
– Listen backlogs > 1
- This allows many pending requests to remain on the listen queue. If a new connection request
arrives and the queue is at the limit, then it deletes one of the pending requests.
• You can only use the Java virtual machine, regardless of the JDK version you are using, in multi-thread
capable (that is, thread-safe) environments. The IBM i platform is thread-safe, but some file systems
are not. For a list of file systems that are not thread-safe, see the Integrated File System topic.
Related concepts
Applying program temporary fixes
Some of the Java topics has information that assumes you have loaded the latest levels of the IBM
Developer Kit for Java on your IBM i server. To get to the latest levels of Java on your server, load the
latest Java Program Temporary Fix (PTF) group.
Getting support for Java on IBM i
Support services for Java on IBM i are provided under the usual terms and conditions for IBM i software
products. Support services include program services, voice support, and consulting services.
Related tasks
Finding job logs for Java problem analysis
Use the job log from the job that ran the Java command, and the batch immediate (BCI) job log where the
Java program ran, to analyze causes of a Java failure. They both may contain important error information.
Collecting data for Java problem analysis
To collect data for an authorized program analysis report (APAR), follow these steps.
If possible, save the source files for any Java classes that are involved in the problem. This is helpful to
IBM when reproducing and analyzing the problem.
4. Save any service programs that contain native methods that are required to run the program.
5. Save any data files that are required to run the Java program.
6. Add a complete description of how to reproduce the problem.
This includes:
• The value of the CLASSPATH environment variable.
• A description of the Java command that was run.
• A description of how to respond to any input that is required by the program.
7. Include any vertical licensed internal code (VLIC) logs that have occurred near the time of failure,
particularly those with a major code of 4700 or 4300.
8. Add the job log from both the interactive job and the BCI job where the Java virtual machine was
running.
9. Add information requested in the IBM Center for Java Technology Developer Diagnostic Guide .
Related concepts
Limitations
This list identifies any known limitations, restrictions, or unique behaviors in Java on the IBM i server.
Applying program temporary fixes
Some of the Java topics has information that assumes you have loaded the latest levels of the IBM
Developer Kit for Java on your IBM i server. To get to the latest levels of Java on your server, load the
latest Java Program Temporary Fix (PTF) group.
Getting support for Java on IBM i
Support services for Java on IBM i are provided under the usual terms and conditions for IBM i software
products. Support services include program services, voice support, and consulting services.
Related tasks
Finding job logs for Java problem analysis
Use the job log from the job that ran the Java command, and the batch immediate (BCI) job log where the
Java program ran, to analyze causes of a Java failure. They both may contain important error information.
Use the online information that is provided at IBM i home page under the topic "Support" for more
information. Use IBM Support Services for licensed program 5770-JV1. Or, contact your local IBM
representative.
You may, at IBM direction, be required to obtain a more current level of the licensed program to receive
Continued Program Services. For more information, see Support for multiple Java Development Kits
(JDKs).
Defect resolution is supported under program services or voice support. Resolving application
programming or debugging issues are supported under consulting services.
The Java application programming interface (API) calls are supported under consulting services, unless:
1. It is clearly a Java API defect as demonstrated by re-creation in a relatively simple program.
2. It is a question that asks for documentation clarification.
3. It is a question about the location of samples or documentation.
All programming assistance is supported under consulting services. This includes the program samples
that are provided in the product. Additional samples may be available on the Internet at IBM i home
page on an unsupported basis.
The IBM Developer Kit for Java LP provides information about solving problems.
Related concepts
Limitations
This list identifies any known limitations, restrictions, or unique behaviors in Java on the IBM i server.
Applying program temporary fixes
Some of the Java topics has information that assumes you have loaded the latest levels of the IBM
Developer Kit for Java on your IBM i server. To get to the latest levels of Java on your server, load the
latest Java Program Temporary Fix (PTF) group.
Related tasks
Finding job logs for Java problem analysis
Use the job log from the job that ran the Java command, and the batch immediate (BCI) job log where the
Java program ran, to analyze causes of a Java failure. They both may contain important error information.
Collecting data for Java problem analysis
Related information
Listed here are sources that relate to Java on the IBM i server.
Web sites
• IBM i Technology Updates for Java
Provide additional details about Java support on IBM i.
• The Source for Java Developers (http://www.oracle.com/technetwork/java/index.html)
Visit Oracle for information about the various uses for Java, including new technologies.
• IBM developerWorks Java technology zone
Offers information, education, and tool to help you use Java, IBM products, and other technologies to
create business solutions.
• IBM alphaWorks® Java
Includes information about new Java technologies, including downloads and links to development
resources.
Javadoc
Javadoc reference information for Java classes can be found at Java 2 Platform, Standard Edition API
Specification by Oracle.
See the following reference information that relates to Java on the IBM i server.
JavaMail
The JavaMail API provides a set of abstract classes that models an electronic (e-mail) system. The API
provides general mail functions for reading and sending mail, and requires service providers to implement
the protocols.
Service providers implement specific protocols. For example, Simple Mail Transfer Protocol (SMTP) is a
transport protocol for sending e-mail. Post Office Protocol 3 (POP3) is the standard protocol for receiving
e-mail. Internet Message Access Protocol (IMAP) is an alternative protocol to POP3.
In addition to service providers, JavaMail requires the JavaBeans Activation Framework (JAF) to handle
mail content that is not plain text. This includes Multipurpose Internet Mail Extensions (MIME), Uniform
Resource Locator (URL) pages, and file attachments.
For license inquiries regarding double-byte (DBCS) information, contact the IBM Intellectual Property
Department in your country or send inquiries, in writing, to:
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
Software Interoperability Coordinator, Department YBWA
3605 Highway 52 N
Rochester, MN 55901
U.S.A.
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.
492 Notices
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 Oracle, Inc. in the United States, other
countries, or both.
Other product and service names might be trademarks of IBM or other companies.
Notices 493
494 IBM i: IBM Developer Kit for Java
IBM®