using jdbc with iseries websphere applications jdbc with iseries websphere applications by craig...

21
Using JDBC with iSeries WebSphere Applications By Craig Pelkie The Java programming language is a great advance over most other programming languages, as a Java program that runs on one platform can usually be ported to another platform and run with no or minor changes. That is made possible by the presence of a compliant Java Virtual Machine (JVM) on the alternate platform. A "compliant JVM" is one that has passed the Sun Microsystems suite of tests to ensure that the JVM provides all of the required support for the level of the JVM. Most business applications require access to one or more databases. It is possible to use techniques to provide "native" access to the database, for example, the IBM AS/400 Toolbox for Java includes classes for record-level access. Those classes closely mimic the types of file I/O operations that iSeries 400 programmers are accustomed to using. However, if you write a Java program using those classes, you have then bound your program to run only against an iSeries 400 database. Although many iSeries 400 shops believe that they will only ever host their database on the iSeries, other shops need to be able to run their applications regardless of the database used. The industry standard technique for database access is SQL. You can develop iSeries 400 Java applications that use SQL by using JDBC. You do not need to have the chargeable Licensed Program Product DB2 Query Manager and SQL Developer's Kit (5722-ST1) installed on your iSeries 400 to develop and use Java programs with JDBC. As explained in the definitive reference about JDBC, JDBC API Tutorial and Reference (Second Edition), Sun Microsystems, ISBN 0-201-43328-1 (page 13), “...(a)s a point of interest, JDBC is the trademarked name and is not an acronym; nevertheless, JDBC is often thought of as standing for ‘Java Database Connectivity.’” About JDBC Drivers A JDBC driver is usually provided with a database product by the database vendor (as they have the greatest incentive to make it possible for applications to be developed that use their product). There are also third-party vendors that provide JDBC drivers. Sun Microsystems, Inc. provides this web page that you can use to search for JDBC drivers for different database products: http://industry.java.sun.com/products/jdbc/drivers Notably, Microsoft does not provide JDBC drivers for their database products (FoxPro, Access, SQL Server), but there are third-party vendors that provide JDBC support for Microsoft products. Features required for an iSeries JDBC driver Among the features that an iSeries JDBC driver must support are the following: Translation of EBCIDC characters (iSeries 400 native format) to Unicode (Java native format) Conversion of packed and zoned numeric fields to Java numeric data types (BigDecimal, Float, Double, Short, Int, Long) Securely provide a user ID and password from the application to the database for log- on authentication

Upload: doankiet

Post on 16-Mar-2018

258 views

Category:

Documents


0 download

TRANSCRIPT

Using JDBC with iSeries WebSphereApplicationsBy Craig Pelkie

The Java programming language is a great advance over most other programminglanguages, as a Java program that runs on one platform can usually be ported to anotherplatform and run with no or minor changes. That is made possible by the presence of acompliant Java Virtual Machine (JVM) on the alternate platform. A "compliant JVM" is onethat has passed the Sun Microsystems suite of tests to ensure that the JVM provides all ofthe required support for the level of the JVM.

Most business applications require access to one or more databases. It is possible to usetechniques to provide "native" access to the database, for example, the IBM AS/400Toolbox for Java includes classes for record-level access. Those classes closely mimic thetypes of file I/O operations that iSeries 400 programmers are accustomed to using.

However, if you write a Java program using those classes, you have then bound yourprogram to run only against an iSeries 400 database. Although many iSeries 400 shopsbelieve that they will only ever host their database on the iSeries, other shops need to beable to run their applications regardless of the database used.

The industry standard technique for database access is SQL. You can develop iSeries 400Java applications that use SQL by using JDBC. You do not need to have the chargeableLicensed Program Product DB2 Query Manager and SQL Developer's Kit (5722-ST1)installed on your iSeries 400 to develop and use Java programs with JDBC.

As explained in the definitive reference about JDBC, JDBC API Tutorial andReference (Second Edition), Sun Microsystems, ISBN 0-201-43328-1 (page 13),“...(a)s a point of interest, JDBC is the trademarked name and is not anacronym; nevertheless, JDBC is often thought of as standing for ‘Java DatabaseConnectivity.’”

About JDBC DriversA JDBC driver is usually provided with a database product by the database vendor (as theyhave the greatest incentive to make it possible for applications to be developed that usetheir product). There are also third-party vendors that provide JDBC drivers.

Sun Microsystems, Inc. provides this web page that you can use to search for JDBC driversfor different database products:

http://industry.java.sun.com/products/jdbc/drivers

Notably, Microsoft does not provide JDBC drivers for their database products (FoxPro,Access, SQL Server), but there are third-party vendors that provide JDBC support forMicrosoft products.

Features required for an iSeries JDBC driverAmong the features that an iSeries JDBC driver must support are the following:

• Translation of EBCIDC characters (iSeries 400 native format) to Unicode (Java nativeformat)

• Conversion of packed and zoned numeric fields to Java numeric data types(BigDecimal, Float, Double, Short, Int, Long)

• Securely provide a user ID and password from the application to the database for log-on authentication

• Provide a means to pass additional parameters to the JDBC driver to control itsoperation (JDBC driver properties)

Driver CategoriesWhen you start learning about JDBC drivers, you will find references to the "JDBC drivertype" or category of driver. The categories provide a method to assess how a particularJDBC driver can be deployed.

Type 1 – JDBC—ODBC BridgeThis type of JDBC driver works with an ODBC driver. Many of the early JDBC drivers wereType 1 drivers, as they could use the existing ODBC driver to provide access to theunderlying database.

Benefits• Can work with databases that don't have a JDBC driver (example: Microsoft Access,

Microsoft SQL Server).

• Can be used with "desktop" database products to provide a simulated environment ofa production database (example: download iSeries 400 tables to Microsoft Access,develop a Java application using those tables, change JDBC driver when program ismoved to iSeries 400).

Drawbacks• Requires the ODBC driver for the database to be installed on the client machine. For

example, if you develop a Java application to work with a Microsoft Access databaseand you then deploy that application and database to client machines, you need toconfigure the Microsoft Access ODBC driver on each client machine.

• Additional overhead of going through multiple layers to the target database can impactperformance.

Type 2 – Native APIJDBC drivers of this type use native API calls (typically written in C or C++) to access theunderlying database. As such, the driver needs to be installed on the host machine. TheJDBC requests issued by your Java application are passed to the driver and translated intothe native API calls to the database. The iSeries 400 native JDBC driver is a Type 2 driver.

Benefits• Typically highly optimized for the underlying database.

• Contained/controlled deployment, must be installed (usually as part of an operatingsystem install).

Drawbacks• Must be installed on the host machine.

• May be tied to a particular level of the operating system or database.

Type 3 – JDBC – NetDrivers of this type translate JDBC calls on the client into a network protocol of the vendors'choosing. The network protocol is then translated into specific requests of the database bya server program that receives the network protocol. For example, JDBC requests might betranslated into XML, sent to a server over HTTP, and translated on the server from XMLinto native database requests.

Benefits• Most flexible type of driver.

Type 4 – Native ProtocolA native protocol JDBC driver sends JDBC calls from the client directly to the databaseusing a TCP/IP sockets connection. The iSeries 400 Toolbox for Java JDBC driver is thistype of driver (it uses the same Host Server support as is used by the IBM Client Access foriSeries 400 product). Note: the IBM Client Access for iSeries 400 product is not required touse the Toolbox for Java JDBC driver.

Benefits• Provides direct path from other machines to the database server.

iSeries 400 JDBC DriversIBM provides two no-charge JDBC drivers with the iSeries 400. The drivers are provided inthe AS/400 Developer Kit for Java Licensed Program Product (LPP) and the AS/400 Toolboxfor Java LPP. Both of those LPPs are non-chargeable features available with a standardOS/400 order.

Developer Kit for Java driverThis driver is the "Type 2" driver. It is installed on the iSeries 400 and is used by Javaprograms running on that server to access the local database or another database that canbe located through the Relational Database Directory Entries on the iSeries 400 (see theWork with Relational Database Directory Entries command, WRKRDBDIRE).

This is the driver that will typically be used in WebSphere Application Server programs thatrun on the iSeries 400.

Specifying the classTo use this JDBC driver, use the following statement in your Java program:

Class.forName("com.ibm.db2.jdbc.app.DB2Driver")

That statement loads the JDBC driver and registers it with the driver manager. Afterloading, you can use JDBC calls to get a connection to a specific database, either on thesame machine or on another machine.

URL for accessThe URL used with this driver is specified using one of the following formats:

jdbc:db2://<database_name>

jdbc:jta:db2://<database_name>

Where <database_name> is the name of a database directory entry on the iSeries 400 or thespecial value *LOCAL to point to the local database (the database that is on the same serveras the program issuing the JDBC call).

The subprotocol modifier jta: (Java Transaction API) provides support for two-phasecommit operations. Use this option if you are working with multiple databases in the sameapplication.

Toolbox for JavaThis driver is initially installed on the iSeries 400 system, but is then usually exported to orinstalled on other systems that will access the iSeries 400 database. The Toolbox for Java

is contained in the file jt400.jar, which by default is installed in the iSeries 400 IntegratedFile System (IFS) in directory:

\QIBM\ProdData\HTTP\Public\jt400\lib

This driver establishes a TCP/IP sockets connection from the Java program to the targetiSeries 400 database, by way of the iSeries 400 Host Servers. You will typically use thisdriver in the following situations:

• Java applications installed on a client machine

• Applets that need to connect back to the iSeries 400 database

• Other servers or server applications that need to work with the iSeries 400 database(for example, run WebSphere Application Server on a Linux or Windows 2000 Servermachine and work with the iSeries 400 database).

Specifying the classTo use this JDBC driver, use the following statement in your Java program:

Class.forName("com.ibm.as400.access.AS400JDBCDriver")

That statement loads the JDBC driver and registers it with the driver manager. Theconnection URL is used to specify the iSeries 400 that contains the database you want towork with.

URL for accessThe URL used with this driver is specified using one of the following formats:

jdbc:as400://<system_name>

jdbc:as400://<tcpip_address>

Where <system_name> or <tcpip_address> are used to point to the iSeries 400 machine thatcontains the database you want to access.

Running the Toolbox driver on the same iSeries 400If you develop a Java application that initially runs remotely (for example, develop/test inVisualAge for Java on a PC workstation using the Toolbox for Java JDBC driver), and thenexport the application to the iSeries 400 server, you should change the JDBC driver andURL for access to use the native JDBC driver.

If you forget to change the driver and URL, your application will still run, assuming that theToolbox for Java classes can be found in the classpath of your server application. However,the Toolbox for Java JDBC driver always makes a TCP/IP sockets connection to thedatabase through the Host Servers. This is not as efficient as the native driver, whichissues native API calls to the iSeries 400 database.

If you develop WebSphere applications, you can avoid this problem by always using adatasource object, rather than directly instantiating the JDBC class in your Java programs.Another alternative is to "soft-code" the class name and URL parameters and pass theminto your Java class at run-time.

Using JDBC with WebSphereCopyright © 2001. Craig Pelkie

ALL RIGHTS RESERVED

7

1) Class. forName(“com.ibm.as400.access.AS400JDBCDriver”);

DriverManager

AS400JDBCDriver

2) Connection conn = DriverManager .getConnection (“jdbc:as400://M270/VAJAVA”,”UID”,”PWD”);

conn

3) Statement sql = conn.createStatement ();

sql

4) ResultSet rs = sql .executeQuery(“select * from parts order by partno”);

rs

5) while ( rs.next()) {

rs.getInt (“PARTNO”);rs.getString (“PARTDS”);

}

6) rs.close();conn.close();

PARTNO PARTDS12301 Quad speed CD ROM12302 SCSI II cable12303 17 inch SVGA Mon

JDBC Objects and their relationshipsA JDBC application typically uses five objects that work with each other. The objects areusually created in a specific order, as there are dependencies among the objects.

JDBC classThe JDBC class is used to create an instance of the JDBC driver. You can use theClass.forName statement to create an instance of the JDBC driver and register it with thedriver manager.

Driver ManagerThe driver manager is responsible for providing the environment within your application forthe JDBC drivers that you might load. Note that you can load as many JDBC drivers asrequired by your application (use the Class.forName statement for each distinct JDBC driver).

ConnectionA connection object is used to create a connection between your Java application and thedatabase. You use the getConnection method of the DriverManager object. The getConnectionmethod uses a JDBC URL to identify the protocol to use (jdbc:), the subprotocol to identifywhich JDBC driver to use (as400: or db2:), and the TCP/IP host name or address of themachine where the database is located, or the actual name of the database.

StatementA statement object is created on a specific connection, meaning that the statement isassociated with a particular database. The two types of statements are Statement andPreparedStatement. A statement is sent to the database for processing with either theexecuteQuery or executeUpdate methods of the statement object.

ResultSetA result set object is created in response to an executeQuery method (SQL SELECT statement).The output of the SELECT statement is returned to your application in the result set. Theresult set includes only those columns and rows that were selected, based on your queryspecifications (the result set might be a subset of the rows available in the queried tables).The order of the rows in the result set depends upon the ORDER BY clause, if any, in theSELECT statement.

If you run a SELECT statement that selects no rows from the queried tables, an empty resultset is returned to your application. A result set is not returned if you use the executeUpdatemethod.

The java.sql packageThe classes, interfaces and exceptions that are used with JDBC are provided in the java.sqlpackage, which is a standard part of the Java Development Kit (JDK). If you use IBMVisualAge for Java, the java.sql package is located in the Java class libraries project, which isautomatically installed in VisualAge for Java.

You will usually code the import java.sql.*; statement as one of the first statements in yourclasses that use JDBC. Once you code that statement, you can refer to the JDBC classesand interfaces by their class or interface name, rather than the fully qualified packagename.

Note: import does not copy code into your class.

The import statement in Java is used as a shortcut to help you refer to classes ina package. For example, the package java.sql contains the classes Connection andStatement to work with SQL connections and statements.

If you don’t include the import java.sql.*; statement, you need to specify the fullclass names as follows:

java.sql.Connection java.sql.Statement

With the import statement, you can simply refer to the classes as Connection andStatement.

Although many Java programmers prefer to use the import statements, they areoptional. You may prefer to use complete class names until you become morefamiliar with the Java package and class structure.

Package javax.sqlThe javax.sql package is included in the J2EE (Java 2 Enterprise Edition) version of Java.The J2EE Software Development Kit (SDK) is freely available from Sun Microsystems, Inc. atthe following web site:

http://java.sun.com/j2ee/index.html

The J2EE provides support for JDBC extensions, servlets, JavaServer Pages, and othertechnologies that are commonly used in server-side development (as opposed to client-side and applet development, which is most closely associated with the Java DevelopmentKit).

Note that package names in J2EE start with javax not java, for Java extensions.

As with the java.sql package, you can use an import statement:

import javax.sql.*;

Some of the commonly used interfaces in the javax.sql package are:

ConnectionPoolDataSourceA factory for PooledConnection objects. (A factory is an object that is used to create otherobjects.)

DataSourceA factory for Connection objects. WebSphere Application Server includes configuration objectscalled data sources, which you can then use in your Java applications.

PooledConnectionA connection object that is able to work in a connection pool (described later in thismanual).

RowSetA row set can be used as a JavaBean in a visual development environment (for example,VisualAge for Java). You can pass parameters to the row set and retrieve results from it, aswell as receive events from the row set.

Using JDBC – Load the driverBefore you can use a JDBC driver in your application, you need to load it. Loading thedriver makes it known to the driver manager, which is responsible for providing theenvironment for your application to connect to a database.

Two techniques to load the driverThere are two generally used techniques to load the JDBC driver:

DriverManager.registerDriver(new com.ibm.as400.access.AS400JDBCDriver());

Class.forName("com.ibm.as400.access.AS400JDBCDriver");

Of the two, Class.forName is preferred, although both statements accomplish the same thing.One advantage of Class.forName is that you can use a variable as the JDBC driver class toload:

Class.forName(jdbcDriver);

By using a variable, you can defer until run-time the actual class name to load.

The JDBC class name must be found in the classpath of the JVM that your application isrunning in.

Which driver to loadYou must select a driver to load based on where your Java program is running and wherethe database you need to access is located:

• Java program and database on the same iSeries 400 – use the "native" driver(com.ibm.db2.jdbc.app.DB2Driver)

• Java program running on a different machine, database on the iSeries 400 – use the"toolbox" driver (com.ibm.as400.access.AS400JDBCDriver)

Using JDBC – get a connectionAfter the JDBC driver is loaded, you can get a connection to the database from yourprogram. The database can be local (on the same iSeries 400 that your Java program isrunning on) or remote (for example, your Java application is running on another machineand needs to access an iSeries 400 database).

The connection URLYou use the DriverManager.getConnection method to create a connection object to a specificiSeries 400 database. The getConnection method uses a connection URL to identify which JDBCdriver to use and the location of the database.

Connection URL for the Native driverThe connection URL is specified as follows:

jdbc – indicates that the JDBC protocol is being used.

db2 –the subprotocol, used by the DriverManager class to locate the iSeries 400 nativeJDBC driver (com.ibm.db2.jdbc.app.DB2Driver).

*LOCAL – refers to the Relational Database Directory Entry name for the databaselocated on the local iSeries 400. If you need to connect to a database on anotheriSeries 400 or DB2 system that supports Distributed Relational Database Architecture

(DRDA), specify that database name instead of *LOCAL. The name that you specifymust be entered in the iSeries 400 Relational Database Directory Entries (use theWRKRDBDIRE command to maintain the list).

Connection URL for the Toolbox driverThe connection URL is specified as follows:

jdbc – indicates that the JDBC protocol is being used.

as400 –the subprotocol, used by the DriverManager class to locate the iSeries 400Toolbox JDBC driver (com.ibm.as400.access.AS400JDBCDriver).

//as400_name – refers to the TCP/IP host name or TCP/IP address of the iSeries 400server. By varying the host name or TCP/IP address, you can use JDBC to connect toany iSeries 400 that you can access in your network.

/VAJAVA – the optional library name that contains tables you want to access. If youomit the library name, you can specify it in your SQL statements.

Specifying the User ID and PasswordIf you don't supply an iSeries 400 user ID and password as part of your JDBC connection,the user ID of the WebSphere Application Server is used (by default, user profileQEJBSVR). If the QEJBSVR user profile has sufficient authority to the database objects,your SQL statements will run.

If you need to specify a different user ID and password, you can include the user ID andpassword as parameters to the getConnection method, or you can put the values into aProperties object and pass that object to the JDBC driver on the getConnection method.

Supply the user ID and passwordConnection conn = DriverManager.getConnection("jdbc:db2://*LOCAL", "userID", "password");

Supply the user ID and password in a Properties objectProperties prop = new Properties();

prop.put("user", "userID_value");prop.put("password", "password_value");

Connection conn = DriverManager.getConnection("jdbc:db2://*LOCAL", prop);

Setting JDBC driver propertiesYou can set properties for the JDBC driver either as part of the connection URL or in aproperties object. For example, to enable tracing and full error reporting, you can useeither of these techniques:

Properties passed on URLConnection conn = DriverManager.getConnection("jdbc:db2://*LOCAL;trace=true;errors=full");

Properties passed in Properties objectProperties prop = new Properties();

prop.put("trace", "true");prop.put("errors", "full");

Connection conn = DriverManager.getConnection("jdbc:db2://*LOCAL", prop);

Additional InformationYou can find more information about JDBC driver connection properties at the iSeries 400Information Center web site maintained by IBM. Go to the following URL and search for"JDBC Connection Properties"

http://publib.boulder.ibm.com/html/as400/infocenter.html

Using JDBC – create a statementOnce you have a valid connection object, you can use it to create one or more statementobjects. A statement object is used to pass an SQL statement from your Java program tothe database. The JDBC driver does not check your SQL statement for validity; it simplypasses it through. If there are any syntactical or execution errors with the statement, theSQL errors are returned to your Java program as a series of one or more SQLExceptionobjects.

An executeQuery statementThe most common use for a statement is to run a query. Use the following template(assume that the conn object is initialized as a valid JDBC connection to the iSeries 400):

Statement stmt = conn.createStatement();ResultSet rs = stmt.executeQuery("select * from parts order by partno");

An executeUpdate statementYou can run SQL statements other than SELECT by using the executeUpdate method of astatement object:

Statement stmt = conn.createStatement();int rowsAffected = stmt.executeUpdate("INSERT INTO APILIB.PARTS (PARTNO, PARTDS) VALUES(19999, 'Test part 19999')")

Using JDBC – prepared statementsMost SQL SELECT statements are run with different selection or ordering criteria, dependingupon user input. Similarly, INSERT, UPDATE and DELETE statements also use different values,depending upon which rows in the table should be affected.

One way to create an SQL statement with variables is to build it up by character stringconcatenation operations:

String sql = "select * from parts where partno=" + request.getParameter("PARTNO")

Although that technique works, it is not ideal from the point of view of the query processor,as it has to parse the statement every time it is sent to the server.

The preferred technique is to create a prepared statement and set the variable parametervalues at run-time. For example, the previous SQL statement could be handled like this:

String sql = "select * from parts where partno=?";PreparedStatement pStmt = conn.prepareStatement(sql);

pStmt.setInt(1, request.getParameter("PARTNO"));ResutlSet rs = pStmt.executeQuery();

Using this technique, the statement is written with the ? character as a parameter marker. Ifyou have multiple parameters in a statement, you simply put a ? character at each pointwhere a value will be supplied at run-time. After coding the SQL statement, you create aPreparedStatement object using the prepareStatement method of the connection object.

To use the prepared statement, use the various setXXX methods of the prepared statementobject (for example, setInt, setString). The setter methods all use two parameters:

Parameter 1 – number of the parameter marker (starting at 1)

Parameter 2 – value to substitute in place for the parameter marker

You must supply a value for each parameter marker in the statement. The value yousupply must be valid for the SQL statement (for example, if you are supplying a Stringvalue, you need to enclose it in single quote characters).

Although it looks like the prepared statement technique is more work, it is one of theprimary techniques available to you to improve SQL performance. Although setting the

string and creating the prepared statement are shown here immediately followed by thesetInt and executeQuery methods, you would most likely put the prepareStatement method in theinit() method of your class, meaning that the preparation is done only once when the classis loaded.

Another reason why you get improved database performance is because the SQLstatement is sent to the server for parsing when the prepareStatement method is called.Because the server can examine the statement before it is used, it can compute the bestaccess plan before the query is processed. Once it has computed the access plan, it savesit so that when the statement is finally submitted for execution (with the executeQuerymethod), the statement can be processed immediately.

Using JDBC – resultsetWhen you run an SQL SELECT statement, you usually expect the server to return one ormore rows from the table to your program. The object used to return data to you is theresult set. A result set is returned even if no rows were selected from the table.

A result set is conceptually like a spreadsheet, with rows and columns of data. If there areany rows of data returned from a table, the returned rows start with the first row in theresult set (that is, there is not a "column heading" row). If you need to retrieve the columnheading values, you can use the result set metadata object which is created and returned toyour program along with the result set. For most applications, you will not need to useresult set metadata, since you will know in advance what columns will be contained in yourresult set.

The result set uses a cursor to determine which row to work with. Although SQL returns a"set" of data, you navigate through the result set one row at a time. When the result set isreturned to you, the cursor is positioned before the first row, if any, in the result set.

You will usually see result set navigation code written like this:

while (rs.next()) {

int dbPartno = rs.getInt("PARTNO");String dbPartds = rs.getString("PARTDS");

}

The rs.next() method returns true if there is a next row in the result set. The while loopgoes through each row in the result set; at the end of the loop, it goes back to rs.next()which retrieves the next row. At the end of the result set, rs.next() returns false and theloop is exited.

You can use the getXXX methods on the result set object to get the values of the columnsfor the current row. The parameter to the getter methods is the column name from thedatabase. Once you retrieve the column of data, you can use it in your Java program asrequired.

JDBC and Connection Pool

Using JDBC with WebSphereCopyright © 2001. Craig Pelkie

ALL RIGHTS RESERVED

15

Database access Database access –– no connection no connection poolpool

1. Request for database services

2. Servlet creates unique connection

3. Request is processed

4. Connection closed, discarded

Using JDBC with WebSphereCopyright © 2001. Craig Pelkie

ALL RIGHTS RESERVED

16

Database access Database access –– with connection with connection poolpool

Conn Conn PoolPool

1. WAS starts, createsconnection pool

2. Request for database services

3. Next available connectionassigned to request

4. Request is processed

5. Connection closed, released back to pool

Configuring a Connection Pool

Figure 1: Select the Create Data Source option in the WebSphere Administrative Console.

Figure 2: You can "create" a new JDBC driver.

Figure 3: Specify the name for the JDBC driver, its class and URL prefix.

Figure 4: The Wizard prompts you for the node (server) to install the data source on.

Figure 5: Assign a name to the data source and the name of the database. The data source name is used in your Javaprogram.

Figure 6: You can configure connection pool parameters on the Advanced tab for the data source.

JDBC CodeFirst pass: VA Java, Console outputThe first pass is a "proof of concept" to establish that the correct JDBC code is being usedto get the intended results: a listing of data in the PARTS table. The output is sent to theVisualAge for Java Console window.

Because the code is running on the development workstation, the iSeries 400 Toolbox forJava (the "remote") JDBC driver is used. That driver makes a TCP/IP network connection tothe iSeries 400 and sends the SQL statement to the database. Because an iSeries 400user ID and password is not provided in the Java code, the Toolbox for Java displays the"sign-on" prompt window and uses that to get the user ID and password.

The value of developing the code in this environment is that it is very easy to debug andmake changes. If the results are correct, it is not difficult to change this program from astand-alone Console output program to a servlet.

JDBCVAJ01Figure 7: This figure show the VisualAge for Java Workbench (background), the Signon to AS/400 prompt, and the Consoleoutput window with the output from the JDBC SELECT statement processing.

import com.ibm.as400.access.*;import java.io.*;import java.sql.*;import java.util.*;

/** * Test JDBC in VisualAge for Java environment

* Creation date: (6/13/2001 1:05:33 AM) * @author: Craig Pelkie */public class JdbcTest1 {

/** * JdbcTest1 constructor comment. */public JdbcTest1() {

super();}

/** * Starts the application. * @param args an array of command-line arguments */public static void main(java.lang.String[] args) {

//********************************************* // Initialize the AS/400 JDBC driver class //********************************************* try { System.out.println("Before Class.forName"); Class.forName("com.ibm.as400.access.AS400JDBCDriver"); }

catch (ClassNotFoundException cnfe) { System.err.println("ClassNotFoundException for " + cnfe.getMessage()); cnfe.printStackTrace(); System.exit(-1); }

//********************************************* // driver initialized, prepare/run SQL //********************************************* try { System.out.println("Before getConnection"); Connection conn = DriverManager.getConnection( "jdbc:as400://M270/VAJAVA;trace=true;errors=full");

System.out.println("Before createStatement"); Statement stmt = conn.createStatement();

System.out.println("Before executeQuery"); ResultSet rs = stmt.executeQuery("SELECT * FROM PARTS ORDER BY PARTNO");

//***************************************** // display column headings //***************************************** System.out.println("Count\tPARTNO\tPARTDS\tPARTQY\tPARTPR\tPARTDT");

//***************************************** // iterate over the result set //***************************************** int i = 0;

while (rs.next()) {

++i; System.out.println(i + "\t" + rs.getInt("PARTNO") + "\t" + rs.getString("PARTDS") + "\t" + rs.getInt("PARTQY") + "\t" + rs.getBigDecimal("PARTPR") + "\t" + rs.getDate("PARTDT")); }

System.out.println("Before rs.close"); rs.close(); conn.close();

}

catch (SQLException sqle) { System.err.println("An SQL exception occurred:");

do { System.err.println("Message: " + sqle.getMessage()); System.err.println("SQLState: " + sqle.getSQLState()); System.err.println("ErrorCode: " + sqle.getErrorCode()); } while (sqle.getNextException() != null); }

catch (Exception e) { System.err.println("Exception occurred: " + e.getMessage()); e.printStackTrace(); }

System.out.println("** Done **"); System.exit(0);}}

Second pass: recode as a servletIn this pass, the code from the Console output is recoded as a servlet. The primarydifference between the two programs is that the servlet output is directed to an HTTP datastream provided by WebSphere Application Server, rather than simply being sent to theConsole.

Once the code is developed on the workstation, it is exported from VisualAge for Java tothe WebSphere directory in the iSeries 400 Integrated File System (IFS). At that point, theservlet needs to be configured in WebSphere and the web application contains the servletmust be restarted. The servlet is then requested in the browser, with the output shownbelow.

In the sample code, the JDBC driver is set to the native driver. The iSeries 400 user ID andpassword are not passed in to the servlet, so the default WebSphere user profile for thejob is used (user profile QEJBSVR).

JDBCSERVLET01Figure 8: After recoding as a servlet, the servlet is exported from VAJ to WebSphere. It is then configured in WebSphere,started, and requested in the browser.

import java.io.*;import java.sql.*;import java.util.*;import javax.servlet.*;import javax.servlet.http.*;

/** * Servlet for testing JDBC * Creation date: (10/3/2001 2:47:40 AM) * @author: Craig Pelkie */public class JdbcPartsServlet extends HttpServlet {

/** * JdbcPartsServlet constructor comment. */public JdbcPartsServlet() {

super();}

/** * This method is called by WebSphere and performs the work. */public void service(HttpServletRequest req, HttpServletResponse res) throws javax.servlet.ServletException, java.io.IOException {

//************************************************************************ // set content type, get print writer //************************************************************************ res.setContentType("text/html");

PrintWriter out = res.getWriter();

//************************************************************************ // write HTML page header //************************************************************************ out.println("<html>"); out.println("<head>"); out.println("<title>JDBC Parts Servlet</title>"); out.println("</head>");

out.println("<body>");

try {

//******************************************************************* // load native iSeries 400 JDBC driver, get connection //******************************************************************* Class.forName("com.ibm.db2.jdbc.app.DB2Driver");

Connection conn = DriverManager.getConnection("jdbc:db2://*LOCAL");

//******************************************************************* // set / prepare SQL statement //******************************************************************* String sql = "SELECT * FROM APILIB.PARTS ORDER BY PARTNO";

PreparedStatement stmt = conn.prepareStatement(sql);

//******************************************************************* // write table headers //******************************************************************* out.println("<table border=\"1\""); out.println("<tr>"); out.println("<td>PARTNO</td>"); out.println("<td>PARTDS</td>"); out.println("<td>PARTQY</td>"); out.println("<td>PARTPR</td>"); out.println("<td>PARTDT</td>"); out.println("</tr>");

//******************************************************************* // execute query, process each row //******************************************************************* ResultSet rs = stmt.executeQuery();

while (rs.next()) {

out.println("<tr>"); out.println("<td>" + rs.getInt("PARTNO") + "</td>"); out.println("<td>" + rs.getString("PARTDS") + "</td>"); out.println("<td>" + rs.getInt("PARTQY") + "</td>"); out.println("<td>" + rs.getBigDecimal("PARTPR") + "</td>"); out.println("<td>" + rs.getDate("PARTDT") + "</td>"); out.println("</tr>");

}

rs.close(); conn.close(); }

catch (Exception e) {

out.println("Exception: " + e); e.printStackTrace(); }

//************************************************************************ // write end of HTML page //************************************************************************ out.println("</table>"); out.println("</body>"); out.println("</html>");

out.close();}}

Copyright © 2003, Craig Pelkie. All Rights Reserved

No part of this presentation or the accompanying computer source code may be reproducedor distributed in any form or by any means, or stored in a database or data retrievalsystem, without the prior written permission of Craig Pelkie, who is the author of thepresentation and the computer source code.

All computer source code distributed with this presentation, either on diskettes, CD-ROM,or available for downloading from sources such as the Internet is Copyright © 2003 CraigPelkie, All Rights Reserved. The source code is for use in computer programs that youdevelop for internal use within your company, or for use within programs that you developfor the use of your clients, when such programs are compiled and distributed in anexecutable computer program such that no part of the source code is readily visible withoutthe aid of a computer program disassembler. No part of the computer source codedistributed with this presentation shall be reproduced in source code format, either printedor in electronic format, by you or by others who you allow to have access to the sourcecode. You shall not cause the source code to be stored on any information retrievalsystem, such as computer Bulletin Board Systems or the Internet. You shall not developany written articles, books, seminar materials, or other presentations that include thesource code provided on the diskettes accompanying this manual or within the manualitself.

For any questions regarding your rights and responsibilities using the computer sourcecode distributed with this presentation, contact Craig Pelkie, Rochester Initiative, who is theowner of the source code.

LIMITATION OF LIABILITY AND DISCLAIMER OF WARRANTY

No representation is made that any of the programs, computer source code, commands, orconfigurations described and depicted in this manual and on the computer source codeaccompanying this presentation are error-free and suitable for any application that youmay develop. Craig Pelkie makes no warranty of any kind, expressed or implied, includingthe warranties of merchantability or fitness for a particular purpose, with regard to theinformation, examples, and computer source code presented in this presentation and onthe accompanying diskettes. Everything provided in this manual and on the accompanyingdiskettes is provided “as is”. Craig Pelkie shall not be liable in any event for incidental orconsequential damages or any other claims, pursuant to your use of any of the techniquespresented in this presentation, or your use of the computer source code in programs thatyou develop, even if Craig Pelkie has been advised of the possibility of such damages.

You are responsible for testing any and all programs, configurations, commands, andprocedures presented in this manual prior to using the programs, configurations,commands, and procedures with important user data. You must ensure that adequate andsufficient backup of important user data is available, in the event that recovery of theimportant user data is required.