DB 2&websphere
DB 2&websphere
DB 2&websphere
DB2 for z/OS and WebSphere: re: The Perfect Couple uple
Configure the DB2 Universal Driver with WebSphere Application Server for z/OS Using SQLJ within WebSphere Studio Application Developer Sample application showing SQLJ support for CMP EJBs
Bart Steegmans Carsten Block John De Dominicis Sean Lee Chao-Lin Liu Egide Van Aerschot
ibm.com/redbooks
International Technical Support Organization DB2 for z/OS and WebSphere: The Perfect Couple January 2005
SG24-6319-00
Note: Before using this information and the product it supports, read the information in Notices on page xix.
First Edition (January 2005) This edition applies to Version 7 of DB2 for z/OS and OS/390 (product number 5675-DB2), DB2 for z/OS Version 8 (product number 5625-DB2), and WebSphere Application Server for z/OS Version 5.02 (product number 5655-I35).
Copyright International Business Machines Corporation 2005. All rights reserved. Note to U.S. Government Users Restricted Rights -- Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
Contents
Figures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ix Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xv Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xvii Notices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xix Trademarks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .xx Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxi The team that wrote this redbook. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxi Become a published author . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxii Comments welcome. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxiii Chapter 1. Introduction to DB2 for z/OS and OS/390 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1.1 Relational database management systems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 1.2 The DB2 Universal Database Family . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 1.2.1 DB2 UDB for Linux, UNIX, and Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 1.2.2 DB2 UDB for iSeries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 1.2.3 DB2 Server for VSE and VM. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 1.2.4 More information on the DB2 UDB family, related tools, and products. . . . . . . . . . 4 1.3 Components of DB2 UDB for z/OS and OS/390 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 1.3.1 DB2 UDB for z/OS and OS/390 address spaces . . . . . . . . . . . . . . . . . . . . . . . . . . 4 1.3.2 DB2 attachment facilities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 1.4 DB2 data structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 1.4.1 Databases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 1.4.2 Storage groups . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 1.4.3 Data sets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 1.4.4 Table spaces. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 1.4.5 Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 1.4.6 Indexes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 1.5 Structured query language (SQL) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 1.5.1 Static SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 1.5.2 Dynamic SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 1.5.3 Industry standards . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 1.6 DB2 concepts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 1.6.1 Referential constraints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 1.6.2 DB2 packages, plans, collections, and package lists . . . . . . . . . . . . . . . . . . . . . . 17 1.6.3 Schemas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 1.7 Accessing DB2 from a Java environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 1.7.1 JDBC fundamentals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 1.7.2 JDBC driver types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 1.7.3 IBM DB2 Legacy Driver. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 1.8 IBM DB2 Universal Driver for SQLJ and JDBC. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 1.8.1 IBM z/OS Application Connectivity to DB2 for z/OS and OS/390 . . . . . . . . . . . . . 24 1.9 Using the DB2 Universal Driver for SQLJ and JDBC . . . . . . . . . . . . . . . . . . . . . . . . . . 26 1.9.1 Required environment variable settings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 1.9.2 DB2 Universal Driver stored procedures and metadata . . . . . . . . . . . . . . . . . . . . 28 1.9.3 Binding DB2 Universal JDBC Driver packages with the DB2Binder utility . . . . . . 29
iii
1.9.4 DB2T4XAIndoubtUtil utility for DB2 UDB for OS/390 and z/OS Version 7 . . . . . . 30 1.9.5 Differences between the DB2 Universal Driver and DB2 Legacy Driver. . . . . . . . 31 1.9.6 JDBC 3.0 APIs specific to the DB2 Universal Driver. . . . . . . . . . . . . . . . . . . . . . . 32 Chapter 2. Introduction to WebSphere for z/OS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1 Java 2 Enterprise Edition (J2EE) overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2 WebSphere Application Server architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3 WebSphere Application Server administration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3.1 Administration console . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3.2 Other tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.4 The WebSphere family . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.5 WAS 5.0.2 features and J2EE support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Chapter 3. WebSphere - DB2 environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.1 Introduction to the sample scenario setup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2 Introduction to DB2 drivers for Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3 Data source definitions in WAS V5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.4 The IBM DB2 Universal Driver for SQLJ and JDBC . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.4.1 Summary of WAS z/OS external changes for the Universal Driver . . . . . . . . . . . 3.5 Configuring Universal JDBC Driver type 2 connectivity . . . . . . . . . . . . . . . . . . . . . . . . 3.5.1 Specifying the Universal JDBC Driver provider. . . . . . . . . . . . . . . . . . . . . . . . . . . 3.5.2 Defining Data Sources under this provider . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.5.3 Setting/verifying the symbolic environment variables . . . . . . . . . . . . . . . . . . . . . . 3.5.4 Defining DB2 Universal Driver - General properties . . . . . . . . . . . . . . . . . . . . . . . 3.5.5 Searching for the package to execute . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.5.6 Linking to the DB2 libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.5.7 Creating a new Application Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.6 Configuring Universal JDBC Driver type 4 connectivity . . . . . . . . . . . . . . . . . . . . . . . . 3.6.1 Using the Universal Driver for type 4 (non-XA) . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.6.2 Using the Universal Driver for type 4 (XA) connectivity . . . . . . . . . . . . . . . . . . . . 3.7 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 36 40 44 45 46 47 48 49 50 50 51 52 52 53 54 57 64 65 68 70 73 78 79 80 88
Chapter 4. DB2 and Java architecture guide . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 4.1 Introduction to J2EE data access architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90 4.2 Servlets and JavaServer Pages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90 4.2.1 Benefits of data access from servlets and JSPs . . . . . . . . . . . . . . . . . . . . . . . . . . 91 4.2.2 Considerations for data access from a servlet . . . . . . . . . . . . . . . . . . . . . . . . . . . 91 4.3 Enterprise JavaBeans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 4.4 Session Beans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 4.5 Stateless session Beans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94 4.5.1 Benefits of data access from a stateless session Bean . . . . . . . . . . . . . . . . . . . . 94 4.5.2 Considerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95 4.6 Stateful session Beans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 4.6.1 Benefits of stateful session Beans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 4.6.2 Considerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 4.7 Entity Beans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 4.8 Bean-Managed Persistence entity Beans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 4.8.1 Benefits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 4.8.2 Considerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99 4.9 Container-Managed Persistence entity Beans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 4.9.1 Benefits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 4.9.2 Considerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 4.10 Message-driven Beans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 4.11 Session facade pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 iv
DB2 for z/OS and WebSphere: The Perfect Couple
4.12 Stored procedures. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.12.1 Benefits of accessing data from stored procedures . . . . . . . . . . . . . . . . . . . . . 4.12.2 Considerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.13 Web services. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.14 SQLJ support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.15 Java Data Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.16 EJB Beans summary. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Chapter 5. DB2 application development in a WebSphere environment . . . . . . . . . . 5.1 JDBC and SQLJ application programming comparison . . . . . . . . . . . . . . . . . . . . . . . 5.1.1 JDBC and SQLJ compared. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.1.2 Best practices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.2 JDBC application programming concepts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.2.1 Java packages for JDBC applications. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.2.2 Using the DB2 Universal JDBC Driver and the DataSource interface . . . . . . . . 5.2.3 Java identifiers and JDBC parameter markers . . . . . . . . . . . . . . . . . . . . . . . . . . 5.2.4 Statement and ResultSet interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.3 SQLJ application programming concepts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.4 Preparing JDBC and SQLJ applications for execution . . . . . . . . . . . . . . . . . . . . . . . . 5.4.1 JDBC program preparation process . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.4.2 SQLJ program preparation process . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.5 Impact of different DB2 bind options on Java applications . . . . . . . . . . . . . . . . . . . . . 5.5.1 OWNER bind option . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.5.2 QUALIFIER bind option . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.5.3 DYNAMICRULES bind option . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.5.4 ISOLATION bind option . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.6 Special registers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.6.1 CURRENT SQLID. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.6.2 CURRENT SCHEMA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.6.3 CURRENT PACKAGESET . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.6.4 CURRENT PACKAGE PATH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.6.5 Using properties to specify special registers. . . . . . . . . . . . . . . . . . . . . . . . . . . . Chapter 6. WebSphere - DB2 security . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1 Introduction to authentication, authorization, and auditing . . . . . . . . . . . . . . . . . . . . . 6.1.1 Authentication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1.2 Authorization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1.3 Auditing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1.4 Application or infrastructure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1.5 DB2-supported authentication, authorization, and auditing . . . . . . . . . . . . . . . . 6.1.6 Choosing what identity to send DB2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1.7 Configuring WebSphere for authentication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1.8 Programmatic authentication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1.9 Default user ID and password authentication . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1.10 Thread identity support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.2 DB2 auditing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Chapter 7. SQLJ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.1 Writing SQLJ versus JDBC applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.1.1 Connections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.1.2 Using SQLJ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.1.3 Using JDBC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.2 Profile customization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.2.1 Profile customization when using unqualified SQL . . . . . . . . . . . . . . . . . . . . . . .
Contents
102 102 103 104 104 104 105 109 110 110 111 112 113 113 114 114 116 116 117 117 120 120 120 120 121 121 121 122 123 124 124 127 128 128 128 128 129 129 130 131 135 135 135 136 139 140 140 144 146 146 148 v
7.2.2 Reducing the number of SQLJ-generated packages . . . . . . . . . . . . . . . . . . . . . 7.2.3 Using manual package versioning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.3 Application design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.3.1 Best practice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.3.2 The detailed application flow. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.3.3 Exceptions and transactions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.3.4 SQL exceptions and SQL warnings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.4 SQLJ in WebSphere Studio Application Developer . . . . . . . . . . . . . . . . . . . . . . . . . . 7.4.1 Setting up the environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.4.2 Create the server and the datasource . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.4.3 Using an SQLJ Java project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.4.4 User-managed persistence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.4.5 Container-managed persistence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.4.6 Customization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.4.7 WAS 5.1.0.1 FixPak . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.5 Deployment to WebSphere Application Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.6 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Chapter 8. Transaction management in a WebSphere environment . . . . . . . . . . . . . 8.1 What transactions are . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.1.1 Local transactions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.1.2 Global transactions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.2 WebSphere transaction management. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.2.1 Transaction demarcation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.2.2 Bean-managed transactions and the UserTransaction interface . . . . . . . . . . . . 8.2.3 Transaction types (for container-managed transactions) . . . . . . . . . . . . . . . . . . 8.3 WebSphere resources and transaction support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.3.1 Resource interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.3.2 Resource transaction isolation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.3.3 Configuring JDBC resources. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.4 DB2 as a transaction manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.4.1 Configuring and exploiting DB2 as a transaction manager . . . . . . . . . . . . . . . . . 8.4.2 DB2 configuration requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.4.3 DB2 or WAS as a transaction manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.5 DB2 as a resource manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.5.1 DB2s support for XA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.5.2 Global transaction support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.6 Considerations for two-phase commit processing. . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.6.1 Lock duration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.6.2 Failure impact . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.6.3 Lock impact from failure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.6.4 How to recover from failures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Chapter 9. DB2 locking in a WebSphere environment . . . . . . . . . . . . . . . . . . . . . . . . . 9.1 DB2 locking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.2 Transaction isolation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.2.1 Isolation levels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.2.2 Overriding lock mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.2.3 DB2 isolation determination in Java applications . . . . . . . . . . . . . . . . . . . . . . . . 9.2.4 Maintaining integrity with isolation Cursor Stability . . . . . . . . . . . . . . . . . . . . . . . 9.2.5 Data sharing considerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.3 WebSphere transaction-related deployment descriptors . . . . . . . . . . . . . . . . . . . . . . 9.3.1 Setting the WebSphere transaction isolation level . . . . . . . . . . . . . . . . . . . . . . .
149 149 150 150 153 154 158 159 160 161 167 172 183 187 188 189 190 191 192 192 192 194 194 195 196 198 198 199 199 202 202 203 204 204 204 205 206 206 207 207 207 209 210 210 212 212 213 214 216 217 217
vi
9.3.2 Entity Bean isolation level (access intent). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.4 Container-managed persistence generated SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.4.1 Who generates the persistence SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.4.2 Access intents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Chapter 10. DB2 - WebSphere performance aspects. . . . . . . . . . . . . . . . . . . . . . . . . . 10.1 Recommended hardware and software configuration. . . . . . . . . . . . . . . . . . . . . . . . 10.2 WebSphere Application Server connection pooling . . . . . . . . . . . . . . . . . . . . . . . . . 10.2.1 What is new in Version 5 - What is in WebSphere Version 4 . . . . . . . . . . . . . . 10.2.2 How connection pooling works - How connection objects are structured . . . . . 10.2.3 WebSphere data sources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.2.4 Connection pooling - Best practices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.3 DB2 and JDBC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.3.1 Adjusting the number of DB2 threads and connections . . . . . . . . . . . . . . . . . . 10.3.2 Enabling DB2 dynamic statement cache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.3.3 Choosing static SQL over dynamic SQL. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.3.4 Usage guidelines for JCC type 2 and type 4 connectivity . . . . . . . . . . . . . . . . . 10.3.5 Enterprise JavaBeans (EJBs) and DB2 access . . . . . . . . . . . . . . . . . . . . . . . . 10.4 WLM classification of WAS and its impact on DB2 . . . . . . . . . . . . . . . . . . . . . . . . . . 10.4.1 How DB2 and WebSphere Servers are structured on z/OS . . . . . . . . . . . . . . . 10.4.2 Enabling WLM dynamic application environments with WAS V5 . . . . . . . . . . . 10.4.3 WebSphere classification and its impact on DB2 . . . . . . . . . . . . . . . . . . . . . . . 10.5 Tuning the storage for z/OS and the Java Virtual Machine. . . . . . . . . . . . . . . . . . . . 10.6 Universal Driver tracing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.6.1 Universal Driver tracing. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.6.2 DB2SystemMonitor class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Chapter 11. Sample application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.1.1 Sample table description. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.1.2 Importing the tables into WSAD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.2 MVC model with entity Beans and a session Bean. . . . . . . . . . . . . . . . . . . . . . . . . . 11.2.1 Creating entity CMP Beans using JDBC from the imported tables . . . . . . . . . . 11.2.2 Container-managed persistence entity Beans with SQLJ. . . . . . . . . . . . . . . . . 11.2.3 Bean and container-managed persistence entity Bean with SQLJ . . . . . . . . . . 11.2.4 Bean-managed persistence entity Beans with JDBC . . . . . . . . . . . . . . . . . . . . 11.2.5 Completing the model with the session Bean . . . . . . . . . . . . . . . . . . . . . . . . . . 11.3 The View component of the MVC model. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.4 Controller component of MVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.5 The enterprise J2EE application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.6 Deployment of the EAR file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.7 Test of the application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
218 218 219 219 221 222 222 223 223 224 228 229 229 229 230 230 232 232 233 233 233 234 235 235 244 245 246 248 249 253 253 273 280 280 290 296 298 306 307 313
. Appendixes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 317 Appendix A. Additional material . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Locating the Web material . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using the Web material . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . How to use the Web material . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Related publications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . IBM Redbooks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Other publications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Online resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 319 319 319 319 321 321 321 322
Contents
vii
How to get IBM Redbooks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 322 Help from IBM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 322 Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323
viii
Figures
1-1 1-2 1-3 1-4 1-5 1-6 1-7 2-1 2-2 2-3 2-4 2-5 2-6 2-7 2-8 2-9 2-10 2-11 2-12 3-1 3-2 3-3 3-4 3-5 3-6 3-7 3-8 3-9 3-10 3-11 3-12 3-13 3-14 3-15 3-16 3-17 3-18 3-19 3-20 3-21 3-22 3-23 3-24 3-25 3-26 3-27 3-28 3-29 Basic data flow in a DB2 subsystem from z/OS and distributed environments . . . . . . 8 DB2 data structure hierarchy and relationships . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 Different types of table spaces available in DB2 UDB for OS/390 and z/OS. . . . . . . 11 Referential constraints between tables DEPT and EMP . . . . . . . . . . . . . . . . . . . . . . 17 Program preparation using the DB2 precompiler or SQL statement coprocessor. . . 18 IBM DB2 Universal JDBC Driver type 2 and type 4 connectivity . . . . . . . . . . . . . . . . 23 DB2 z/OS Application Connectivity and DB2 Universal Driver implementations . . . . 25 J2EE architecture. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 J2EE roles with an IBM perspective . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 Content of the EAR file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 WebSphere as a HTTP server plug-in . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 Controllers and servants, the server instance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 Base Application Server node . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 Multiple Base Application Server nodes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 One Base Application Server node with multiple servers . . . . . . . . . . . . . . . . . . . . . 43 Two-system sysplex, deployment manager. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 Administrative Console login . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 Administrative Console home page . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 The WebSphere pyramid . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 Configuration used in our sample scenario . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 Type 2 drivers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 Login screen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 Admin console after login. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 Available JDBC providers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 List of available JDBC providers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 Driver properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 JDBC new provider list. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 Additional properties of the DB2 Universal JDBC Driver Provider. . . . . . . . . . . . . . . 57 New Data Source. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 General Properties 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 General Properties 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 General Properties 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 Additional Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 Custom Properties 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 Custom Properties 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 Custom Properties 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 Custom Properties 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 WebSphere Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 Symbolic parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 Application Server selection. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 Servant selection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 Additional properties under Process Definition/Servant. . . . . . . . . . . . . . . . . . . . . . . 67 Custom Properties under Servant/Java Virtual Machine . . . . . . . . . . . . . . . . . . . . . . 68 New property . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 Start command and arguments for Servant . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 Environment entries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 New environment entry . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 Adding the STEPLIB variable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
ix
3-30 3-31 3-32 3-33 3-34 3-35 3-36 3-37 3-38 3-39 3-40 3-41 3-42 3-43 3-44 3-45 3-46 5-1 5-2 5-3 5-4 5-5 6-1 6-2 6-3 6-4 6-5 6-6 7-1 7-2 7-3 7-4 7-5 7-6 7-7 7-8 7-9 7-10 7-11 7-12 7-13 7-14 7-15 7-16 7-17 7-18 7-19 7-20 7-21 7-22 7-23 7-24 8-1 x
Select Application Servers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 Create a new server. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 Create new Application Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 Overview with new Application Server. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 Configuration hierarchy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 Overview of Application Servers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 Configuration of new server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 type 4 driver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 Create new JDBC provider . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 JDBC Providers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 Configuration for XA JDBC provider . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83 Manage WebSphere Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 DB2 Universal JDBC Driver (XA). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 New Data Source type 4 definition to DBD8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 Custom Properties selection for the Data Source . . . . . . . . . . . . . . . . . . . . . . . . . . . 86 Properties for a type 4 Data Source different from type 2 . . . . . . . . . . . . . . . . . . . . . 86 Properties for a type 4 Data Source different from type 2 . . . . . . . . . . . . . . . . . . . . . 87 SQLJ program preparation using the DB2 JDBC Legacy Driver . . . . . . . . . . . . . . . 118 SQLJ program preparation process using the DB2 Universal JDBC Driver . . . . . . 119 Setting the currentSQLID property. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122 Setting the currentSchema property . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 Setting the currentPackageSet property . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124 Adding the securityMechanism property . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132 Specifying a Beans Run-As value. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133 Setting the Res-Auth value within an EJB reference to a datasource . . . . . . . . . . . 134 Setting JCA user identity and password . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134 Setting the container and component JCA identities . . . . . . . . . . . . . . . . . . . . . . . . 135 Enabling Sync To OS thread support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136 The SQLJ roadmap from the client container to DB2 . . . . . . . . . . . . . . . . . . . . . . . 150 Best practice overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153 Application flow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154 Setting the transaction type in WebSphere Studio Application Developer . . . . . . . 156 WSAD preferences - Automatically build resource on save . . . . . . . . . . . . . . . . . . 160 WSAD SQLJ preferences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160 Adding sqlj files as text files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161 Create a new server. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162 Creating a new server and server configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . 162 Create a JAAS entry . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163 Creating a JDBC provider, step 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164 Creating a JDBC provider, step 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165 Creating a data source, step 1. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166 Creating a data source, step 2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167 Create a Java Project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168 SQLJ customization script options. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169 Create a new SQLJ file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169 The directory for the SQLJ test project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171 Content of project ItsoSqlj . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172 SQLJ files and Java inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173 Mapping strategies for CMP Beans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184 Container-managed persistence and SQLJ. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185 Abstract persistence schema. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186 Verifying FixPak WAS 5.1.0.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189 Two-phase commit processing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193
8-2 8-3 8-4 8-5 8-6 8-7 8-8 8-9 9-1 10-1 10-2 10-3 10-4 10-5 10-6 10-7 10-8 10-9 11-1 11-2 11-3 11-4 11-5 11-6 11-7 11-8 11-9 11-10 11-11 11-12 11-13 11-14 11-15 11-16 11-17 11-18 11-19 11-20 11-21 11-22 11-23 11-24 11-25 11-26 11-27 11-28 11-29 11-30 11-31 11-32 11-33 11-34 11-35
Deployment Descriptor: Bean options for transaction management . . . . . . . . . . . . Method declaration of transaction type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Container transaction types for method execution. . . . . . . . . . . . . . . . . . . . . . . . . . Universal JDBC Providers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . DB2 Universal JDBC Driver DataSource Custom Properties . . . . . . . . . . . . . . . . . DB2 UDB for z/OS as the transactions manager. . . . . . . . . . . . . . . . . . . . . . . . . . . Native DDF XA support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Single Global Transaction crossing multiple Application Servers . . . . . . . . . . . . . . Resource reference isolation settings for session Beans . . . . . . . . . . . . . . . . . . . . State of a connection object. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Connection pool parameter specification. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Statement cache size. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using type 2 connectivity for local DB2 access . . . . . . . . . . . . . . . . . . . . . . . . . . . . Connecting a WAS to a DB2 for z/OS via the type 4 XA Universal Driver. . . . . . . . Connecting a WAS to a DB2 for z/OS via a DB2 router system and a type 2 driver WebSphere Application Server configurations . . . . . . . . . . . . . . . . . . . . . . . . . . . . JVM Custom Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Custom Properties trace options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . MVC design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . MVC design with session Bean as entry to model. . . . . . . . . . . . . . . . . . . . . . . . . . Application sample tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . New Connection. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Connection definition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Confirm Filters selection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Filter setting to NULLID . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . New look of the DB Servers pane . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . New button. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Project selections. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . EJB level specification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Project name and Enterprise Application. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Import to folder in EJB project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Select of the import folder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . EJB project after import . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . NULLID.DEPT table overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . NULLID.DEPT table columns . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . NULLID.DEPT table Primary Key . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . NULLID.DEPT table foreign keys . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Columns of EMP_PHOTO_RESUME table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . RDB to EJB Mapping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Back-end folder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mapping bottom-up . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . CMP type2.0 and name prefix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Map.mapxmi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Files generated by EJB to RDB Mapping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Generated code for DEPT table. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Outline view of table EMP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A department can have 0..m employees (0..1->0..m) . . . . . . . . . . . . . . . . . . . . . . . Beans - Relationships . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Defined relationship between Emp-Dept . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Deployment descriptor - Overview. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dept CMP entity Bean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Deployment and RMIC code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Added finders for CMR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Figures
195 196 197 200 201 203 205 206 218 224 227 228 231 231 232 233 237 241 246 247 248 250 250 251 252 253 253 254 254 254 255 255 256 257 257 258 258 259 260 260 260 261 261 262 262 264 267 267 268 269 270 271 271 xi
11-36 11-37 11-38 11-39 11-40 11-41 11-42 11-43 11-44 11-45 11-46 11-47 11-48 11-49 11-50 11-51 11-52 11-53 11-54 11-55 11-56 11-57 11-58 11-59 11-60 11-61 11-62 11-63 11-64 11-65 11-66 11-67 11-68 11-69 11-70 11-71 11-72 11-73 11-74 11-75 11-76 11-77 11-78 11-79 11-80 11-81 11-82 11-83 11-84 11-85 11-86 11-87 11-88 xii
Java packages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Changing qualifier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Changing the SQLJ option. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Sqlj and Java code after translation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . skeleton of the Customization script . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Additions for SQLJ under SQLJAntScripts directory . . . . . . . . . . . . . . . . . . . . . . . . SQLJ Customization script after . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Target pane from Ant . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Properties pane . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Beans panel for Emp_photo_resume . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Enterprise Bean creation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . New Bean in project. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Give a name to the Bean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Selecting local or remote interfaces. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Java files created . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The six original BMP classes/interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Beans panel of the EJB Deployment Descriptor . . . . . . . . . . . . . . . . . . . . . . . . . . . ITSODB2 to jdbc/ITSO1. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . New session Bean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . New Enterprise Bean window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Create an Enterprise Bean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Enterprise Bean details . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Session Bean layout view . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Data transfer between controller and model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Deployment Descriptor Bean section for ITSOAccess . . . . . . . . . . . . . . . . . . . . . . References in deployment descriptor to entity Beans . . . . . . . . . . . . . . . . . . . . . . . Select Beans to generate deployment code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Views for MVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Controller . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Select Web/Dynamic Web Project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Project Name . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . J2EE level and application. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Including Struts support and some JSP tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Struts level 1.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Struts operation principle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Webcontent directory structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mapping in Struts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Actionservlet in the Web project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Modules in application ItsoEAR1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Installing a new application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Accept the default . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . installation options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Overview of the projects part of the J2EE application . . . . . . . . . . . . . . . . . . . . . . . JNDI names for the EJBs. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Specifying the real datasource name. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . jdbc Data Source references . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . References to EJBs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . BMP reference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Virtual host . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Application server selection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Check protection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Install confirmation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
272 273 274 275 275 276 276 277 278 279 280 281 281 281 282 283 289 289 290 291 291 292 292 293 294 295 296 297 299 299 300 300 301 301 302 303 303 304 306 307 308 308 309 309 310 310 311 311 312 312 312 313 313
Figures
xiii
xiv
Tables
1-1 1-2 1-3 1-4 1-5 2-1 3-1 4-1 5-1 6-1 7-1 7-2 8-1 9-1 9-2 9-3 9-4 9-5 10-1 11-1 Columns. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 Columns. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 JDBC differences between the DB2 Universal Driver and the DB2 Legacy Driver . . 31 SQLJ differences between the DB2 Universal Driver and the DB2 Legacy Driver . . 32 JDBC APIs specific to the DB2 Universal Driver . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 Some of the J2EE APIs supported by WAS 5.0.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 Supported Driver Providers with WAS v5.02 on z/OS . . . . . . . . . . . . . . . . . . . . . . . . 51 Data access comparison . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105 Comparison of JDBC and SQLJ characteristics . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 Client accounting strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136 Subset of columns in the employee table from the DB2 sample database . . . . . . . 144 SQLJ isolation levels and their corresponding DB2 counterparts . . . . . . . . . . . . . . 145 Summary of JDBC Driver Provider support for WebSphere z/OS . . . . . . . . . . . . . . 201 Compatibility of page and row lock modes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211 Lock mode compatibility for table space and partition locks . . . . . . . . . . . . . . . . . . 211 Lock mode override . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213 DB2 UDB for z/OS and JDBC/SQLJ isolation mapping. . . . . . . . . . . . . . . . . . . . . . 214 Access Intent SQL append summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220 Trace level options for the DB2 Universal Driver for SQLJ and JDBC . . . . . . . . . . 236 Connection properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251
xv
xvi
Examples
1-1 1-2 1-3 1-4 1-5 1-6 1-7 1-8 1-9 1-10 3-1 3-2 3-3 3-4 5-1 5-2 5-3 6-1 6-2 7-1 7-2 7-3 7-4 7-5 7-6 7-7 7-8 7-9 7-10 7-11 7-12 7-13 7-14 7-15 7-16 7-17 7-18 7-19 7-20 7-21 7-22 7-23 7-24 9-1 10-1 10-2 10-3 10-4 CICS command-level services used with the CICS attachment facility . . . . . . . . . . . . 6 SQL statement that returns all columns from table EMP . . . . . . . . . . . . . . . . . . . . . . 13 Employees with a salary above $50,000 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 Sample export statements for the PATH environment variable . . . . . . . . . . . . . . . . . 26 Sample export statements for the LIBPATH environment variable . . . . . . . . . . . . . . 27 Sample export statements for the CLASSPATH environment variable . . . . . . . . . . . 27 Running the DB2Binder utility . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 Running the DB2T4XAIndoubtUtil utility . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 DDL to create the SYSIBM.INDOUBT table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 Casting an instance of the JDBC class to an instance of the DB2-only class . . . . . . 32 Properties file for SSID DBD8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 Start procedure for Servant . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 included member with updated STEPLIB for DB2 V8 . . . . . . . . . . . . . . . . . . . . . . . . 70 Include member WSD7SZ with STEPLIB for DB2 V7 . . . . . . . . . . . . . . . . . . . . . . . . 77 Importing classes in a JDBC application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 UPDATE statement using parameter markers. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 Compiling a Java application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117 Setting the workstation client strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 WSConnection using setClientInformation method . . . . . . . . . . . . . . . . . . . . . . . . . 137 Look up of the datasource using default values. . . . . . . . . . . . . . . . . . . . . . . . . . . . 141 Look up of the datasource in detail . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142 Caching the lookup information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142 Getting a connection in SQLJ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 Creating the context using Universal Driver features. . . . . . . . . . . . . . . . . . . . . . . . 143 Writing a SELECT statement using SQLJ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145 Disable automatic creation of DB2 packages during customization . . . . . . . . . . . . 148 Simple user transaction example. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155 setRollbackOnly() on the sessioncontext. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156 Handling of a SQLException . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158 Handling SQLWarning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159 Simple SQLJ source file. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170 The sqlj.project.properties file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171 The Ant script used to bind the packages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171 DBAEmployee.java file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174 DBAEmployeeServlet.sqlj file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175 DBAEmployeeEJB.sqlj file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177 Create a data transfer object based on information in the request . . . . . . . . . . . . . 180 Create an employee without using a transaction . . . . . . . . . . . . . . . . . . . . . . . . . . . 180 Create an employee using a user transaction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181 Calling SQLJ from a session Bean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182 Calling SQLJ from an entity Bean with Bean-managed persistence . . . . . . . . . . . . 182 EJB QL example from our sample application. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186 NullPointerException thrown by WAS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188 Example of a datasource lookup with a resource reference . . . . . . . . . . . . . . . . . . 217 Global driver properties file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237 Universal Driver trace output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238 Data source level trace output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241 WSSystemMonitor example. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244
xvii
11-1 11-2 11-3 11-4 11-5 11-6 11-7 11-8 11-9 11-10 11-11 11-12 11-13 11-14 11-15 11-16
getImage() method. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . empl.Department . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Business method for getting Department information . . . . . . . . . . . . . . . . . . . . . . . CMP definitions for EMP table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . CMR definitions for EMP table->DEPT table relationship . . . . . . . . . . . . . . . . . . . . EJBQL statement in the deployment descriptor. . . . . . . . . . . . . . . . . . . . . . . . . . . . Finder in ITSOEmpLocalHome.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Binding of the SQLJ packages. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . PhotoEmployeeBMPKey class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Local home interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Local interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . BMP Bean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getEmployee() method. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getEmployee method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ITSOEmployee.jsp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Action class for employee.do . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
264 265 265 266 266 268 269 278 282 284 284 284 293 295 297 305
xviii
Notices
This information was developed for products and services offered in the U.S.A. IBM may not offer the products, services, or features discussed in this document in other countries. Consult your local IBM representative for information on the products and services currently available in your area. Any reference to an IBM product, program, or service is not intended to state or imply that only that IBM product, program, or service may be used. Any functionally equivalent product, program, or service that does not infringe any IBM intellectual property right may be used instead. However, it is the user's responsibility to evaluate and verify the operation of any non-IBM product, program, or service. IBM may have patents or pending patent applications covering subject matter described in this document. The furnishing of this document does not give you any license to these patents. You can send license inquiries, in writing, to: IBM Director of Licensing, IBM Corporation, North Castle Drive Armonk, NY 10504-1785 U.S.A. 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. Information concerning non-IBM products was obtained from the suppliers of those products, their published announcements or other publicly available sources. IBM has not tested those products and cannot confirm the accuracy of performance, compatibility or any other claims related to non-IBM products. Questions on the capabilities of non-IBM products should be addressed to the suppliers of those products. This information contains examples of data and reports used in daily business operations. To illustrate them as completely as possible, the examples include the names of individuals, companies, brands, and products. All of these names are fictitious and any similarity to the names and addresses used by an actual business enterprise is entirely coincidental. COPYRIGHT LICENSE: This information contains sample application programs in source language, which illustrates programming techniques on various operating platforms. You may copy, modify, and distribute these sample programs in any form without payment to IBM, for the purposes of developing, using, marketing or distributing application programs conforming to the application programming interface for the operating platform for which the sample programs are written. These examples have not been thoroughly tested under all conditions. IBM, therefore, cannot guarantee or imply reliability, serviceability, or function of these programs. You may copy, modify, and distribute these sample programs in any form without payment to IBM for the purposes of developing, using, marketing, or distributing application programs conforming to IBM's application programming interfaces.
xix
Trademarks
The following terms are trademarks of the International Business Machines Corporation in the United States, other countries, or both:
AIX AS/400 Cloudscape CICS Distributed Relational Database Architecture DB2 Connect DB2 Universal Database DB2 DRDA Enterprise Storage Server Everyplace IBM ibm.com IMS iSeries MVS OS/2 OS/390 OS/400 PR/SM Rational Redbooks Redbooks (logo) RACF S/390 VTAM WebSphere z/Architecture z/OS zSeries
The following terms are trademarks of other companies: Microsoft, Windows, Windows NT, and the Windows logo are trademarks of Microsoft Corporation in the United States, other countries, or both. Java and all Java-based trademarks and logos are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States, other countries, or both. UNIX is a registered trademark of The Open Group in the United States and other countries. Other company, product, and service names may be trademarks or service marks of others.
xx
Preface
DB2 for z/OS is a high-performance DBMS, with a very strong reputation in high-volume transaction workloads based on relational technology. WebSphere Application Server is a transaction monitor based on object-oriented technology, very much in sync with the J2EE standard. Can we marry the object world and relational world to create a high-volume, high-performance end-to-end OLTP environment? The answers can be found in this IBM Redbook. This book gives a broad understanding of the installation, configuration, and use of the IBM DB2 Universal Driver for SQLJ and JDBC in a DB2 for z/OS and OS/390 Version 7, and DB2 for z/OS Version 8 environment, with IBM WebSphere Application Server for z/OS for z/OS Version 5.02. It describes both type 2 and type 4 connectivity (including the XA transaction support) from a WebSphere Application Server on z/OS to a DB2 for z/OS and OS/390 database server. This publication also demonstrates the advantages of SQLJ in a DB2 environment, the SQLJ support in the IBM application development tool WebSphere Studio Application Developer, as well as the SQLJ support for Enterprise JavaBeans using container managed persistence.
xxi
New York, and will soon join the DB2 development organization at the Silicon Valley Lab, San Jose as a DB2 for z/OS Performance Analyst. Chao-Lin holds a Masters of Science degree in Computer Science from Johns Hopkins University. Egide Van Aerschot works for the IBM Program Support Center in Montpellier, France since 1998, and is a member of the New Technology Center team, supporting and providing education for J2EE projects, WebSphere Business Integration, and connections to legacy systems. Before this he worked for IBM Belgium as an Account Systems Engineer, responsible for many projects related to transactional processing with major Belgium customers. During this period he also participated in several residencies in the United States. He graduated from the University of Louvain as a civil engineer. Thanks to the following people for their contributions to this project: Emma Jacobs International Technical Support Organization, San Jose Center Rich Conway Bob Haimowitz Julie Czubik International Technical Support Organization, Poughkeepsie Center Maria Sueli Almeida Sigi Bigelis Bill Bireley Delmar Blevins Maryela Weihrauch IBM Silicon Valley Laboratory, San Jose Kim Johnson IBM WebSphere Development, Poughkeepsie Terasa Kan IBM WebSphere Architecture and Development, Rochester Connie Tsui IBM Toronto Laboratory, Canada
xxii
Comments welcome
Your comments are important to us! We want our Redbooks to be as helpful as possible. Send us your comments about this or other Redbooks in one of the following ways: Use the online Contact us review redbook form found at:
ibm.com/redbooks
Mail your comments to: IBM Corporation, International Technical Support Organization Dept. QXXE Building 80-E2 650 Harry Road San Jose, California 95120-6099
Preface
xxiii
xxiv
Chapter 1.
Performance and scalability enhancements such as new streamlined application drivers (ODBC, OLE DB, JDBC, and SQLJ) and new client architecture Business intelligence capabilities to easily organize data allowing for faster and more insightful queries Currently, the available editions of DB2 UDB for Linux, UNIX, and Windows Version 8.2 and the operating systems on which they operate include: DB2 UDB Enterprise Server Edition available for AIX, HP-UX, Linux, Solaris, Windows NT, Windows 2000, and Windows 2003 operating systems. DB2 UDB Workgroup Server Unlimited Edition available for AIX, HP-UX, Linux, Solaris, Windows NT, Windows 2000, Windows 2003, and Windows XP operating systems having up to four CPUs. DB2 UDB Workgroup Server Edition available for AIX, HP-UX, Linux, Solaris, Windows NT, Windows 2000, Windows 2003, and Windows XP operating systems having up to four CPUs. DB2 UDB Personal Edition available for Linux, Windows NT, Windows 2000, Windows 2003, and Windows XP (with V8 Fixpack 4 or later) operating systems. DB2 UDB Express Edition available for Linux, Windows NT, Windows 2000, Windows 2003, and Windows XP operating systems having up to two CPUs. It comes in two flavors: DB2 UDB Express Edition (named user option), where registered users are entitled to the database DB2 UDB Express Edition CPU Option, where each available CPU must be entitled DB2 UDB Universal Developers Edition available for AIX, HP-UX, Linux, solaris, Windows NT, Windows 2000, Windows 2003, and Windows XP operating systems. Attention: Each developer must have an individual license. The software in this package cannot be used for production systems. DB2 UDB Personal Developers Edition available for Linux, Windows NT, Windows 2000, Windows 2003, and Windows XP operating systems. For more detailed information see: http://www.ibm.com/software/data/db2/udb/ On the Linux, UNIX, and Windows platforms, we also have the suite of DB2 Connect products that provide the application enablement and robust, highly scalable communication infrastructure for connecting Web, Windows, UNIX, Linux, OS/2, and mobile applications to S/390 and AS/400 data. DB2 Connect comes in several flavors: DB Connect Enterprise Edition DB2 Connect Personal Edition DB2 Connect Unlimited Edition DB2 Connect Application Server Edition For more information on DB2 Connect, see:
http://www.ibm.com/software/data/db2/db2connect/
1.2.4 More information on the DB2 UDB family, related tools, and products
Of course, the latest information on the complete DB2 UDB family is available on the Internet at the following URL:
http://www.ibm.com/software/data/db2/
As a user, you may be familiar with ssnmMSTR as the place to look for system messages related exclusively to DB2.
Important: In DB2 UDB for z/OS Version 8, the NO WLM ENVIRONMENT keyword has been deprecated. Existing DB2-managed stored procedures continue to work in V8, but all newly created stored procedures in a DB2 UDB for z/OS Version 8 subsystem require a WLM environment defined on the CREATE PROCEDURE statement.
CICS
The CICS attachment facility, language interface module DSNCLI, is provided by the CICS product. It receives CICS application requests and passes them to DB2. Example 1-1 shows the standard CICS command-level services that can be used.
Example 1-1 CICS command-level services used with the CICS attachment facility EXEC CICS WAIT EXEC CICS ABEND
By issuing DB2 commands, an authorized CICS terminal operator is able to control and monitor DB2 and the attachment facility.
IMS
The IMS attachment facility, program interface DFSLI000, is required to access DB2 from an IMS environment. It receives and interprets requests for access to DB2 databases using exits provided by IMS subsystems. The IMS attachment facility also allows an authorized IMS terminal operator the ability to issue DB2 commands such as starting and stopping DB2 databases.
TSO
The TSO attachment facility offers unique functionality. It is required for binding application plans and packages and to execute online DB2 functions. In fact, the CICS and IMS attachment facilities depend on the TSO attachment facility for these functions. Access to DB2 in foreground through a TSO terminal or in batch mode through the TSO terminal monitor program (TMP) can be accomplished with the TSO attachment facility. In addition, two command processors are provided: DSN command processor - Primarily used for batch jobs, uses the TSO attachment facility and runs as a TSO command processor DB2 Interactive (DB2I) - An interactive connection to DB2 allowing users to run SQL statements, issue DB2 commands, and run DB2 utilities using Interactive System Productivity Facility (ISPF) panels With the TSO attachment facility, load module DSNELI, access to DB2 is fairly simple. On the other hand, this also means that an application has less control over the state of the connections and, when using DSN services, applications running under the control of DSN.
TSO
attachment facility
MSTR
address space
DDF
address space
IMS
attachment facility
CICS
attachment facility
z/OS environment
CAF RRSAF
Distributed environment
DBM1
address space
IRLM
address space
Figure 1-1 Basic data flow in a DB2 subsystem from z/OS and distributed environments
A request from a distributed environment is very similar to the data flow originating from within a z/OS environment (local attachment). The significant difference is using the DDF address space to establish a connection as opposed to an attachment facility. This is also the case when using JDBC Type 4 connectivity provided by the IBM DB2 Universal JDBC Driver to connect to a DB2 for z/OS subsystem. In this scenario, the Universal Driver is acting as a DRDA application requester to establish a connection into the DDF address space (acting as a DRDA application server) of the DB2 for z/OS subsystem. This is discussed in more detail in Accessing DB2 from a Java environment on page 19.
Database
Table space
Storage group
Table
Volume 1
Index space
Volume 2
Index Volume 3
1.4.1 Databases
In DB2 for z/OS, a database is a logical grouping of data objects. A database is defined by using the CREATE DATABASE statement. The default database is named DSNDB04. A single database, for example, can contain all the data that is associated with one application or with a group of related applications. Collecting that data into one database allows you to start or stop access to all the data in one operation. You can also grant authorization for access to all the data as a single unit. Assuming that you are authorized to do so, you can also access data that is stored in different databases. Databases in a DB2 UDB for z/OS environment are fundamentally different compared to databases in DB2 UDB for Linux, UNIX, and Windows environments. For example, in a DB2 UDB for z/OS environment: Recovery logs are not database specific. All the databases in the entire DB2 subsystem use the same recovery logs. DB2 configuration parameters (DSNZPARMs) are for the entire DB2 subsystem. Databases such as the DB2 catalog database (DSNDB06), default database (DSNDB04), and the work file database (DSNDB07) are not isolated and are able to interact with each other. These are shared within the DB2 subsystem. In a DB2 UDB for Linux, UNIX, and Windows environment: Each database contains its own logs and configuration files.
Databases are isolated from each other. This means that, without any middleware intervention (or using DB2 federated database technology), a query involving tables from two different databases is not possible. The DB2 catalog and temporary space are created as table spaces, and are specific to a certain database.
Segmented
This divides the available space into groups of pages called segments. Each segment is the same size. The size of the segment is determined by the SEGSIZE keyword when the table space is created. The integer specified for SEGSIZE must be a multiple of 4 and must be between 4 and 64, inclusive. A segment contains rows from only one table. You can have one or more tables in a segmented table space.
Partitioned
This divides the available space into separate units of storage called partitions. Each partition is backed by a physical data set and stores data of only one table. The number of partitions is determined when the table space is created with the NUMPARTS keyword. In DB2 for z/OS Version 8, an integer from 1 to 4096 can be used when specifying a value for NUMPARTS. Partitions of a given table space can be independently assigned to different storage groups.
10
Simple
This is the type of table space created if neither LOB, NUMPARTS or SEGSIZE is specified when defining a table space. Unlike segmented table spaces, the rows of different tables are not kept separate in a simple table space. It is for this reason, although simple table spaces can contain more than one table, it is recommended (in general) that only one table exists at any given time in a simple table space.
Database
Partitioned table space
Storage group A
Table
Table
Table Volume 1
Table
Segmented table space
Volume 2 Table
Volume 3
Volume 4
Table
Table
Auxiliary Table
Volume 5
Volume 6
Figure 1-3 Different types of table spaces available in DB2 UDB for OS/390 and z/OS
1.4.5 Tables
Tables are logical structures, and are made up of an ordered set of columns. A table is defined using the CREATE TABLE statement. Every table must have one or more columns, but the number of rows can be zero or more. Although the data is physically stored in a data set at the table space level, the table structure is referred to when accessing the data.
Only auxiliary tables can store LOB data in LOB table spaces. Auxiliary tables are defined using the CREATE AUXILIARY TABLE statement. A LOB auxiliary table is always associated with a non-LOB table that is defined in a non-LOB table space. This non-LOB table is called a base table. The base table contains one or more (logical) LOB columns. The values in the LOB column are a pointers to the actual LOB data in the auxiliary table. In order to retrieve the LOB data, a query against the base table is performed. A LOB table space must be in the same database as the table space that contains the base table.
1.4.6 Indexes
An index is an ordered set of pointers to rows of a table. As an index in a book points to a page that a specific topic is discussed, you can think of a DB2 index in the same way. Each
Chapter 1. Introduction to DB2 for z/OS and OS/390
11
index entry points to a specific row of a table. Each index is based on the values of data in one or more columns of a table. Each index occupies its own index space (a physical data set on disk). An index is defined using the CREATE INDEX statement. Once the index is defined, DB2 maintains the index. For example, whenever a row is inserted into the table, a corresponding index entry is automatically created in the index by DB2. However, maintenance such as reorganizing or recovering an index is not automatically performed by DB2. The DB2 Universal Database for z/OS Version 8 Utility Guide and Reference, SC18-7427, contains additional information on the DB2 REORG and RECOVER utilities. The most common use for an index is to improve performance and ensure uniqueness. In most cases, access to data is faster with an index than with a table space scan of the entire data. There are different types of indexes that can be defined.
Unique indexes
Unique indexes ensure that no duplicate values of the index key exist in the table. Unique indexes are also an important part of implementing referential constraints among the tables in your DB2 database. You cannot define a foreign key unless the corresponding primary key already exists and has a unique index defined against it.
Clustering indexes
Clustering indexes direct DB2 to insert rows into the table in the order of the clustering key values. The first index that you define on the table serves implicitly as the clustering index unless you explicitly specify the CLUSTER keyword when you create or alter another index. In DB2 UDB for z/OS Version 8, CLUSTER can be specified for any index, whether or not it is a partitioning index.
Partitioning indexes
To indicate which rows go into which partition of a partitioned table space, you select one or more (partitioning) columns, and indicate for each partition the highest value that should go into that partition. The highest value for a partition is referred to as the limit key of the partition. Before DB2 for z/OS Version 8, the partitioning key columns and the limit key values in the PART VALUES clause are specified on the CREATE INDEX statement. This type of partitioning is referred to as index-controlled partitioning. Beginning with DB2 for z/OS Version 8, there is a new option to defining table-controlled partitioning by using partitioning clause (PARTITION BY) on the CREATE TABLE statement. An index is considered to be a partitioning index if the left-most columns in the index are the same as the partitioning columns, and have the same collating sequence as the partitioning columns (that you specify the limit keys for). Because prior to DB2 for z/OS Version 8 all partitioned table spaces are index-controlled partitioned table spaces, the index that you specify the partitioning columns and limit keys for, is by definition a partitioning index. Prior to Version 8 that index is always physically partitioned, as well as the explicit clustering index for the partitioned table. In Version 8, a partitioning index is not always physically partitioned, nor does it have to be the clustering index. For more information see DB2 for z/OS Version 8 Everything you ever wanted to know, ... and more, SG24-6079.
12
Secondary indexes
Secondary indexes are indexes that are not partitioning indexes but are defined against a partitioned table space. Traditionally, secondary indexes are used to enforce a uniqueness constraint, or to provide a better access path to data for queries. In DB2 UDB for z/OS Version 8, there are two types of secondary indexes: Data-partitioned secondary index (DPSI) - A DPSI has the same number of partitions as the partitioned table space in which the referenced table resides. Index keys in a particular index partition reference only data of the same table space partition. DPSIs can also be a clustering index. DPSIs cannot be unique. Nonpartitioned secondary index (NPSI) - Basically, an index that performs the traditional roles of a secondary index and is not partitioned. NPSIs can be created against a table in a partitioned or nonpartitioned table space. A NPSI resides in a single index space (although it may consist of multiple physical data sets, for example, when using the PIECESIZE keyword on the CREATE INDEX statement).
Having a business need to see all the information for each employee may not be practical. Let us say we want to know only the employees having a salary greater than $50,000. Example 1-3 depicts the SQL statement that can be used to return results showing only the last name of the employee and the salary of the employee for all employees who have a salary above $50,000. The result of the query is shown in Table 1-2 on page 14.
Example 1-3 Employees with a salary above $50,000 SELECT LASTNAME, SALARY FROM TABLE EMP
13
WHERE SALARY > 50000; Table 1-2 Columns LASTNAME HOWE BAI RAITAKARI SALARY 85100 82500 120500
SQL statements are divided into three categories: Data Definition Language DDL refers to the SQL statements that create or modify data objects. The CREATE, ALTER, and DROP statements are examples of DDL. DCL identifies SQL statements that (mainly) affect security and user authorization when attempting to access DB2 data objects. GRANT, REVOKE, and LOCK TABLE statements are examples of DCL.
Data Manipulation Language DML identifies SQL statements that access the actual data. DML includes SQL statements such as SELECT, UPDATE, INSERT, and DELETE. When an SQL statement is executed, a sequence of internal operations takes place to optimize data retrieval. This transformation occurs when the SQL statement is prepared. This transformation is also known as binding. All executable SQL statements must be prepared before they can be executed. The result of preparation is the executable or operational form of the statement. There are primarily two categories of SQL. There is static SQL and dynamic SQL. When the SQL statement is prepared, the persistence of its operational form are the primary factors that distinguish static SQL from dynamic SQL.
14
Dynamic SQL can also be used by so-called call-level interfaces, such as ODBC. In this case, the SQL statement is not embedded into the host language, so there is no need to precompile the program itself prior to execution. The SQL statement is passed to the DBMS as an input parameter to a callable function implemented by the call-level interface. For more information, see DB2 Universal Database for z/OS Version 8 ODBC Guide and Reference, SC18-7423, and Squeezing the Most Out of Dynamic SQL with DB2 for z/OS and OS/390, SG24-6418. Complete SQL statement syntax as well as examples are available in the DB2 Universal Database for z/OS Version 8 SQL Reference, SC18-7426. Additional information on the traditional program preparation process is discussed in DB2 packages, plans, collections, and package lists on page 17. Complete details regarding precompilation, preparation of static SQL statements, compilation of modified source programs, and dynamic statement caching are available in the DB2 Universal Database for z/OS Version 8 Application Programming and SQL Guide, SC18-7415.
15
Figure 1-4 on page 17 illustrates the primary and foreign key relationships in sample tables DEPT and EMP. These are the same tables and referential constraints that are used in the examples throughout this publication. Tables DEPT and EMP have two referential constraints between them. In addition, table DEPT has a self-referencing constraint. The name given to a constraint is arbitrary. However, it is a good idea to try to give the constraint a meaningful name. Referential constraint RDEPT represents a relationship between the WORKDEPT column of table EMP and the primary key of table DEPT, column DEPTNO. This constraint is in place to ensure that each record in the EMP table has a valid department number, which is in the DEPT table. In addition, if a record is deleted from the DEPT table, this constraint is specifically defined to set the WORKDEPT column to NULL for all employees who had the department number that was deleted. This is accomplished by defining the referential constraint as ON DELETE SET NULL. Referential constraint REMP represents a relationship between the MGRNO column of table DEPT and the primary key of table EMP, which is column EMPNO. REMP is similar to RDEPT, the difference being the direction of the constraint (from table DEPT to table EMP) and the columns involved. This constraint is in place to ensure that each record in the DEPT table has a valid employee number in table EMP for the manager of the department. When a record is deleted from table EMP and that record happens to be an employee who managed a department, this constraint is defined to set the MGRNO column to NULL for all departments that had the employee number that was deleted. Much like the RDEPT constraint, this is accomplished by defining the referential constraint as ON DELETE SET NULL. Referential constraint RSELFD is a self-referencing constraint involving only table DEPT. By definition, a foreign key must point to the primary key of a table. This rule is being honored as RSELFD references column ADMRDEPT of table DEPT and points back to its own primary key, which is column DEPTNO. Unlike constraints RDEPT and REMP, RSELFD is defined as ON DELETE CASCADE. This referential constraint is in place to ensure that the department number in column ADMRDEPT is a valid department number. This is done by making sure the department number specified in column ADMRDEPT is also specified in column DEPTNO. When a record in DEPT is deleted, this constraint propagates the delete operation to the dependent rows.
16
Table DEPT
Primary Key
MGRNO
ADMRDEPT
Table EMP
Primary Key Referential constraint RDEPT
EMPNO
17
Each package contains only one DBRM. When a package is bound, there are many bind options that can be specified. These options determine how the SQL statements in the DBRM will ultimately execute in DB2. Bind options are very powerful. Some of the application characteristics they can influence are: The user ID used for authorization checking How DB2 locks data and when the locks are released Whether DRDA orDB2 private protocol is used when connecting to a remote site If parallel processing is used when a query is run If the local dynamic statement caching should be used In general, a plan is similar to a package in terms of bind options; however, the differences are: Packages and/or DBRMs are bound in a plan. A plan relates an application process to a local instance of DB2. One or more DBRMs can be directly bound in a plan. One or more packages can be bound in a plan. A plan can be made up of both DBRMs and packages. In almost all cases, an application must have a plan bound before it can run. There is one exception to this rule. A (explicit) plan is not required when using a distributed connection into DB2. When accessing DB2 through DDF, the package (which is required) runs under a system plan called DISTSERV.
Source program
Linkedit
Object program
Load module
DB2 Precompiler
DBRM
Modified source
Compile or assemble
BIND PACKAGE
BIND PLAN
Plan
Object program
Linkedit
Package
Load module
Figure 1-5 Program preparation using the DB2 precompiler or SQL statement coprocessor
Creating a package or a plan, a process unique to DB2, involves binding one or more DBRMs using the BIND PACKAGE or BIND PLAN commands. Complete syntax for the BIND PACKAGE and BIND PLAN commands as well as detailed information about the bind options 18
DB2 for z/OS and WebSphere: The Perfect Couple
are documented in the DB2 Universal Database for z/OS Version 8 Command Reference, SC18-7416. Note, however, that when using SQLJ with the IBM DB2 Universal Driver for SQLJ and JDBC, no DBRM is produced when the serialized profile is customized. For more information, see 5.4.2, SQLJ program preparation process on page 117.
Collections
There are many binding strategies that can be utilized to best suit the environment the application will run in, one of which is to use a collection. A collection is an arbitrary name given to a group of associated packages. To help visualize the concept of a collection, think of a collection as a department name, and the employees that work in the department as the packages. The collection name is a parameter that is specified as part of the BIND PACKAGE command.
Package lists
As indicated by its name, a package list is simply a list of packages that determines which packages are included in an application plan. The package list is specified with the PKLIST parameter of the BIND PLAN command. A collection can also be specified with the PKLIST parameter. The order in which packages or collections in the PKLIST are specified is important. The same order will be used for the search order at run time. This can affect performance. The use of packages, plans, and collections in a WebSphere environment is discussed in more detail in Chapter 5, DB2 application development in a WebSphere environment on page 109.
1.6.3 Schemas
A schema is a collection of named objects. The named objects can include distinct types, functions, stored procedures, sequences, and triggers. An object is assigned to a schema when it is created. The schema name of the object determines the schema to which the object belongs. When a distinct type, function, sequence, or trigger is created, it is given a qualified, two-part name. The first part is the schema name (or the qualifier), which is either implicitly or explicitly specified. The second part is the name of the object. When a stored procedure is created, for example, it is given a three-part name. The first part is a location name, which is implicitly or explicitly specified; the second part is the schema name, which is implicitly or explicitly specified; and the third part is the name of the object. Schemas extend the concept of qualifiers for tables, views, indexes, and aliases to enable the qualifiers for distinct types, functions, stored procedures, sequences, and triggers to be called schema names. Note: The qualifier, or owner of a table name, can also be considered a schema name, even though no explicit CREATEIN authorization is required to create a table with a specific qualifier.
19
servers of different types. This server focus makes it the architecture of interest for DB2 for OS/390 and z/OS developers. JDBC defines the standard Application Programming Interface (API) for accessing relational database systems, such as DB2, from Java. This API is the fundamental building block for writing DB2 Java applications. The SQLJ specification is currently not part of the J2EE standard, but is an ISO/ANSI standard. It consists of the following parts: Part 10 specifies the SQLJ language syntax and semantics for embedded SQL statements in a Java application. American National Standards Institute (ANSI) has accepted this part of the SQLJ specification for standardization (document number ISO/IEC 9075-10:2000). The International Standards Organization (ISO) has accepted the SQLJ specification, Part 10. Part 13 specifies extensions that define: Installation of Java classes in a relational database Invocation of Java static methods as SQL stored procedures or functions SQL:2003-conforming object data types and extensions for accessing Java classes as SQL structured types ANSI has accepted Part 13 of the SQLJ specification for standardization (document number ISO/IEC 9075-13:2002). DB2 UDB for z/OS Version 8 support for SQLJ includes Part 10 of the SQLJ specification and a subset of Part 13. Both JDBC and SQLJ can be used to create Java applications and applets that access DB2. DB2s support for JDBC allows Java applications to access local DB2 data or remote relational data on a server that supports Distributed Relational Database Architecture (DRDA). Java applications use SQLJ for static SQL and JDBC for dynamic SQL to access any relational database. SQLJ applications exploit JDBC as an underlying foundation for tasks such as connecting to databases and handling SQL errors. This allows SQLJ to inter-operate with JDBC, making it possible for an application program to use JDBC and SQLJ within the same unit of work.
The most current information on the latest JDBC specification available and future developments can be obtained at the following Sun Microsystems Web site:
http://java.sun.com/products/jdbc/
Type 1
Commonly referred to as the JDBC-ODBC bridge driver, type 1 drivers map the JDBC API to another data access API, such as ODBC. Type 1 JDBC drivers are limited in portability because of the fact that they are generally dependent on a native library. The overhead involved in having to use two APIs (JDBC and ODBC) degrades performance. DB2 for z/OS does not supply a type 1 driver.
Type 2
Type 2 drivers are written partly in the Java programming language and partly in native code. These drivers use a native client library specific to the data source to which they connect. Although portability is limited due to the platform-specific native code, the type 2 driver is currently the most commonly used driver type, as it provides the best performance when local to the database. DB2 UDB for OS/390 and z/OS offers two type 2 drivers: IBM DB2 JDBC/SQLJ 2.0 Driver, also known as the IBM DB2 Legacy Driver IBM DB2 Universal Driver for SQLJ and JDBC
Type 3
A type 3 driver is a driver that is written in pure Java. With the type 3 driver, a Java client is used to communicate with a middleware server using a network-specific protocol. The middleware server translates the client request in order to access the data source. DB2 for OS/390 and z/OS does not supply a type 3 driver.
Type 4
Type 4 drivers are written in pure Java and implement the database protocol for a specific data source. The client connects directly to the data source. DRDA is the protocol that is used when connecting to a DB2 system as a data source. The type 4 driver is fully portable since it is written purely in Java. The DB2 Universal Driver supports type 4 connectivity. Additional information on JDBC driver types and the different scenarios when they can/should be used is available in the DB2 for z/OS and OS/390: Ready for Java, SG24-6435.
21
More details on JDBC and SQLJ Universal Driver Type 4 XA connectivity distributed transaction support are also documented in the DB2 Universal Database for z/OS Version 8 Application Programming Guide and Reference FOR JAVATM , SC18-7414. The IBM DB2 Universal JDBC Driver (containing type 2, type 4, and type 4 XA support) is shipped as an optional installable Function Module Identifier (FMID) JDB8812 with DB2 UDB for z/OS Version 8. For DB2 UDB for OS/390 and z/OS Version 7, APAR PQ80841 delivers the IBM DB2 Universal JDBC Driver under FMID JDB7712. Tip: The latest maintenance level for the IBM DB2 Universal Driver for SQLJ and JDBC, at the time of writing this publication, is APAR PQ95284.
Attention: The DB2 JDBC Legacy Driver is also packaged in FMID JDB7712 in a DB2 UDB for OS/390 and z/OS Version 7 environment, and FMID JDB8812 in a DB2 UDB for z/OS Version 8 environment. However, the HFS sub-directories used for the Universal Driver and the Legacy Driver are different.
Java application
DriverManager or DataSource
Type 2 connectivity
DDF
Local DB2 subsystem
DRDA (potential)
Figure 1-6 IBM DB2 Universal JDBC Driver type 2 and type 4 connectivity
23
Java 2 Technology Edition, SDK 1.3.1 or later is required to use the IBM DB2 Universal JDBC Driver. At the time of writing this publication, the DB2 Universal Driver supports the following JDBC and SQLJ functions: All methods described in the JDBC 1.2 and JDBC 2.0 specifications. Most methods described in the JDBC 3.0 specification SQLJ statements that perform equivalent functions to all JDBC methods Implementation of Java user-defined functions and stored procedures (Universal Driver type 2 connectivity only) Global transactions that run under WebSphere Application Server Version 5.02 (with APAR PQ80079) and later Distributed transaction support that implements the Java 2 Platform, Enterprise Edition (J2EE) Java Transaction Service (JTS) and Java Transaction API (JTA) specifications (Universal Driver type 4 connectivity to DB2 UDB for OS/390 Version 7 or DB2 UDB for z/OS Version 8)
1.8.1 IBM z/OS Application Connectivity to DB2 for z/OS and OS/390
IBM z/OS Application Connectivity to DB2 for z/OS and OS/390 is a no-charge, optional feature of DB2 Universal Database Server for OS/390 and z/OS Version 7 and DB2 UDB for z/OS Version 8. The purpose of this feature is to deliver connectivity for Java-based enterprise applications on z/OS to a remote DB2 for z/OS database server. The driver: Implements JDBC 3.0 specifications and SDK 1.3.1 or SDK 1.4.1 to deliver the maximum flexibility and performance required for enterprise applications Delivers robust connectivity to the latest DB2 for z/OS and WebSphere Application Server for z/OS Provides Type 4 connectivity with XA distributed transaction support (two-phase commit) Allows custom Java applications that do not require an application server to run in a remote partition and connect to DB2 z/OS Attention: The IBM z/OS Application Connectivity to DB2 for z/OS and OS/390 feature provides connectivity from a z/OS or OS/390 remote partition or system only. For access from any other operating system or platform, including z/Linux, to DB2 for z/OS and OS/390, you must obtain a separate license for the edition of DB2 Connect that is appropriate for your environment. Using JDBC Type 2 driver connectivity to access data on a remote DB2 subsystem requires a local DB2 subsystem to act as a request router (DRDA application requester). When using the type 4 connectivity provided by the z/OS Application Connectivity feature, the dependency on a local DB2 subsystem for the sole purpose of routing requests to access data on a remote DB2 subsystem is eliminated. As illustrated in Figure 1-7 on page 25, this is accomplished by the JDBC type 4 XA driver using the DRDA protocol to connect directly to the DDF address space of the remote DB2 subsystem. You must have a DB2 UDB for OS/390 and z/OS Version 7 or Version 8 license to order this no-charge feature. Other facts related to the IBM z/OS Application Connectivity to DB2 for z/OS and OS/390 feature are: It is packaged under FMID HDDA210. Having an exclusive FMID allows the feature to be installed independently on any given z/OS system or LPAR without having to install an entire DB2 subsystem.
24
It can be used to access data on a DB2 UDB server for OS/390 Version 6 subsystem. However, certain technical limitations apply. For example, XA two-phase commit functionality is not supported. DB2 UDB for OS/390 and z/OS Version 7 does not have built-in support for distributed transactions that implement the XA specification. 1.9.4, DB2T4XAIndoubtUtil utility for DB2 UDB for OS/390 and z/OS Version 7 on page 30, discusses how it is still possible to include DB2 V7 subsystems in transactions involving two-phase commit processing. In addition, Chapter 8, Transaction management in a WebSphere environment on page 191, discusses best practices related to distributed transactions. DB2 UDB for z/OS Version 8 has native XA support in DRDA allowing two-phase commit processing.
z/OS
Unix System Services (USS)
IBM DB2 for z/OS Application Connectivity
(DB2 Universal JDBC Driver provided by FMID HDDA210)
z/OS
DB2 UDB for z/OS V8
Type 4 (XA or non-XA) via DRDA
DDF
z/OS
USS
DDF
WebSphere Application Server DB2 Universal JDBC Driver
(DB2 JDBC Universal Driver provided by FMID JDB8812)
Type 4
Possible but NOT recommended
Figure 1-7 DB2 z/OS Application Connectivity and DB2 Universal Driver implementations
25
1.9 Using the DB2 Universal Driver for SQLJ and JDBC
The package name of the DB2 Universal Driver is com.ibm.db2.jcc.DB2Driver. The package is contained in the db2jcc.jar file. File db2jcc.jar contains the JDBC driver and SQLJ run time. File sqlj.zip contains the reference implementation of the standard SQLJ precompiler. It contains the classes that are needed to prepare SQLJ applications for execution under the DB2 Universal JDBC Driver. The HFS directory of the DB2 Universal Driver files is dependent on the product that provided the driver: HFS directory for DB2 UDB for OS/390 and z/OS Version 7 During DB2 V7 installation, the DB2 Legacy JDBC Driver default directory usr/lpp/db2/db2710/ is created when job hlq.SDSNBASE(DSNISMKD) is run. When APAR PQ80841 is applied to a DB2 V7 subsystem delivering the DB2 Universal Driver, default directory usr/lpp/db2/db2710/jcc/ is created. HFS directory for DB2 UDB for z/OS Version 8 During DB2 V8 installation, the DB2 Legacy JDBC Driver default directory usr/lpp/db2810/ as well as DB2 Universal Driver default directory usr/lpp/db2810/jcc/ is created by job hlq.SDSNBASE(DSNISMKD). HFS directory for IBM z/OS Application Connectivity to DB2 for z/OS During product installation, running hlq.SDDABASE(DDAISMKD) creates the default directory usr/lpp/jcct4 for the DB2 Universal Driver.
Example 1-4 Sample export statements for the PATH environment variable If using DB2 UDB for z/OS Version 8: export PATH=/usr/lpp/db2810/jcc/bin:$PATH If using z/OS Application Connectivity to DB2 for z/OS: export PATH=/usr/lpp/jcct4/bin:$PATH If using DB2 UDB for OS/390 and z/OS Version 7: export PATH=/usr/lpp/db2/db2710/jcc/bin:$PATH
LIBPATH
The DB2 Universal Driver requires native (C or C++) dynamic load libraries (DLLs) to be available when using type 2 connectivity. The DLLs are provided with the driver and reside in the /lib sub-directory.
26
To include the directory that contains these DLLs to the LIBPATH environment variable, the export statement is used. Example 1-5 provides sample export statements using the default installation directories. Only one export statement is required in the .profile, depending on which installation is being used.
Example 1-5 Sample export statements for the LIBPATH environment variable If using DB2 UDB for z/OS Version 8: export LIBPATH=/usr:/usr/lib:/usr/lpp/db2810/jcc/lib:$LIBPATH If using z/OS Application Connectivity to DB2 for z/OS: export PATH=/usr/lpp/jcct4/bin:$PATH If using DB2 UDB for OS/390 and z/OS Version 7: export LIBPATH=/usr:/usr/lib:/usr/lpp/db2/db2710/jcc/lib:$LIBPATH
CLASSPATH
The DB2 Universal Driver requires four class files to be in the CLASSPATH environment variable. These class files reside in the /classes sub-directory. They are: This file contains all JDBC classes and the SQLJ run-time classes for the DB2 Universal JDBC Driver. This file contains a subset of the J2EE classes that are needed by the DB2 Universal Driver. This file contains the classes that are needed to prepare SQLJ applications for execution under the DB2 Universal Driver. This file is the license which permits access to the DB2 for z/OS server.
db2jcc_license_cisuz.jar
To include these files in the CLASSPATH environment variable, the export statement is used. Example 1-6 provides sample export statements using the default installation directories. Only one export statement is required in the .profile, depending on which installation is being used.
Example 1-6 Sample export statements for the CLASSPATH environment variable If using DB2 UDB for z/OS Version 8: export CLASSPATH=/usr/lpp/db2810/jcc/classes/db2jcc.jar:\ /usr/lpp/db2810/jcc/classes/db2jcc_javax.jar:\ /usr/lpp/db2810/jcc/classes/sqlj.zip:\ /usr/lpp/db2810/jcc/classes/db2jcc_license_cisuz.jar:$CLASSPATH If using z/OS Application Connectivity to DB2 for z/OS: export CLASSPATH=/usr/lpp/jcct4/classes/db2jcc.jar:\ /usr/lpp/jcct4/classes/db2jcc_javax.jar:\ /usr/lpp/jcct4/classes/sqlj.zip:\ /usr/lpp/jcct4/classes/db2jcc_license_cisuz.jar:$CLASSPATH If using DB2 UDB for OS/390 and z/OS Version 7: export CLASSPATH=/usr/lpp/db2/db2710/jcc/classes/db2jcc.jar:\ /usr/lpp/db2/db2710/jcc/classes/db2jcc_javax.jar:\ /usr/lpp/db2/db2710/jcc/classes/sqlj.zip:\ /usr/lpp/db2/db2710/jcc/classes/db2jcc_license_cisuz.jar:$CLASSPATH
27
28
The complete list of DB2 subsystem parameters that can be updated online is documented in Appendix C of DB2 Universal Database for z/OS Version 8 Installation Guide, GC18-7418. In DB2 UDB for z/OS Version 8, the default value for the DESCRIBE FOR STATIC option on installation panel DSNTIP4 (DSNZPARM DESCSTAT) is YES for new installations (not when you migrate an existing subsystem). Important: It is imperative to rebind all packages that intend to use the DESCRIBE SQLDA generated by the DESCSTAT DSNZPARM after changing to DESCSTAT=YES.
Metadata requirement using DB2 UDB for OS/390 and z/OS V6 and V7
The metadata availability and uniform view specification the DB2 Universal Driver requires is delivered by APAR PQ62695 for DB2 UDB for OS/390 Version 6 and DB2 UDB for OS/390 and z/OS Version 7 environments. APAR PQ62695 modifies installation job stream member DSNTIJMS to create 13 stored procedures as well as tables, views, and user-defined indexes (on the DB2 catalog) used by the stored procedures. These stored procedures allow the DB2 JDBC Universal Driver to retrieve schema-based catalog metadata. DSNTIJMS resides in the DB2 hlq.SDSNSAMP library. Important: Before running DSNTIJMS, make sure that DSNZPARM DESCSTAT is set to YES.
Attention: APARs PQ72453, PQ78165, and PQ83561 should also be applied to resolve initial implementation errors in APAR PQ62695. This functionality is also required when using the DB2 Universal Driver (as well as the ODBC driver) to connect to a DB2 OS/390 or z/OS subsystem from a Linux, UNIX, or Windows V8 platform. SYSADM authority is not required to install the metadata stored procedures.
1.9.3 Binding DB2 Universal JDBC Driver packages with the DB2Binder utility
The DB2Binder utility is a component of the DB2 Universal Driver that binds the driver packages and grants EXECUTE authority on the packages to PUBLIC. Assume a DB2 UDB for z/OS Version 8 subsystem has the following settings: A host name wtsc54.itso.ibm.com Uses port 38070 A DB2 location name of DBD8
29
The DB2Binder utility can be run using the syntax shown in Example 1-7 on a z/OS UNIX System Services command line.
Example 1-7 Running the DB2Binder utility java com.ibm.db2.jcc.DB2Binder -url jdbc:db2://wtsc54.itso.ibm.com:38070/DBD8 \ -user SYSADM -password mypass
1.9.4 DB2T4XAIndoubtUtil utility for DB2 UDB for OS/390 and z/OS Version 7
Although native support for two-phase commit transactions does not exist for DB2 UDB for OS/390 and z/OS Version 7 subsystems, they can be included in distributed transactions using the type 4 Universal Driver after running the DB2T4XAIndoubtUtil utility against those V7 servers. This utility allows DB2 UDB for OS/390 and z/OS Version 7 servers to emulate distributed transaction (two-phase commit) support when using Type 4 XA connectivity. You will not find the DB2T4XAIndoubtUtil utility in an HFS directory. It is not a file. It is a component of the DB2 Universal Driver. The utility is used to create a table named SYSIBM.INDOUBT. This table stores information about in-doubt global transactions. In addition, the utility also binds a package named T4XAIndbtPkg. This package contains SQL statements used to insert, delete, and read rows from the SYSIBM.INDOUBT table. Assume a DB2 UDB for OS/390 and z/OS Version 7 subsystem has the following settings: IP address of 9.12.4.26 Uses port 38060 DB2 location name of DBD7 A user with SYSADM authority, which is required to run this utility, can run the DB2T4XAIndoubtUtil utility using the syntax shown in Example 1-8 on a z/OS UNIX System Services command line.
Example 1-8 Running the DB2T4XAIndoubtUtil utility java com.ibm.db2.jcc.DB2T4XAIndoubtUtil -url jdbc:db2://9.12.4.26:38060/DBD7 \ -user SYSADM -password mypass
Tip: The IP address or domain name, port, and DB2 location name can be determined by issuing the -DISPLAY DDF command, or by finding the DSNL004I message in ssnmMSTR of the DB2 UDB for OS/390 and z/OS Version 7 subsystem. If finding a user with SYSADM authority to run the DB2T4XAIndoubtUtil program is a problem, and you have the PTF for APAR PQ95881 installed, you can create the SYSIBM.INDOUBT table manually, and use the new -bindonly option of the DB2T4XAIndoubtUtil program to bind the required packages. When you use the -bindonly option, it is sufficient to have BIND authority; SYSADM is not required in that case. APAR PQ95881 adds two options to the DB2T4XAIndoubtUtil program: -bindonly When this option is specified, DB2 does not create the SYSIBM.INDOUBT table (which requires SYSADM authority). It only binds the T4XAIndbtPkg package. The SYSIBM.INDOUBT table can be created by executing the sample SQL shown in Example 1-9.
Example 1-9 DDL to create the SYSIBM.INDOUBT table CREATE TABLESPACE INDBTTS USING STOGROUP ...
30
LOCKSIZE ROW BUFFERPOOL BP0 SEGSIZE 32 CCSID EBCDIC; CREATE TABLE SYSIBM.INDOUBT ( indbtXid VARCHAR(140) ,uowId VARCHAR(25) FOR ,pSyncLog VARCHAR(150) ,cSyncLog VARCHAR(150) FOR BIT FOR FOR BIT DATA NOT NULL DATA NOT NULL BIT DATA BIT DATA) IN INDBTTS;
-jdbcCollection
<Collection name for JCC packages>. If the JDBC (dynamic) packages were bound (using the DB2Binder program) with a collection name other than "NULLID", then you must specify that collection name using the -jdbcCollection option, so that the DB2T4XAIndoubtUtil program can prepare its dynamic statements correctly.
Additional details on the DB2T4XAIndoubtUtil utility are documented in the DB2 Universal Database for z/OS Version 8 Application Programming Guide and Reference FOR JAVATM , SC18-7414.
1.9.5 Differences between the DB2 Universal Driver and DB2 Legacy Driver
There are a number of fundamental differences between the IBM DB2 Legacy Driver and the IBM DB2 Universal JDBC Driver. A handful of these differences when using JDBC and SQLJ with the different drivers are listed in Table 1-3 and Table 1-4 on page 32.
Table 1-3 JDBC differences between the DB2 Universal Driver and the DB2 Legacy Driver JDBC functionality Scrollable and updatable ResultSets Read-only connections IBM DB2 Universal Driver Supports scrollable and updatable ResultSets A read-only connection can be made through the readOnly property for a Connection or DataSource object Returns data from a ResultSet.getString call for a CHAR FOR BIT DATA or VARCHAR FOR BIT DATA column as a lowercase hexadecimal string Uses LOB locators internally under the following circumstances: Always, for fetching data from scrollable cursors Never, for fetching data from stored procedure result sets If the fullyMaterializeLobData connection property is set to true, in all other cases IBM DB2 Legacy Driver Supports only non-scrollable and non-updatable ResultSets Does not support read-only connections
31
Table 1-4 SQLJ differences between the DB2 Universal Driver and the DB2 Legacy Driver SQLJ functionality Scrollable and updatable iterators SQLJ program preparation IBM DB2 Universal Driver Supports scrollable and updatable iterators. Additional SQLJ translator parameters when translating source program-name.sqlj files to serialized profiles. Customize serialized profiles with the db2sqljcustomize command. By default, db2sqljcustomize automatically binds four (one for each isolation level) DB2 packages (DBRMs are not generated as output). If automatic bind was not performed by the db2sqljcustomize command, the db2sqljbind utility should be used to bind packages. A plan is not required. Using the DataSource interface to connect to a data source Before you can use a default connection context, the logical name jdbc/defaultDataSource must be registered with the Java Naming and Directory Interface (JNDI). IBM DB2 Legacy Driver Supports only non-scrollable and non-updatable iterators. Fewer SQLJ translator parameters. Customize serialized profiles with the db2profc command. Four DBRMs (one for each DB2 isolation level) and customized serial profiles are generated as output. You can bind the DBRMs directly into a plan or bind the DBRMs into packages and then bind the packages into a plan. Additionally, the four JDBC packages named DSNJDBC.DSNJDBCx by default must also be bound into the SQLJ plan. Creates a connection to the local data source for the default connection context.
The complete list of differences is in the DB2 Universal Database for z/OS Version 8 Application Programming Guide and Reference FOR JAVATM , SC18-7414.
A few of the interfaces and methods that can only be used with the DB2 Universal Driver are listed in Table 1-5 on page 33.
32
Table 1-5 JDBC APIs specific to the DB2 Universal Driver Interface DB2Connection Method getDB2CurrentPackagePath Result Returns a list of DB2 package collections, which are searched for when looking for the DB2 Universal JDBC Driver packages or SQLJ packages. Specifies a list of collection IDs that DB2 searches when looking for the DB2 Universal JDBC Driver DB2 packages. Returns the collection ID for the connection. Specifies the collection ID for the connection. When you set this value, you also set the collection ID of the DB2 Universal JDBC Driver instance that is used for the connection. Returns the current trace destination for the DB2 Universal Driver. Enables or disables the DB2 Universal Driver trace, or changes the trace destination during an active connection. Returns a DB2Sqlca object from a java.sql.Exception that is produced by the DB2 Universal Driver. Prints diagnostic information after a java.sql.Exception is thrown under a DB2 Universal Driver. Converts a com.ibm.jcc.DB2RowID object to bytes. Returns error message text. Returns an SQL error code value. Returns the SQLCA SQLSTATE value.
setDB2CurrentPackagePath
getDB2CurrentPackageSet setDB2CurrentPackageSet
getJccLogWriter setJccLogWriter
DB2Diagnosable
getSqlca
printTrace
The complete list of supported methods is documented in DB2 Universal Database for z/OS Version 8 Application Programming Guide and Reference FOR JAVATM , SC18-7414.
33
34
Chapter 2.
35
Tier 0
Applet Container Applet
Tier 1
Web Container JSP Servlet
Tier 2
EJB Container EJB
Tier 3
Enterprise Information System DB2 CICS
J2EE roles
J2EE also defines a set of roles that apply to various steps in the entire development, deployment, and maintenance life-cycle. The roles help identify the tasks and people involved, and who is responsible for the different tasks. Product provider is the implementor and supplier of a J2EE product that includes the component containers, J2EE platform APIs, and other features defined in the J2EE specification. IBM is a provider with, for instance, WebSphere Application Server and DB2. Application component provider is the creator of Web components, enterprise Beans, or enterprise applications. Application assembler takes a set of components developed by the application component providers and assembles them into an enterprise application archive.
36
Deployer is responsible for deploying the enterprise application into the operational environment. This typically means to install, configure, and start the enterprise application on the application server. System administrator is responsible for the operational environment in which the enterprise application runs, including the network infrastructure. Tool provider provides tools used for the development and packaging of application components. IBM is a tool provider with the WebSphere Studio Application Developer (WSAD) suite. Note: Starting with Version 6 that became available in December 2004, WSAD also has a new name, and is now called IBM Rational Application Developer for WebSphere Software. However, since this publication was written using Version 5, we still use the term WSAD throughout this book. You can group these roles into three categories. The product provider and the tool provider have a product focus, while the application component provider and the application assembler focus on the application. Finally the deployer and the system administrator have their focus on the run-time environment. In Figure 2-2 we look at the roles through IBM glasses. The tool used during development and assembly of applications is WebSphere Studio Application Developer (WSAD), while the run-time product is WebSphere Application Server. The component provider uses WSAD to create the components needed for an enterprise application, which is assembled into an Enterprise Application Archive (EAR) file by the application assembler. The EAR file is then handed to the deployer that deploys it. Finally the administrator makes sure it is all up and running smoothly.
To o l P ro v id e r
P ro d u c t P ro v id e r
W SAD
W AS
C om ponent P ro v id e r
A s s e m b le r
D e p lo y e r
A d m in is tra to r
C o m p o n e n ts
37
operates with four tiers. Tier 0 is the client-side tier, while the other tiers are referred to as server-side tiers.
38
A Web module groups servlets, JSPs, HTML files, images, and other Web-related files, and is packaged in Web Application Archives (.WAR) files. Web archives are deployed into the Web container. EJB modules EJB modules group related EJBs in a single module, and are packaged in Java Archive (JAR) files. EJB archives are deployed into the EJB container. Resource adapters Resource adapters support access to the Enterprise Information System outside the J2EE server. A resource adapter provides an API for accessing these data, for example, via a CICS resource adapter.
Application DD
Client Class
Client DD
Web DD
EJB DD
Client Container
Web Container
EJB Container
Note: The EAR file can contain an arbitrary number of the described archives, but it does not have to contain them all. In enterprise applications without enterprise Beans, specific client modules or any resource other than a database, only contain Web modules.
J2EE benefits
The J2EE specification provides customers with a standard by which to compare J2EE offerings from vendors and develop applications that run on any J2EE-compliant platform. Comprehensive, independent Compatibility Test Suites ensure vendor compliance with J2EE standards.
39
Some benefits of deploying to a J2EE-compliant architecture include: A simplified architecture based on standard components, services, and clients, that takes advantage of the write-once, run-anywhere Java technology. J2EE containers provide for the separation of business logic from resource and life-cycle management, which means that developers can focus on writing business logic and simplify their development. Services providing integration with existing systems, including Java Database Connectivity (JDBC), Java Message Service (JMS), Java Interface Definition Language (Java IDL), the JavaMail API, and Java Transaction API (JTA and JTS) for reliable business transactions. Scalability to meet demand by distributing containers across multiple systems and using database connection pooling, for example. A better choice of application development tools and components from vendors providing standard solutions. A flexible security model that provides single sign-on support, integration with legacy security schemes, and a unified approach to securing application components. The J2EE specifications are the result of an industry-wide effort that involves a large number of contributors. IBM has contributed in defining more than 80 percent of the J2EE APIs.
HTTP Server
HTTP request
WAS Plug-in
Web Container
EJB Container
In WAS for z/OS Version 5, the MVS address space in which the Java Virtual Machine (JVM) resides is called a servant. Multiple servants may be started by WLM, based on work queued by a controller region. Figure 2-5 on page 41 illustrates this.
40
Server
JCL Controller Region JCL WLM Server Region #2 Java Virtual Machine Server Region #1 Java Virtual Machine
Server Instance CR SR
The structure in the dotted box in Figure 2-5 is known as a server. Throughout this book we use the symbol pointed to by the curved arrow to represent it. On a given z/OS system, or LPAR, a collection of servers is grouped into a node, and a collection of nodes makes up a cell. A cell is the top-level in the WebSphere Application Server architecture. The cell is an administrative domain, or in other words, the boundaries the administrative applications reach. In the next sections we describe different operation environments for WebSphere Application Server. We start out with the simplest environment, then extend to more complex ones.
41
The base application server is administered using a browser-based application called the Administrative Console, which is a J2EE application itself. The administrative application is not written to be multi-servant capable; therefore only one servant region must be spawned, when the server runs the administrative application. Note: Throughout this chapter the terms administrative application and the Administrative Console are used interchangeably, whatever applies best. The administrative application is the code running inside WebSphere, while the Administrative Console is the browser-based interface to it. WebSphere for z/OS Version 5 uses an ISPF customization dialog process, called the WebSphere Installer, to create a number of jobs used to install the application server, but that topic is out of the scope of this book. For information about the customization dialog, see WebSphere Information Center at:
http://publib.boulder.ibm.com/infocenter/wasinfo/index.jsp
Node
Server Instance CR SR
Administrative Console
Cell
Daemon
Node
Server Instance CR SR
Administrative Console
42
Administrative Console we can create new servers and install applications within these new servers, thus creating a very flexible environment. As mentioned earlier, only one servant region must be spawned in the server where the administrative application runs. If we want to test our application in a multi-servant environment, this configuration allows us to do so. However, this configuration does not provide us with the same isolation as with multiple Base Application Server nodes. It is possible to install the administrative application in multiple servers, but these instances all have the same privileges within the cell. Any instance is able to install, delete, or modify any application in the other servers.
Server Instance B CR SR
Figure 2-8 One Base Application Server node with multiple servers
Note: With the Base Application Server node configuration, it is not possible to start and stop servers from within the Administrative Console. This has to be done from the MVS console. The various configurations with the Base Application Server node are great for simple isolated environments. They are good as a first start to learn about WebSphere, and they are good for development, testing, and the like. But in the world of production this configuration is often insufficient. There are several things a base application server cannot do: It must be contained on one z/OS system or LPAR. Servers cannot be stopped and started via the Administrative Console. Servers cannot be grouped into a logical clustered environment for load balancing and failover. This is where network deployment comes into play. It solves the above limitations, even when we only have one z/OS system or LPAR.
Network deployment
We now look at an environment with two z/OS systems, or LPARs, on which we have two servers each, as illustrated in Figure 2-9 on page 44. What we want is to administer these four servers as one from a central location. This can be obtained with the deployment manager, which is a special kind of base application server in which a special version of the administrative application runs. The deployment manager does not interact with the servers directly, it communicates with node agents, which in turn control the servers in the node. This implies that we have one 43
node agent for each node. We now have a single cell with multiple nodes that spans systems in a sysplex. The cell is under the management of the deployment manager, and only one deployment manager is permitted per cell, even when the cell spans z/OS systems. Note: The deployment manager is not a single point of failure. If the deployment manager for some reason is unavailable, the only impact is that you are unable to install any applications in the managed servers, or start/stop the servers. The run-time environment is unaffected.
Cell
Daemon
Deployment Manager
Administrative Console
Daemon
Node 1
Server Instance A CR Node Agent SR
Node 2
Server Instance C CR Node Agent SR
Server Instance B CR SR
Server Instance D CR SR
SYSA
SYSB
Note that Figure 2-9 has one cell, but two systems. Therefore, as stated earlier, two daemon servers are required. There are no restrictions in the architecture of WebSphere z/OS that prevent us from having multiple cells in a sysplex. And the cells do not have to span systems; they can be contained entirely within one system. Note: Nodes are created as base application nodes, and then federated into the cell. When a node is added to the cell, the deployment manager can be used to create servers and applications within the added node.
44
After login, the home page of the Administrative Console is shown (Figure 2-11 on page 46). Apart from the possibility to administer the WebSphere Application Server from here, there are a few references to additional support sites: WebSphere Application Server on IBM.com The place for support, including WebSphere Flashes, FAQs, Hints and Tips, and Technotes. You will also find information about downloads, libraries, news, and other useful information. WebSphere Developer Domain Technical articles, best practices, tutorials, and a lot of more in the WebSphere Application Server Zone. Infocenter The complete source for product documentation, including tasks, reference, and conceptual information on product features and functions.
45
In subsequent chapters of this book we use the Administrative Console to configure our WebSphere Application Server environment. For a detailed description of how to use the Administrative Console, consult IBM WebSphere Application Server V5.0 System Management and Configuration, SG24-6195.
46
Further information is available through the Infocenter, accessible from the home page of the Administrative Console, or the Web site:
http://www-306.ibm.com/software/webservers/appserv/zos_os390/library
The start page of the Infocenter contains a comprehensive list of documents named Version 5.0 for z/OS documentation.
Business portals
Products in this part of the pyramid are used to extend the customer experience. They consist of four product families: WebSphere Commerce Powerful sell-side solutions to handle the challenges encountered in customer and trading partner environments. It provides selling, buying and channel management solutions, from a simple online sales channel, to e-procurement, to a completely integrated, multi-tier demand chainall on a single, unified platform. WebSphere Portal
47
A single point of personalized interaction with applications, content, processes, and people. WebSphere Everyplace Software for extending e-business applications to mobile devices everyplace software makes it possible to access data from a broad range of mobile devices. It delivers Web pages and e-business applications to the screens of cell phones and wireless PDAs. WebSphere Voice Software for enabling natural voice interactions with applications and data. Voice software uses speech as the user interface for data exchange. It is an extensive family that includes development tools and technologies transcription, voice response, message center services, access to business applications, and text translation between language.
Business integration
Business integration, which is the last side of the pyramid, is actually the heart of e-business. It is about integrating data, applications, processes, and people across and beyond the company, giving the power to make existing IT investment available to e-business. A vast set of products is available for integrating nearly everything with anything.
Further information can be found in the WebSphere Application Server Information Center at http://public.boulder.ibm.com/infocenter/wasinfo/index.jsp, or use the link in the Administrative Console.
48
Chapter 3.
49
WTSC55
DB2 tables
WTSC54
W AS V5
Application Server
T4
D D F
DBD7
Other DB2 address spaces
T2
Application Server
W AS V5
T4
D D F
T2
Application Server
z/OS
Figure 3-1 Configuration used in our sample scenario
DB2 tables
z/OS
Figure 3-1 shows an important aspect of the Driver type access. With local DB2 access using type 2 connectivity, only one DB2 subsystem can be accessed from within one application server. As a consequence, to have local access to DBD7 and DBD8 on WTSC54 it is required to have two servers, which is of course possible in a WebSphere Application Server Base Node (BN) and in a Network Deployment Node (ND) configuration. When connecting from the WAS running on WTSC55, we use type 4 connectivity to the DB2 for z/OS and OS/390 systems running on WTSC54. The type 4 driver that is used here is the z/OS Application Connectivity to DB2 for z/OS and OS/390 no-charge feature of DB2 for z/OS and OS/390 Version 7, and DB2 for z/OS Version 8. This driver is also known as the type 4 XA driver. For more information see 1.8.1, IBM z/OS Application Connectivity to DB2 for z/OS and OS/390 on page 24. More details about the scenario can be found in Chapter 11, Sample application on page 245.
50
DB2 Universal Driver for SQLJ and JDBC, we concentrate on the two driver types that are available from within a WAS that runs in a z/OS system, namely type 2 and type 4 connectivity. A description of all available driver types can be found in many documents, for example, in 1.7.2, JDBC driver types on page 21, and Chapter 3, Accessing DB2 from Java, in DB2 for z/OS and S/390: Ready for JAVA, SG24-6435. Three JDBC driver providers can be configured with WAS V5 on z/OS, after installation of PTF UQ85128 for WAS V5 to access DB2 for z/OS: DB2 for z/OS Local JDBC Provider (RRS) (a rename of the existing legacy driver) DB2 Universal JDBC Driver Provider DB2 Universal JDBC Driver Provider (XA) Table 3-1 provides an overview of the functionality supported by the different WAS V5.02 JDBC Driver Providers.
Table 3-1 Supported Driver Providers with WAS v5.02 on z/OS JDBC Driver type supported T2 support T4 support DB2 for z/OS Local JDBC Provider (RRS) YES NO DB2 Universal JDBC Driver Provider 2-phase commit with RRS 1PC to DB2 on z/OS To DB2 on other platforms not verified DB2 Universal JDBC Driver Provider XA Not on z/OS 2PC to DB2 on z/OS To DB2 on other platforms not verified
51
3.4 The IBM DB2 Universal Driver for SQLJ and JDBC
To access DB2 databases, a (new) JDBC Driver called the IBM DB2 Universal Driver for SQLJ and JDBC has been made available by IBM, both for z/OS and distributed platforms. To use the DB2 Universal Driver with WAS z/OS, the installation must have installed one of the following flavors of the driver: The DB2 for z/OS Version 8 DB2 Universal JDBC Driver. The driver is packaged as part of DB2 for z/OS V8. This version supports both type 2 and type 4 connectivity. The DB2 for z/OS Version 7 DB2 Universal JDBC Driver. This driver support is provided by APAR PQ80841 (and follow-on maintenance) on DB2 for z/OS and OS/390 V7. This version supports both driver types 2 and 4. Note: The DB2 Universal Driver Release 2.3.72 (available the PTF for APAR PQ93458) now officially supports type-4 XA connectivity to remote DB2 for Linux, UNIX, and Windows servers. However, accessing non-DB2 for z/OS databases from a WebSphere for z/OS V5.0 and V5.1 is not officially supported by WebShpere for z/OS. The standalone DB2 Universal JDBC Driver type 4 product (also known as z/OS Application Connectivity to DB2 for z/OS and OS/390). This version only supports type 4 connectivity to DB2 for z/OS databases. If this driver is installed, and you are using WebSphere for z/OS, then the DB2 Universal JDBC Driver Provider (XA) must be used on WAS z/OS to access remote DB2 for z/OS databases. (The use of the DB2 Universal JDBC Driver Provider using type 2 connectivity cannot be used since there is no local DB2 subsystem to connect to.) After the driver code (irrespective of which one of the aforementioned drivers you want to use) has been installed (into the HFS), you have to configure the Data Sources using the WAS Administrative Console application, or via the WebSphere administrative scripting program (wsadmin). Support in WAS for configuring Data Sources based on the new Universal Driver is added via PTF UQ85128 (APAR PQ80079). This maintenance should be applied to WAS V5 level W502002. This new support assumes that all driver specifics be available in the correct places within the HFS, and basically changes the admin console panels, so that Data Sources using the new drivers can be configured.
3.4.1 Summary of WAS z/OS external changes for the Universal Driver
The external changes that are made as a part of the WAS z/OS support for the new DB2 Universal Driver are summarized below: New environmental variables are provided to define the DB2 Universal JDBC Driver configuration to WAS z/OS. Two new JDBC Providers are provided to support the configuration of Data Sources that use the new DB2 Universal JDBC Driver. The DB2 390 Local JDBC Provider (RRS) option has been replaced by a new DB2 for z/OS Local JDBC Provider (RRS). New coexistence rules are defined regarding the coexistence of the legacy DB2 JDBC Driver, the DB2 Universal JDBC Driver, and Cloudscape. New setup is required for configuring the DB2 Universal JDBC Driver to WAS z/OS. The function of the DB2930LocalDataStorehelper and DB2390DataStoreHelper are consolidated into the DB2DataStoreHelper. The old helpers are retained for compatibility.
52
Data Sources definitions, which are stored in the HFS system, have a hierarchical approach: JDBC provider The provider definition specifies the facilities (Java classes, code) that can be used by Data Sources under this provider. As indicated, two new providers have been added to support the Universal Driver, and the previous legacy provider has been renamed. Before we can define a data source, we first have to install the appropriate JDBC provider. Data Sources under the JDBC provider The Data Source, together with the Custom Properties linked to it, give more details about the physical database that backs the definition, and how it has to be accessed (remotely, locally). Some security elements can also be defined on this level.
SQLJ
SQLJ
SQLJ runtime
Common layer
JDBC
JDBC
SQLJ runtime
Common layer
T2 Native Libraries
T2 Native Libraries
T2
DB2 Connect
T2
D D F Other DB2 address spaces
DRDA
z/OS
DB2 tables
Figure 3-2 Type 2 drivers
53
The current (prior to the Universal Driver) type 2 driver (now called the Legacy JDBC driver), which replaced the older type 1 driver, has been around since WAS V4. This driver has been renamed to DB2 for zOS Local JDBC Provider (RRS). The configuration of this driver (and also the renamed one) for WAS V5 is explained in the document Using DB2 for z/OS in WebSphere for z/OS Version 5, TD101072, available from the Techdocs Web site at:
http://www-03.ibm.com/support/techdocs/atsmastr.nsf/WebIndex/TD101072
The Universal Driver also allows type 2 connectivity. This means that we have an additional flavor of the type 2 driver that can be configured. The Universal Driver allows the use of multiple driver types (type 2 and type 4 connectivity) with this driver code. In this section we describe how to configure type 2 connectivity using Universal Driver with WAS V5.
On the screen that is returned (Figure 3-3), provide a user ID, and click OK.
54
On the general WAS V5 admin screen in the left frame, expand Resources, and select JDBC Providers (Figure 3-4).
In order to have the possibility to attach to a particular DB2 subsystem per server (remember that we need to connect a V7 and a V8 DB2 system to the local WAS), we have to make the definitions in the server scope. Verify at this time that you work in the scope of one particular server; otherwise change the scope, and click Apply.
55
On the previous screen you saw a list of available JDBC providers; if the DB2 Universal JDBC Driver Provider is not among them, we have to add it. Click New. This will present a list of candidate JDBC providers, as shown in Figure 3-6.
In the drop-down list, select the DB2 Universal JDBC Driver Provider, and click Apply. This brings us to the General Properties window (Figure 3-7).
Have a look at the properties of this new provider. Notice that we have not yet defined the following symbolic variables. This will be done later (Figure 3-19 on page 65).
${DB2UNIVERSAL_JDBC_DRIVER_PATH} ${UNIVERSAL_JDBC_DRIVER_PATH} ${DB2UNIVERSAL_JDBC_DRIVER_NATIVEPATH}
56
In the right columns of the display a contextual explanation is given for all properties. Click Apply again. The new JDBC provider is now defined for this server, but the definition is not saved yet. It is good practice to save the changes at this time (by clicking the Save button). After the save, we return to the JDBC Provider list in which the new provider should be present now (Figure 3-8).
Figure 3-9 Additional properties of the DB2 Universal JDBC Driver Provider
As we want to define a WAS V5 Data Source, select Data Sources. This takes us to the window shown in Figure 3-10 on page 58.
57
No Data Source has been defined at this point. Click New for a new Data Source. In the next windows, Figure 3-11, Figure 3-12 on page 59, and Figure 3-13 on page 60, we define the properties of the (new) Data Source. In the right column contextual information is provided about the meaning of each of the properties.
Some properties are marked as mandatory (with a red asterisk). We provide information for the following fields: Name (display) This is a label; specify a name that is as meaningful as possible.
58
JNDIName
By convention this should start with jdbc/; we should use a name that expresses as close as possible the addressed DB2 and driver type. jdbc/T2DBD8 (DBD8 on Local via type2) The JNDIName will have to be set in the Deployment Descriptors of the Web Applications and EJBs, or if the name defined in the descriptors is not a defined JNDI name of a Data Source, it will have to be overridden in the deployment dialog.
Check this box if CMP EJBs will make use of this Data Source.
This parameter influences the performance of JDBC. SQLJ has been prepared in advance. JDBC statements that are used repetitively are prepared the first time and can been cached afterwards in prepared state. This is the user ID/password that will be used to access DB2 with component managed security. The alias has to be defined beforehand. This is the user ID/password that will be used to access DB2 with container managed security. The alias has to be defined beforehand.
59
Other general properties are displayed. When all properties have been filled in or accepted click Apply.
JAAS alias
Java Authentication and Authorization Services (JAAS) is a Java API to establish an authenticated user ID. This API can be invoked in several instances, in particular when connecting to DB2. This connection can be established on behalf of two environments: Container (using the user ID of the thread that is executing) Component/application (the user ID is explicitly passed on the getConnection call) The selection between the two options is made in the Deployment Descriptor (EJB, Web application) with the "res-auth" option. A JAASAlias (userID/password) can be specified using the Administrative Console application via Security JAAS Configuration J2C Authentication Data. For each of the two options, JAAS aliases are defined beforehand (see above), and then set for a particular DataSource. The option to define a JAASAlias is available on the data source definition panel by JDBC Providers JDBC-provider-name Data Sources datasource-name, in the Component-managed or Container-managed Authentication Alias field. Several JAASAliases can be defined and one of those can then be set as a JAASAlias reference for application or component. More information can be found in WebSphere datasource settings for authentication on page 134 (for a WAS environment), and Setting up JAAS security entries on page 163 (for a WSAD environment). The Data Source is now available, and it is now time to save our changes. After this, return to the JDBC Provider/Data Source for additional definitions. The new Data Source has a logical name (JNDI name), but is not yet connected to any real DB2 subsystem. Under the General Properties of the Data Source, a selection Additional Properties is shown (Figure 3-14 on page 61).
60
Select Custom Properties. The next window (Figure 3-15, Figure 3-16 on page 62, Figure 3-17 on page 63, and Figure 3-18 on page 64) shows many properties. We first define whether this Data Source is accessed via type 2 or type 4 connectivity, and what DB2 subsystem the Data Source is linked to. Properties have to be changed accordingly. All have contextual explanations in the Description column. It is also indicated whether the property is required (true) or not (false). When you want to change a property, click the property name and change the value. After each change, click OK, and at the end, Save all values in the WAS configuration.
61
The values are: databaseName This is the location name of the DB2 system you want to connect to (DBD8 in our case. Note that on our systems, the DB2 subsystem name is the same as the DB2 location name. That is not necessarily the case in your installation.) This is a definition for a type 2 Data Source, so we specify 2.
driverType
traceLevel
The DB2 trace level for logging to the logWriter or trace file. At this point we do not require any tracing so we specify 0. Without any code change required, this setting controls whether LOB locators are used to fetch LOB data. For now, we use the default setting true.
fullyMaterializeLobData
62
More information about the following parameters can be found in 5.6, Special registers on page 121. currentPackageSet Specifies the content of the CURRENT PACKAGESET special register. The CURRENT PACKAGESET special register is used as a collection name, when searching for an appropriate package to execute. Identifies the default schema name used to qualify unqualified database object references. Identifies the name of the qualifier (schema) name when using a shadow catalog for retrieving metadata information about DB2 objects stored in the DB2 catalog.
currentSchema cliSchema
63
preTestSQLString
Specify a dummy select from an existing table. This statement is used for the pre-test connection function, for example, SELECT 1 FROM SYSIBM.SYSDUMMY1. Initializes the CURRENT SQLID special register with the value specified here. We specify ITSOUSER. This value specifies the default schema name that is used to qualify unqualified database objects in dynamically prepared SQLstatements if currentSchema is not used.
currentSQLID
This concludes the definition of a Data Source using type 2 connectivity with the DB2 Universal Driver. However, we still have to set the values for the symbolic variables that were used when defining the JDBC provider before.
64
We must set values for the following symbolic variables: ${DB2UNIVERSAL_JDBC_DRIVER_PATH} /usr/lpp/db2810/jcc/classes ${UNIVERSAL_JDBC_DRIVER_PATH} /usr/lpp/db2810/jcc/classes ${DB2UNIVERSAL_JDBC_DRIVER_NATIVEPATH} /usr/lpp/db2810/jcc/lib This can easily be done with the New selection if they do not exist yet, or by a change otherwise. Each time, enter the variable name, value, and optionally a description. Repeat it, and if required correct it. Afterwards, the list of variables should look like Figure 3-20.
for specifying various run-time options that the DB2 Universal JDBC Driver uses for type 2 connectivity. These options are specified as properties in the form of parameter=value. Refer to Customizing the DB2 Universal JDBC Driver global properties file in DB2 Universal Database for z/OS Version 8 Application Programming Guide and Reference FOR JAVATM , SC18-7414, or the README file packaged with the DB2 Universal JDBC Driver for a detailed description of each of the properties that can be specified. This file is not required, but if not provided, the Universal Driver runs using default processing. There are different ways to specify a DB2 Universal Driver general properties file; however, when running in a WebSphere Application Server environment, the recommended way to specify the properties file is as a JVM system property. In that case, the fully qualified HFS file name must be provided as input to the Universal Driver. You can specify a JVM system property as follows:
db2.jcc.propertiesFile = <fully-qualified-hfs-filename>
Since such driver general properties are typically specific to a driver load (that is, server) versus to all servers using the JDBC provider, it is best that this jvm property be set at the server level. We use the following properties file (Example 3-1) when connecting to DBD8.
Example 3-1 Properties file for SSID DBD8 db2.jcc.ssid=DBD8 db2.jcc.override.traceFile=/u/rc54/cel541nd541sc54ws541sc54/tracejava
Of specific interest is the db2.jcc.ssid property. This property can be set to specify the DB2 subsystem identifier (not the DB2 location name) to be used by the DB2 Universal JDBC Driver type 2 processing as the local subsystem name the driver should connect to. If this property is not provided, then the driver will use the subsystem identifier it finds in the DSNHDECP load module. DSNHDECP is loaded using the search sequence specified in the STEPLIB environment variable, or the //STEPLIB DD name concatenation. If that DSNHDECP load module does not accurately reflect the desired subsystem, or multiple subsystems may be using a generic DSNHDECP, then this property must be specified. Also noteworthy is the following trace property supported by the Universal Driver:
db2.jcc.override.traceFile = <fully-qualified-hfs-filename>
This property enables driver global java-side tracing inside the driver. You can reference the properties file in the following way: Connect to the Admin Console as usual, select Servers Application Servers, and click the server where you want to add the jvm property (Figure 3-21 on page 67).
66
From the Server page that was selected, go to Process Definition Servant (Figure 3-22).
On the Servant page, go down to Additional Properties at the bottom of the page. Click Java Virtual Machine (Figure 3-23).
On the Java Virtual Machine page, again go down to Additional Properties at the bottom of the page. Click Custom Properties (Figure 3-24 on page 68).
67
On the Custom Properties page, click New to configure a new JVM property under the server. The name of the property should be db2.jcc.propertiesFile, as shown in Figure 3-25.
The value of the property should be the fully qualified HFS file name that you have created and populated with the DB2 Universal JDBC Driver properties that you want the type 2 driver to use under the selected server (with information like in Example 3-1 on page 66). Once you have done this, click OK and save the configuration. This is a specification for the JVM of the servants of a particular Application Server. Therefore, we cannot have a second one referencing another local DB2.
68
Again there are two options. They are mutually exclusive: db2.jcc.planName Specifies the DB2 plan name that is used by the RRS attach to create the thread when a JDBC or SQLJ connection to a data source is established; for example: db2.jcc.planName=MYSQLJPL When you bind that plan you can include the collections that you want DB2 to search for packages using the PKLIST keyword; for example: BIND PLAN(MYSQLJPL) PKLIST(TESTCOLL.*, PRODCOLL.*) This is the same as you would normally do with static COBOL programs. You can override db2.jcc.planName by setting the planName property for a Connection or DataSource object. Specifies a list of collections that is used to search for a package when a JDBC or SQLJ connection to a data source is established. You can use this property if you do not bind plans for your SQLJ programs or for the JDBC driver. The format of the package list is: db2.jcc.pkList=TESTCOLL.*,PRODCOLL.* You can override db2.jcc.pkList by setting the pkList property for a Connection or DataSource object. *
db2.jcc.pkList
If you do not specify the db2.jcc.planName property or the db2.jcc.pkList property. The DB2 Universal JDBC Driver uses the db2.jcc.pkList default value of NULLID.*, unless you specify currentPackageSet or current PackagePath (custom) property on the DataSource or Connection object. Note: When the db2.jcc.planName option is used, the user ID associated with the WebSphere address space needs to be authorized to execute the plan. DB2 checks EXECUTE ON PLAN authority when RRS creates the thread. This is before the driver can switch to the user ID that is used on the getConnection() call.
currentPackagePath Specifies a list of collections on the server. The DB2 server searches these collections for the DB2 packages for the DB2 Universal JDBC Driver. currentPackagePath and currentPackageSet are used in the same way as the DB2 CURRENT PACKAGESET and CURRENT PACKAGE PATH special registers, but can be set inside or outside (at the DataSource) of the application. The precedence rules for the currentPackagePath and currentPackageSet properties follow the precedence rules for the DB2 CURRENT PACKAGESET and CURRENT PACKAGE PATH special registers. You can also use the planName and pkList properties at the DataSource and Connection object level in a similar way as you use db2.jcc.planName and db2.jcc.pkList driver configuration properties.
69
The value of the Z parameter, which in the example has a default, can be overridden also via the Administrative Console application to point to another include member. To do this, go to Application Servers Servername Process Definition Servant and change, as appropriate, the property value of startCommandArgs (Figure 3-26 on page 71).
70
Note: In a Base Node (BN) configuration, WAS V5 application servers cannot be started and stopped via the Administrative Console. The required libraries can also be specified by using the Export function of Unix System Services. This has to be done via the Custom Property settings of the Servant. Go to Servers Application Servers Server-name Process Definition Servant. In the this panel, select Environment Entries at the bottom (Figure 3-27).
A new environment variable has to added, or changed if already existing (Figure 3-28 on page 72).
71
Fill in the name and the value for the new variable (Figure 3-29); in our case:
STEPLIB=$STEPLIB:DB2xx.SDSNEXIT:DB2xx.SDSNLOAD:DB2xx.SDSNLOD2
Note: The header of the panel is Custom Properties, whereas in fact you are defining environment variables, so do not let the heading mislead you.
Save the configuration, and we are done. Attention: The previous approach for adding the DB2 libraries to an Application Server has not been verified. We experienced time outs in the Admin Console application after the above changes had been made. This concludes the definition of the type 2 driver for DBD8. Note again that we can only associate one DB2 system when using type 2 connectivity per Application Server. This is because we have to specify the JVM System property db2.jcc.propertiesFile, by which we have to point to the properties file that will be used by the 72
DB2 for z/OS and WebSphere: The Perfect Couple
Universal Driver. The scope for the definition of this variable is a (JVM) property of an Application Server. If you need the ability to connect to another local DB2 using a type 2 connectivity, you have to define it in a second Application Server (or use a DRDA connection even though the DB2 system is local to the Application Server). Nevertheless, it can be useful to define other data sources using type 2 connectivity for the same DB2 subsystem. In the Custom Properties section, you can specify properties that could be specific for specific applications or Beans. For example, they can be using different CurrentSQLID, currentPackageSet, or trace parameters.
The following window that is presented is the Create New Application Server window, as shown in Figure 3-31 on page 74.
73
Enter the following information: Server name: wsc54asc54 Select template: Existing application server Click Next. This takes you to the window shown in Figure 3-32.
Click Finish. This takes us to the window in Figure 3-33 on page 75 with an overview of the Application Servers including the new server, and an invitation to save to the master configuration.
74
Click Save to save the configuration. Let us now have a look at the HFS file system, where the actual configuration resides. The mount point for our WAS V5 is WebSphereBS/V5R0M0/BS01. From here we find two branches (subdirectories): Daemon AppServer Under AppServer, we find the Cell/Node/Server hierarchy configuration. As shown in Figure 3-34 on page 76, we have two servers, and each server has a was.env file, which is directly addressed via a symbolic link from the mount point. The server subdirectory is fine, but the name of the symbolic link, CL541.ND511.BBOS001, was generated by the Admin Console application. We will now change this.
75
/<mount point>
Syml CL541.CL541.WS541D Syml CL541.ND541.BBOS001 Syml CL541.ND541.WS541
+--/Daemon +--/AppServer +--/config +--/cells +--/cel541 +--cell.xml +--/applications +--/clusters +--/nodes +--/nd54 +--node.xml +--serverindex.xml +--/servers +--/ws541sc54 +--was.env +--/ws541sc54a +--was.env
Figure 3-34 Configuration hierarchy
Daemon
CR
Base Node
CR
Server
Servant
Server
Cell
CR
Servant
In the Admin Console, return to the overview panel of the Application Servers and select the new server (Figure 3-35).
After selecting the server, the window shown in Figure 3-36 on page 77 appears. It shows the properties of the new server, including the short name that we want to change.
76
Override the short name, for example, WS541A (in capitals). Click OK and save the configuration. This will create a new symbolic link CL541.ND541.WS541A in Figure 3-34 on page 76 for the new server that can be used in the start command of the server. The new Application Server is defined, but what about the start command? The start command for the first application server looks like:
START WS5541C,JOBNAME=WS541,ENV=CL541.ND541.WS541
In both cases, the ENV parameter represents the symbolic link to the was.env file of the server. In both cases we use the same start JCL procedure. However, since the second server will have to point to DBD7 (our DB2 V7 subsystem), we have to include the //STEPLIB DD statements that reference to the DB2 V7 libraries. Remember from Example 3-2 on page 70 that the procedure can point to an include member via the Z parameter, like Example 3-3 on page 70, in which we added the DB2 V8 libraries. We have to create a new member (Example 3-4), and reference it via the Z parameter at startup:
START WS5541C,JOBNAME=WS541A,ENV=CL541.ND541.WS541A,Z=WSD7SZ
This is the way it has to be done in a Base Node configuration. In a Network Deployment node, servers can be started by the Admin Console, but the new Z parameter also has to be added to the Process Definition Servant startCommandArgs field of the new server, like in Figure 3-26 on page 71.
Example 3-4 Include member WSD7SZ with STEPLIB for DB2 V7 //* //* Output DDs //* //CEEDUMP DD SYSOUT=*,SPIN=UNALLOC,FREE=CLOSE Chapter 3. WebSphere - DB2 environment
77
The new server does not have its own admin console application. All definitions, JDBC providers, and data sources are always done via this prime server. We also create a data source (for type 2 connectivity) for the second Application Server ws541asc54 with JNDIname:
jdbc/T2DBD7 (DBD7 on Local via type2)
To do so, we can use the procedure outlined in Defining Data Sources under this provider on page 57. Attention: If we need access to two or more DB2 subsystems from within the same Application Server, we have to use a mixture of T2 and T4 data sources.
78
SQLJ
SQLJ runtime
JDBC
SQLJ
SQLJ runtime
JDBC
Common layer
Java Classes
T4 (only to z/OS)
Common layer
z/OS
DRDA DRDA
T4
Java Classes
T2
D D F Other DB2 addres spaces
SQLJ
SQLJ runtime
JDBC
Common layer
Java Classes
DRDA
T4
z/OS
DB2 tables
Distributed platform
The type 4 driver for z/OS is delivered with DB2 Version 8 and available also for DB2 V7 via the maintenance stream. WAS PTF UQ85128 allows WAS V5 to specify the DB2 Universal Driver when configuring a data source. It comes in two flavors: DB2 Universal JDBC Driver Provider (non-XA) One-phase commit to DB2 on z/OS DB2 Universal JDBC Driver Provider (XA) Two-phase commit to DB2 on z/OS
79
To use this provider, you must have the DB2 Universal Driver for SQLJ and JDBC for DB2 Version 7 or DB2 Version 8 installed and configured to WAS z/OS (as discussed in 1.9, Using the DB2 Universal Driver for SQLJ and JDBC on page 26). Tip: This driver with single phase commit (1PC) capabilities may be used when DB2 is the only resource manager involved in a transactional unit of work.
80
Most of the steps for defining type 4 XA connectivity are the same as for type 2 connectivity, except that you do them under another JDBC provider. This provider for T4 XA connectivity first has to be added to our provider list. As we only have one Application Server on WTSC55, and the data sources we will add are using type 4 connectivity, we can make the definitions at the Node scope, or even at the Cell scope level. As we did for the type 2 connectivity before, we verify the presence of the Universal JDBC driver for XA. If not, we add it. To add a new JDBC provider, log into the Admin Console, and select Resources JDBC Providers New. Then select DB2 Universal JDBC Driver Provider (XA) in the drop-down list, as shown in Figure 3-38. If that option is not there, it is very likely that WAS z/OS is not at the 502002 level. (Support in WAS z/OS for configuring Data Sources based on the new Universal Driver is added via PTF UQ85128 (APAR PQ80079)).
If you see the DB2 Universal JDBC Driver Provider (XA) in the list of JDBC providers overview (Figure 3-39 on page 82), the provider is OK.
81
Now we need to check the properties (and the symbolic variables they use) for this provider. Selecting the DB2 Universal JDBC Driver Provider (XA) provider takes us to a window with configuration properties, as in Figure 3-40 on page 83. The information provided by the Admin Console application for the CLASSPATH and Implementation Classname should be OK.
82
Also notice the symbolic variables. They must be specified, as before, using the Admin Console, via Environment Manage WebSphere Variables (Figure 3-41 on page 84). The following variable needs to be defined: DB2UNIVERSAL_JDBC_DRIVER_PATH, pointing to /usr/lpp/jcct4/classes This is where the type 4 XA driver Java classes are installed on WTSC55. There is no need for other variables like DB2UNIVERSAL_JDBC_DRIVER_NATIVEPATH; as the T4 driver is a pure Java driver, there is not need for a native library. This also means that it is not required to change the WAS V5 JCL startup procedures to add the DB2 libraries to them.
83
On the new panel that shows up, click New to define a data source. This takes you to a window where you can define the basic properties for the Data Source to be defined. This is shown in Figure 3-43 on page 85.
84
In the general properties section we give adequate names for the mandatory properties. We used names that express as closely as possible the DB2 we want to address, as well as the type of connection we want to use. Name JNDIname ITSOT4DBD8 jdbc/WTSC54T4DBD8 (connecting to DBD8 on WTSC54 via a type 4 connection) Since CMP EJBs will make use of this Data Source, we check the box.
The JNDIname will have to be set in the Deployment Descriptors of the WebApps and EJBs; or if the name defined in the descriptors is not a defined JNDIname of a Data Source, it will have to be overridden during the Deployment dialog. Click OK. You can now see the Data Source that you just defined. Select the Data source, and go to the bottom of the next window that is presented to you. Below the General Properties, you find the Additional Properties section (Figure 3-44 on page 86). Select Custom Properties.
85
The properties in the Custom Properties panel that need to be specified are slightly different (from the type 2 driver), as this is the definition of a Data Source that is using a type 4 connection. Figure 3-45 and Figure 3-46 on page 87 show the main properties for type 4 connectivity that are different from a type 2 connection.
Figure 3-45 Properties for a type 4 Data Source different from type 2
They are: databaseName The location name of the DB2 you want to connect to.
86
driverType
To indicate that this is the definition for a Data Source with type 4 connectivity. (Note that in our systems the DB2 subsystem name is the same as the DB2 location name. This is not necessarily the case in your installation.) IP address or host name.
serverName
Figure 3-46 Properties for a type 4 Data Source different from type 2
portnumber
This is the port number that the DB2 system that we want to connect to is listening on. It can be obtained by using the -DIS DDF command. The DB2 trace level for logging to the logWriter or trace file. It would normally be set to 0 (zero). The trace file that will be used when the trace is active. Without any code change required, this setting controls whether LOB locators are used to fetch LOB data.
traceLevel
traceFile fullyMaterializeLobData
After this the configuration should be saved. The Data Source definition has to be repeated for each remote DB2 we want to connect to. We also need connectivity to our V7 DB2 system, so we create a Data Source pointing to DBD7. The JNDIname would be: jdbc/WTSC54T4DBD7 (DBD7on WTSC54 via type 4 connectivity) After saving the configuration, this concludes the installation of the Data Sources that we need for type 4 connectivity.
87
3.7 Summary
A WAS V5 system on z/OS can now be configured with three JDBC Drivers for DB2 access, offering T4 and T2 support. Currently only T4 to another DB2 on z/OS is supported from within WebSphere. The new Universal Driver gives 2-phase commit (2 PC) support for both type 2 and type 4 connectivity. This allows the creation of a Global Unit of Work (GUOW) under WAS V5, which can include, besides access to transactional systems like IMS and CICS, access to a local DB2 and/or to remote DB2 systems. The legacy DB2 JDBC driver, now renamed to DB2 for z/OS Local JDBC Provider (RRS) in the Administrative Console dialog panels, and although still available at this time, will probably be phased out in the future. Customers are strongly encouraged to use, or convert to using, the IBM DB2 Universal Driver for SQLJ and JDBC.
88
Chapter 4.
89
90
The flexibility of the servlet environment does not prohibit business type functions from being embedded into servlets and JSPs. However, such an approach should be seriously considered before implementing. The main goal of a servlet is to provide a dynamic HTML response to an HTTP request. As a result, clients used to invoke servlets can be limited in function, implying that business function embedded in a servlet may be limited to a finite group of clients. We will discuss more robust models for business applications in the Enterprise JavaBeans section.
Flexibility
With the flexibility of servlets described above, there is a strong need for tight control of application development techniques to ensure that applications are being developed with good behavior, and to ensure that developers cooperate to reuse software components. Taken to the extreme, each application developer could write his own presentation logic, business logic, and infrastructure for an end-to-end business function within a servlet. The
Chapter 4. DB2 and Java architecture guide
91
servlet could even provide two-phase commit workload, robust security, network-based services, and database access within a servlet. However, this type of service is labor intensive, potentially could be limited to servlet access, and many of the functions could be bought off the shelf from vendors when a different Java approach is used.
Infrastructure
Vendors, such as IBM, focus on providing infrastructure services to support the development, execution, and operation of complex, world class enterprise applications. In many cases, choosing to exploit only servlets and home-grown applications to implement business function increases the applications development cost and potentially hurts performance. Complex function such as failure and recovery are difficult to test, and rarely do developers consider complex and sometimes obscure failure tests. By leveraging a vendor for infrastructure, applications immediately gain the benefits of extreme testing by both the vendor and other customers of the vendor. Consider complex failure and recovery scenarios or incorrectly implemented security. Vendors provide these functions and the quality of their implementations and economies of scale are what drive the lower cost to exploiters of vendor solutions. If it were easy, every company would be in the business of providing application server function. Review 4.3, Enterprise JavaBeans on page 92, for more information on the infrastructure service provided by software vendors, including IBM.
92
Below are some select EJB infrastructure services a container must provide according to the J2EE specification: Location transparency so that Java objects can be accessed on remote servers as if they were local Transaction support including two-phase commit support for accessing multiple EJBs at multiple physical locations and for accessing multiple resources (resource managers) in the same unit of work A JDBC interface for database access Container managed database persistence (for Container Manager Persistence entity Beans) Security infrastructure for authentication and authorization Exception handling for error handling Java Naming Directory Interface support to help provide abstraction for all resources referenced in the application These functions are accessed via a standardized API. When the application is deployed, a deployment descriptor is used to detail to the container the implementation of these services. While within the application, JDBC access has a generic interface to communicate with a database; and the deployment descriptor gives the container specific information regarding which data source the application is exploiting, what the underlying database vendor supports, at what physical location the database is, etc. The deployment descriptor will also frequently determine how transactions and security are implemented. Since EJBs have standardized mechanisms for invocation, as new protocols and standards evolve, vendors implement mechanisms to leverage pre-existing EJBs from the new protocol or paradigms. From the origins of the EJB standard, an HTTP request could trigger a servlet to call an EJB. Also, EJBs have always had a standard remote interface for Java clients, known as Remote Method Invocation (RMI). As new standards have emerged, the new technologies have been fully embraced by the EJB specification and vendors implementing containers. For example, message-driven Beans are a recent addition to the EJB specification. These Beans allow the invocation of existing EJBs by an asynchronous message-based request. Web Services, described in 4.13, Web services on page 104, allow the invocation of EJBs by clients that are not even Java compatible. If the business logic in these EJBs were implemented in traditional programming paradigms, it is likely that the applications would need significant re-architecture to be leveraged. EJBs allows new applications to leverage existing business logic built according to the EJB specification. All application functions, not only database access, can benefit from these services implemented by a container. The J2EE specification breaks application actions into different EJB types. Each interact and are managed by the container in a different manner. Session Beans provide actions and generally contain business logic. Entity Beans represent data that transactions and business logic act upon. These Beans are defined in more detail in the following sections.
93
From an application design perspective, session Beans can be considered analogous to a verb. Session Beans should be used to perform some action or carry out a transaction. Session Beans are frequently the first EJB referenced within the container from external clients such as a servlet. The session Beans provide a business action interface for presentation layers to invoke. In robust applications, multiple layers of session Beans can be used to provide a function; see 4.11, Session facade pattern on page 102, for more information. As an EJB, session Beans benefit from the infrastructure provided by the EJB container. They allow developers to focus on providing business function without the need to programatically handle security, transaction management, network access, etc. In many implementations, session Beans act as the gateway to application functions and are responsible for sending (marshalling) incoming requests to the right business functions implemented in other session Beans. Since they are frequently the entry point to the server, they generally control where security policies are enforced and transactions begin and end. Exploiting these infrastructure services can be implemented manually by the application developer, but are generally not programatically performed. Instead the infrastructure functions are implemented as part of the session Bean deployment descriptor.
Stateless scalability
Since stateless Beans are stateless and non-conversational, there is a significant performance and availability benefit. After a method invocation, the session Bean is fully available for any other client without the need to persist session-specific data. This is especially useful in a clustered Web server environment, such as WebSphere. Since every request is generic, any request can be routed to any specific server instance in the cluster that supports the stateless session Bean. This allows stateless session Beans to scale extremely well both vertically and horizontally. In almost all cases, the scalability limitations for stateless session Beans are dictated by common resources access outside of the container such as the relational database.
Stateless failover
Since the session Bean has no state, a server failure or recycle simply means that requests can be routed to other session Bean instances at other application server instances in a clustered environment. This provides premium server failover characteristics. 94
DB2 for z/OS and WebSphere: The Perfect Couple
4.5.2 Considerations
Following are some considerations when using stateless session Beans.
95
readily available. In some applications, highly scalable and well behaving applications are simply not required, so session Beans may cause a burden on application developers.
Relationship implementation
Relationships between tables and data need to be implemented within the session Bean. It is common for session Beans to implement a data access layer that will allow columns within a database to be instantiated into Java objects. The objects are then used by the business portion of the application, and then when object attribute changes occur, the objects are externalized using the data access layer (see 4.15, Java Data Objects on page 104). It is important that actions against the data representing objects are valid from a data relationship perspective. This means that session Beans, just as other function-based transaction managers, require that transactions understand the relationship between the multiple tables and data within, but if using a data access framework, the relationships will extend into the Java objects as well.
4.6.2 Considerations
Let us now look at the major considerations when using stateful session Beans.
State management
For variables and objects that the container can automatically passivate and activate, the container is configured to externalize the variables out to a WebSphere-managed session area (passivation directory). For WebSphere Application Server for z/OS, the session area is within a shared file system. Although transparent to the application and unlikely to occur with a high frequency, these stateful objects undergoing life cycle management can cause extra I/O to shared resources and may degrade performance.
Connection management
One of the resources that the container cannot automatically passivate and activate is database connections. A stateful session Bean then must provide logic to implement, create, and destroy connections within the passivate/activate section, or make database connections non-session based, and have each method create and destroy a connection.
Transaction management
Since the Bean must be able to activate and passivate the connection, transaction management may become more difficult. If the transactions need to span the entire life span of the conversation, or across multiple method calls, then an activate mechanism must be in place to re-establish the exact state of the transaction before it was passivated. This can be a difficult or poor-performing task. Consider the case where each method within a connection issues a DB2 update, with all method calls in a single transaction. If the Bean were to be passivated, the connection and the transaction would need to end and upon activation. A replay of all events would need to occur.
Availability
Since the stateful session Bean is tied to a specific server, if the server fails, the entire Bean fails and the request cannot be re-routed to an alternate server. The client must handle retry of the function.
97
4.8.1 Benefits
We first have a look at the benefits of using Bean-managed persistence EJBs.
98
4.8.2 Considerations
Now let us look at some of the important considerations when using Bean-managed persistence EJBs.
Relationship implementation
See Relationship implementation on page 96.
99
managing the entity Bean. See Affinity routing requirement on page 97 for additional information. This prohibits workload distribution across a clustered server environment.
4.9.1 Benefits
As before, we first look a the benefits.
Relationships
Relationships are a recently added function within WebSphere, and are also part of a new edition to the EJB specification. Relationships extend referential integrity relationships in databases into the container. This enforces object-based relationships in the application to ensure that applications interact with session Beans correctly. The relationships can be derived from the referential integrity relationships in the database or defined as part of the deployment descriptor.
100
4.9.2 Considerations
Let us also look at some considerations related to CMP Beans.
Diagnosis skills
While the implementation of CMP Beans has certainly improved, without intimate knowledge of the underlying persistence model, it can be difficult to identify where defects are occurring and provide corrective action.
Database schema
CMP datastores generally need to be highly normalized. Since all access to the database occurs through a single Bean, there should be a one-to-one mapping between a table and an entity Bean. This also makes it difficult to exploit an existing database for use with CMP Beans.
Configuration complexity
There are many deployment descriptors that ultimately affect how persistence code is implemented in the container. Since the specific behavior is hidden from the application developer, it is difficult to understand what the cause of inappropriate behavior is. In many cases, vendor-specific deployment descriptors can have a major impact on how the SQL is generated. In addition, each RDBMS has different locking characteristics, and controlling lock contention can be a challenge in an environment where you do not control the underlying SQL functions.
101
A common implementation of an MDB would be to receive a message from a queue that invokes a transaction within a session Bean, which subsequently performs some action against a database.
102
database must be leveraged. In some of these cases, it may be appropriate to reuse business function already included within a stored procedure. In addition, new stored procedures developed for a J2EE application can also be executed by applications outside of the J2EE environment.
4.12.2 Considerations
Next we look at some stored procedure considerations.
103
perceived performance benefits for executing a stored procedure. Unless network time and traffic is reduced, this will result in increased elapsed time.
104
105
Benefits Full EJB infrastructure exploitation Similar development paradigm as CICS, or other transactional-based environments Robust protocol access Stateless scalability Stateless failover OLTP SQL techniques for high scalability can be implemented by application developer No restrictions on data schema Can concurrently execute against data with non-Java OLTP applications
Considerations Data access is implemented by Java code and requires SQL expertise. Must implement data relationships via SQL.
Notes
Same as above
Same as above. Non-transient database connections and transactions must be implemented in passivate/activate. State management overhead.
Similar in function to a stateless session Bean, except that the client maintains a conversation with the Bean. The Bean maintains data across the entire conversation.
Full support of container infrastructure Robust protocol access Enforced separation of application layers
Relationships need to be implemented. Limited database schema. Limited co-existence. Affinity routing.
106
Benefits Full support of container infrastructure Robust protocol access Enforced separation of application layers Checkbox SQLJ support Automatic support for future enhancements through regeneration Relationships can be implemented by container
Considerations Affinity routing. Black box diagnostics. No application co-existence. Limited database schema support.
Notes
Stored procedure
Can be written in any language Can be collocated with the data Can be shared by non-Java applications Can leverage existing SP Reduced network traffic Excellent for batch type functions that require manipulation or inspection of many rows; can significantly reduce cost of Java object creation Can be used to invoke DB2 utility functions and maintenance operations Gateway to other zSeries resources
May incur additional unnecessary overhead for local Web servers. Does not have access to container services such as naming server. SPs are not session oriented (do not maintain state).
Persistence code locking behavior may prohibit a stored procedure from concurrent insert/update/delete activity against the same data CMPs or BMPs access.
107
108
Chapter 5.
109
This chapter does not focus on the details of the program flow phases. They are thoroughly discussed in Chapter 7, SQLJ on page 139, and also documented in the DB2 Universal Database for z/OS Version 8 Application Programming Guide and Reference FOR JAVATM , SC18-7414. This section does point out some fundamental differences between JDBC and SQLJ.
Authorization checking is performed against the ID of the user at run time before an SQL statement is executed. Data types are not checked at compile time. Developer must include certain code in JDBC programs resulting in larger source code when compared to equivalent SQLJ source code. A separate statement is required for each bind variable and specifies the binding by position number.
110
111
executing the application is not used for authorization checking against the SQL statements. In summary: Only the user ID of the package owner requires the necessary privileges to run all the SQL statements in the application. DB2 bind options are discussed further in 5.5, Impact of different DB2 bind options on Java applications on page 120. Users who need to run the application only need the EXECUTE authority against the package (or plan). They do not have or need any additional privileges against the DB2 tables used by the application. This eliminates the possibility of the user being able to modify the data in the DB2 tables at any time, using any other tool that allows them to connect to the database. Only granting EXECUTE authority to users who need to run the application, and only granting the necessary privileges to the applications BIND OWNER, ensures that the data can only be modified under approved business controls. When using type 2 connectivity, a user requires EXECUTE authority on the application plan to run the program, as opposed to having EXECUTE authority on the package. The application plan then includes the appropriate package(s) in the PKLIST bind parameter. However, the same security concept applies. Authorization still occurs at the program level and not at the user level. (Remote applications use a system plan called DISTSERV. No explicit authorization to execute the DISTSERV plan is required. You only need to be able to execute the remote package that your application is referencing.)
112
It is worth noting that importing does not really load any code. It only allows you to use a short-hand notation when referencing the classes incorporated in the imported packages. Finding the actual classes at execution time is done based on the CLASSPATH information.
5.2.2 Using the DB2 Universal JDBC Driver and the DataSource interface
The DataSource interface was introduced with the JDBC 2.0 specification and resides in the javax.sql package. A DataSource object is a factory for Connection objects. The implementations of the DataSource interface offered by the DB2 Universal Driver are: com.ibm.db2.jcc.DB2SimpleDataSource This is the simplest data source provided by the Universal Driver. It is not enabled for connection pooling, nor does it support distributed transactions. It can be used with type 2 or type 4 connectivity. This datasource does not support type 4 XA connectivity. com.ibm.db2.jcc.DB2DataSource This is a data source with a rudimentary pooling manager. com.ibm.db2.jcc.DB2XADataSource A factory for XA connections. The DB2XADataSource, DB2XAConnection, and DB2Xid interfaces provide all the things needed by a JTA implementation. These interfaces are currently supported for type 4 connectivity. This datasource supports connection pooling provided by WebSphere Application Server or another application server. It supports distributed transactions. com.ibm.db2.jcc.DB2ConnectionPoolDataSource A factory for pooled connections. The DB2ConnectionPoolDataSource and DB2PooledConnection interfaces provide all the necessary hooks to implement a connection pooling module. This datasource is used by the WAS pooling module. 3.3, Data source definitions in WAS V5 on page 51, provides additional details on using DataSource objects in a WebSphere environment. Note: From a WebSphere Application Server for z/OS standpoint, only com.ibm.db2.jcc.DB2ConnectionPoolDataSource and com.ibm.db2.jcc.DB2XADataSource DataSource are exposed.
113
An object that implements the DataSource interface is usually registered with a JNDI service provider. JNDI is used to provide a logical name to the DataSource object. A DataSource object can be created and managed using WebSphere. Some benefits when using JNDI include: The JDBC application that uses the DataSource object can refer to the object by its logical name, and does not need any information about the underlying data source. There is no need to modify the JDBC application if the data source attributes change.
Statement interface
The Statement interface contains many methods. The most commonly use methods are: executeQuery() - Typically used to execute SELECT statements. This method returns a ResultSet object containing the database result set produced by the SQL query executed.
114
executeUpdate() - Primarily used to execute INSERT, UPDATE, or DELETE statements. This method can also be used to execute DDL statements. A ResultSet object is not returned. close() - Although a Statement object is automatically closed during its garbage collection process, using this method to explicitly close the Statement object immediately releases database and JDBC resources held by the Statement object. A limitation of the Statement interface is that it can only work with fixed SQL. In other words, the actual SQL statement is hard-coded in the application, and does not use parameter markers. Even though the SQL statement itself does not change, being a JDBC application, the SQL statement is still treated under the dynamic SQL model at run time. With the DB2 Universal Driver, the Statement interface can be used to call stored procedures that do not have parameters. The PreparedStatement and CallableStatement interfaces are sub-interfaces of the Statement interface. Unlike the Statement interface, parameter markers can be used with these two interfaces. This functionality provides increased SQL statement flexibility within JDBC applications.
PreparedStatement interface
The PreparedStatement interface supports any SQL statement containing input parameter markers. The PreparedStatement interface can also be used for SQL statements with no parameter markers. With the DB2 Universal Driver, the PreparedStatement interface can be used to call stored procedures that have input parameters and no output parameters, and that do not return result sets. The the PreparedStatement interface: Provides the ability to precompile an SQL statement that will be issued quite often. Has performance advantages, because the statement is compiled and optimized only once. After syntax check, compilation, and optimization, a handle is returned to the JDBC driver. At the end of the program the statement handle is discarded.
CallableStatement interface
The CallableStatement interface also supports the invocation of a stored procedure. Stored procedures with input parameters, output parameters, or input and output parameters, or no parameters can be called with the CallableStatement interface. With the DB2 Universal JDBC Driver, you can also use the Statement interface to call stored procedures, but those stored procedures must have no parameters. For the JDBC/SQLJ Driver for OS/390, you must use the CallableStatement interface, even if the stored procedure has no parameters. Allow working with stored procedures that return output parameters. Centralize the business logic in terms of manageability and also in terms of running the query. Enforce uniformity across applications, as well as provide security to the database access. Last beyond the execution of the program. For the DB2 Legacy Driver, the CallableStatement interface must be used to call stored procedures even if the stored procedures do not have parameters.
115
Callable statement considerations when using the Universal Driver can also be found on the following IBM Web site:
http://publib.boulder.ibm.com/infocenter/db2help/index.jsp?topic=/com.ibm.db2.udb.doc/ad /c0010281.htm
The considerations for callable statements are as follows when you use the DB2 Universal Driver: Uncatalogued stored procedures are not supported. CALL statements are only describable to DB2 UDB for Linux, UNIX, and Windows Version 8. If you will be accessing a back-level server, you must either set the input parameters or register the output parameters to the same data types that are declared for the underlying stored procedure. CALL parameters cannot be literals or expressions. If you are either querying data from callable statements or querying database metadata catalog information against DB2 for OS/390 and data retrieval is requested by column name (that is, methods such as ResultSet.getInt("columnName") are used), the DESCSTAT DSNZPARM needs be set to YES. If it is not, a -516 error will be returned. On DB2 UDB for OS/390 and z/OS Versions 6 and 7, two callable statements cannot keep their cursors open simultaneously against the same stored procedure.
ResultSet interface
The ResultSet interface provides access to the results that a query generates. The ResultSet interface has the same purpose as the cursor that is used in embedded SQL applications in other languages.
116
117
SQLJ Source
SQLJ translator
Modified Source
(sqlj command)
Serialized profile
Customize
(db2profc command)
Compile
(javac command)
Four DBRMs
BIND PACKAGE
BIND PLAN
Plan
Four Packages
Figure 5-1 SQLJ program preparation using the DB2 JDBC Legacy Driver
The process is: 1. Translate the SQLJ source code. The sqlj command can be invoked from the z/OS UNIX System Services command line, and is used to invoke the DB2 UDB for z/OS SQLJ translator. This step produces modified source code and one or more serialized profiles. The modified source code is then compiled using the javac command to generate a Java class file. Note: The available options and form of the sqlj command depend on the driver that you use. All forms of the sqlj command are documented in the DB2 Universal Database for z/OS Version 8 Application Programming Guide and Reference FOR JAVATM , SC18-7414. 2. Customize the serialized profile using the db2profc command to produce standard DB2 for OS/390 and z/OS DBRMs. Although this is an optional step, it is highly recommended. If the serialized profiles are not customized, the SQLJ application will run under the dynamic SQL model, and not under the static SQL model. 3. Bind plans or packages.
118
preparation process when using the Universal Driver. This is illustrated in Figure 5-2 on page 119.
SQLJ Source
SQLJ translator
Modified Source
(sqlj command)
Serialized profile
Customize
(db2sqljcustomize command)
Figure 5-2 SQLJ program preparation process using the DB2 Universal JDBC Driver
SQLJ program preparation using the DB2 Universal JDBC Driver includes these steps: 1. Translate the source code using the SQLJ translator via the sqlj command. The result is modified Java source code (all SQLJ statements are now replaced with real Java statements) and one or more serialized profiles. The modified source code is then compiled using the javac command to generate a Java class file. Note: The available options and form of the sqlj command depend on the driver that you are using. All forms of the sqlj command are documented in the DB2 Universal Database for z/OS Version 8 Application Programming Guide and Reference FOR JAVATM , SC18-7414. 2. Customize the serialized profiles using the db2sqljcustomize command to produce a customized serialized profile. When using the db2sqljcustomize command, you have the (default) option to produce DB2 packages at a specified data source. Note: When customizing a serialized profile, the customizer (db2profc or db2sqljcustomize) normally produces four packages for each serialized profileone for each isolation level (UR, CS, RS, and RR). More information about SQLJ profile customization using the Universal Driver can be found in 7.2, Profile customization on page 146.
119
120
statements. The default is NO. NO means that the positioned UPDATEs are executed as dynamically prepared statements. The DYNAMICRULES(BIND) option also causes the SET CURRENT SQLID statement to have no impact on a static SQLJ program, because those statements affect only dynamic statements that are bound with DYNAMICRULES values other than BIND.
121
122
123
124
Properties can be set in one of the following ways: Using setXXX methods - Properties are applicable to the following DB2-specific implementations that inherit from com.ibm.db2.jcc.DB2BaseDataSource: com.ibm.db2.jcc.DB2SimpleDataSource com.ibm.db2.jcc.DB2DataSource com.ibm.db2.jcc.DB2ConnectionPoolDataSource com.ibm.db2.jcc.DB2XADataSource
For example, to initialize the CURRENT PACKAGE PATH special register, you can set the currentPackagePath property by invoking the method:
DB2SimpleDataSource ds1=new DB2SimpleDataSource(); ds1.setCurrentPackagePath("myprivcol,devcol,prdcol");
Note: Notice that the property name is currentPackagePath (starting with lower case), whereas the set method uses an upper case setCurrentPackagePath. You can also specify properties when using DriverManager. On the DriverManager.getConnection call, you can specify a java.util.Properties value in the info parameter. In a java.lang.String value in the url parameter of a DriverManager.getConnection call. The last two options are merely mentioned for completeness, as we highly recommend the use of the DataSource interface over DriverManager. For a complete list of all properties supported by the DB2 Universal Driver, see DB2 Universal Database for z/OS Version 8 Application Programming Guide and Reference FOR JAVATM , SC18-7414.
125
126
Chapter 6.
127
6.1.1 Authentication
There are multiple mechanisms for validating the identity of a requestor. The most common implementation is to challenge the requestor for a user ID and password. The user ID and password are static entities that generally do not change for an extended period of time, although some security policies can enforce a relatively frequent password change. The major drawback of such an approach is that if a users user ID and password are compromised, other users can easily assume their identity. For non-encrypted user IDs and passwords that flow across a TCP/IP network, it is relatively easy to sniff the user ID and password. There are implementations of authentication other then user ID and password challenges. A less secure approach is simply a user ID without the requirement for a password. A more secure approach includes authentication standards such as Kerberos. In Kerberos implementations, a third-part authentication server in conjunction with public and private keys and a timestamp are able to allow a requester and server to verify each others identity. The important notion about Kerberos is that the tokens used to authenticate a user are not static. Each time an exchange is created the actual credentials exchanged are based upon a number of public and private keys and a timestamp. That means that even if the security ticket was intercepted, it would be extremely difficult to derive value out of it. The details are beyond the scope this book since, even though the DB2 JDBC driver and DB2 for z/OS support Kerberos, WebSphere currently does not exploit this function. The important notion in Kerberos is that a security token is generated for each request using a combination of algorithms against private and public keys.
6.1.2 Authorization
Authorization is the process of controlling access to resources based upon the authentication of an end user. As part of the system, a security policy dictates what resources a specific identity can access and what type of access is allowed. For example, in a relational database, an authenticated end user must be authorized to access a table for the intended action (select, insert, update, delete). If the user is only authorized to read a table, attempts to insert, update, or delete will be denied, but attempts to select will be permitted.
6.1.3 Auditing
Auditing is the process of recording actions taken by users. This includes actions that are both permitted and denied. A good auditing implementation will allow review of all actions by end users. Not only are the actions recorded, but the service that authenticated the user and allowed or denied the user authorization to access a resource must all be recorded. Auditing logs must also be blocked from update by users of system. The ability to remove an auditing entry would invalidate the benefit of the auditing system.
128
USERID_ONLY_SECURITY (4):
ENCRYPTED_PASSWORD_SECURITY (7):
129
ENCRYPTED_USER_AND_PASSWORD_SECURITY (9): User IDs and passwords are required and are encrypted when sent on the network. ENCRYPTED _USER_AND _DATA_SECURITY(12): The user ID and password are required for authentication, the user ID and data are sent encrypted, and the password is sent in clear text. User ID and password are required and encrypted; data is encrypted as well. Kerberos infrastructure is exploited; no user IDs or passwords are sent. Note that this is not supported within a WebSphere environment.
KERBEROS_SECURITY (11):
If a user ID and password are specified, DB2 issues a Security Access Facility (SAF) check to verify that the user ID and password are valid. Once the thread is successfully authenticated, the user executes with the authorization of the specified user ID and password. The AUTHID is then associated with the thread within DB2. To exploit the user ID only mechanism, the TCPALVER DSNZPARM at the server must be set to YES. Please note that setting this parameter to yes is strongly discouraged and is analogous to giving away all of the data within the database. A user would only need to know a valid user ID to get access to a system. According to the Java programming guide, if you do not specify a value for this property, the most secure mechanism supported by the server is attempted. However, in our testing we found that not specifying a value within WebSphere resulted in the use of user ID and password in clear text.
130
While we generally agree it is a good idea to have an end users identity flow with a user all the way through the transaction and through the datastore, there are multiple issues in a WebSphere environment that prohibit this propagation of authorization.
Performance
The connection pooling function, probably the most important optimization for performance within the datasource, allows connections to be repeatedly reused without the need to establish a new connection, which is expensive. Unfortunately, in WebSphere Version 5, the connection pooling is organized and maintained by authorization ID. Connections or applications that want to use unique authorization IDs cannot share connections or benefit from connection pooling.
131
132
In addition to the Run-As attribute, the Res-Auth deployment descriptor within the WSAD environment indicates who should be attempting to provide the identity, the application or the container. This attribute lets the container know if the application plans on providing a programmatic user ID and password. Res-Auth, which is short for Resource Authentication, can be set to either container or application. The value is set within the deployment descriptors reference to the datasource. This same window also sets the isolation level for the datasource, as discussed in 9.3.1, Setting the WebSphere transaction isolation level on page 217. Figure 6-3 on page 134 shows the res-auth value being set within the deployment descriptors reference for a datasource.
133
Figure 6-3 Setting the Res-Auth value within an EJB reference to a datasource
134
The user ID and password must be a valid SAF user ID, if they are to be used for connectivity to DB2 and referenced in the datasource definition. Once the JCA authorization IDs are defined, the datasource can specify an ID to be used if the datasource is accessed with res-auth=container, and a separate ID if res-auth=application is used. Figure 6-5 displays how to set the value. Component-managed aliases are used for res-auth=application, and container-managed aliases are used for res-auth=container.
135
Once global security is enabled, the application also requires that Sync to OS Thread is enabled for the server. Within the Security Global security z/OS Security options tab of the Administrative Console, the option to allow sync to os can be enabled by flagging the check box, as shown in Figure 6-6.
For your application, Run-As caller should be set for the Bean in the deployment descriptor; and within the reference to the datasource, resauth should be set to container; and no value for container-managed alias should be specified in the datasource definition.
136
String ClientAccountingInformation
Maximum length 22
In standard header NO
Note that if any applications set these fields, the values will not be reset when returned to the connection pool. Applications must all set these values at the beginning of the transaction to correctly collect and report data based upon these fields. As mentioned above, the upcoming version of WebSphere Application Server will make it easier to set the DB2 client strings. The plan is to allow you to wrap the Connection with a WSConnection class (com.ibm.websphere.rsadapter.WSConnection). This interface provides a number of methods, such as setClientInformation, getClientInformation (and getSystemMonitor). This API allows you to set client information on the WebSphere connection. Some of the client information will be passed on to the back-end database, if the database supports such functionality (which is the case for DB2). A simplified code snippet is shown in Example 6-2. The only intention is to demonstrate how much easier it will become to set the client strings in a WAS environment in the near future.
Example 6-2 WSConnection using setClientInformation method import com.ibm.websphere.rsadapter.WSConnection; .....
137
try { InitialContext ctx = new InitialContext(); // Perform a naming service lookup to get the DataSource object. DataSource ds = (javax.sql.DataSource)ctx.lookup("java:comp/jdbc/myDS"); } catch (Exception e) {;} WSConnection conn = (WSConnection) ds.getConnection(); Properties props = new properties(); props.setProperty(WSConnection.CLIENT_ID, "user123"); props.setProperty(WSConnection.CLIENT_ACCOUNTING_INFO , "accounting1"); props.setProperty(WSConnection.CLIENT_APPLICATION_NAME, "appname"); ... conn.setClientInformation(props); conn.close();
The example shows that you do not use a DB2Connection object to set the client strings in a WAS environment, but use WSConnection instead.
138
Chapter 7.
SQLJ
This chapter describes the use of embedded SQL in Java, also known as SQLJ. We also compare SQLJ to JDBC, that is, dynamic SQL in Java applications. Next, we look at how to write an application using SQLJ in a WebSphere Application Server environment, and how to use SQLJ with WebSphere Studio Application Developer. This chapter contains the following topics: Writing SQLJ versus JDBC applications Profile customization Application design SQLJ in WebSphere Studio Application Developer
139
7.1.1 Connections
Before we can execute any SQL statements against a DBMS, we need a connection. Though written in different ways, getting a connection from SQLJ is identical to getting a connection from JDBC. In fact, SQLJ uses JDBC to retrieve a connection. Two different methods can be used to obtain a connection to a DBMS in Java: The DriverManager interface The DataSource interface When using the DriverManager interface, the names of both the driver and the database are coded directly into the method calls within the application code. Using a DataSource object instead of DriverManager removes this direct coding of driver and database names from the application. This information is kept and maintained separately, for instance, in WebSphere Application Server. The data source is then retrieved by a lookup with a logical name known to the application. Important: When accessing DB2 from WebSphere Application Server, we always use the DataSource interface. One of the reasons is that we get connection pooling with the DataSource interface. The result is better scalability and more robust applications. In this book we concentrate entirely on using the DataSource interface. If you are interested in the DriverManager interface, please refer to DB2 for z/OS and OS/390: Ready for Java, SG242-6425, as well as DB2 Universal Database for z/OS Version 8 Application Programming Guide and Reference FOR JAVATM , SC18-7414.
140
DataSource versus datasource In this section we use the terms DataSource and datasource, but even though they are
spelled the same, they are different things, which is of course a little confusing. The
In the above example, the InitialContext loads the object stored in JNDI on the server where it is instantiated. That is a local look up. We actually have the opportunity to look up objects that live in the JNDI on any server. To do this, we initialize the InitialContext class with a set of properties that tells the InitialContext which server to use. This is shown in Example 7-2 on page 142. In this example we explicitly specify the user ID and password as well.
Chapter 7. SQLJ
141
Example 7-2 Look up of the datasource in detail import import import import import javax.naming.InitialContext; javax.naming.Context; javax.sql.DataSource; java.sql.Connection; java.util.Properties;
Properties prop = new Properties(); // #1 properties.put( Context.PROVIDER_URL, iiop://hostname:portnumber); // #2 properties.put( Context.INITAL_CONTEXT_FACTORY, com.ibm.websphere.naming.WsnInitialContextFactory); InitialContext context = new InitialContext( properties); // #3 DataSource ds = (DataSource) context.lookup(jdbc/ITSO); Connection conn = ds.getConnection( userId, password);
If the object we are looking for lives on another server, we can tell the InitialContext which server to use by adding a PROVIDER_URL, as shown. Your system administrator can supply you with the information about the hostname and the portnumber. When we specify the PROVIDER_URL, we also need to specify the Java class that is doing the job on the server specified. This is done by specifying the INITIAL_CONTEXT_FACTORY. The one used by WebSphere Application Server is shown in the example. Now the InitialContext has the information to look up the DataSource, and we get the connection with a specific user ID and password. Tip: Lookup through the Java Naming and Directory Interface (JNDI) is fairly costly. That is why we only want to do the lookup once, and keep the reference in a cache. This cache is usually implemented as a static Java class using a hash-table. Example 7-3 is without error handling, but shows the concept. See itso.sqlj.servlet.HomeFactory in the sample application for a complete implementation.
Example 7-3 Caching the lookup information public class MyCache { private static MyCache cvSingleton = new MyCache(); private Hashtable ivCache = new Hashtable(); private HomeFactory() { // Load the datasources into the cache InitialContext initialContext = new InitialContext(); ivCache.put("jdbc/ITSO1", initialContext.lookup("jdbc/ITSO1"); ivCache.put("jdbc/ITSO2", initialContext.lookup("jdbc/ITSO2"); } public static final MyCache getInstance() { return cvSingleton; } public Object getDataSource( String jndiName) { return ivCache.get( jndiName);
142
} }
The steps are: 1. This is where we define the context class. The name after the reserved word context must be a valid Java class name. 2. This is where we create the connection. This step is identical to the JDBC approach. We can set additional attributes on the connection in this step as well, for instance, setting the autocommit feature to false. As with JDBC, we can choose to retrieve the connection with or without specifying a user ID and password. 3. Finally, we create an instance of the context class. Notice that the connection we created in step 2 is passed as a parameter to the constructor of the context class. With the DB2 Universal Driver, we have a simpler way to create the connection context. We can add a with-clause to the context definition, as shown in Example 7-5. Here we specify the datasource directly, so we do not need to manually create a connection. Note that step 2 is obsolete in this case. If we need to supply the user ID and password, we give them as parameters to the constructor of the context class.
Example 7-5 Creating the context using Universal Driver features // step 1 : #sql public static context MyConnectionContext with (dataSource=jdbc/ITSO1); // step 3a: MyConnectionContext myContext = new MyConnectionContext(); // step 3b: if we want to specify userid and password, we use MyConnectionContext myContext = new MyConnectionContext( userid, password);
Tip: The context class simply wraps the connection, and if we need to get hold of it, we simply call getConnection() on the context class. We can, for instance, disable the autocommit feature by calling myContext.getConnection().setAutoCommit(false);
Chapter 7. SQLJ
143
For more information about setting additional attributes on the connection context, refer to Chapter 3 of DB2 Universal Database for z/OS Version 8 Application Programming Guide and Reference FOR JAVATM , SC18-7414.
Important: Even though the context is optional, we highly recommend that you specify it. If the context is not specified, an implicit context is created, namely the default context. The default context is a static variable and therefore shared by every thread in the same JVM. This can lead to a throughput bottleneck, but worse, another thread can change the default context while we are using it. Conclusion: We always use a specific context. Let us now have a look at the employee table in the sample database that comes with DB2. A subset of the columns is shown in Table 7-1.
Table 7-1 Subset of columns in the employee table from the DB2 sample database Column name EMPNO Description Employee number (the primary key)
144
Description First name of the employee Last name of the employee Date of hire Yearly salary in dollars
We want to retrieve these columns into a Java application for the employee with the EMPNO equal to 000130. Apart from creating the connection context, we need to define some host variables that we can select the values into. With the context at hand, along with the host variables, we are ready to write our SELECT statement, as shown in Example 7-6.
Example 7-6 Writing a SELECT statement using SQLJ String empno= 000130; // Define the connection context #sql public static context MyContext with (dataSource=jdbc/ITSO1); // Host variables to select into String firstname = null; String lastname = null; java.sql.Date hiredate = null; java.math.BigDecimal salary = null; // Create an instance of the context class MyContext context = new MyContext(); // The SQLJ Select statement #sql [context] { SELECT FIRSTNME, LASTNAME, HIREDATE, SALARY INTO :firstname, :lastname, :hiredate, :salary FROM EMP WHERE EMPNO = :empno } // Tell the Transaction Manager that we are done with the connection for now context.close();
Assuming we are running within the scope of a transaction in WebSphere Application Server, closing the context will not close the underlying connection. We just put the connection in a valid state for commit, leaving to the Transaction Manager to commit, or rollback, when appropriate. In 7.3, Application design on page 150, we discuss in more detail how to handle the connection from different parts of a J2EE application. The SQL statement can be almost any DB2 statement that can be statically prepared. Additionally, there is a special statement to set the isolation level for the current transaction:
#sql [context] { SET TRANSACTION ISOLATION LEVEL level};
Where level is one of values the listed values in Table 7-2. Please be aware that both JDBC/SQLJ and DB2 use the term repeatable read, but for different purposes.
Table 7-2 SQLJ isolation levels and their corresponding DB2 counterparts SQLJ isolation level READ UNCOMMITTED DB2 isolation level UR (uncommitted read)
Chapter 7. SQLJ
145
For further information about the SQLJ language, refer to DB2 for z/OS and OS/390: Ready for Java, SG24-6435. Important: SQLJ only runs as static SQL when it has been customized. Uncustomized SQLJ runs as JDBC and dynamic SQL under the covers. So uncustomized SQLJ is potentially slower than JDBC, due to the overhead of the SQLJ run-time library. More information about profile customization can be found in 7.2, Profile customization on page 146.
In the statement above, iter is an instance of a public SQLJ iterator class, and resultset is a JDBC ResultSet object. The other way around is possible as well, but not recommended, as the result is implementation defined, which is another way of saying that it may or may not work as you expect. However, it does work with the DB2 Universal Driver. To convert an SQLJ iterator into a JDBC result set, use the getResultSet method on the iterator class.
ResultSet rs= iter.getResultSet();
146
Important: The real strengths of SQLJ come only into play through the customization process. Do not expect better performance of SQLJ programs over equivalent JDBC programs if no customization has taken place. In fact, uncustomized SQLJ will rather run slightly slower because of some additional overhead in the SQLJ run time. The profile customizer for the DB2 Universal Driver (db2sqljcustomize) adds customization information to each entry in the profile. As mentioned before, this customization information is DBMS specific, and additional program preparation steps may be necessary before the customized program can successfully be run against the database. In the case of DB2, during profile customization, a DB2 package is created in the database catalog (actually, four packages by default, one for each isolation level). The serialized profile is also updated by the customization process. The DB2 customization information includes the package name (supplied when invoking the profile customizer command); a timestamp indicating when the customization took place; and a consistency token, used to ensure that the database package matches the profile. When an SQLJ implementation reads a serialized profile at run time, it checks for available customizations that are compatible with that particular implementation. When no such customization is found, the SQLJ run time falls back to using dynamic SQL; that is, it reads the actual SQL text of the statements, and prepares and executes these statements dynamically using JDBC calls. This is in fact one of the beauties of SQLJ, as opposed to other languages with embedded SQL support. Whereas in COBOL, for example, you are required to bind your program against the database after translationotherwise, you get a run-time error when executing itthis is not the case with SQLJ. Rather, you simply translate the program and the SQLJ run time will figure out whether the program has been customized. This is very convenient during program development, since you can omit the customization (and bind) step until your program is ready for deployment. Important: However, if the profile has been customized for DB2 (customization information present in the serialized profile), and for some reason the package has not been bound against the database during (or after) customization, you receive a -805 SQL error (package not found) at run time. You will also receive this error when the package had been bound before, but the SQLJ file was retranslated and re-customized without rebinding the package. In this case, the consistency token recorded in the profile does not match the one in the database. So once the profile has been customized for DB2, you must have a matching package bound in the database. In this case, SQLJ run time will not revert to using JDBC. When using the customizer provided with the DB2 Universal Driver, the profiles remain platform independent, even after customization, because SQLJ implementations are required to ignore customization information they do not know about. (This is not the case when using the customizer provided with the DB2 Legacy Driver (db2profc).) In fact, it is possible to customize one profile several times, once for each target database system. This makes it possible to run the program unchanged against, say, DB2 and Oracle databases. However, all DB2 implementations across the DB2 family use the same customization. You do not have to customize again when switching from a DB2 for Linux, Unix, and Windows to DB2 for z/OS and OS/390 when using the DB2 Universal Driver.
Chapter 7. SQLJ
147
As mentioned before, by default, db2sqljcustomize automatically binds the DB2 packages. You can use it an option to disable automatic creation of packages during customization. You need to specify the -automaticbind NO parameter in that case. This is shown in Example 7-7 with a serialized profile called Test_SJProfile0.ser.
Example 7-7 Disable automatic creation of DB2 packages during customization db2sqljcustomize -automaticbind NO Test_SJProfile0.ser
If the packages are not bound during customization, you can use the db2sqljbind utility to bind packages at a later time. Java applications that use the DB2 Universal Driver require packages but no plans. The DB2 packages are bound at the data source (DB2 system) that you specify in the -url parameter (of the db2sqljbind or db2sqljcustomize command). The -url parameter is always a hostname:portnumber combination. This means that even when binding against a (local) DB2 system on the same z/OS, you use a remote bind (and access that DB2 via DDF.) This implies that you must have DDF set up and active before you can start using the DB2 Universal Driver. Important: DDF must be set up and active before you can customize profiles using the DB2 Universal Driver.
148
That will produce four packages, one for each isolation level: HELLO1, HELLO2, HELLO3 and HELLO4 in the TESTBART collection. This customizer option will be supported in RAD V6. (IBM Rational Application Developer for WebSphere Software (RAD) is the new name that WSAD will have starting with V6.)
This will generate a single package HELLOUR in the TESTBART collection with isolation level UR. The customizer option -singlepkgname will be supported in RAD V6. (IBM Rational Application Developer for WebSphere Software (RAD) is the new name that WSAD will have starting with V6.) For more information see 7.4.6, Customization on page 187; and 11.2.2, Container-managed persistence entity Beans with SQLJ on page 273.
149
Packages that use the same version string are overwritten when bound, whereas -pkgversion AUTO will always generate a new version, and can lead to an explosion of the number of packages in the system, especially in a development environment. The BIND package command to copy packages from one environment to the next is also easier when you manually specify the version string, than having to use the one generated by DB2.
Servlet
Java
SQLJ
BMP SB CMP
DB2
Figure 7-1 The SQLJ roadmap from the client container to DB2
With the focus on WebSphere Application Server, we do not look at the scenario where the client container is a Java stand-alone program. We will concentrate on the Web browser scenario. However, writing a Java stand-alone program that either calls SQLJ directly or uses session Beans as access point, use the code from the servlet described in the following sections. Accessing a session Bean from a Java stand-alone program is almost identical to accessing the session Bean from a servlet. For further information about creating a Java stand-alone program using EJBs, refer to EJB 2.0 Development with WebSphere Studio Application Developer, SG24-6819.
150
JSPs, and EJBs, where EJBs represent the Model, JSPs represent the View, and servlets represent the Controller. There are two different kinds of Enterprise JavaBeans: Session Beans (SB) and entity Beans (EB). Entity Beans represent data (they correspond to a row in a DB2 table), while session Beans implement business logic. A common approach when designing EJB applications with entity Beans and session Beans is to use a facade in front of entity Beans that protects the persistent data layer, and controls all the client access. In this way, the session Bean can tie together multiple data source access into a single process, and act as a single point of entry into the business layer. Another benefit of using a session Bean facade to the entity Beans is performance. Enterprise Beans in their nature are distributed objects, and all calls to the Beans are remote calls. To improve performance, the 2.0 specification added a local interface to the Beans. This local interface is supported by WebSphere Application Server V5. Methods on the local interface are invoked directly on the Bean, which gives a much better performance, but then the caller must live in the same JVM as the entity Bean. Using the facade session Bean, we can decide only to use the local interface of the entity Beans.
Session Beans - Stateless vs stateful A session Bean can either be stateful or stateless. The difference is that a stateful session Bean can maintain a state between calls on the Bean. We can use a stateful session Bean to
maintain a session with a client, but there are many other ways to obtain this functionality. Usually the session Beans are accessed from a servlet in the Web container, where sessions are an issue as well. If we already have some session handling in the Web container, why should we choose to add additional session handling in the EJB container? Another issue about stateful session Beans is that they demand a lot of work from the container, so they can easily become a performance problem. We do not believe stateful session Beans to be the predominant choice, and in fact, we would think twice before using them. Our recommendation is to keep the session information in the Web container, and use stateless session Beans.
151
interface, while the entity Beans that are accessed through a session Bean facade should use the local interface. This gives us the best combination of performance and scalability. Note: Stateless session Beans are pooled by the EJB container in WebSphere Application Server, which is a huge performance optimization. The price to pay for using the remote interface is little compared to the benefit of the scalability.
152
EJB Container
2
Remote Call
Servlet
Forward
SB
Local call
CMP
Web Browser
4
Response
DTO
SQLJ
DB2
JSP
In the next section, we describe the complete flow in more detail, but for now let us have a look at the big picture: 1. The Web browser issues a request for a URL, which at some point reaches the servlet. 2. The servlet invokes a method on a stateless session Bean through its remote interface. The session Bean either calls a CMP through its local interface or calls the DB2 directly by issuing a SQLJ command. The result is returned to the servlet in a DTO. 3. The servlet sends the DTO to the JSP. 4. The JSP generates the HTML output and sends it back to the Web browser. Note: The JSP is actually just another servlet. When a JSP is invoked, it is translated into a servlet and then loaded to run in the Web container.
Chapter 7. SQLJ
153
Browser Client
Input Page
1
Data Sources
HTML
2
13
10
Enterprise Enterprise Enterprise Enterprise Bean Enterprise Bean Bean Bean Bean
7 8
DO
Web Server
Plug-in 4
JNDI
Connection Pool
DB2
The flow is: 1. A Web client requests a URL in the browser (input page). 2. The request is routed to the Web server over the Internet. 3. The Web server immediately passes the request to the Web server plug-in. All requests go to the WebSphere plug-in first. 4. The Web server plug-in examines the URL, verifies the list of hostname aliases from which it will accept traffic, and chooses a server to handle the request. 5. A stream is created. The stream is the connection to the Web container. The Web container receives the request and, based on the URL, dispatches it to the proper servlet. 6. JNDI is now used to look up the session Bean requested by the servlet. 7. JNDI will direct the servlet to the corresponding EJB container, which then instantiates the EJB that is requested. 8. The session Bean will now go back into the JNDI either to look up an entity Bean, or to look up the datasource. If an entity Bean is used, the entity Bean will do the look up of the datasource. 9. The SQLJ statement is executed, and data is sent back to the enterprise Bean. 10.Data Objects (DOs), also known as Data Transfer Objects, are created and handed back to the servlet. 11.The servlet sends the DOs to the JSP. 12.The JSP generates the HTML that is sent back through the WebSphere plug-in to the Web server. 13.The Web server sends the HTML to the browser.
handled differently, as no exceptions are thrown. We start out by defining transaction demarcation.
Transaction demarcation
Determining when a transaction begins and ends is called transaction demarcation. We can choose to either control when transactions begin and end programmatically, by using Bean-Managed Transactions (BMT) demarcation, or we can delegate this to the container through container-managed transaction (CMT) demarcation.
Bean-managed transactions
Bean-managed transactions must explicitly declare when the transaction starts, what behavior is part of the transaction, and when it ends. This is accomplished through the use of the UserTransaction interface specified in the Java Transaction API (JTA). This interface provides the necessary methods for controlling the transaction. Example 7-8 shows a simple example on how to use the interface.
Example 7-8 Simple user transaction example // declare the user transaction UserTransaction transaction = null; try { // get a UserTransaction via JNDI look up InitialContext ctx = new InitialContext(); tran = ctx.lookup( java:comp/UserTransaction); // begin the transacition tran.begin(); // do transaction work, usually execute SQL statements, then commit tran.commit(); } catch ( Exception e ) { // rollback the transaction if any error had occoured if ( transaction != null ) transaction.rollback(); }
Only Beans that are declared to use Bean-managed transactions, via the deployment descriptor, may use the UserTransaction interface. The container throws an exception if doing otherwise. A UserTransaction is not restricted to the EJB container; it can be obtained in a servlet as well. We can set the transaction type either by manually editing the deployment descriptor or by using the editor in WebSphere Studio Application Developer, as shown in Figure 7-4 on page 156.
Chapter 7. SQLJ
155
Figure 7-4 Setting the transaction type in WebSphere Studio Application Developer
Note: Even though it is possible to manage the transaction ourselves, we do not recommend the use of Bean-managed transactions. The task quickly becomes quite complicated, which might lead to non-robust applications.
Container-Managed Transactions
The simpler and much more elegant solution is to let the container manage the transactions for you. There is no need to write any transaction logic, because this is handled by the container at run time. Instead of intertwining the code with transaction demarcation, we simply declare the Bean to use container-managed transaction demarcation in the deployment descriptor. In addition, we can declare additional transactional attributes that govern the behavior of the Beans in the transaction. The transactional behavior of CMTs can be set either globally at the Bean level, or on the individual methods of the Bean. Depending on how the transaction attributes are defined, the container will either start, continue, suspend, ignore, stop, or throw an exception on a transaction, when a Beans method is invoked. A detailed description of these attributes can be found in Chapter 8, Transaction management in a WebSphere environment on page 191. The container determines whether to roll back or to commit based on two different things. First of all, it is possible to mark the transaction for rollback only by calling the method setRollbackOnly on the SessionContext object. The container then guarantees that the transaction is rolled back when completed. However, it will not force an end to the transaction immediately. We can use the getRollbackOnly method on the SessionContext object to determine if the transaction has been marked for rollback. This is illustrated in Example 7-9.
Example 7-9 setRollbackOnly() on the sessioncontext try { // call DB2 } catch ( SQLException e) { if ( e.getErrorCoe() == 4 ) { getSessionContext().setRollbackOnly(); } } // Do something if the transaction is not marked as setRollbackOnly if ( getSessionContext().getRollbackOnly() == false ) { // Do something else
156
Exceptions
The container also uses the exceptions to handle transactions, which we will take a close look at hereafter.
System exceptions The system exceptions in J2EE include unexpected RuntimeException, RemoteException,
EJBException, and all exceptions that inherit from them. Therefore, it may include both checked and unchecked exceptions. System exceptions represent more serious unexpected conditions within the system that are not business related, and that prevent the method from successfully completing. If the method is executed within a transaction, the transaction will be rolled back immediately. Any system exception that is not caught by a Bean will be caught by the container. The container will intercept the exception, and then throw back to the client either a java.rmi.RemoteException or a javax.ejb.EJBException, depending on whether the method was invoked through the remote interface or the local interface. Important: The container does roll back the transaction when a system exception is thrown. Usually we just propagate any system exception to the container, which will then throw the appropriate java.rmi.RemoteException or javax.ejb.EJBException.
Application exceptions The application exception in J2EE is a checked exception in Java terms. A checked exception
must either be caught in the method, or be represented in the throws clause of the methods signature. The Java compiler enforces this. If a checked exception is neither caught or declared in the methods signature, a compilation error occurs. Application exceptions are used to specify a logical error, a business logic error. Whether a transaction should be rolled back or committed depends on the business logic. Therefore, it is the responsibility of the application programmer to roll back the transaction if required. It is not the responsibility of the container. If any application exception should result in rollback of the transaction, the exception must be caught, and one of the following two scenarios must take place: Mark the transaction as rollbackOnly. This is done by calling the setRollbackOnly method on the session context object, as described in Example 7-9 on page 156. The container guarantees that the transaction is rolled back at the end. Notice that the method flow continues. Throw a system exception. The exception thrown can either be an instance of one of the general exceptions javax.ejb.EJBException or java.rmi.RemoteException, or any user-defined run-time exception. The method will be aborted immediately, and the transaction terminated instantly. The method flow is discontinued.
Chapter 7. SQLJ
157
Important: The container does not roll back the transaction when an application exception is thrown. Usually we catch any application exception, checked exception, in the Bean, nest it into an EJBException, and then throw the EJBException to tell the container to roll back the transaction.
SQLException
This is an actual exception that is thrown by the JDBC driver. This means that we must catch the exception in our Bean. SQLException is a subclass of java.lang.Exception and is therefore a checked exception. This means that we have to catch the exception in our Bean code if we want to roll back the transaction. In Example 7-10 we show how to do this.
Example 7-10 Handling of a SQLException #sql public static context MyContext with (dataSource=jdbc/ITSO1); try { MyContext context = new MyContext(); #sql [context] { INSERT INTO EMP VALUES (123,,,)}; } catch ( SQLException e ) { throw new EJBException( e); }
If the SQLJ statements are separated from the enterprise Beans and written in separate Java utility classes, we just propagate any application exception, including SQLException, to the calling client. The utility classes are often unaware of the context in which their methods are invoked. It is therefore unlikely that the utility classes can perform any sensible error handlingthis is left to where the business logic is implemented in the session Beans.
SQLWarning
As SQLWarnings are not thrown, we are obviously not able to catch them. SQLWarnings are added silently to the execution context. Each SQLJ statement is associated with an execution context. The execution context allows us to control how the statement is executed, and to retrieve information about the statement after the execution. We can, for instance, set a query time-out for the statement, or we can retrieve information about how many rows were affected by a statement. We can retrieve any SQLWarnings through the execution context. For more information about the execution context, see section 10.7 in DB2 for z/OS and 390: Ready for Java, SG24-6435.
158
To check for a DB2 warning, we invoke the getWarnings method on the execution context after we execute the SQL statement. getWarnings returns the first SQLWarning object that an SQL statement generates. Subsequent SQLWarning objects are chained to the first one. Example 7-11 shows how to retrieve the SQLwarning via the execution context object.
Example 7-11 Handling SQLWarning #sql public static context MyConnectionContext with (dataSource=jdbc/ITSO1); MyConnectionContext MyContext = new MyConnectionContext(); ExecutionContext execContext = new ExcectionContext() // Execute the SQL #sql [MyContext, execContext] { SELECT LASTNAME INTO :lastname FROM EMP WHERE EMPNO = 100 }; // Check for SQLWarning objects SQLWarning warning = execContext.getWarnings(); if (warning != null ) { // Handle warning }
Tip: The ExecutionContext can be used for purposes other than just checking for SQLWarnings. The class has a number of methods that can be used to control the execution of SQL statements in SQLJ. Some methods are applicable before the associated SQL statement is executed, and some are only applicable after their associated SQL statement is executed. Note also that we have a connection context (Mycontext) and an execution context (execContext) in the example above. You can also acquire a default execution context from the connection context by using the following:
ExecutionContext execContext = MyContext.getExecutionContext();
Chapter 7. SQLJ
159
WSAD preferences
Through the WSAD preferences accessible from Window Preferences Data SQLJ (Figure 7-6), we can control how WSAD works with SQLJ files.
The fields are: SQLJ translator JAR file Full path and file name of the JAR file containing the SQLJ class library that implements SQLJ translation support. If DB2 is installed the file is <db2home>/java/sqlj.zip, where <db2home> is where DB2 is installed, by default C:\Program Files\IBM\SQLLIB.
160
SQLJ translator class name Fully package-qualified name of the SQLJ class used for translating SQLJ statements. The default is sqlj.tools.Sqlj. SQLJ Java source folder Name to use for the folder containing SQLJ Java source files. This preference is only used if we choose to create a specific source folder when we define our SQLJ project. If the source folder and the output folder are the same, then generated Java files are put in the same folder as the SQLJ files. SQLJ customization script folder Name to use for the folder containing SQLJ Ant scripts. Color for SQL clause in editor Color in which SQLJ statements are displayed in the Java editor. Enable debugging from SQLJ file If selected, debugging will occur in SQLJ files, instead of the generated Java files. If you change this preference, you must rebuild the project for the change to take effect.
Team support
In almost every project, there is more than one developer involved, and therefore we can use the team support facilities in WSAD. This includes a version control system as CVS or Rational Clearcase. In these cases, it is a good idea to tell WSAD to treat sqlj files as text files. This is done in the preferences for team support, accessible via Windows Preferences Team File content, as shown in Figure 7-7. Click the Add button and enter sqlj, then click the OK button. WSAD will automatically choose ASCII as contents.
Chapter 7. SQLJ
161
This opens the wizard for creating a new server and server configuration. Enter a name for the server, and select WebSphere version 5.1 Test Environment in the server type list and click Finish (Figure 7-9). The new server shows up in the Server Configuration window.
To open the server configuration editor, double-click the server name in the Server Configuration window. In this editor, we create and maintain datasources.
162
Chapter 7. SQLJ
163
To use the Universal Driver we need three jar-files to be in the class path: db2jcc.jar, db2jcc_license_cu.jar, and db2jcc_license_cisuz.jar. The first file contains the driver, while the other two are licence files. When only access to DB2 for z/OS is required, it is sufficient to include db2jcc_license_cisuz.jar. Enter a name for the JDBC provider, T4nonXA, and make sure the class path is correct. Then select Finish (Figure 7-12 on page 165). The new JDBC provider now shows up in the list.
164
Select the new JDBC provider, and click the Add button next to the datasource list. Select DB2 Universal JDBC Driver Provider in the list, and select the radio button labeled Version 5.0 data source, and click Next. This bring us to the window shown in Figure 7-13 on page 166.
Chapter 7. SQLJ
165
Fill in the window as shown above. Specify ITSO1 as the datasource name and jdbc/ITSO1 as the JNDI name. Also make sure to select the proper Data source helper class name. As we plan to use CMP Beans, make sure to check the Use this data source in container-managed persistence (CMP) box. Click Next. This takes us to Figure 7-14 on page 167.
166
Here we need to specify a number of Resource Properties to make the data source work properly. You must at least specify the following properties: databaseName driverType serverName portNumber EnableSQLJ Click Finish. This concludes the datasource setup. Note that in Figure 7-13 on page 166 we also specified a component-managed and container-managed authentication alias (BARTR4). This concludes the server (and data source) setup. Our DB2 location name, for example, DBD8. Since this is a type 4 connection, the driverType must be 4. Our hostname where DBD8 resides, wtsc54.itso.ibm.com. The portnumber DBD8 is listening on, 38070. As we are using SQLJ, make sure to specify True.
167
SQLJSource as the new folder name, and click OK. Click OK again, and answer Yes to the confirm dialog that is displayed next. This brings us back to the screen in Figure 7-15. Click Finish.
168
We only fill in the URL and the options, leaving the User and Password fields empty. The URL is the URL to the database to which the SQLJ is to be bound (jdbc:db2://wtsc54.itso.ibm.com:38070/DBD8). In the Options field we specify the options to the bind process, for instance, the DB2 collection name that will contain the bound packages. This is done by entering the -COLLECTION <collectioname> parameter. If we are using unqualified SQL statements, we can specify the qualifier used by entering -QUALIFIER ITSOUSER. Note: In DB2 Version 7, the options specified are case sensitive (-COLLECTION). They have to be in upper case. In DB2 Version 8, the option keywords are not case sensitive.
The SQLJ editor is now open, and we can enter our SQLJ code. In this example, we just create a very simple SQLJ file with a context definition and one SQLJ statement, as shown in Example 7-12 on page 170. Save the SQLJ source (File Save).
Chapter 7. SQLJ
169
Example 7-12 Simple SQLJ source file package itso.sqljtest; import java.sql.*; import sqlj.runtime.ref.*; public class Test { #sql public static context MyContext with (dataSource=jdbc/ITSO1); public String select( String empno) throws SQLException { MyContext ctx = new MyContext(); String lastname = null; #sql [ctx] { SELECT LASTNAME INTO :lastname FROM EMP WHERE EMPNO = :empno}; return lastname; } }
170
The SQLJ source file we created (Test.sqlj) is located in the SQLJ Source directory. Every time we save this file, WSAD invokes the translator and creates a new java file (Test.java) and a new profile file (Test_SJProfile0.ser). As the .ser file is generated each time we save the SQLJ source file, the timestamp in the .ser file is updated each time as well. This means that we need to bind again every time we save the SQLJ source file, if we want the SQL to run as static SQL all the time. Two files are created in the SQLAntScripts directory. The properties file contains information about the database, the target collection, and the mapping between each profile (.ser file), and the root package name for the profile. The XML file contains the Ant script itself. The information in the properties file can be edited through the dialog where we specify the SQLJ customization script options; see Figure 7-16 on page 169. The content of the file is shown in Example 7-13.
Example 7-13 The sqlj.project.properties file #Tue Mar 09 16:58:18 PST 2004 db.options=-COLLECTION SQLTEST db.url=jdbc\:db2\://wtsc54.itso.ibm.com\:38070/DBD8 pkg.root.itso.sqljtest.Test_SJProfile0=Test_S0
The Ant script file is updated each time we generate the script, which is step 4 above. The content of the file is shown in Example 7-14. We do not get into details about the content of the Ant script. It is a completely auto-generated file, and it works.
Example 7-14 The Ant script used to bind the packages <project name="Profile sqlj.customize.xml" default="customizeAll" basedir="."> <property file="sqlj.project.properties"/> <property environment="env"/> <property name="cp" value="${env.CLASSPATH}"/> <target name="customizeAll" depends=" itso.sqljtest.Test" > <property name="customizeAll" value="true"/> </target> <!-- You must ensure the rootpkgname for each profile does not --> <!-- conflict with an existing package in the database. --> <target name="itso.sqljtest.Test" unless="customizeAll" > <java fork="true" failonerror="true" classname="com.ibm.db2.jcc.sqlj.Customizer" classpath="${cp};;..\bin"> <arg value="-url"/><arg value="${db.url}"/>
Chapter 7. SQLJ
171
<arg value="-user"/><arg value="${db.user}"/> <arg value="-password"/><arg value="${db.password}"/> <arg value="-rootpkgname"/><arg value="${pkg.root.itso.sqljtest.Test_SJProfile0}"/> <arg line="${db.options}"/> <arg value="-path"/><arg value="..\SQLJJavaSource"/> <arg value="itso\sqljtest\Test_SJProfile0.ser"/> </java> <copy file="..\SQLJJavaSource\itso\sqljtest\Test_SJProfile0.ser" todir="..\bin\itso\sqljtest" /> </target> </project>
Note: If we compare the above structure with the one from Figure 7-18, we notice that the generated files are located in the same directory. This is because we did not define a special folder for the source files.
172
With user-managed persistence, we have to consider two scenarios to manage transactions: One scenario where we use container-managed transactions, and the other scenario where we write our own code for transaction handling. Container-managed transactions are covered by the examples with the session Bean and the BMP entity Bean. The servlet example covers how to write our own code for the transaction handling. Let us have a look at the code in the three aforementioned files. There is one Java file and two SQLJ source files. The SQLJ statements in the two SQLJ source files are identical, but we need two different files, because we have to handle the connection differently. The Java file contains common information and behavior for the two SQLJ source files. The SQLJ statements are kept in both SQLJ source files for clarity. In the SQLJ code we want access to the information in the DBAEmployee class. One way of doing this is to use inheritance. We want the Java classes generated from the SQLJ files to inherit from (the same as extend from) the DBAEmployee class. DBAEmployee is called the super class of any classes that extend from it (Figure 7-20).
DBAEmployeeEJB.sqlj
Figure 7-20 SQLJ files and Java inheritance
DBAEmployeeServlet.sqlj
DBAEmployee.java
In our scenario we use the class empl.Employee as data transfer object (DTO) for the employee, which is located in another Java package, so we need to have an import statement. This statement tells the JVM where to find the class. The common information in DBAEmployee.java for the two SQLJ files (DBAEmployeeEJB.sqlj and DBAEmployeeServlet.sqlj) is the following: The datasource As we are connecting to the same datasource from both SQLJ source files, we put the name of the datasource in this class. Host variables SQLJ works with host variables. These host variables must be declared locally, and are of course identical for both SQLJ source files, as they relate to the attributes of the employee table. The type of the host variables must match the columns data type in DB2. See Chapter 4 of DB2 Universal Database for z/OS Version 8 Application Programming Guide and Reference FOR JAVATM , SC18-7414, for a list of mappings between Java data types and DB2 data types. Utility methods
Chapter 7. SQLJ
173
Two utility methods are supplied. These methods copy data between the host variables and an employee object. employee2hostvars will copy the fields from the employee object to the host variables, while hostvars2employee will copy the host variables to the employee object. The entire source of DBAEmployee.java is listed in Example 7-15.
Example 7-15 DBAEmployee.java file package itso.sqlj; // The Data Transfer Object, representing an employee import empl.Employee; public abstract class DBAEmployee { /* ** The JNDI name of the datasource. jdbc/ITSO1 must be defined as a datasource in ** the Websphere Application Server */ protected static String DATASOURCE = "jdbc/ITSO1"; /* ** Host variables, used in the SQLJ statements */ protected String empno = null; protected String firstnme = null; protected String lastname = null; protected String workdept = null; protected String phoneno = null; protected String job = null; protected String sex = null; protected java.sql.Date birthdate = null; protected String midinit = null; protected java.sql.Date hiredate = null; protected short edlevel = 0; protected java.math.BigDecimal salary = null; protected java.math.BigDecimal bonus = null; protected java.math.BigDecimal comm = null; /* ** Copy the values of host variables to the employee object passed to the method. */ protected void hostvars2employee( Employee employee) { employee.empno = empno; employee.firstnme = firstnme; employee.lastname = lastname; employee.workdept = workdept; employee.phoneno = phoneno; employee.job = job; employee.sex = sex; employee.birthdate = birthdate; employee.midinit = midinit; employee.hiredate = hiredate; employee.edlevel = edlevel; employee.salary = salary; employee.bonus = bonus; employee.comm = comm; }
174
/* ** Copy data from the employee, passed to the method, to the host variables */ protected void employee2hostvars( Employee employee) { empno = employee.empno; firstnme = employee.firstnme; lastname = employee.lastname; workdept = employee.workdept; phoneno = employee.phoneno; job = employee.job; sex = employee.sex; birthdate = employee.birthdate; midinit = employee.midinit; hiredate = employee.hiredate; edlevel = employee.edlevel; salary = employee.salary; bonus = employee.bonus; comm = employee.comm; } }
DBAEmployeeServlet.sqlj
We create the DBAEmployeeServlet.sqlj file as described in Step 3: Create the SQLJ source file on page 169. The important issue in this file is the way we create and handle the connection context. The program is shown in Example 7-16. In this example we explicitly retrieve a connection from the datasource and create the connection context with that connection. This is the old fashioned way to create the connection context.
Example 7-16 DBAEmployeeServlet.sqlj file package itso.sqlj; import import import import import java.sql.*; javax.naming.*; javax.sql.*; sqlj.runtime.ref.*; empl.Employee;
// #1 public class DBAEmployeeServlet extends DBAEmployee { // #2 #sql static context SqlContextNonUniversalDriver; // #3 private SqlContextNonUniversalDriver ivMyCtx = null; // #4 public DBAEmployeeServlet() throws SQLException, NamingException { Context ctx = new InitialContext(); DataSource ds = (DataSource) ctx.lookup(DATASOURCE); Connection conn = ds.getConnection(); conn.setAutoCommit(false); ivMyCtx = new SqlContextNonUniversalDriver(conn); }
Chapter 7. SQLJ
175
// #5a public void create(Employee employee) throws SQLException, NamingException { employee2hostvars(employee); #sql [ivMyCtx] { INSERT INTO EMP VALUES ( :empno, :firstnme, :midinit, :lastname, :workdept, :phoneno, :hiredate, :job, :edlevel, :sex, :birthdate, :salary, :bonus, :comm ) }; } // #5b public Employee findByPrimaryKey(String key) throws SQLException, NamingException { #sql [ivMyCtx] { SELECT EMPNO, FIRSTNME, MIDINIT, LASTNAME, WORKDEPT, PHONENO, HIREDATE, JOB, EDLEVEL, SEX, BIRTHDATE, SALARY, BONUS, COMM INTO :empno, :firstnme, :midinit, :lastname, :workdept, :phoneno, :hiredate, :job, :edlevel, :sex, :birthdate, :salary, :bonus, :comm FROM EMP WHERE EMPNO = :key }; // Create an Employee object Employee employee = new Employee(); hostvars2employee(employee); return employee; } // #6a public void commit() throws SQLException { #sql [ivMyCtx]{ COMMIT }; ivMyCtx.close(); } // #6b public void rollback() throws SQLException { #sql [ivMyCtx]{ ROLLBACK }; ivMyCtx.close(); } }
The steps are: 1. When we create a new SQLJ file by using the wizard, as shown in Figure 7-17 on page 169, we do not have the possibility to specify a super class. This has to be done manually by adding extends DBAEmployee to the class definition. 2. This line defines the connection context suitable for all drivers. When processed by the SQLJ preprocessor, this line will create an inner Java class called SqlContextNonUniversalDriver. This generated class is the connection context class that wraps the DB2 connection. 176
DB2 for z/OS and WebSphere: The Perfect Couple
Note: The name SqlContextNonUniversalDriver does not indicate that the Universal Driver cannot use this construct. It only indicates that this was the only way to set up a connection context prior to the Universal Driver. Using the Universal Driver provided, an additional way to set up a connection context is available, as shown in Example 7-17. 3. We need an instance of the connection context class defined in the previous step. This instance is on the class level, as we want to use the same connection until we either call commit or roll back. 4. We create the instance of the connection context class in the constructor of the class. To create the connection we first do a lookup of the datasource by calling JNDI. When we have the datasource, we get a connection from it, and create the connection context class with the received connection. Notice that we call setAutoCommit(false) on the connection object to avoid it from committing every time we are issuing an SQL statement. 5. The create method and the findByPrimaryKey method are using the connection in the same way. It is simply used between the brackets, telling the preprocessor to use that particular connection context when it creates the Java code. We do not close the context. 6. When we want to commit our SQL statements we call commit. That will execute an SQL COMMIT and then close the connection context. The same applies for rollback. Note: In this example we are saving the connection context inside the class. This means that all SQL statements we want to execute in the same unit of work have to be defined in the class. If we have SQL statements in different classes, and we want to execute the statements in the same unit of work, we would create the connection context outside the class, and pass it as a parameter to each method.
DBAEmployeeEJB.sqlj
We create the DBAEmployeeEJB.sqlj file as described in Step 3: Create the SQLJ source file on page 169. This SQLJ file is created with the requirement that it is used within a transaction. Furthermore, we create the connection context in an easier way, without doing a look up of the datasource. This way of creating the connection context is much simpler, but is only supported by the Universal Driver. The program is shown in Example 7-17.
Example 7-17 DBAEmployeeEJB.sqlj file package itso.sqlj; import import import import import // #1 public java.sql.*; javax.naming.*; javax.sql.*; sqlj.runtime.ref.*; empl.Employee; class DBAEmployeeEJB extends DBAEmployee {
// #2 #sql public static context SqlContextUniversalDriver with (dataSource="jdbc/ITSO1"); // #3 public DBAEmployeeEJB() throws SQLException { } // 4a public void delete( String key) throws SQLException {
Chapter 7. SQLJ
177
SqlContextUniversalDriver myCtx = new SqlContextUniversalDriver(); // SQLJ Statement #sql [myCtx] { DELETE FROM ITSOUSER.EMP WHERE EMPNO = :key }; // Hand over the connection to Websphere, that will close it when needed myCtx.close(); } // 4b public void update( Employee employee) throws SQLException { SqlContextUniversalDriver myCtx = new SqlContextUniversalDriver(); employee2hostvars( employee); // SQLJ Statement #sql [myCtx] { UPDATE ITSOUSER.EMP SET FIRSTNME = :firstnme, MIDINIT = :midinit, LASTNAME = :lastname, WORKDEPT = :workdept, PHONENO = :phoneno, HIREDATE = :hiredate, JOB = :job, EDLEVEL = :edlevel, SEX = :sex, BIRTHDATE = :birthdate, SALARY = :salary, BONUS = :bonus, COMM = :comm WHERE EMPNO = :empno }; // Hand over the connection to Websphere, that will close it when needed myCtx.close(); } // 4c public void create( Employee employee) throws SQLException, NamingException { SqlContextUniversalDriver myCtx = new SqlContextUniversalDriver(); employee2hostvars( employee); #sql [myCtx] { INSERT INTO ITSOUSER.EMP VALUES ( :empno, :firstnme, :midinit, :lastname, :workdept, :phoneno, :hiredate, :job, :edlevel, :sex, :birthdate, :salary, :bonus, :comm ) }; // Hand over the connection to Websphere, that will close it when needed myCtx.close(); }
178
// 4d public Employee findByPrimaryKey( String key) throws SQLException, NamingException { SqlContextUniversalDriver myCtx = new SqlContextUniversalDriver(); // SQLJ Statement #sql [myCtx] { SELECT EMPNO, FIRSTNME, MIDINIT, LASTNAME, WORKDEPT, PHONENO, HIREDATE, JOB, EDLEVEL, SEX, BIRTHDATE, SALARY, BONUS, COMM INTO :empno, :firstnme, :midinit, :lastname, :workdept, :phoneno, :hiredate, :job, :edlevel, :sex, :birthdate, :salary, :bonus, :comm FROM ITSOUSER.EMP WHERE EMPNO = :key }; // Hand over the connection to Websphere, that will close it when needed myCtx.close(); // Create an Employee object Employee employee = new Employee(); hostvars2employee( employee); return employee; } }
The steps are: 1. As with DBAEmployeeServlet, we want to extend the Java class DBAEmployee, which we must do manually by adding extend DBAEmployee to the class definition. 2. We create the connection context by directly specifying the datasource, which is only supported by the Universal Driver. 3. We do not do anything in the constructor of the class. Note that we do not have a connection context at the class level to instantiate. 4. In every method where we are executing SQL, we do the same three things. First we create a connection context, then we execute the SQL, and finally we close the connection context. When we create the connection context, the transaction manager will ensure that we always use the same connection within the same transaction. When we close the connection context, we are not closing the underlying connection, we just tell the transaction manager that we are done with the connection, that is, to set the connection in a valid state for commit. Note: We do not need the commit and rollback methods anymore; this is left to the transaction manager.
Servlet
In the Web container, where servlets are executed, we are not in the scope of any transaction. When it comes to handle a connection to DB2, we have two possibilities. Either we create a user transaction and execute our statements within the boundaries of this user transaction, or we can operate on the connection itself, by calling commit and rollback.
Chapter 7. SQLJ
179
Attention: Even though we are giving the examples here, remember that accessing SQLJ directly from the servlet is not a best practice. See 7.3.1, Best practice on page 150. In the examples in this section, we call the method getEmployeeFromRequest. This method will extract information about an employee from the HttpServletRequest object, and return an instance of the data transfer object empl.Employee with the employee information from the request. The method is shown in Example 7-18. In the examples, we do not go into details about exception handling. We simply catch and throw exceptions to illustrate where things can go wrong, and how to get on. Exception handling usually differs from application to application, but it is very important to have good coding guidelines for the exception handling process.
Example 7-18 Create a data transfer object based on information in the request private Employee getEmployeeFromRequest( HttpServletRequest req) throws Exception { // Create an employee instance Employee employee = new Employee(); // Fill in information from the request employee.empno = (String) req.getParameter("EMPNO"); employee.firstnme = (String) req.getParameter("FIRSTNME"); ... employee.bonus = new BigDecimal( (String) req.getParameter("BONUS")); employee.comm = new BigDecimal( (String) req.getParameter("COMM")); // return the employee instance return employee; }
180
The Steps are: 1. First of all we create an instance of the Employee data transfer object with information taken from the request. 2. Then we create an instance of the class DBEmployeeServlet. In the constructor of this class the connection is created. 3. Then we invoke the create method passing the employee object as the parameter. 4. If the call to DB2 succeeds, no error will be thrown and we call commit on the dbaEmployee object. 5. If the call to DB2 failed, an exception is thrown. As we need to roll back the connection, we must catch the exception and call rollback on the dbaEmployee object.
The steps are: 1. As before, we get an employee from the request. 2. Then we get a UserTransation object, by a lookup in JNDI. The UserTransaction is the interface used to handle the boundaries of a transaction manually. WAS comes with a built-in Transaction Manager that handles the transaction issues in the EJB container. Based on information in the deployment descriptors for the enterprise Beans, the Transaction Manager automatically creates or reuses a transaction. To give us the possibility to get full control of the transaction boundaries, we can obtain an instance of a UserTransaction object, which is the programmers hook into the
Chapter 7. SQLJ
181
Transaction Manager. This is useful if we, for instance, want to extend the transaction boundaries to the Web container. 3. The we start the scope of the transaction. 4. Then we create an instance of the DBAEmployeeServlet class and invoke the create method passing the employee object as the parameter. 5. If the call to DB2 was successful we commit the transaction. 6. If the call to DB2 failed then we roll back the transaction.
Session Bean
In this example we show how to call SQLJ from a session Bean. We now use the DBAEmployeeEJB utility class. We do not have to care about either the connection or the transaction. The method on the session Bean is invoked within the boundary of a transaction, and we only have to obey the EJB container rules for exception handling. A code snippet is shown in Example 7-21. The method createEmployee is a method on the session Bean that is accessed through the remote interface.
Example 7-21 Calling SQLJ from a session Bean public void createEmployee(Employee employee) throws EJBException { try { // #1 DBAEmployeeEJB dbaEmployee = new DBAEmployeeEJB(); // #2 dbaEmployee.create(employee); } catch (Exception se) { // #3 throw new EJBException(se); } }
The steps are: 1. First of all we create an instance of the DBAEmployeeEJB utility class. 2. Then we invoke the create method passing the employee object as the parameter. 3. If the call to DB2 would fail, we catch the exception and throw an EJBException. Throwing the EJBException will tell the container to roll back the transaction. The big difference between the above example and the example with the servlet is that we do not have to worry about any connection or transaction. This makes the code much easier to read, more simple, and more reliable.
182
DBAEmployeeEJB dbaEmployee = new DBAEmployeeEJB(); dbaEmployee.create( employee); } catch ( Exception se) { throw new CreateException(); } }
The only difference with the session Bean example is that we throw a CreateException and not an EJBException. The reason for this is that creating an entity Bean is a part of the Beans life-cycle methods, and they are only called by the container. These methods are not accessible from the client. On the Beans home interface there will be a create method that takes an Employee object as a parameter. When a client, usually a session Bean, is calling this method, the container will call the ejbCreate method. There are special rules for these call back methods, for instance, that the ejbCreate method must throw a CreateException. See EJB 2.0 Development with WebSphere Studio Application Developer, SG24-6819, for a detailed description of how to manage the lifecycle of an entity Bean with Bean-managed persistence.
CMP mapping
The mapping between the enterprise Beans and the DB2 tables is stored in a file called map.mapxmi. The information in this file supplies the deployment tool with information on how to do the mapping between the enterprise Beans and the database. One piece of information in the file is whether to use SQLJ. The map itself associates fields in the enterprise Beans with table columns. This map can be obtained in three different ways, which are called mapping strategies: Top down This approach is also known as forward engineering. Based on existing entity Beans, new tables are created. This is the easiest way to create the mapping when no legacy (existing) database is involved. The limitation is that we are not in charge of the database design. Bottom up This approach is also known as reverse engineering. Based on existing tables, new entity Beans are automatically created for you. The limitation is that we do not design the Beans ourselves, so they may not match our business needs. Meet in the middle This approach is the compromise of the other two approaches, and is the most flexible one. Based on existing tables and existing entity Beans we create the mapping manually.
Chapter 7. SQLJ
183
We do not have any of the limitations imposed by the other approaches, but the maintenance of the mapping is more cumbersome. Figure 7-21 summarizes the three approaches.
Top-Down
Bottom-Up
Define
Generated
Generated
Generated
Manual
Generated
Imported
Imported
DB2
Create
Existing
Existing
Which of the three approaches to use depends on the situation. If the database already exists, we will either use the bottom-up or the meet-in-the-middle approach, depending on how close the database design is to the business model we want for our Beans. Important: We have to be careful with the top-down approach, as the physical database might end up being a nice design, but with extremely poor performance. Especially in applications with a large number of online transactions, there can be a big difference between the logical and the physical database design. Always have a DBA check the database design.
Next time we generate deployment code the .ser file is created in the Websphere_deploy folder that is associated with the DB2 back-end.
Chapter 7. SQLJ
185
EBJ QL looks very much like traditional SQL. A query consists of a SELECT clause, a FROM clause, and an optional WHERE clause. The SELECT clause must always return a single value. This value can either be a field of an entity Bean or an object reference.
SELECT e.lastname FROM Emp AS e WHERE e.empno = ?1 SELECT Object(e) FROM Emp e WHERE e.lastname like ?1
The first statement returns a collection of the CMP field lastname (a collection of String objects), while the second statement returns a collection of Emp instances. Note that the AS keyword in the first example is optional; it is used for clarity only. Note: Even though EJB QL looks like ordinary SQL, it is a new typed expression language. A EJB QL expression is a query based on objects and return objects; it never returns a row from DB2. The EJB QL statements are mapped to methods of our entity Beans through the deployment descriptor. Example 7-23 is part of the deployment descriptor from our sample application. It maps the EJB QL statement with the method findByLastName(String lastname) to the Employee entity Bean.
Example 7-23 EJB QL example from our sample application <entity id="ContainerManagedEntity_1076532486891"> <ejb-name>Employee</ejb-name> .......... <query> <description>EJBQL query for employees in 1 department</description> <query-method> <method-name>findByLastName</method-name> <method-params> <method-param>java.lang.String</method-param> </method-params> </query-method> <ejb-ql>SELECT OBJECT(e) FROM Emp e WHERE e.lastname like ?1</ejb-ql> </query>
186
</entity>
WebSphere extensions
WebSphere Application Server provides extensions to EJB QL to make it more specific and flexible. These extensions include subqueries, ORDER BY and HAVING clauses, and expressions with SQL date and time formats. Note that these extensions are vendor-specific. If we choose to use them, we might not be able to deploy our Beans in another EJB 2.0 compliant container. A comprehensive walkthrough of the EJB QL and WebSphere extensions can be found in EJB 2.0 Development with WebSphere Studio Application Developer, SG24-6819. Tip: EJB QL is a relatively new specification and is evolving constantly. As EJB QL uses the same syntax as SQL, more and more of the reserved words in SQL will also become reserved words in EJB QL. It is therefore recommended that we do not use any reserved words from SQL in our EJB QL statements.
7.4.6 Customization
An important task when using SQLJ is the customization and bind process. This is the step where the DB2 packages are created and bound to DB2, making our SQL statements execute as static SQL. As long as the packages are not bound to DB2, our SQL statements will run as dynamic SQL. The customizer will automatically (by default) bind the packages against the database. This means that once the profiles have been customized against DB2, we must have a matching package bound in the database. If not, an SQLException is thrown, indicating a package not found exception. The customization process adds DBMS-specific information to the serialized profile. In case of DB2, this information includes the package name, a timestamp indicating when the customization took place, and a consistency token used to ensure that the database package matches the profile. When using the Universal Driver, the profiles remain platform independent after customization, because SQLJ implementations are required to ignore customization information they do not know about. All DB2 implementations across the DB2 family use the same customization. We do not have to customize again when switching from a DB2 for Linux, Unix, and Windows to DB2 for z/OS and OS/390 when using the DB2 Universal Driver.
Isolation levels
SQLJ allows you to change the isolation level at the beginning of a new transaction, using the SET TRANSACTION ISOLATION LEVEL clause. However, each package in DB2 is created to use a specific isolation level. Therefore, the profile customizer, by default, creates four packages, one for each isolation level. The names of these packages consist of the root package name and a suffix of 1 through 4, corresponding to the isolation levels UR, CS, RS, and RR respectively. Since a package name in DB2 can be up to eight characters long, the root name must not exceed seven characters. In our sample scenarios, we use the root name CPHEMP, resulting in these four packages: CPHEMP1 - For isolation level UR (uncommitted read) CPHEMP2 - For isolation level CS (cursor stability) CPHEMP3 - For isolation level RS (read stability) CPHEMP4 - For isolation level RR (repeatable read)
Chapter 7. SQLJ
187
If we only want to enable one of the packages, we can either free the packages for the unwanted isolation levels, or we can tell the profile customizer to create the required package only for a specific isolation level. We do this by specifying this bind option:
-singlepkgname pkgname -bindoptions isolation isolation level
Where isolation level is the isolation level we want the package to use, and we must use the DB2 syntax (UR, CS, RS, RR), not the JDBC notation (1, 2, 3, 4). In WSAD, we must specify this in SQLJ customization script dialog along with the package name, as shown in Figure 7-16 on page 169.
Online checking
By default, the profile customizer runs with online checking enabled if we have entered a value in the URL field in the SQLJ customization script dialog; see Figure 7-16 on page 169. When online checking is enabled, the SQLJ customizer queries the DB2 catalog on the target database server to verify whether our SQLJ statements will be able to run on that server. This is a great benefit, as we have all our SQL statements validated on bind time, and not at run time. Online checking will recognize errors or potential problems such as: Misspelled names (table names, view names, column names, and so on) Lack of authorization (for example, an INSERT statement on a table for which the package owner lacks permission) Data type mismatches (for example, if we are trying to update a numeric column with a string value) Another important feature of the online checking is that it will help the DB2 optimizer to find the best access path. If online checking is disabled, the optimizer might find a poor access path due to lack of information.
188
Unfortunately, at the time of writing there was no FixPak for WSAD that solved the problem. However, FixPak 5.1.0.1 for WAS solves the problem, and this FixPak can be applied manually to the WAS V5.1 installed under WSAD.
Enter Application Server + 5.1.0.1 in the entry field, and select -Updates (code fixes) in the combo box. Then submit the search. The result of the search will not be unique, but gives you a limited number of items. The correct FixPak is named WebSphere Application Server 5.1 Cumulative Fix 1. Select the package and scroll down to the table with the downloadable packages. Click the item named Windows - Base and follow the download instructions. The downloaded file is named was510_cf1_win.zip, which must be unzipped before the FixPak can be installed. Important: Do not unzip the FixPak with pkUnzip, as this might destroy the image. Use WinZip instead.
Chapter 7. SQLJ
189
The thing to remember is to do the profile customization. Without this, the SQLJ will run as dynamic SQL. The profile customization can even be executed from within WSAD using the Ant script that WSAD creates. This is described in Step 4: Generate the customization script on page 170. We use the following customization options:
-COLLECTION SG246319 -QUALIFIER ITSOUSER -BINDOPTIONS "OWNER(ITSOUSER)"
The entire deployment process is described in 11.6, Deployment of the EAR file on page 307.
7.6 Summary
With WebSphere Studio Application Developer now fully supporting the development of applications using SQLJ, it is very simple to use static SQL in our applications instead of ordinary JDBC. Especially if we are using Enterprise JavaBeans with container-managed persistence, the use of SQLJ is very easy. The only extra work is the profile customization, which is a very small price to pay for the benefits obtained by using SQLJ.
190
Chapter 8.
191
Two-phase commit
In a two-phase commit transaction, one agent acts as the transaction manager (or coordinator) and all other agents are known as resource managers or participants. Within the
192
transaction, resources are enlisted in the transaction by the transaction coordinator as they are referenced. Enlistment allows the transaction manager to maintain a list of all resources participating in the unit of work and allows all the participants to share a common token to identify the transaction for all parties. While application work is occurring within the transaction, if a resource encounters a failure, a notification is sent to the coordinator and the coordinator instructs all the participants to roll back. If the transaction manager fails, the resource managers recognize that a communication failure occurred and immediately roll back the transaction. Once application work at all of the resources is complete, the process for committing the actions works in two phases. Depicted in Figure 8-1, the transaction manager sends a prepare to all of the participants indicating that there will be no additional work in the transaction. The resource (managers) hardens all changes and acknowledges the prepare request. Once the resource hardens its changes, the resource manager considers the transaction in doubt since the resource only knows its own state and has not been informed of the other resources state by the transaction coordinator.
If the transaction manager does not receive a successful prepare acknowledgement from all of the resources, the transaction manager instructs all of the resource managers to roll back. If the transaction manager receives successful acknowledgement, all resources are then instructed to commit the unit of work. The commit instructions inform the resources that all of the resources in the process have now agreed to commit and that each resource should log the final commit and the transaction will no longer be considered in doubt. Once all of the resources acknowledge the commit, the transactions manager logs a forget record for the transaction to indicate that no further action or processing is required for the transaction. If a failure of a resource or transaction manager occurs while the transaction is considered in doubt by any of the resources, the resources must maintain integrity until communication with the transaction manager is re-established and the transaction outcome can be determined. This implies that resources, such as locks acquired during the transaction and are held until commit, must continue to be held until the final transaction outcome can be determined.
193
Manual action can also instruct resource managers to commit or roll back a transaction without re-establishing communication with the transaction manager. This is known as a heuristic decision. Although not required, in some cases a transaction coordinator can also be a resource manager.
deployment descriptors. A deployment descriptor defines whether the Bean will be BMT or
CMT, as shown in Figure 8-2 on page 195. To access the deployment descriptor, use the EJB perspective and double-click the EJB deployment descriptor within the EJB project. Once the deployment descriptor has been opened, either click the Bean name from the Overview tab, or click the Bean tab located at the bottom of the EJB deployment descriptor window.
194
Transaction demarcation is independent of actions performed against resources within the transaction. Applications should not attempt to commit or roll back individual resources within a transaction context; instead, implicit action for CMTs or explicit UserTransaction methods for BMTs should start and end transactions. Performing actions such as getConnection or con.close do not affect the transaction. Important: Within an EJB transaction, do not attempt to issue transaction controls to individual resources. All transaction demarcation should occur independently of the resources involved within the transaction. You can close or open a connection multiple times within a transaction and not affect the transaction or its atomicity.
195
Attention: Bean-managed transactions (BMT) should not use the setRollbackOnly() method; instead they should explicitly roll back the UserTransaction and call the rollback() method. It is important to differentiate between transaction demarcation and access to resources. If a call to a method does not need to manage the beginning or the end of the transaction, the method does not need to instantiate a UserTransaction object. Applications should only instantiate the UserTransaction object if specific action is required in order to begin or end the transaction. For example, a transaction session Bean could call many methods that write to a database or send JMS messages without the need to reference or manage the transaction. As a result, classes and methods developed for use within a Bean-managed transaction should be relatively easy to port to an EJB with Container Managed Transactions (CMT). It is a good idea not to mix the management of the transaction with access to resources (including exception management). Instead, isolate the resource access and the use of the UserTransaction interface.
Once the entire Bean or the Bean methods have been selected, a user can choose the transaction type, as shown in Figure 8-4 on page 197.
196
The transaction types are defined as follows: Supports If a client calls the method with a transaction context, the transaction context is used. If the client calls without a context, the Bean behaves in the same manner as Not Supported. If a client calls the method with a transaction context, the transaction context is used. If the client calls without a transaction context, a new transaction context is created. If a client calls with a transaction context, the current context is suspended and a new transaction context is created. The new transaction context is used for the execution of the Bean. At completion, the transaction context is ended and the original transaction context is resumed. If the client calls without a context a new context is created. The client must call with a transaction context. Failure to do so throws a TransactionRequiredException. The client must call without a transaction context. Failure to do so results in an exception being thrown. If a client calls with a transaction context, the context is suspended and the method is executed without a transaction context. Once the method completes, the original transaction context is resumed. If the client calls without a context, the method is invoked without a context.
Required
RequiresNew
If you do not explicitly choose a transaction type for the Bean or its methods, the default setting is Requires. For most applications there is no need to change the default. The bulk of applications use the Requires option to ensure that two-phase commit coordination can be supported.
197
EJBContext setRollbackOnly()
Container-managed transactions do not have the ability to explicitly commit or roll back a transaction. If an application encounters an error while working with a resource and wants to throw an exception, the container will not always automatically roll back the transaction. As a result, it is important that applications have the ability to explicitly set a flag to prevent the transaction from committing. The method setRollbackOnly() on the EJBContext allows an application to prevent the container from committing the transaction, which ultimately forces a roll back.
198
199
Which JDBC provider to exploit depends on whether an application requires two-phase commit support and what type of JDBC driver will be used.
200
201
Driver provider
driverType property
4 4
202
The figure shows multiple approaches to reaching the remote locations sanjose and dallas from a WebSphere application. The WebSphere datasource databaseName can reference either a target location where application data resides or it can reference the location name of the gateway subsystem, newyork. If the target location is used, tables residing at the location can be referenced with two-part names and tables at other locations can be referenced with three-part names. Alternatively, the first contact machine can be referenced in the datasource and three-part names used to reference tables at other locations. Tip: When using DB2 as a transaction manager, the transaction manager subsystem is the location referenced in the WebSphere datasource. A three-part table name is a reference to a table within an SQL statements, which concatenates the location as the highest qualifier of the table reference. Three-part names have the form of location.qualifier.table, where the location is the subsystem where the table resides, as defined within the executing systems communications database (CDB). The qualifier is the owner or explicit qualifier or the table, and the table is the name of the table. Restriction: When executing on DB2 UDB for z/OS an application cannot reference more then one location within a single SQL statement.
203
Universal Database for z/OS Version 8 Administration Guide, SC18-7413, or Distributed Functions of DB2 for z/OS and OS/390, SG24-6952. To support all variations of the configuration, it is a good idea to bind the JDBC packages at the destination DB2 subsystems. Since the JDBC driver packages are versioned, multiple DB2 JDBC driver maintenance levels can be bound at the same server. At a minimum, the JDBC driver packages must be bound at each of the locations referenced within a DB2 datasource and the local or first contact subsystem must have the remote package bound into the local collection. To allow remote package execution, the local collection needs to include references to the remote subsystem packages. By default, JDBC executes within the NULLID collection. The NULLID collection should therefore include the packages at each of the locations. Refer to DB2 Universal Database for z/OS Version 8 Command Reference, SC18-7416, for information on binding packages at remote locations.
simply convert XA requests to DB2 UDB for z/OS Version 7 DRDA requests without an explicit new function to support XA at the DB2 server. To avoid impacting the V7 code stability by retrofitting XA support back into DB2 V7, a different approach was taken. To provide this support in Version 7, the state of a XA global transaction is stored in a facility that is available for DB2 at restart. For data sharing, every member of a data sharing group needs to be able to determine the status of any transaction regardless of which member processed the transaction. To provide a group-wide transaction tracking mechanism, V7 provides a new table, SYSIBM.INDOUBT, and a method to inform other members what the outcome of their in-doubt transactions should be, based upon instructions from the transaction manager. Due to DB2s data sharing implementation policy of reading, but not writing to other members logs, members cannot roll back or commit transactions on each others behalf. The SYSIBM.INDBOUT table in Version 7 is created by a utility program shipped with the XA-enabled type 4 JDBC driver. The utility, DB2T4XAIndoubtUtil, creates the table and defines a package that DB2 exploits to track transaction status in the table (via static SQL). These objects or packages should not be created, altered, or dropped without the use of the utility. Detailed instructions for the utility are provided in the DB2 Universal Database for z/OS Version 7 Application Programming Guide and Reference FOR JAVA, SC26-9932. As depicted in Figure 8-8, Version 8 replaces the SYSIBM.INDOUBT table with changes in the DRDA protocol flow to support the XA protocol, and by exploiting the Shared Communications Area (SCA) within the Coupling Facility (CF). The SCA provides cross-member coordination when operating in data sharing mode, which results in the entire group sharing transaction status information. This storage is exploited by DB2 to manage the list of global transactions and their state across members so that DB2 UDB for z/OS can be considered an available XA resource, even when all members of the group have not been restarted. The Version 7 solution requires inserts into a DB2 table to coordinate the transaction status for every transaction. When one member fails, it is very likely that the INDOUBT table will have retained locks (until the member is restarted). Those may prevent transactions running on other members from running. Version 8s exploitation of internal memory structures, specialized log records, and the SCA provides improved scalability. For high-volume two-phase commit XA global transactions, IBM strongly recommends that customers exploit DB2 UDB for z/OS Version 8. Figure 8-8 shows the two implementations of tracking global transaction (XID) status.
DB2 V7 WebSphere
XID in table SYSIBM. INDOUBT
DB2 V8
XID in CF Structure (SCA)
DB2 V7
Universal JDBC T4
DB2 V8
205
JavaBeans (EJBs) that reside on physically different servers. Each of those Beans can access a single DB2 server. This single unit of work spans multiple separate connections but logically behave as if they were the same thread. See Figure 8-9 for a depiction of how a single transaction can span multiple physical machines.
WebSphere WebSphere Application Server Application Server JDBC T4 JDBC T4 AIX AIX
WebSphere WebSphere Application Server Application Server JDBC T4 JDBC T4 AIX AIX
z/OS
In Version 7, DB2 introduced a feature known as global transaction support for JDBC applications via the datasource interface. This allows multiple threads to behave as the same transaction. When multiple JDBC connections are participating in a global transaction, all branches of the transaction are sharing locks. Uncommitted changes made by one branch are visible to every branch. When implementing a shared connection architecture such as above, consider the following restrictions: Parallel sysplex is not supported for global transactions. All agents must process against a single subsystem (a single member of a data sharing group) in order to share locks. Claim/drain processing is not supported for lock sharing. This implies that CREATE, DROP, ALTER, GRANT, and REVOKE may time out or deadlock between branches. In Version 7, updates to a partitioning key may also result in a deadlock or time out. An explicit LOCK TABLE may time out or deadlock between branches.
JDBC
z/OS
JDBC
206
For example, if the other resources within the transaction do not maintain locks, such as a Java Messaging Service (JMS) or WebSphere MQ Series, applications should exploit DB2 as the last resource enlisted in the transaction. If DB2 is the last resource accessed in the transaction, locks will be held for a shorter period of time, and potentially will not need to be held while work is being performed at other resources. Conversely, if DB2 is accessed first in the transaction, then locks will continue to be held while other resources are accessed. This can significantly reduce overall concurrency.
207
208
Chapter 9.
209
Lock mode
DB2 uses a hierarchy of locks where a single transaction may acquire locks at multiple levels and on multiple objects. The hierarchy differs based upon the table space type the table is created within. Most locking discussions focus on two levels, the first, or least granular being the table space lock (simple or segmented table spaces) or the partition lock (partitioned table space). A subordinate, more granular sized lock is a page (LOCKSIZE PAGE or ANY) or row level (LOCKSIZE ROW) lock. Segmented tables have a third intermediate level of locking, known as table level locks, which we will not discuss since table level locks are generally the result of lock escalatio,n which should be avoided, or an application requesting an explicit table lock. Both of these should not occur within a transactional application environment such as WebSphere. Tip: Table spaces accessed within an online transaction processing environment, such as WebSphere, should use LOCKSIZE ANY or LOCKSIZE ROW. LOCKSIZE TABLE or LOCKSIZE TABLESPACE should be avoided. Partition/table space level locks are most frequently used to show a transactions interest in a particular table while page/row level locks control the access to individual instances of data within the table.
page locks being acquired by a transaction. With row level locking, when applications access multiple rows that reside on a page, locks must be successively acquired for each row. Rows and pages have the following locks: S (Share) The lock owner and any concurrent process can read, but not change, the locked page or row. Concurrent processes can acquire S or U locks on the page or row or may read data without acquiring a page or row lock. The lock owner can read, but not change, the locked page or row. Concurrent processes can acquire S locks or might read data without acquiring a page or row lock, but no concurrent process can acquire a U lock. The lock owner can read or change the locked page or row. A concurrent process can access the data if the process runs with UR isolation.
U (Update)
X (Exclusive)
IX (Intent Exclusive)
Table 9-2 summarizes the compatibility of table space and partition lock modes.
Table 9-2 Lock mode compatibility for table space and partition locks Lock mode S U IS Yes Yes IX No No S Yes Yes U Yes No SIX No No X No No
211
IX Yes Yes No No
S Yes No No No
U Yes No No No
SIX Yes No No No
X No No No No
Isolation modes can be set in multiple fashions including a bind parameter, an explicit method call in JDBC, or within an SQL statement. More information regarding how to set isolation modes is in DB2 isolation determination in Java applications on page 213.
212
Table 9-3 Lock mode override SQL option USE AND KEEP EXCLUSIVE LOCKS USE AND KEEP UPDATE LOCKS USE AND KEEP SHARED LOCKS DB2 lock mode X U S
By using any of these options, you tell DB2 to acquire and hold a specific mode of lock on all the qualified pages or rows (stage 1 qualified when using RS). All locks are held until the application commits. Although this option can reduce concurrency, it can prevent some types of deadlocks and can better serialize access to data.
Connection con.setTransactionIsolation()
A method in JDBC, Connection con.setTransactionIsolation(xxx) allows an application or execution environment to set the transaction isolation for the connection. In SQLJ, the SET TRANSACTION ISOLATION LEVEL statement provides the same functionality. Since you can mix JDBC methods and SQLJ directives within an SQLJ application, both methods will work in an SQLJ application and will affect the isolation of the entire transaction regardless of whether the application switches between JDBC and SQLJ. Transaction isolation should only be set at the beginning of the transaction before any SQL is executed. Restriction: You can only set transaction isolation at the beginning of a transaction. Internally, DB2 manages the multiple isolation levels in a similar fashion to static applications. The JDBC driver uses packages that have been bound with different isolation levels for statements with a transaction isolation. DB2 implements each of the different isolation levels via four versions of JDBC driver packages, each version bound with a different isolation level. When a JDBC application changes the transaction isolation level, the driver is actually dynamically changing JDBC driver packages. Similarly, SQLJ preprocessing produces four versions of an application-specific SQLJ package, generated via the db2sqljcustomize utility. The isolation levels within DB2 do not directly correlate to the isolation levels in the JDBC specification and the isolation levels used in the interface to set the transaction environment. To map the two values, review Table 9-4 on page 214. When calling setTransactionIsolation(), applications specify the JDBC keyword to set the transaction isolation. Note that in a WebSphere environment (prior to WebSphere V5.1) this method is not directly accessible from the application, and should not be exploited (see 9.3.2, Entity Bean isolation level (access intent) on page 218).
213
Table 9-4 DB2 UDB for z/OS and JDBC/SQLJ isolation mapping DB2 UDB for z/OS UNCOMMITTED READ (UR) CURSOR STABILITY (CS) READ STABILITY (RS) REPEATABLE READ JDBC/SQLJ /WebSphere TRANSACTION _READ_UNCOMMITED TRANSACTION_READ_COMMITTED TRANSACTION_REPEATABLE_READ TRANSACTION_SERIALIZABLE
Restriction: WebSphere applications (prior to WebSphere V5.1) do not allow the programmatic exploitation of the setTransactionIsolation() method. This method is not promoted to the WebSphere-implemented connection interface. In order to set the transaction isolation level programatically, you must run WebSphere V5.1.
To maintain integrity and exploit isolation cursor stability (CS), applications must use a mechanism beyond the isolation level to ensure that other transactions do not have the opportunity to successfully update data between the time when the data is selected and the target data is updated. This can be accomplished by either using an update cursor or overqualified predicates on an update statement.
Update cursor
Update cursors are commonly used in non-Java applications to process a set of data returned by a query and take some action based upon that returned data. The cursor is used to parse through all of the qualifying rows of a query and update the rows if necessary. While fetching through a cursor, the current row (or page) on which the cursor is positioned is locked and other potential updaters are prevented from updating or deleting the row. While positioned on the row, only the application that is using the cursor can update the row. For example:
DECLARE CURSOR C1 FOR SELECT SALARY FROM EMP WHERE LASTNAME =LEE FOR UPDATE OF SALARY; OPEN CURSOR C1; FETCH FROM C1 INTO :SAL UPDATE EMP SET SALARY = 1000000 WHERE CURRENT OF C1;
In a JDBC application, the declaration and processing of a cursor occur with a different syntax, but the concept is basically the same. Instead of processing a cursor, a PreparedStatement is created and a ResultSet is used to process the results.
PreparedStatemnt p1 = new PreparedStatement(SELECT SALARY, FIRSTNME FROM EMP WHERE LASTNAME = ? FOR UPDATE, TYPE_FORWARD_ONLY, CONCUR_UPDATABL); ResultSet rs = p1.executeQuery(); String s1 = null; String s2 = null; while (rs.next()) { s1 = rs.getString(1); s2 = rs.getString(2); if (s2.compareTo(Sean) == 0) { rs.updateString(s1); rs.updateRow();}
As an alternative to using a cursor to guarantee that data has not changed after retrieving it, applications can use an update with additional predicates to ensure integrity. Two approaches are generally used for overqualified predicates, a timestamp, or full predication. For the timestamp approach, a (unique) timestamp column is required on the table, and the timestamp is read with every select, passed to the application with the data to be updated, and then used as a qualifying predicate in the WHERE clause of the update statement. If the update statement returns no rows updated, then the data has been updated since the data was originally selected, and the transaction must be restarted. In addition, update statements must set the timestamp column to the current timestamp (of the update). Frequently the timestamps are defined with default values of the current timestamp. It is worth noting that this method is not fully guaranteed to prevent other updates. It is highly unlikely, but feasible, for two threads to execute within a close enough time to update with the same current timestamp. In order to have unique value, you should use the GENERATE_UNIQUE function
Chapter 9. DB2 locking in a WebSphere environment
215
in DB2 for z/OS Version 8 (or a ROWID defined as GENERATED ALWAYS in earlier DB2 versions). The full predication approach selects all columns within the table and passes all values to the application until the update occurs. When the update occurs, all of the columns in the table are specified as predicates.
CURRENTDATA
CURRENTDATA is a DB2 bind option for ISOLATION(CS) applications, which helps to determine the currency of data returned in a cursor. The JDBC driver is bound with CURRENTDATA(YES) by default. Application developers frequently mistake this option as a mechanism for protecting against the singleton update case, or as a reason to use ambiguous cursors. An ambiguous cursor is a cursor with a select statement that does not express FOR READ ONLY or FOR UPDATE. The CURRENTDATA option has little impact on integrity for these cases. In some specific ISOLATION(CS) applications, if CURRENTDATA(NO) is specified, then DB2 will try not to take a lock, as a result of a DB2 locking optimization technique called lock avoidance. Unfortunately, for isolation CS applications, ambiguous cursors will not provide locks to protect integrity in cases when a work file is exploited. As a result, lock protection for ambiguous cursors are access path dependent. Access paths that exploit a work file cannot be defined as updatable. Application developers should use an additional cursor or overqualified predicates as logically close to the select as possible to reduce the timing window for intermediate updates by other applications. As a rule, regardless of the CURRENTDATA option, isolation CS applications should always express their intent within a cursor and singleton selects should use overqualified expressions to ensure integrity.
216
To avoid these scenarios, consider the use of isolation CS and the use of MAXROWS 1 with LOCKSIZE ANY to simulate row level locking. This alternative does reduce the number of rows within a page, but it increases the number of getpages, virtual storage/buffer pool utilization, and the number of I/Os. A detailed performance analysis should be completed before implementing this change.
Using a resource reference allows an additional level of indirection between the application and the datasource. This also allows the deployer to set the transaction isolation level for the application in the resource reference. A resource reference is added to the deployment descriptor within the WSAD environments deployment descriptor under the resources tab, as shown in Figure 9-1 on page 218. At execution time, the application looks up this reference (as a result of the java:comp/env, WebSphere knows this to be a reference) and then the reference points to the real datasource. As you can see in the example, the isolation level can also be set for the transaction.
217
218
wsPessimisticUpdate
wsPessimisticRead
wsOptimisticUpdate
wsOptimisticRead
wsPessimisticUpdateNo-Collisions wsPessimisticUpdate-Exclusive
Each of these access intents results in different SQL being generated for the entity Bean persistence code. For CMP Beans, isolation level is specified as part of the SQL statements within the persistence and retrieval methods for the Bean. A summary of the appendages to the persistence code for each access intent is listed in Table 9-5 on page 220.
219
TRANSACTION_REPEATABLE_READ
TRANSACTION_REPEATABLE_READ
YES
wsPessimisticRead
TRANSACTION_REPEATABLE_READ
NO
NO NO NO
TRANSACTION_SERIALIZABLE
YES
wsOptimisticUpdate
This access intent has the benefit of allowing isolation CS access to tables to ensure integrity. As described in Searched updates with overqualified predicates on page 215, this access intent generates persistence SQL with overqualified predicates to ensure integrity between selects and updates of the data. The full predicate option is used during the update to ensure that there is no integrity exposure since the data selection methods and data update methods do not pass a cursor or maintain locks. There is a limitation within the WebSphere persistence code regarding the over qualification of predicates. Columns within the table that are nullable are not included in the overqualified predicate list. As a result, data integrity exposures can occur if another application updates the columns that are nullable. It is generally not recommended to use nullable columns in Java applications, but the opportunity for data loss does exist and application developers should be aware of this restriction. Important: Use of wsOptimisticUpdate and nullable columns can result in a data integrity exposure and data loss. Do not use wsOptimisticUpdate on tables that contain any nullable columns.
220
10
Chapter 10.
221
Cached DASD. To maximize your performance, we recommend a fast DASD subsystem, for example, IBM Enterprise Storage Server (also known as Shark), running with a high cache read/write hit rate. OSA Express on zSeries 990. For high-bandwidth applications, we recommend at least a one gigabit Ethernet connection. If your applications have extremely high bandwidth requirements, you may need additional Ethernet connections. Software configuration In general, the latest software levels with the most recent PTFs applied perform best. In a WebSphere - DB2 environment this means: WebSphere Version 5.0.2 Statement cache enhancement New JDBC Providers support (DB2 Universal Driver) Customizable Performance Monitoring Infrastructure (PMI) Deferred Write operations for EJB 2.0 CMPs
Java SDK 1.3.1 DB2 and JDBC Drivers Version 8 IBM DB2 Universal Driver for SQLJ and JDBC Unicode support DDF communication database enhancements Enhancements for stored procedures and UDFs
z/OS Release 5
WebSphere Application Server for z/OS Version 5 has its own connection pooling. The connection pooling support for z/OS in V5 is consistent with other WebSphere platforms. Support for the new DB2 Universal JDBC Driver (sometimes referred to as DB2 JCC Driver) is provided in WebSphere for z/OS Release 5.02 with PTF level W502002. As discussed in 3.2, Introduction to DB2 drivers for Java on page 50, the following new JDBC providers have been included in the JDBC provider selection list when using the Administrative Console application: DB2 for z/OS Local JDBC Provider (RRS) The DB2 for z/OS Local JDBC Provider (RRS) option replaces the previous DB2 390 Local JDBC Provider (RRS) option. DB2 for z/OS Local JDBC Provider (RRS) supports the creation of WebSphere Application Server V5.0 data sources and V4.x level data sources. This provider is also referred to as DB2 Legacy JDBC Driver. DB2 Universal JDBC Driver Provider This is a non-XA JDBC provider. The JCC driver supports both type 2 and type 4 drivers. Transaction processing using type 4 connectivity is performed using one-phase commit. Transaction processing using type 2 connectivity utilizes Resource Recovery Services (RRS) to coordinate transactions with two-phase commit or one-phase commit. DB2 Universal JDBC Driver Provider supports the creation of both WebSphere V4.x and V5.0 data sources. DB2 Universal JDBC Driver Provider (XA) This is an XA JDBC provider with type 4 connectivity. The J2EE XA transaction architecture is supported by the Universal JDBC Driver under this provider. This permits the coordination of XA transactions across multiple resources using two-phase commit processing. Note: DB2 Universal JDBC Driver Provider (XA) only supports creation of the WebSphere V5.0 data sources, and not the creation of WebSphere V4.x level data sources.
10.2.2 How connection pooling works - How connection objects are structured
A unique Java Naming and Directory Interface (JNDI) name is needed to configure a unique data source or connection factory. A connection pool is created based on the JNDI name and its configuration information. A separate connection pool exists for each configured data source or connection factory. Connections can only be shared by applications if the connections are obtained from the same pool. The connections, out of the same pool, are not shared automatically. Sharing happens only under certain conditions (that is, the connection properties are the same).
223
For illustration purposes, connection objects can be in one of three states (see Figure 10-1). Does Not Exist In Free Pool In Use Before a connection is created, it is in the Does Not Exist state. After the connection is created, and has not been allocated to an application. The connection is allocated to an application, and currently active.
A connection leaves the In Use Pool when the connection is closed. This could mean an application closes the connection, or a transaction involving shared connections has ended. When a connection is closed by an application, one of the following can happen: The connection will move to the Does Not Exist state if and only if the connection is stale. An un-shareable connection will return to the In Free Pool. A shareable connection will move to the In Free Pool if the connection is not being used by other connection handles (that is, the transaction has ended). A shareable connection may stay in the In Use state if the connection is being used by other connection handles. When sharing connection handles across transaction boundaries, the physical connection (managed connection) may stay in the In Use state even when the transaction is done. Once the handle is touched again (used again), the connection handle will be associated with another similar managed connection, which may or may not be the same managed connection as before, but must have the same properties. Connections move from the In Free Pool state to the Does Not Exist state only during pool maintenance. Pool maintenance runs are based on the Reap Time value set for the connection pool. For more information on Reap Time, see Reap Time on page 225.
Connection Pool
Connection Tim eout Unused Tim eout
Reap Tim e
In Free Pool
Aged Tim eout
In Use
Connection properties - Transaction ID - JNDI nam e - Resource authentication - Isolation level (access intent)
Sh ar ed
Reap Time Timeout Connection Timeout Aged Timeout Unused Timeout Purge Policy Statement cache size
Max Connections
The Max Connections parameter specifies the maximum number of physical connections that can be created in the pool. Once this number is reached, no new physical connections are created and the requester waits until a connection that is currently in use returns to the pool, or a ConnectionWaitTimeoutException is thrown. For example, if the Max Connections value is set at 10, and there are ten physical connections in use, the pool manager waits for the amount of time specified in Connection Timeout for a physical connection to become free. If a physical connection is not available within the Connection Timeout interval, the pool manager throws a ConnectionWaitTimeoutException. If Max Connections is set at 0, it means there is no limit to the number of physical connections in the pool. The Connection Timeout value is ignored. Better performance can be achieved if you: Set the maximum connection pool value lower than the value for the Max Connections in the Web container. Consider the number of Central Processors (CPs) in your environment. The maximum connection pool setting should be lower when there are fewer CPs for WebSphere. In general, lower settings (1030 connections) perform better than higher settings (100 or greater). The default setting, 10, is a good starting point. Realize each entity Bean transaction requires an additional connection to the database to handle the transaction. Consider this when calculating the maximum/minimum number of connections.
Min Connections
The Min Connections parameter specifies the minimum number of physical connections that need to be maintained. Until this number is reached, the pool maintenance thread does not discard physical connections. However, no attempt is made to bring the number of connections up to the minimum. If you set a value for Aged Timeout (defined later), the minimum is not maintained. All connections with an expired age are discarded. Set the minimum number in accordance to your environmental needs. The default setting is 1.
Reap Time
The Reap Time parameter defines the interval, in seconds, between runs of the pool maintenance thread. For example, if Reap Time is set to 60, the pool maintenance thread runs every 60 seconds. The Reap Time interval affects the accuracy of the Unused Timeout and Aged Timeout settings. The smaller the interval, the greater the accuracy. When the pool maintenance thread is invoked, it moves the following connections from the In Free Pool to the Does Not Exit state: Connections whose Unused Timeout is expired if the pool contains more than the minimum connections. Connections whose Aged Timeout is expired.
225
The Reap Time interval also affects performance. Smaller intervals mean the pool maintenance thread runs more often, degrading performance. Set the Reap Time lower than the Unused Timeout and Aged Timeout intervals for optimal performance. The pool maintenance thread can be disabled by setting the Reap Time to 0. In that case, the Unused Timeout and Aged Timeout parameters are ignored.
Connection Timeout
The Connection Timeout parameter defines the interval, in seconds, after which a request for connection times out, and a ConnectionWaitTimeoutException is thrown. The wait is necessary when the pools maximum number of connections have been reached. For example, If Connection Timeout is set to 180 and the maximum number of connections is reached, the pool manager waits for 180 seconds for an available physical connection. If a physical connection is not available within this time, the pool manager throws a ConnectionWaitTimeoutException. If Connection Timeout is set to 0, the pool manager waits as long as necessary (potentially forever) until a connection can be allocated. If Max Connections is set to 0, it means there is no limit for physical connections in the pool, and the Connection Timeout value is therefore ignored.
Aged Timeout
The Aged Timeout parameter defines the interval, in seconds, before a physical connection is discarded. Setting Aged Timeout to 0, which is the default, supports physical connections remaining in the pool, at the In Free Pool state, indefinitely. Set the Aged Timeout higher than the Reap Time interval for optimal performance.
Unused Timeout
The Unused Timeout parameter defines the interval, in seconds, after which an unused or idle connection is discarded. Physical connections in the In Free Pool state are discarded only if these connections are higher than the minimum connections. Set the Unused Timeout higher than the Reap Time interval for optimal performance.
Purge Policy
The Purge Policy parameter defines how to purge connections when a stale connection or fatal connection error is detected. The valid values are: EntirePool All connections in the pool, including connections for both In Use and In Free Pool, are marked stale. Connections in the In Free Pool state are closed immediately. Connections in the In Use state are closed, and a StaleConnectionException is thrown during the next operation on that connection. New getConnection requests from the application result in new connections to the database. A purge policy of the EntirePool offers the safest choice. FailingConnectionOnly Only the connection involved with the StaleConnectionException is closed. There is no guarantee that the rest off the connections in the pool are all valid. Therefore, application recovery becomes more complicated. 226
DB2 for z/OS and WebSphere: The Perfect Couple
You can specify these parameters via the Connection Pools option of the datasource via the Administrative Console. Click Resources JDBC Providers DB2 Universal JDBC Driver Provider Data Sources ITSO1 Connection Pools (Figure 10-2).
227
As always, you specify the statement cache size for a datasource via the Administrative Console. Click Resources JDBC Providers DB2 Universal JDBC Driver Provider Data Sources ITSO1 (Figure 10-3).
holding resources that are not being used, and leaves more available connections in the pool for other applications. Additionally, it removes the temptation to use the same connection for multiple transactions. Of course, there may be times in which this is not feasible, such as when using BMP. Do not reuse the statement handle without closing it first. To prevent resource leakage, close prepared statements before reusing the statement handle to prepare a different SQL statement with the same connection. Do not manage data access in Container Managed Persistence (CMP) Beans. The reason for using a CMP Bean is to hide the details of the data access. By default, users of CMPs cannot manage their own data access. If a CMP Bean is written to manage its own data access, this data access may become part of a global transaction. It is certainly necessary to pay attention to the transaction requirements of each method to achieve data integrity and business objectives. If a user needs more fine-grained control over the details of their data persistence, then they should use Bean-Managed Persistence Beans (BMPs) instead of CMPs. Finally, it is also possible for the user to perform data access functions in session Beans and servlets.
229
addition to saving the JDBC precompiled SQL cost that WebSphere statement caching (caching the prepared statement object) offers. The following DB2 system parameters (in DSNZPARM) should be reviewed: CACHEDYN = YES means the DB2 global dynamic statement cache is enabled. MAXKEEPD specifies the maximum number of SQL statements kept in the local statement cache. (This parameter only applies to applications that also use the KEEPDYNAMIC(YES) bind option.) EDMPOOL specifies the size of the EDM pool. If you store the statements from the global dynamic statement cache in the EDM pool, you may have to adjust the size (make it bigger) to allow for those statements. Otherwise, you may end up pushing out other objects (SKPTs, SKCTs, and DBs) from the EDM pool. EDMDSPAC and EDMDSMAX (V7) specify that the statements in the global dynamic statement cache will not reside in the EDM pool, but in a separate data space. EDMDSPAC specifies the startup value, whereas EDMDSMAX specifies the maximum size the data space can be changed to via the -SET SYSPARM command. EDMSTMTC (V8) specifies the size of the global dynamic statement cache. The global dynamic statement cache resides above the 2 GB bar in V8. In V8, the global dynamic statement cache is always in a separate storage area from the EDM pool.
230
Performance considerations
Which connectivity type gives the best performance? Type 2 or type 4 connectivity? Tests conducted by the Silicon Valley Labs performance experts concluded the following: When accessing DB2 V7 or DB2 V8 back-end databases that reside on the same z/OS system image (LPAR) that the application is running on, type 2 connectivity provides better throughput and CPU utilization than type 4 connectivity. This is due to the network overhead. The JCC type 4 driver is implemented using the DRDA protocol over a TCP/IP network connection. Applications accessing local databases residing on the same z/OS system image using the JCC type 2 driver do not need to go over a TCP/IP network link. This is true even if the TCP/IP connection does not really need to go out on a physical network link. The fact that we need to go through additional layers (TCP/IP and DDF) introduces CPU and elapsed time overhead that can be avoided when using a local attachment via the JCC Type 2 driver (see Figure 10-4).
C e ll Y
M STR
z/OS Image
IR L M DBM1
D aem on
Node X
S to re d S t o rP er d ocs P ro c s
DDF
T2
A p p S e rve r
When accessing DB2 V7 or DB2 V8 back-end databases residing on a different z/OS system image (remote databases) than the application (WebSphere), type 4 connectivity (see Figure 10-5) achieved significant performance improvements over using type 2 connectivity to a local DB2 system, whos DDF DRDA Application requester function is used to communicate with the remote DB2 (illustrated in Figure 10-6 on page 232).
Cell Y
z/OS Image A
Daemon
IRLM DRDA / TCPIP
DBM1
Node X
AppServer
T4 XA
DDF
Figure 10-5 Connecting a WAS to a DB2 for z/OS via the type 4 XA Universal Driver
The configuration shown in Figure 10-5 is also known as z/OS Application Connectivity to DB2 for z/OS and OS/390, or the type 4 XA driver. It is a separately orderable, no-charge feature of DB2 for z/OS and OS/390 Version 7 and DB2 for z/OS Version 8.
z/OS Image B
231
MSTR
Cell Y
z/OS Image A
MSTR
Daemon
DBM1
IRLM
IRLM DDF
DBM1
Node X
Stored Stored Procs Procs
DDF
AppServer
T2
Figure 10-6 Connecting a WAS to a DB2 for z/OS via a DB2 router system and a type 2 driver
232
z/OS Image B
MSTR
MSTR DBM1
Daemon
IRLM
Cell Y AppServer
Controller
Node X
AppServer
DDF
233
servant regions. The WebSphere for z/OS system address spaces and DB2 address spaces should be given a fairly high priority. As work comes into the system, the work classification of the enclaves should be based on your business goals. Set up service classes with a velocity goal for the following address spaces: Daemon and controller address spaces should be classified so they get assigned the SYSSTC service class. By default, address spaces for VTAM, TCP/IP, and IRLM are also classified as SYSSTC. These address spaces should always have a higher dispatching priority than the DBMS and WebSphere servant address spaces. Servant address spaces should be classified as a high STC importance service class. The velocity goals for WebSphere servant regions are only important during startup or restart. After the transactions begin running, WLM ignores the WebSphere servants velocity goals, and assigns a priority based on the goals of transactions that are running in the servant regions. The services class assigned to the transaction will also determine the WLM goal for other work such as the work done inside the DB2 address spaces. The service class of the WebSphere transactions should not have a higher importance than the DB2 address spaces. Similarly, when you set response time goals for DDF threads or for WLM established stored procedures, the only work controlled by the DDF or stored procedure velocity goals is the work performed for DB2 that cannot be attributed to a users transaction. The users work runs under separate goals for the enclave. The WLM application environment is used for work running under servants. The work can be classified based on server name, server instance name, user ID, and transaction classes (that you can set up yourself). WLM uses subsystem type CB for WAS work. Percentage response time goal is recommended. It is usually a good idea to make the goals achievable. For example, a goal that 80 percent of the work will complete in .25 seconds is a typical goal. Velocity goals for application work are not meaningful and should be avoided.
10.5 Tuning the storage for z/OS and the Java Virtual Machine
WebSphere for z/OS has much higher demands on virtual memory than a traditional workload. Since real storage is needed to back virtual storage, the real storage usage is also high. Therefore: Allocate enough virtual storage. Specify REGION=0M in the JCL procedures that are used to run servant regions. This parameter tells the operating system to give all the available storage to the region. Allocate enough real storage. For controllers and servants, real storage utilization depends on the size of the Java Virtual Machine (JVM) heapsize. Recommendation: In a large and heavily used environment, 2G of central storage may not be enough to handle the real storage demands of high-volume Java applications. You may need to consider running in 64-bit mode (ESAME mode or z/Architecture mode). Running in 64-bit mode gives you the ability to define more than 2 GB of central storage. This option is available for zSeries machines that run OS/390 V2R10 or later. Tune the size of JVM heap size. Specifying sufficient JVM heap size is important to Java performance. The JVM has thresholds it uses to manage the JVMs storage. When these thresholds are reached, the garbage collector (GC) is invoked to free up unused storage. Garbage collection can cause significant degradation of Java performance.
234
It is good for the Initial Heap Size to equal the Maximum Heap Size because it allows the allocated storage to be completely filled before GC kicks in. If not, GC will run more frequently than necessary, potentially impacting performance. Make sure the region is large enough to hold the specified JVM heap. Beware of making the Initial Heap Size too large. While it initially improves performance by delaying garbage collection, it ultimately affects response time when garbage collection eventually kicks in (because it runs for a longer time). Paging activity on your system must also be considered when you set your JVM heap size. If your system is already paging heavily, increasing the JVM heap size might make performance worse rather than better. To determine if you are being affected by garbage collection, you can enable Verbose Garbage Collection on the JVM Configuration tab. The default is not enabled. This will write a report to the output stream each time the garbage collector runs. This report should give you an idea of what is going on with Java GC. The default of 256M is a good starting point. However, it may need to be raised for larger applications. The Java heap size should be monitored. Run with the Just In Time (JIT) compiler active. Make sure the Disable JIT is not selected in the General Properties section of the Configuration Tab. The default is JIT enabled. Do not specify the debug version of the JVM libjava_g in your LIBPATH. Performance degradation occurs when running with the debug version of the JVM. Make your CLASSPATH efficient. Only point to the classes you need, and place the frequently referenced classes first.
235
Trace levels
Table 10-1 lists the available trace levels for the Universal Driver. The constants representing these levels are declared in class com.ibm.db2.jcc.DB2BaseDataSource. You can combine individual levels using bitwise OR operations.
Table 10-1 Trace level options for the DB2 Universal Driver for SQLJ and JDBC Constant name TRACE_NONE TRACE_CONNECTION_CALLS TRACE_STATEMENT_CALLS TRACE_RESULT_SET_CALLS TRACE_DRIVER_CONFIGURATION TRACE_CONNECTS TRACE_DRDA_FLOWS TRACE_RESULT_SET_META_DATA TRACE_PARAMETER_META_DATA TRACE_DIAGNOSTICS TRACE_SQLJ TRACE_XA_CALLS TRACE_ALL Dec value 0 1 2 4 16 32 64 128 256 512 1024 2048 -1 Hex value 0x0000 0x0001 0x0002 0x0004 0x0010 0x0020 0x0040 0x0080 0x0100 0x0200 0x0400 0x0800 0xFFFFFFFF
Usually, TRACE_DRDA_FLOWS should be turned off since it generates a lot of output. For example, to enable all trace levels except TRACE_DRDA_FLOWS, you could simply code ~TRACE_DRDA_FLOWS (~ is the bitwise NOT operator in Java).
Driver-wide tracing
To trace the activity of all connections using the Universal Driver, you can use specifications in the DB2 Universal Driver global properties file. (This is the same file where you specify the local DB2 subsystem name for type 2 connectivity.) As with most things in a Java world, there a many different ways to set configuration properties. The easiest way is probably to put them in a normal file, and set up the db2.jcc.propertiesFile Java system property that points to that file. The following driver configuration properties are related to tracing: db2.jcc.traceFile Enables the Universal Driver to trace for Java driver code, and specifies the name of the file on which the trace file names will be based. You can specify a fully qualified z/OS UNIX System Services file name for the db2.jcc.traceFile property value. For most properties there is a way to override any existing values at the Connection or DataSource level. The db2.jcc.override.traceFile property overrides any traceFile property value that might have been specified for a Connection or DataSource object. (If the configuration property begins with db2.jcc.override, the configuration
db2.jcc.override.traceFile
236
property is applicable to all connections and overrides any Connection or DataSource property with the same property name. If the configuration property begins with db2.jcc or db2.jcc.default, the configuration property value is a default. Connection or DataSource property settings override that value.) db2.jcc.t2zosTraceFile Enables the Universal Driver trace for C/C++ native driver code for type 2 connectivity, and specifies the name on which the trace file names are based. This property is required for collecting trace data for C/C++ native driver code, and therefore only applies to type 2 connectivity. You normally use this trace under the direction of IBM Software Support.
db2.jcc.t2zosTraceBufferSize Specifies the size of a trace buffer in virtual storage that is used for tracing the processing that is done by the C/C++ native driver code. This value is also the maximum amount of C/C++ native driver trace information that can be collected, and therefore only applies to type 2 connectivity. Specify a value in kilobytes. The default is 256 KB. This property is used only if the db2.jcc.t2zosTraceFile property is set. Recommendation: To avoid a performance impact, specify a value of 1024 or less. You normally set this trace property under the direction of IBM Software Support. Example 10-1 is what our sample properties file looks like.
Example 10-1 Global driver properties file db2.jcc.ssid=DBD8 db2.jcc.traceFile=/u/rc54/cel541nd541sc54ws541sc54/tracejava db2.jcc.t2zosTraceFile=/u/rc54/cel541nd541sc54ws541sc54/tracezos
Now that we have the content of the global driver properties file, we need to point WAS to the file. This is done by setting the up the db2.jcc.propertiesFile system property. In a WebShpere Application Server environment, this is done via a Custom Property on the JVM. These can be set at the WAS server level (see Figure 10-8).
See also 3.5.4, Defining DB2 Universal Driver - General properties on page 65, for more details on how to specify custom properties.
237
238
currentSQLID=null, cursorSensitivity=0, clientApplicationInformation=null, currentSchema=null, clientWorkstation=null } [ibm][db2][jcc] END TRACE_CONNECTS [ibm][db2][jcc][Time:1103812831057][Thread:WebSphere t=006cc4d0][Connection@371ee0e5] T2zosConnection () called // ***** Trace records specific to z/OS type 2 connectivit are marked [t2zos] ***** [ibm][db2][jcc][t2zos] [Thread:WebSphere t=006cc4d0][com.ibm.db2.jcc.t2zos.T2zosReusableConnection@371ee0e5] flowConnect () tracepoint 1 [ibm][db2][jcc][t2zos] (database name) [ibm][db2][jcc][t2zos] (ASCII) (EBCDIC) [ibm][db2][jcc][t2zos] 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF 0123456789ABCDEF [ibm][db2][jcc][t2zos] 0000 C4C2C4F800 ..... DBD8. [ibm][db2][jcc][t2zos] [ibm][db2][jcc][t2zos] (user) [ibm][db2][jcc][t2zos] (ASCII) (EBCDIC) [ibm][db2][jcc][t2zos] 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF 0123456789ABCDEF [ibm][db2][jcc][t2zos] 0000 C2C1D9E3D9F100 ....... BARTR1. ... [ibm][db2][jcc][Connection@371ee0e5] BEGIN TRACE_CONNECTS [ibm][db2][jcc][Connection@371ee0e5] Successfully connected to server jdbc:db2:DBD8 [ibm][db2][jcc][Connection@371ee0e5] User: BARTR1 [ibm][db2][jcc][Connection@371ee0e5] Database product name: DB2 [ibm][db2][jcc][Connection@371ee0e5] Database product version: DSN08015 [ibm][db2][jcc][Connection@371ee0e5] Driver name: IBM DB2 JDBC Universal Driver Architecture [ibm][db2][jcc][Connection@371ee0e5] Driver version: 2.1.43 [ibm][db2][jcc][Connection@371ee0e5] DB2 Application Correlator: TBD for T2zos [ibm][db2][jcc][Connection@371ee0e5] END TRACE_CONNECTS [ibm][db2][jcc][Connection@371ee0e5] BEGIN TRACE_CONNECTS [ibm][db2][jcc][Connection@371ee0e5] Successfully connected to server jdbc:db2:DBD8 [ibm][db2][jcc][Connection@371ee0e5] User: BARTR1 [ibm][db2][jcc][Connection@371ee0e5] Database product name: DB2 [ibm][db2][jcc][Connection@371ee0e5] Database product version: DSN08015 [ibm][db2][jcc][Connection@371ee0e5] Driver name: IBM DB2 JDBC Universal Driver Architecture [ibm][db2][jcc][Connection@371ee0e5] Driver version: 2.1.43 [ibm][db2][jcc][Connection@371ee0e5] DB2 Application Correlator: TBD for T2zos [ibm][db2][jcc][Connection@371ee0e5] END TRACE_CONNECTS ... [ibm][db2][jcc][Time:1103812831807][Thread:WebSphere t=006cc4d0][ConnectedProfile@1f42e0fb] getStatement (SELECT EMPNO , FIRSTNME , MIDINIT , LASTNAME , HIREDATE , CASE SEX WHEN 'M' THEN 1 ELSE 0 END , SALARY FROM EMP ) called [ibm][db2][jcc][Time:1103812831847][Thread:WebSphere t=006cc4d0][RTStatement@45120fb] <constructor> () called ... [ibm][db2][jcc][Time:1103812832255][Thread:WebSphere t=006cc4d0][RTStatement@45120fb] executeRTQuery () called [ibm][db2][jcc][Time:1103812832255][Thread:WebSphere t=006cc4d0][PreparedStatement@57fca0f8] executeQuery () called [ibm][db2][jcc][t2zos] [Thread:WebSphere t=006cc4d0][com.ibm.db2.jcc.t2zos.T2zosPreparedStatement@10e820f8] getNativeStatement () tracepoint 1 [ibm][db2][jcc][t2zos] (pCONN) 355087216 // *****The trace indicates the package name being used - in this case a static SQLJ package ***** [ibm][db2][jcc][t2zos] (package name) [ibm][db2][jcc][t2zos] [ibm][db2][jcc][t2zos] 0 1 2 3 4 5 6 7 8 9 A B C D E F [ibm][db2][jcc][t2zos] 0000 C5D4D7D3D6E8F300 [ibm][db2][jcc][t2zos]
239
(section number) 5 (consistency token) 0 1 2 3 4 5 6 7 8 9 A B C D E F 4D41447044434C71 (ASCII) (EBCDIC) 0123456789ABCDEF 0123456789ABCDEF MADpDCLq (.....<.
0000
Specifies the name of a file into which the Universal Driver writes trace information. (The traceFile property is an alternative to the logWriter property for directing the output trace stream to a file.) For Universal Driver type 2 connectivity, the db2.jcc.override.traceFile global property value overrides the traceFile property value. Specifies whether to append to or overwrite the file that is specified by the traceFile property. The default is false, which means that the file that is specified by the traceFile property is overwritten. Specifies what to trace. The trace levels that you can specify are described in Trace levels on page 236.
traceFileAppend
traceLevel
These properties can also be set for a Connection object, but our interest here is DataSources, as they are the preferred way to set up a connection to a data source in WebSphere. To set these properties on the WebSphere datasource, you use the Administrative Console. Navigate to Resources JDBC Providers provider-name Data Sources datasource-name Custom Properties (Figure 10-9 on page 241).
240
This example only sets the traceFile and traceLevel properties, as these are supported by the Admin console panels. If you want to use traceDirectory and traceAppend, you would have to create these as additional custom properties (using the New button). Figure 10-3 shows (edited) trace output from a type 4 XA connection. (As with the driver-wide trace file, this one is also written in ASCII, and you have to download it in binary to read it.)
Example 10-3 Data source level trace output // *****Again we start with a driver configuration listing versions and options used ***** [ibm][db2][jcc] BEGIN TRACE_DRIVER_CONFIGURATION [ibm][db2][jcc] Driver: IBM DB2 JDBC Universal Driver Architecture 1.7.9 [ibm][db2][jcc] Compatible JRE versions: { 1.3, 1.4 } [ibm][db2][jcc] Target server licensing restrictions: { z/OS: enabled; SQLDS: enabled; iSeries: enabled; DB2 for Unix/Windows: enabled; Cloudscape: enabled } .... [ibm][db2][jcc] Java class path = /WebSphereBS/V5R0M0/BS02/AppServer/properties:/WebSphereBS/V5R0M0/BS02/AppServer/lib/bootstrap.jar:/WebSphe reBS/V5R0M0/BS02/AppServer/lib/urlprotocols.jar:/WebSphereBS/V5R0M0/BS02/AppServer/lib/j2ee.jar:/WebSphereB S/V5R0M0/BS02/AppServer/lib/lmproxy.jar [ibm][db2][jcc] Java native library path = /usr/lpp/java/IBM/J1.3/bin:/usr/lpp/java/IBM/J1.3/bin/classic:/WebSphereBS/V5R0M0/BS02/AppServer/lib [ibm][db2][jcc] Path of extension directory or directories = /usr/lpp/java/IBM/J1.3/lib/ext:/WebSphereBS/V5R0M0/BS02/AppServer/java/jre/lib/ext [ibm][db2][jcc] Operating system name = z/OS [ibm][db2][jcc] Operating system architecture = 390
241
Operating system version = 01.05.00 File separator ("/" on UNIX) = / Path separator (":" on UNIX) = : User's account name = ASSR1 User's home directory = /tmp User's current working directory = /WebSphereBS/V5R0M0/BS02/AppServer END TRACE_DRIVER_CONFIGURATION BEGIN TRACE_CONNECTS
// *****The trace indicates connection start, listing all properties used ***** [ibm][db2][jcc] Attempting connection to wtsc54.itso.ibm.com:38070/DBD8 [ibm][db2][jcc] Using properties: { password=********, dataSourceName=null, traceDirectory=null, portNumber=38070, fullyMaterializeLobData=true, currentSQLID=null, securityMechanism=3, clientAccountingInformation=null, cliSchema=null, resultSetHoldability=2, serverName=wtsc54.itso.ibm.com, currentPackageSet=SG246435, loginTimeout=0, planName=null, traceFile=/u/rc55/cel551nd551sc55/traceT4XA, currentFunctionPath=null, kerberosServerPrincipal=null, retrieveMessagesFromServerOnGetMessage=true, cursorSensitivity=0, currentPackagePath=null, currentSchema=null, clientUser=null, keepDynamic=0, driverType=4, clientApplicationInformation=null, description=null, readOnly=false, clientWorkstation=null, pkList=null, deferPrepares=true, jdbcCollection=NULLID, databaseName=DBD8, traceLevel=-1, traceFileAppend=false, user=BART } [ibm][db2][jcc] END TRACE_CONNECTS // *****The trace indicates type 4 connectivity specific entries by [t4] ***** // *****Also note the type 4 connectivity also shows the DRDA flows (like EXCSAT) and buffer content ***** [ibm][db2][jcc] [T4][time:1103815956665][thread:WebSphere t=006cad90][tracepoint:1][Request.flush] [ibm][db2][jcc][t4] SEND BUFFER: EXCSAT (ASCII) (EBCDIC) [ibm][db2][jcc][t4] 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF 0123456789ABCDEF [ibm][db2][jcc][t4] 0000 0068D00100010062 1041001E115E8482 .h.....b.A...^.. ..}..........;db [ibm][db2][jcc][t4] 0010 F2918383E68582E2 978885998540A37E .............@.~ 2jccWebSphere t= [ibm][db2][jcc][t4] 0020 F0F0F6838184F9F0 000A116DA6A3A283 ...........m.... 006cad90..._wtsc [ibm][db2][jcc][t4] 0030 F5F5000E115AC4C2 F2D1C3C340F14BF0 [email protected]. 55...!DB2JCC 1.0 [ibm][db2][jcc][t4] 0040 001C140414030007 24070007240F0007 ........$...$... ................ [ibm][db2][jcc][t4] 0050 1440000614740005 1C010007000C1147 [email protected] . .............. [ibm][db2][jcc][t4] 0060 D8C4C2F261D1E5D4 ....a... QDB2/JVM [ibm][db2][jcc][t4] [ibm][db2][jcc] [t4][time:1103815956668][thread:WebSphere t=006cad90][tracepoint:2][Reply.fill] ... [ibm][db2][jcc][Connection@6f5b2602] BEGIN TRACE_CONNECTS [ibm][db2][jcc][Connection@6f5b2602] Successfully connected to server jdbc:db2://wtsc54.itso.ibm.com:38070/DBD8 [ibm][db2][jcc][Connection@6f5b2602] User: BART [ibm][db2][jcc][Connection@6f5b2602] Database product name: DB2 [ibm][db2][jcc][Connection@6f5b2602] Database product version: DSN08015 [ibm][db2][jcc][Connection@6f5b2602] Driver name: IBM DB2 JDBC Universal Driver Architecture [ibm][db2][jcc][Connection@6f5b2602] Driver version: 1.7.9 [ibm][db2][jcc][Connection@6f5b2602] DB2 Application Correlator: G90C041C.G498.0101008ED8A4 [ibm][db2][jcc][Connection@6f5b2602] END TRACE_CONNECTS [ibm][db2][jcc][t4] DRDA manager levels: { SQLAM=7, AGENT=7, CMNTCPIP=5, RDB=7, SECMGR=6 } [ibm][db2][jcc][Time:1103815956735][Thread:WebSphere t=006cad90][Connection@6f5b2602] setDB2ClientUser (BART) called [ibm][db2][jcc][Time:1103815956736][Thread:WebSphere t=006cad90][Connection@6f5b2602] setDB2ClientWorkstation (wtsc55) called [ibm][db2][jcc][Time:1103815956736][Thread:WebSphere t=006cad90][Connection@6f5b2602] setDB2ClientApplicationInformation (db2jccWebSphere t=006cad90) called [ibm][db2][jcc][Time:1103815956736][Thread:WebSphere t=006cad90][DB2XAConnection@d1da60d] getConnection () called ...
242
[ibm][db2][jcc][Time:1103815957228][Thread:WebSphere t=006cad90][Customization@21a5a601] getProfile () returned com.ibm.db2.jcc.sqlj.c@772c2601 [ibm][db2][jcc][Time:1103815957228][Thread:WebSphere t=006cad90][ConnectedProfile@772c2601] getStatement (SELECT EMPNO , FIRSTNME , MIDINIT , LASTNAME , HIREDATE , CASE SEX WHEN 'M' THEN 1 ELSE 0 END , SALARY FROM EMP ) called [ibm][db2][jcc][Time:1103815957295][Thread:WebSphere t=006cad90][RTStatement@5eca6601] <constructor> () called [ibm][db2][jcc][Time:1103815957369][Thread:WebSphere t=006cad90][PreparedStatement@3ef42601] getMaxFieldSize () called [ibm][db2][jcc][Time:1103815957369][Thread:WebSphere t=006cad90][PreparedStatement@3ef42601] setMaxFieldSize (0) called [ibm][db2][jcc][Time:1103815957369][Thread:WebSphere t=006cad90][PreparedStatement@3ef42601] getFetchSize () returned 0 [ibm][db2][jcc][Time:1103815957370][Thread:WebSphere t=006cad90][ConnectedProfile@772c2601] getStatement () returned com.ibm.db2.jcc.sqlj.g@5eca6601 [ibm][db2][jcc][Time:1103815957370][Thread:WebSphere t=006cad90][PreparedStatement@3ef42601] setMaxRows (0) called [ibm][db2][jcc][Time:1103815957370][Thread:WebSphere t=006cad90][PreparedStatement@3ef42601] setMaxFieldSize (0) called [ibm][db2][jcc][Time:1103815957370][Thread:WebSphere t=006cad90][PreparedStatement@3ef42601] setQueryTimeout (0) called [ibm][db2][jcc][Time:1103815957371][Thread:WebSphere t=006cad90][RTStatement@5eca6601] executeRTQuery () called [ibm][db2][jcc][Time:1103815957371][Thread:WebSphere t=006cad90][PreparedStatement@3ef42601] executeQuery () called [ibm][db2][jcc] [t4][time:1103815957390][thread:WebSphere t=006cad90][tracepoint:1][Request.flush] [ibm][db2][jcc][t4] SEND BUFFER: EXCSQLSET (ASCII) (EBCDIC) [ibm][db2][jcc][t4] 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF 0123456789ABCDEF [ibm][db2][jcc][t4] 0000 004ED05100010048 201400442113C4C2 .N.Q...H ..D!... .+}...........DB [ibm][db2][jcc][t4] 0010 C4F8404040404040 4040404040404040 ..@@@@@@@@@@@@@@ D8 [ibm][db2][jcc][t4] 0020 E2C7F2F4F6F4F3F5 4040404040404040 ........@@@@@@@@ SG246435 [ibm][db2][jcc][t4] 0030 4040E2E8E2D3D5F2 F0F0404040404040 @@........@@@@@@ SYSLN200 [ibm][db2][jcc][t4] 0040 404040405359534C 564C303101810027 @@@@SYSLVL01...' ...<.<...a.. [ibm][db2][jcc][t4] 0050 D053000100212414 0000000017534554 .S...!$......SET }............... [ibm][db2][jcc][t4] 0060 20434C49454E5420 5553455249442742 CLIENT USERID'B ..<..+.......... [ibm][db2][jcc][t4] 0070 41525427FF002DD0 5300010027241400 ART'..-.S...'$.. .......}........ [ibm][db2][jcc][t4] 0080 0000001D53455420 434C49454E542057 ....SET CLIENT W .........<..+... [ibm][db2][jcc][t4] 0090 524B53544E4E414D 4527777473633535 RKSTNNAME'wtsc55 ....++.(........ [ibm][db2][jcc][t4] 00A0 27FF003FD0530001 0039241400000000 '..?.S...9$..... ....}........... [ibm][db2][jcc][t4] 00B0 2F53455420434C49 454E54204150504C /SET CLIENT APPL ......<..+...&&< [ibm][db2][jcc][t4] 00C0 4E414D4527646232 6A63635765625370 NAME'db2jccWebSp +.(.....|....... [ibm][db2][jcc][t4] 00D0 6865726520743D30 3036636164393027 here t=006cad90' .........../.... [ibm][db2][jcc][t4] 00E0 FF005FD043000100 592414000000004F .._.C...Y$.....O ...}...........| [ibm][db2][jcc][t4] 00F0 53455420434C4945 4E5420414343544E SET CLIENT ACCTN .....<..+......+ [ibm][db2][jcc][t4] 0100 47274A4343303130 37304A564D202020 G'JCC01070JVM ............(... [ibm][db2][jcc][t4] 0110 2020202020202020 202020206462326A db2j ...............| [ibm][db2][jcc][t4] 0120 6363576562537068 65726520743D3030 ccWebSphere t=00 ................ [ibm][db2][jcc][t4] 0130 4241525420202020 272C5827303027FF BART ',X'00'. ................ [ibm][db2][jcc][t4] 0140 005BD00100020055 200C00442113C4C2 .[.....U ..D!... .$}...........DB [ibm][db2][jcc][t4] 0150 C4F8404040404040 4040404040404040 ..@@@@@@@@@@@@@@ D8 [ibm][db2][jcc][t4] 0160 E2C7F2F4F6F4F3F5 4040404040404040 ........@@@@@@@@ SG246435 [ibm][db2][jcc][t4] 0170 4040C5D4D7D3D6E8 F340404040404040 @@.......@@@@@@@ EMPLOY3 [ibm][db2][jcc][t4] 0180 404040404D414470 44434C7100050008 @@@@MADpDCLq.... (.....<..... [ibm][db2][jcc][t4] 0190 211400007FFF0005 215D01 !.......!]. ...."....). [ibm][db2][jcc][t4] [ibm][db2][jcc] [t4][time:1103815957430][thread:WebSphere t=006cad90][tracepoint:2][Reply.fill] [ibm][db2][jcc][t4] RECEIVE BUFFER: SQLCARD (ASCII) (EBCDIC) [ibm][db2][jcc][t4] 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF 0123456789ABCDEF [ibm][db2][jcc][t4] 0000 000BD04300010005 2408FF002FD05200 ...C....$.../.R. ..}..........}.. ...
243
ibm][db2][jcc][t4] 00C0 08241B0000079BFF [ibm][db2][jcc][t4] 00D0 09C3C8D9C9E2E3C9 [ibm][db2][jcc][t4] 00E0 E200F1F9F6F560F0 [ibm][db2][jcc][t4] 00F0 00005275000CFF00 [ibm][db2][jcc][t4] 0100 E5C9D5C3C5D5E9D6 [ibm][db2][jcc][t4] 0110 C5E2C900F1F9F5F8 [ibm][db2][jcc][t4] 0120 000100004650000C ...
Note: If you are tracing a type 4 connection, as in the example above, you can also see the DRDA flows, including the content of the send and receive buffers (provided TRACE_DRDA_FLOWS tracing is active).
Note that we also use the WSConnection class (not DB2Connection), as in Example 6-2 on page 137.
244
11
Chapter 11.
Sample application
In this chapter we describe a sample application using Enterprise JavaBeans (mostly entity Beans) of different types, to show how DB2 data can be accessed from within Web applications using data source definitions based on the new IBM DB2 Universal Driver for SQLJ and JDBC.
245
11.1 Introduction
Our sample Web application is based on the contents of the DB2 IVP tables provided with DB2 for z/OS Version 8. Our scenario uses a Model View Controller (MVC2) approach, as shown in Figure 11-1. Note: In the MVC1 model, the controller was also provided as a Java ServerPage. In the MVC2 model, it is Servlet.
View
1.
Controller
Java Servlet Navigator
4. 3. 2.
Model
Backend Transaction: EJB CICS IMS DB2 JMS(MQI) Java
HTTP(S)
5.
In the MVC model there are three clearly distinct groups of components: Controller: Accepts queries from the browser, dispatches the required actions to the models, and interacts for presentation with the views. It acts as the navigator in the design. The controller always contains a Servlet. Views: Composed of JavaServer Pages and special Servlets (in case some MIME types are not supported by JSP), they are responsible for rendering the output to the user. Models: These are the business components. The real work is done here. A model can be a group of Enterprise JavaBeans, both session and entity, a connector to a transaction in a transaction manager (CICS,IMS), or it can be a simple JavaBean with some logic. Although the main interest of this book lays in DB2 and access to DB2 from WAS, we should not forget that DB2 is a database manager, and that it comes to life on behalf of transactions. The transactions trigger the accesses to DB2. To access the DB2 data, we use several kinds of entity Beans (EJBs) in our sample application. The transaction in a WAS environment often originates from a browser, and the results have to be presented back to this browser. The access to DB2 tables is located inside the models. We use all combinations of entity Beans to access those DB2 tables in our sample application. We will start out building the model part of our design. Later in a Web project we will add the controller and the view. The model in our case is composed of one session Bean, which receives the requests from dispatched actions in the controller, and collects the required data from entity Beans, which then is returned to the controller component and presented by the views.
246
In Figure 11-2 we recognize the three MVC parts. The requests come from the browser, and are accepted by the controller.
b ro w s e r
M odel
E n t it y B e a n s
V ie w
C o n t r o lle r
a c t io n s
IT S O A c c e s s S e s s io n E J B
g e tE m p lo y e e () g e tIm a g e () g e tD e p a rtm e n t() g e tD e p E m p lo y e e L is t()
J S P 's
S e r v le t
T4
A c tio n C o n tro l
T2
DB2
E J B 's
The DB2 sample tables provided with DB2 for z/OS V8 show a lot of complex aspects of DB2, especially in the area of referential integrity. Since this publication focuses on the WebSphere Application Server (WAS) aspects of using DB2, and we like to cover the elements offered by the EJB 2.0 specification, we simplified the set of sample tables. We only use the Employee (EMP), Department (DEPT) and the Emp_Photo_Resume (EMP_PHOTO_RESUME) tables, and the relationships that have been defined between these tables through foreign keys (FK). The Emp_Photo_Resume table is a stand-alone table and contains BLOB data (a picture of the employee) and CLOB data (the employees resume) that we use to demonstrate the usage of LOB columns in Java-DB2 programs. We will now concentrate on the model. The model has a front-end session Bean with the four business methods that can be triggered by a browser request: employeeEJB.do -> getEmployee(): To retrieve the details of an employee getImage(): To retrieve the picture of an employee departmentEJB.do -> getDepartment(): To retrieve the details of a department departmentListEJB.do -> getDepartmentList(): To list the employees belonging to a department All demands from the controller actions are passed through this session Bean, which with parameters passed in a container (actually a java.util.HashMap), it makes a selection of entity Beans to collect the requested information from, and passes it back to the controller via a data transfer Bean. The session Bean is responsible for the lookup of the entity Beans and for collecting some of the contents of the data transfer Beans. In our sample scenario (Figure 11-2), we use several types of entity Beans. We use container-managed persistence (CMP) Beans using JDBC or SQLJ, which have been generated by Websphere Application Studio Developer (WSAD). We also use Bean-managed persistence (BMP) with JDBC and SQLJ for some tables.
247
The development of the design is be done under WSAD V5.1 on a workstation (Windows-based in our case). We use and show the following aspects of the application: Connecting from WSAD to DB2 and import of table schemas Mapping of the tables to container-managed persistence Beans (CMP) Definition and exploitation of the container-managed relationships (CMR) Using the EJBQL language to add additional finders Generation of the deployment code Integration of the CMP Beans in a Web project based on Struts Integration of the BMP Beans with JDBC code Integration of the CMP Beans with SQLJ code Integration of the BMP Beans with SQLJ code
D a ta b a s e IT S O D B L
Ta b le S p a c e T S L O B 1
BASE TABLE E M P _ P H O TO _ R E S U M E
P rim ary K e y E M P N O
TABLE EMP
P rim a ry K e y E M P N O
IN D E X X E M P 2
(W O R K D E P T )
IN D E X X E M P _ P H O TO _ R E S U M E
F o re ign K e y R D E P T o n co lu m n W O R K D E P T ON DELETE SET N ULL F ore ig n K e y R E M P o n co lu m n M G R N O O N D E LE T E S E T N U L L
(E M P N O )
L O B Ta b le S p a c e T S L O B 2
AUX TABLE A U X _ P S E G _ P H O TO
Ta b le S p a c e T S D E P T
IN D E X X D E P T 1
(D E P T N O )
TABLE DEPT
P rim a ry K e y D E P T N O
L O B Ta b le S p a c e T S L O B 3
AUX TABLE A U X _B M P _ P H O TO
IN D E X X D E P T 2
(M G R N O )
IN D E X X D E P T 3
(A D M R D E P T )
F o reig n K e y R S E L F D o n c olu m n A R M R D E P T ON DELETE CASCAD E
L O B Ta b le S p a c e T S L O B 4
AU X TABLE AU X_EM P _R ES U M E
A ll o b je cts c re a te d b y IT S O U S E R (S C H E M A is IT S O U S E R )
We also have three relationships between the tables, defined by the following foreign keys: EMP(workdept) -> DEPT(deptno) = RDEPT DEPT(mgnro) -> EMP(empno) = REMP DEPT(admrdept) -> DEPT(deptno) = RSELFD
248
EMP_PHOTO_RESUME
This table contains large object (LOB) columns. Physically, the logical table is materialized by a base table and one auxiliary table for each (LOB) column, which can be a binary one (BLOB) or a character one (CLOB). There are no relations with other tables, but a primary key exists on the EMPNO column. The EMP_PHOTO_RESUME table has one CLOB and two BLOB (picture) columns.
Connecting to DB2
Before we can do any development work with the DB2 tables in WSAD, it is required to connect to the DB2 system where they are located. To generate container-managed persistence (CMP) entity Beans, we have to import the schema metadata information from DB2 into the WSAD workbench. This happens in a data perspective of WSAD. First we have to define a connection to the DB2 system. When connecting to a DB2 V7 or V8 system using the IBM DB2 Universal Driver for SQLJ and JDBC, we have a choice in the connection type (T2 or T4). Since our data model is identical on DBD7 and DBD8, it does not really matter which system we use. All preparation work shown in this publication has been done against a DB2 V8 system, using type 4 connectivity. Note: This connection is only used for importing table schemas, not when running the actual application under a WebSphere Application Server.
249
Connection definition
In the data perspective, inside the DB Servers pane, located in the bottom-left part of the WSAD window, right-click New Connection (Figure 11-4).
A New Database Connection window pops up, as shown in Figure 11-5. Fill in the fields, as indicated in Figure 11-5, and select to use a connection using T4 connectivity. Note: At the time of writing, the selection option Database vendor type in WSAD did not include DB2 Universal Database for OS/390, V8, but functionally it makes no difference.
Table 11-1 on page 251 explains the important fields of Figure 11-5.
250
Table 11-1 Connection properties Field name Connection name Database Value DBD8T4 DBD8 Comment Any name that describes the connection. Location name of the DB2 for z/OS system that harbors your tables. Will be corrected in a future WSAD release. Select the JCC driver. IP host name. Port number DBD8 is listening on. This is automatically selected (and cannot be updated), and is related to the selection made in the JDBC driver field. Mandatory JAR files, containing the driver classes. Automatically filled in based on the information provided in JDBC driver, host, and port number. Remember that type 4 connectivity requires the following information in the connection URL: - DDF TCP/IP port on DBD8 - Location name of DBD8
Database vendor type JDBC driver Host Port number JDBC driver class
DB2 Universal Database for OS/390, V7 IBM DB2 UNIVERSAL DRIVER wtsc54.itso.ibm.com 38070 com.ibm.db2.jcc.DB2Driver
Class location
Connection URL
Click Finish. A secondary window Confirm Filters, shown in Figure 11-6, pops up. It provides you with the possibility to define filters, so that only the metadata for a selection of the tables in the DB2 subsystem are imported. The filter usage is quite important, as a DB2 for z/OS can have many tables. An import of the metadata of all tables would take too long and not be useful.
At this time click Update Filter. The next widow that appears is shown in Figure 11-7 on page 252. There we can specify filter criteria.
251
We set the filter to enabled, and specify SCHEMA LIKE NULLID%. Click OK on the current pop-up and then Continue on the new Confirm Filters pop-up. For our sample scenario, three tables are imported: NULLID.EMP NULLID.DEPT NULLID.EMP_PHOTO_RESUME (1) (2) (3)
Table (1) and (2) are, as already mentioned, interrelated by referential integrity constraints, and as a result, will have interrelated entity Beans. Table (3) is a stand-alone table in the WSAD project. If the result of this import is not as expected, errors, or only partial data, review first the DBV8 installation and preparation. This setup is described in 1.9, Using the DB2 Universal Driver for SQLJ and JDBC on page 26, and in UDB for z/OS Installation Guide, GC18-7418. After the import completes, the new look of the DB Servers pane in WSAD should look like Figure 11-8 on page 253. Still being in the Data perspective, in the same DB Servers pane, notice the new connection named DBD8T4, which has been used for the import, and under the name of the connection (DBD8T4), the metadata for the three imported tables. In our case, we had a set of tables with a NULLID qualifier.
252
11.2.1 Creating entity CMP Beans using JDBC from the imported tables
When creating Enterprise JavaBeans using WSAD, they have to reside in an EJB project. In this section we generate container-managed Persistence (CMP) Beans that use JDBC for our three tables that we imported in the previous section.
A pop-up (Figure 11-10 on page 254) shows up with the project/type selections.
253
We select EJB in the left column, and EJB project in the right column. Click Next. A window like Figure 11-11 shows up next.
Indicate an EJB2.0 project and click Next. EJB 2.0 types are new with WAS V5 and J2EE 1.3. Enter the name ItsoEJB1 as the EJB project name (Figure 11-12), and do not forget to also enter a name for the Enterprise Application (EA) this project is part of. We choose the name Itso1EAR, as all ingredients of J2EE projects finally are packaged in an Enterprise Archive (EAR) and deployed via this file in the WebSphere containers. It is not required to create a client EJB project in our scenario.
Finally, click Finish, and the two projects (ItsoEJB1 and Itso1EAR) are created.
254
Right-click Import to Folder. In the new window (Figure 11-14) that shows up, we have to indicate the project/folder in which the tables have to be imported.
Click the Browse button. This allows us (in a new pop-up) to navigate to the project/folder EjbModule under the ItsoEJB1 project. After clicking OK the Folder selection line is filled in, and we click Finish. The system will ask a few times for the creation authorization of new subfolders. Those should be confirmed, and finally after a while the ItsoEJB1 project looks like Figure 11-15 on page 256 (in the Data Definition window of the Data perspective).
255
In the project tree we notice the additional sub folders that have been created META-INF/backends/DB2UDBOS390_v7_1. Note: The usage of the DB2UDBOS390_v7_1 directory may be confusing. We indeed work with a DB2 V8 system, but the DB2 V8 labeling was not yet supported in WSAD V5.1 at the time of writing. In the J2EE perspective, in the top left Project Navigator view, under the sub folder META-INF/backends/DB2UDBOS390_v7_1, we find metafiles *.tblxmi for the three imported tables. These files will be the sources for the Entity EJBs mapping. The backends notion indicates already that we can have tables from several backends in the same EJB project. Before we can do the mapping, we will have a look at those files and verify that all required ingredients are present. One important requirement is that each table, which will be mapped to an entity Bean, must have a primary key. We can open the *.tblxmi files with the table editor. We start with the NULLID.DEPT table. Double-clicking the file NULLID_DEPT.tblxmi opens up a first pane (see Figure 11-16 on page 257), which is the overview pane. At the bottom, we have a menu with thumbnails that allows us to walk through different panes. All this information has been picked up from the metadata imported from DB2 into the project.
256
The table NULLID.DEPT has five columns and two foreign keys defined. Column DEPTNO has been defined as a primary key. At first glance the definition seems to be OK. By clicking the Columns pane (Figure 11-17), we can obtain more information about the individual columns.
The information shown in Figure 11-17 is for the DEPTNO column. It is probably a good idea to browse through all columns and look at their definitions to get a better feel for this. Switch to the Primary Key tab. This takes us to Figure 11-18 on page 258, which shows the primary key settings.
257
Adjustments can be made, but in our case this is not required. Click the Foreign Key tab. The information about foreign keys, displayed in Figure 11-19, is quite interesting.
It shows a foreign key REMP relationship between the MGRNO column in table NULLID.DEPT, and the primary key field in table NULLID.EMP.
258
RSELFD is a second referential relationship corresponding to column ADRMDEPT in table NULLID.DEPT and related to the primary key field of the same table. We can look at the other two tables in a similar way. Our development experience shows that we may have a problem with the EMP_PHOTO_RESUME table. Open EMP_PHOTO_RESUME.tblxmi (Figure 11-20).
Select the Columns tab (Figure 11-20). The EMP_ROWID column is interpreted as a BLOB data type by WSAD (not the ROWID data type). Because we do not use this column in any of our queries directly, we can safely delete the EMP_ROWID column. (In addition, having the wrong data type is likely to cause problems during the generation process as well.) Restriction: Normally the presence of the ROWID should be transparent for the CMP generation, but currently this is a work-around. We are ready now for the next step, building the EJBs. Using bottom-up mapping from the relational database model, we build one CMP entity EJB for each table.
259
Make sure to be in a J2EE perspective, and have (in the left-upper corner) the Project Navigator view active. Put the focus on the ItsoEJB1 project. Right-click Generate EJB to RDB Mapping, as shown in Figure 11-21.
A first window (see Figure 11-22) pops up. We accept the defaults, and click Next.
Again, we accept the default on the next window (Figure 11-23). The EJB construction will be done bottom-up. The starting point is the table metadata, because these are EJBs for existing tables. Click Next.
260
Some information on this panel is crucial. Although older 1.1 CMP Beans still can be generated, but go the 2.x way, as only this type offers the new facilities. We also specify the project folder in which we like the EJB code to be packaged and a prefix that will be put in front of the artifact names. Click Finish. The mapping is now being created, and will complete after a while. We can verify a few things of interest. When the generation completes, the overview map is opened automatically (Figure 11-25), and we can look at mappings between the DB2 attributes and the properties of the CMP Beans.
Interesting to look at are the files prepared by the CMP generation process. We can look at them from different perspectives. Let us try using a Java perspective, as shown in Figure 11-27 on page 262.
261
In the ItsoEJB1/ejbModule project folder, we find a newly created package ejb.empl, in which we distinguish three groups of Java files (one group for each EJB). Each group is composed of four files (Bean, Key, LocalHome, Local (object)). The Beans that have been generated here can only be used via a local reference. (We did not select the option for remote reference.) This is new in EJB2.0. Let us have a quick look at the generated code, for example, for the DEPT table (Figure 11-27).
local hom e/interface ITSO DeptLocalH om e
finder
prim arykey/class IT SO DeptKey
lifecycle m ethods
m p ro
o tio
262
Attention: Local means that the caller (in our case the session Bean and the EJBs that are called), the entity Beans, has to reside in the same Java Virtual Machine (JVM). In the Figure 11-27 on page 262 you recognize the generated Java classes and interfaces for Bean DEPT. In the local/interface and Bean/class we find the same accessors (setters and getters). The accessors have been automatically promoted to the local interface. We also see the localhome/interface, which currently only has one finder method. More finders could be added or generated, so that the Bean can be approached by other means than its primary key. By opening (double-clicking) the file ITSODeptBean.java, we discover that accessors (getters and setters) have been generated for all table columns, except the columns ADMRDEPT and MGRNO, which are used as foreign keys to the DEPTNO (primary key in this DEPT) and EMPNO (primary key in EMP), but we find four additional accessors for EMP, DEPT, RSELFD, and REMP. The signatures of the methods clearly show what is obtained through those getters. The useful getters are:
public abstract ejb.empl.ITSODeptLocal getRselfd();
The previous signature is an abstract declaration for method getRselfd, which is the result of the referential integrity definition between field ADMRDEPT in table DEPT and the primary key of the same table DEPT. The method returns a local DEPT object, which is the administrative department this DEPT belongs to.
public abstract java.util.Collection getDept();
This signature is an abstract declaration for method getDept, which is also the result of the referential integrity definition between field ADRMDEPT in table DEPT and the primary key of the same table DEPT. The method returns a collection of local DEPT objects, all administered by this department.
public abstract ejb.empl.ITSOEmpLocal getRemp();
The previous signature is an abstract declaration for method getRemp, which is the result of the referential integrity definition between field MGRNO in table DEPT, and the primary key of table EMP. The method returns the local EMP object corresponding to the MGRNO as an employee attribute (EMPNO) in table EMP.
public abstract java.util.Collection getEmp();
This signature is an abstract declaration for method getEmp, which is a result of the referential integrity definition between field WORKDEPT in table EMP and table DEPT. The method returns a collection of local EMP objects, all belonging to the same WORKDEPT. By double-clicking the ITSOEmpBean.java file, we see that accessors (getters and setters) have been generated for all table columns, except the column WORKDEPT, which is used as a foreign key to the DEPTNO (primary key in DEPT). However, we find two additional accessors groups for DEPT and RDEPT. The useful getters are:
public abstract ejb.empl.ITSODeptLocal getRdept();
The previous signature is an abstract declaration for method getRdept, which is a result of the referential integrity definition between field WORKDEPT in table EMP and table DEPT. The method returns a local DEPT object corresponding to the WORKDEPT attribute in EMP as a department attribute (DEPTNO).
public abstract java.util.Collection getDept();
263
The previous signature is an abstract declaration for method getDept, which is the result of the referential integrity definition between field MGRNO in table DEPT and table EMP. The method returns a collection of local DEPT objects, all managed by the same MGRNO. When we switch to a J2EE perspective, and we look to the outline view (Figure 11-28) in the left bottom corner, while we have the ITSOEmpBean Java code displayed in the right-upper pane, we see that the getEmpno() method available in the Bean has not been promoted to the local interface. The getEmpno() method should have the indication L in front to indicate that it was promoted. We will do this manually. To do so, put focus on the getEmpno() method in the outline view, right-click Enterprise Bean Promote to Local Interface.
The same operation also has to be performed for the getDeptno() method on the ITSODeptBean and getEmpno() on the ITSOEmp_photo_resumeBean. Accessing the individual attributes of the CMP Bean one by one via the local interface is not the most efficient way of working. Each access to a getter could trigger the start of a transaction if the transactional attribute of the EJB method was not set correctly. To accommodate this problem we will use data transfer JavaBeans, which will transit between the CMP Bean and our application code and by which we can get all the information from the CMPBean in one operation. To do so, we add an additional business method to each Bean, getDepartment(deptno) for the ITSODeptBean, gand etEmployee(empno) for the ITSOEmpBean, returning all information in one JavaBean. These methods must also be promoted to the local interfaces on the Outline view. The Java classes for the data transfer must also be added, or made available through a linkage to a utility project ItsoUtil. We also add a business method getImage() (see Example 11-1) in the ITSOEmp_photo_resumeBean.java class, and this has to be promoted to the object class ITSOEmp_photo_resumeLocal.java as well. This corresponds to a getter on the getBmp_photo attribute, and expresses better what we want to acquire.
Example 11-1 getImage() method public byte[] getImage() { return getBmp_photo(); }
264
In Example 11-2 we show the data transfer Bean Java code for the department. From a theoretical point of view this is a real Bean. It has properties for which setters and getters are defined. The Bean also implements the Serializable interface. It is located in project ItsoUtil.
Example 11-2 empl.Department package empl; /** * department class for SG24-6319 */ public class Department implements Serializable { public String deptno; public String deptname; public String location; public String mgrno; public String admrdept; public String getAdmrdept() { return admrdept; } public String getDeptname() { return deptname; } public String getDeptno() { return deptno; } public String getLocation() { return location; } public String getMgrno() { return mgrno; } }
The new business method that has been added in the ITSODeptBean looks like Example 11-3.
Example 11-3 Business method for getting Department information public empl.Department getDepartment() { System.out.println("++ITSODeptBean_getDepartment"); empl.Department department = new empl.Department(); department.deptno = getDeptno(); department.deptname = getDeptname(); department.location = getLocation(); department.mgrno = getRemp().getEmpno(); department.admrdept = getRselfd().getDeptno(); return department; }
The actions required for the Emp table are similar, and are not explained in more detail.
265
section for the EMP Bean in Example 11-4 (not all CMP fields are shown). This was completely generated by the importing wizard.
Example 11-4 CMP definitions for EMP table <entity id="ContainerManagedEntity_1076976661213"> <ejb-name>Emp</ejb-name> <local-home>ejb.empl.ITSOEmpLocalHome</local-home> <local>ejb.empl.ITSOEmpLocal</local> <ejb-class>ejb.empl.ITSOEmpBean</ejb-class> <persistence-type>Container</persistence-type> <prim-key-class>ejb.empl.ITSOEmpKey</prim-key-class> <reentrant>False</reentrant> <cmp-version>2.x</cmp-version> <abstract-schema-name>Emp</abstract-schema-name> <cmp-field id="CMPAttribute_1076976661303"> <field-name>empno</field-name> </cmp-field> <cmp-field id="CMPAttribute_1076976661313"> <field-name>firstnme</field-name> </cmp-field> <cmp-field id="CMPAttribute_1076976661314"> <field-name>midinit</field-name> </cmp-field> <cmp-field id="CMPAttribute_1076976661323"> <field-name>lastname</field-name> </cmp-field> ............................. <cmp-field id="CMPAttribute_1076976661404"> <field-name>comm</field-name> </cmp-field> </entity>
The imported metadata also describe relationships between the tables. As a consequence, WSAD also adds relation description sections to the deployment descriptor, through the usage of container-managed relation (CMR) fields. This is new in CMP 2.0. As an illustration, Example 11-5 shows the section that is the result of the relationship (RDEPT foreign key) from the EMP table (column WORKDEPT) to the DEPT tables primary key.
Example 11-5 CMR definitions for EMP table->DEPT table relationship <ejb-relation> <ejb-relation-name>Emp_To_Dept</ejb-relation-name> <ejb-relationship-role id="EJBRelationshipRole_1076976661413"> <ejb-relationship-role-name>rdept</ejb-relationship-role-name> <multiplicity>Many</multiplicity> <relationship-role-source> <ejb-name>Emp</ejb-name> </relationship-role-source> <cmr-field> <cmr-field-name>rdept</cmr-field-name> </cmr-field> </ejb-relationship-role> <ejb-relationship-role id="EJBRelationshipRole_1076976661414"> <ejb-relationship-role-name>emp</ejb-relationship-role-name> <multiplicity>One</multiplicity> <relationship-role-source> <ejb-name>Dept</ejb-name> </relationship-role-source> <cmr-field>
266
Figure 11-29 shows the relationship in a picture. As a result of the CMR definitions, we have a getEmp() method on the Dept object and a getRdept() method on Emp. The property names come from the CMR names.
rdept(getRdept())
0..m
Emp
0..1
Dept Emp
empno
Emp
empno
emp(getEmp())
Another way to look at those relationships starts from the Beans tab of the deployment descriptor window. Open the deployment descriptor with its built-in editor by double-clicking the XML file. Then select the Beans tab and scroll to the relationships section, and expand the Emp-to-Dept relationship (Figure 11-30).
267
Click Edit on the relationship that you want yo look at, and then Next. A window like Figure 11-31 should appear. Note the characteristics of this relationship: Multiplicity: Defines whether an object or a collection is returned CMR field referencing: Determines the property name (emp on Dept, rdept on Emp)
We will now extend the deployment descriptor with EJB Query Language (EJBQL). This query tool is available since specification EJB 2.0. We will use it to have an additional find facility by Name on the EMP table through the CMP Bean. To achieve this, we must complete two tasks:
Adding the EJBQL statement description to the deployment descriptor Defining an additional finder in the ITSOEmpLocalHome.java interface
EJBQL statements belong to a particular entity Bean, and must be defined in a <query> section, inside the <entity> Bean scope. Example 11-6 shows the EJBQL description that has to be added inside the Entity section of the EMP Bean. To add the statement, you can directly edit the deployment descriptor XML file (Source tab), or use the Add button of the query section in the Beans tab of the deployment descriptor in WSAD.
Example 11-6 EJBQL statement in the deployment descriptor <entity id="ContainerManagedEntity_1076532486891"> <ejb-name>Employee</ejb-name> .......... <query> <description>EJBQL query for employees in 1 department</description> <query-method> <method-name>findByLastName</method-name> <method-params>
268
<method-param>java.lang.String</method-param> </method-params> </query-method> <ejb-ql>SELECT OBJECT(e) FROM Emp e WHERE e.lastname like ?1</ejb-ql> </query> </entity>
The additional finder that has to be added to the ITSOEmpLocalHome is shown in Example 11-7.
Example 11-7 Finder in ITSOEmpLocalHome.java /** * Finds instances by Lastname(via like): */ public java.util.Collection findByLastName(java.lang.String lastname) throws javax.ejb.FinderException;
After adding this finder, it may be a good idea to add an index on the lastname column, for performance reasons.
269
Note the presence of the three entity EJBs. At the bottom, we have several tabs to walk through the different parts of the deployment descriptor. We select the Beans one by one, and make the required additions. We first select the Dept Bean by clicking it (Figure 11-33).
The most important information to add at this moment is the binding information for JDBC to access DB2 data (WebSphere Bindings). This information is indirect; it is a reference to a resource definition that is assumed to be available in the WAS V5 servers (containers) that will be running this application. We use the name jdbc/ITSO1. This name can be changed at deployment. We set the container authorization type to Container. Connections to the data will be authorized based on the container (thread) (or in some cases the component JAAS alias will be used). Each EJB also has a lookup name (JNDIname) with which it can be found in the name space. We simplify this name by taking off the first ejb. We repeat the operation for the two other Beans and save the descriptor. Note: JDBC lookup names should by convention start with jdbc/. EJB lookup names should by convention start with ejb/.
270
Additional classes are created by the wizard. Some of those classes are a concrete implementation of the abstract definitions in the original Bean classes. Also, additional finders are now available. Those are visible in the concrete classes and have been promoted to EJSLocalCMPxxxHome classes, which implement the original LocalHome interface. We will have a look to those new finders for the Dept table (Figure 11-35). We are not supposed to make any changes to the generated Java code. To see these additional classes, it is best to switch to the Java perspective/package explorer view.
LocalH om e interface
new finders
The additional finders are a result of the CMR definitions in the deployment descriptor. The most useful finders for the Dept Bean are:
public ejb.empl.ITSODeptLocal findByPrimaryKey_Local(ejb.empl.ITSODeptKey primaryKey) public java.util.Collection findDeptByRempKey_Local(ejb.empl.ITSOEmpKey key) public java.util.Collection findDeptByRselfdKey_Local(ejb.empl.ITSODeptKey key) Chapter 11. Sample application
271
The EMPBean also got an additional finder as a result of the RDEPT relation:
public java.util.Collection findEmpByRdeptKey_Local(ejb.empl.ITSODeptKey key)
The next additional finder is a result of the EJBQL statement that we defined:
public java.util.Collection findByLastName_Local(java.lang.String lastname)
The only finder that we should use directly is the one that we added for EJBQL. All others are internal, and used implicitely by the getters and setters added as a result of the CMR fields. This concludes the preparation of the three CMP Beans for the imported tables: Dept JNDIname (ejb.empl.ITSODeptLocalHome) Emp JNDIname (ejb.empl.ITSOEmpLocalHome) Emp_photo_resume JNDIname (ejb.empl.ITSOCMPEmp_photo_resume) All three are part of one EJB project included in the EAR file called Itso1EAR.
Besides the general supporting packages, whose names start with com.ibm., and org.omg., we find three packages starting with ejb.empl related to the entity Beans. Two packages are general, while the third one seems to be back-end related. We conclude that we could have generated code for other back-ends in the same project. The differences are concentrated in one package, while the other packages are common. To find out what is specific to this package, we can open file ITSOEmpBeanFunctionSet_f2676a0f.java, for example. In this file you find the JDBC code for the (Create, Retrieve, Update, Delete (CRUD)) methods, and as we started from tables with a NULLID qualifier, the table references in the statements are unqualified.
272
page 57, and Figure 3-18 on page 64 for more details on how to specify datasource custom properties.
Put the focus on the ITSOUSER subdirectory (by clicking it), right-click, select Rename, and change to NULLID. As before, in the Data Perspective in the Navigator view, drill down in the file hierarchy under the project/ejbModule/META-INF/backends to the NULLID.EMP_PHOTO_RESUME.tblxmi file, and open it by double-clicking. In the window on the right that shows up, go to the Columns pane and delete the column EMP_ROWID. We never use this column in any query, and it causes problems in the generation process. After this, save the file. We now switch to a J2EE perspective, and we generate the four base classes of the CMP Bean by putting focus on the ItsoEJBPhotoCMPSQLJ project, right-click, select Generate EJB to RDB mapping. To be able to distinguish the new EJB from the existing CMP version, we use as a prefix ITSOSQLJ. At this time we have four classes/interfaces generated, and the file Map.mapxmi was opened in the right pane.
273
Before continuing we have to prepare the project/backend for using SQLJ instead of JDBC. When you highlight the project name in the middle subpane of the Map.mapxmi panel for this backend (see Figure 11-38), the bottom part shows the properties that will be used during the generation of the code.
In the Properties pane at the bottom, expand the SQLJ line, and change the value from false to true, and then save the map. The project itself must also be enabled for SQLJ. To do so, highlight the project, right-click, and in the pull-down list select Add SQLJ Support. This creates an additional subdirectory SQLJAntScripts under the project. Note: Ant (a command script language build into WSAD) will drive the program preparation and package bind process on the host for SQLJ. The last change to make before generating the deployment code is, like before, to add our business method getImage() in the ITSOSQLJEmp_photo_resumeBean.java class, and also promote it to the object class ITSOSQLJEmp_photo_resumeLocal.java. Save both classes. Now we can generate the deployment code for the CMP/SQLJ Bean by highlighting the project, right-clicking, and selecting Generate Deployment and RMIC code. This time more additional classes are generated. They are related to the SQLJ access. We find in our project, among others, the subdirectory (see Figure 11-39 on page 275) websphere_deploy.ItsoEJBPhotoCMPSQLJ.DB2UDBOS390_V7_1. It contains sqlj code, which was directly translated in Java code. During this translation, a .ser file (a serialized profile, which is a serialization of the class sqlj/runtime/profile/Profile) was also created. This
274
serialized profile, FS_DBD8_SJProfile0.ser, contains an entry for each SQL statement that has been created for the CMP Bean by the deployment generator. It is the input for the profile customization process, which (by default) drives the creation of the packages (with static SQL) on the system (z/OS), where finally everything will be deployed and run. (It is possible to split the customization process and bind process into two steps if required.)
The EJB code is now generated for SQLJ, but (as outlined in 7.2, Profile customization on page 146) additional steps are required to turn SQLJ programs into real static SQL. Those additional steps can be executed from within WSAD under the guidance of an Ant script. Note: An Ant script is the equivalent of a Make file but for Java preparation.
275
The db2 profile customization process (db2sqljcustomize) uses a type 4 connection to the DB2 system (DBD8). Therefore we need to specify a URL with a host name, port number, and DB2 location name. If you want, you can also specify additional (bind) parameters, such as a collection name you want the package to be bound into. url Options jdbc:db2://wtsc65.itso.ibm.com:38070/DBD8 -COLLECTION SG246319
The DB2 packages that will be created should all be grouped under a common collection. This a value that we can choose, but it should remembered. Click OK. A file sqlj.project.properties is created under the SQLJAntScripts directory in the project. Highlight the project, right-click, and select Generate SQLJ Customization script. This step changes sqlj.project.properties created in the previous step, but also added a new file sqlj.customize.xml, which contains input for the Ant utility (Figure 11-41).
Highlight the project again, right-click, and select Properties SQLJ Customization script (Figure 11-42).
In Figure 11-42 the name of the serialized profile was added together with a proposed (default) package prefix of maximum seven characters, because one package will be generated for each of the four isolation levels and a 14 will be appended to the name. We change this name to avoid conflicts with other package names. We change to CPHOEMP. Note that, besides the COLLECTION, we added additional parameters QUALIFIER and BINDOPTIONS. This is additional information for the bind process, since we have unqualified SQL statements (see the FS_DBD8.sqlj member of this backend, for example). With these bind options, the unqualified table names in the SQL statements are prefixed with the ITSOUSER qualifier. Click OK to save. At this point we are ready to run the Ant utility for the customization script through a type 4 connection, and generate the packages in the specified collection. 276
DB2 for z/OS and WebSphere: The Perfect Couple
Highlight the sqlj.customize.xml file, right-click, and select Run Ant. On the first panel that shows up (Figure 11-43), switch to the Properties pane.
Here we use the Add button on the right side to add additional properties required for a successful bind on DB2 z/OS. Add the following: db.user: BARTR1 db.password: xxxxxxx
277
When this is done, click Run. The output of the bind should be similar to the output shown in Example 11-8.
Example 11-8 Binding of the SQLJ packages Buildfile: C:\itsosj\IBM\wsappdev51\workspace\ItsoEJBPhotoCMPSQLJ\SQLJAntScripts\sqlj.customize.xml websphere_deploy.ItsoEJBPhotoCMPSQLJ.DB2UDBOS390_V7_1.FS_DBD8: [java] [ibm][db2][jcc][sqlj] [java] [ibm][db2][jcc][sqlj] Begin Customization [java] [ibm][db2][jcc][sqlj] Loading profile: websphere_deploy\ItsoEJBPhotoCMPSQLJ\DB2UDBOS390_V7_1\FS_DBD8_SJProfile0 [java] [ibm][db2][jcc][sqlj] Customization complete for profile ..\ejbModule\websphere_deploy\ItsoEJBPhotoCMPSQLJ\DB2UDBOS390_V7_1\FS_DBD8_SJProfile0.ser [java] [ibm][db2][jcc][sqlj] Begin Bind [java] [ibm][db2][jcc][sqlj] Loading profile: websphere_deploy\ItsoEJBPhotoCMPSQLJ\DB2UDBOS390_V7_1\FS_DBD8_SJProfile0 [java] [ibm][db2][jcc][sqlj] Driver defaults(user may override): BLOCKING ALL VALIDATE BIND [java] [ibm][db2][jcc][sqlj] Fixed driver options: DATETIME ISO DYNAMICRULES BIND [java] [ibm][db2][jcc][sqlj] Binding package CPHOEMP1 at isolation level UR [java] [ibm][db2][jcc][sqlj] Binding package CPHOEMP2 at isolation level CS [java] [ibm][db2][jcc][sqlj] Binding package CPHOEMP3 at isolation level RS [java] [ibm][db2][jcc][sqlj] Binding package CPHOEMP4 at isolation level RR [java] [ibm][db2][jcc][sqlj] Bind complete for websphere_deploy\ItsoEJBPhotoCMPSQLJ\DB2UDBOS390_V7_1\FS_DBD8_SJProfile0 customizeAll: BUILD SUCCESSFUL Total time: 3 seconds
When everything runs fine, four packages for different Isolation levels are created on the DB2 for z/OS system (DBD8).
278
This concludes preparation of the CMPSQLJ project for the table EMP_PHOTO_RESUME with qualifier ITSOUSER. The generated SQLJ code is located in websphere_deploy.ItsoEJBPhotoCMPSQLJ.DB2UDBOS390_V7_1.FS_DBD8.sqlj. When we open this file, we clearly see the SQL instructions, which are unqualified.
The information to add is the binding information for JDBC/SQLJ. This information is indirect. It is a reference to a resource definition that is assumed to be available in the WAS V5 servers (containers) running this application. We select the name jdbc/ITSO1. This name can be changed at deployment time if required. Again, we set the container authorization type to Container. Each EJB also has a lookup name (JNDIName) with which it can be found in the name space. We simplify this name by taking off the first ejb. We should now be able to use this PhotoBean also in the model from within the session Bean. Emp_photo_resume: JNDIname (ejb.empl.ITSOCMPSQLJEmp_photo_resume) This CMP/EJB project is also included in EAR Itso1EAR.
279
280
Click Next and you will get a new pop-up for selecting the type of Bean (Figure 11-48).
Select Entity BMP, and specify the Bean name, Source folder, and Default package as indicated above. Click Next and go to the window shown in Figure 11-49.
281
Since the EJB 2.0 specification, EJBs can have local and remote interfaces. Leave the panel as is, with only the local interface selected, and click Finish. Note: Both interfaces are possible. The remote interfaces use the Object Request Broker; the caller and the object that is called can reside in separate containers. With local interfaces both reside in the same container, or in practice in the same Java Virtual Machine (JVM). Four Java files are created in the package ejb.empl, as indicated in Figure 11-50.
Besides this, the META-INF information (deployment descriptor ejb-jar.xml, IBM extensions, etc.) has also been prepared. All those files have to be completed. The difference between the CMP approach and the BMP approach is that in this case (BMP) those files are only placeholders and the code has to be written manually. The first file we tackle is PhotoEmployeeBMPKey.java, shown in Example 11-9.
Example 11-9 PhotoEmployeeBMPKey class package ejb.empl; /** * Key class for Entity Bean: PhotoEmployee */ public class PhotoEmployeeBMPKey implements java.io.Serializable { static final long serialVersionUID = 3206093459760846163L; /** Implementation field for key attribute: photo_format */ //public java.lang.String photo_format; public PhotoEmployeeBMPKey() { } /** Implementation field for key attribute: empno */ public java.lang.String empno; /** Creates a key for Entity Bean: Employee */ public PhotoEmployeeBMPKey(java.lang.String empno) { this.empno = empno; } /** Creates a key for Entity Bean: Employee,Emp_photo */ public boolean equals(java.lang.Object otherKey) { if (otherKey instanceof ejb.empl.PhotoEmployeeBMPKey) { ejb.empl.PhotoEmployeeBMPKey o = (ejb.empl.PhotoEmployeeBMPKey) otherKey; return (super.equals(otherKey)); } return false; } /** Returns the hash code for the key. */ public int hashCode() { return (super.hashCode());
282
} }
The PhotoEmployeeBMPKey program contains the reference to the primary key of the PhotoEmployee table. The key Empno is a string of six characters. Figure 11-51 shows a schematic representation of a BMP Bean. We recognize the artifacts. The object and home can exist in local and remote versions. This makes a total of six.
local/remote home
create
bean
ejbCreate ejbPostCreate
client
ORB
by reference
te mo re al loc
findbyPrimaryKey find...
ejbFindbyPrimaryKey ejbFind...
local/remote object
loc al re mo te
business methods
setters getters
primarykey
In our scenario we only use local versions. Note: Clients allways access the API on the home for finders and creation, and on the object for business methods, which include setters/getters and whatever methods are provided. All business methods are implemented on the Bean, but those that have to be used from a client must be promoted on the object. The so-called life-cycle methods require a compulsory implementation on the Bean. Those methods are driven by the container when needed. What does it mean in practice? The create, finder methods on the home have a corresponding EjbCreate, EjbFinder on the Bean. The callback methods that are automatically invoked by the EJB container must be present on the Bean and coded to fulfill their role as expected. In this design an entity Bean reflects the contents of one row in a relational database. EjbCreate() EjbLoad() EjbStore EjbRemove() -> Create a new row. -> Load the row. -> Update the row. -> Delete the row.
All business methods (our methods) that we like to invoke must be present on the Bean and promoted to the object interface. For example, we would like to have a method
283
getImage() to get the image of an employee. The method must be written on the Bean and then promoted to the object interface. The Java code for the other BMP sources is shown hereafter. The local home interface (Example 11-10) has two lifecycle methods defined: create() and findByPrimaryKey(). In the Bean, we find the counterparts of the methods with ejb in front.
Example 11-10 Local home interface package ejb.empl; /** * Local Home interface for Enterprise Bean: PhotoEmployeeBMP */ public interface PhotoEmployeeBMPLocalHome extends javax.ejb.EJBLocalHome { /** * Creates an instance from a key for Entity Bean: PhotoEmployeeBMP */ public ejb.empl.PhotoEmployeeBMPLocal create() throws javax.ejb.CreateException; /** * Finds an instance using a key for Entity Bean: PhotoEmployeeBMP */ public ejb.empl.PhotoEmployeeBMPLocal findByPrimaryKey( ejb.empl.PhotoEmployeeBMPKey primaryKey) throws javax.ejb.FinderException; }
The local interface (Example 11-11) has one business method defined: getImage(). This is a result of the promotion of the method from the Bean.
Example 11-11 Local interface package ejb.empl; /** * Local interface for Enterprise Bean: PhotoEmployeeBMP */ public interface PhotoEmployeeBMPLocal extends javax.ejb.EJBLocalObject { public byte[] getImage(); }
Notice that in Example 11-12, the life-cycle callback methods start with Ejb. As mentioned, the presence of these methods is mandatory, even though there is no code associated with the non-select part. The getImage() method, which is the business method in this Bean, requires the promotion to the object. The getImage() method returns the BLOB, a picture of the employee. The access to DB2 is using JDBC. You can also see that the SQL select statement is unqualified.
Example 11-12 BMP Bean package ejb.empl; //import empl.G5Exception; /** * Bean implementation class for Enterprise Bean: PhotoEmployee */ public class PhotoEmployeeBMPBean implements javax.ejb.EntityBean { private javax.ejb.EntityContext myEntityCtx; private boolean debugOn = true; static final String emplphotozos = "SELECT EMPNO, BMP_PHOTO FROM EMP_PHOTO_RESUME WHERE EMPNO = ?";
284
private javax.sql.DataSource ds; private byte[] imagebytes; private String empno; private java.sql.Connection conn; private java.sql.PreparedStatement pstmt; private ejb.empl.PhotoEmployeeBMPKey prikey; private String imagetype = "gif"; private static String dsname = "ITSODB2"; // <========== initialize dsname ====== private java.sql.Blob image; boolean isModified; /** * ejbActivate */ public void ejbActivate() { } /** * ejbLoad */ public void ejbLoad() { //if (this.imagebytes != null) // return; java.sql.ResultSet rs = null; ejb.empl.PhotoEmployeeBMPKey prikey = (ejb.empl.PhotoEmployeeBMPKey) myEntityCtx.getPrimaryKey(); String empno = prikey.empno; System.out.println("++PhotoEmployeeBMPBean_ejbLoad " + empno); try { conn = ds.getConnection(); rs = selectByPrimaryKey(empno); if (rs != null) { if (!rs.next()) { System.out.println( "++PhotoEmployeeBMPBean_ejbLoad NO photo"); } else { if (this.debugOn) System.out.println( "++PhotoEmployeeBMPBean_ejbLoad extracting photo"); do { java.sql.Blob image; image = rs.getBlob(2); if (image != null) { this.imagebytes = image.getBytes((long) 1, (int) image.length()); if (this.debugOn) System.out.println( "++PhotoEmployeeBMPBean_ejbLoad photolength " + this.imagebytes.length); } else { System.out.println( "++PhotoEmployeeBMPBean_ejbLoad getBlob() returned NULL"); } } while (rs.next()); } rs.close(); } pstmt.close(); conn.close(); } catch (java.sql.SQLException ex) { System.out.println( "++PhotoEmployeeBMPBean_ejbLoad SQLException " + ex.toString());
285
throw new javax.ejb.EJBException( "++PhotoEmployeeBMPBean_ejbLoad SQL error " + ex.getMessage()); } catch (Exception ex) { System.out.println( "++PhotoEmployeeBMPBean_ejbLoad Exception " + ex.toString()); throw new javax.ejb.EJBException( "++PhotoEmployeeBMPBean_ejbLoad error " + ex.getMessage()); } if (this.debugOn) System.out.println("++PhotoEmployeeBMPBean_ejbLoad returning"); return; } /** * ejbPassivate */ public void ejbPassivate() { } /** * ejbRemove */ public void ejbRemove() throws javax.ejb.RemoveException { } /** * getEntityContext */ public javax.ejb.EntityContext getEntityContext() { return myEntityCtx; } /** * setEntityContext */ public void setEntityContext(javax.ejb.EntityContext ctx) { myEntityCtx = ctx; try { try { this.ds = itso.ibm.servlets.GetFromCtx.getDs(dsname); if (this.ds == null) System.out.println( "++PhotoEmployeeBMPBean_JNDIlookup datasource NULL"); else { System.out.println( "++PhotoEmployeeBMPBean_JNDIlookup datasource OK"); } } catch (Exception e) { System.out.println( "++PhotoEmployeeBMPBean_JNDIlookup datasource exception " + e.toString()); } } catch (Exception ex) { System.out.println( "++PhotoEmployeeBMPBean_setEntityContext " + ex.toString()); } } /** * unsetEntityContext */ public void unsetEntityContext() { myEntityCtx = null; } /**
286
* ejbCreate */ public ejb.empl.PhotoEmployeeBMPKey ejbCreate() throws javax.ejb.CreateException { System.out.println("++PhotoEmployeeBMPBean_ejbCreate"); return null; } /** * ejbPostCreate */ public void ejbPostCreate() throws javax.ejb.CreateException { } /** * ejbFindByPrimaryKey */ public ejb.empl.PhotoEmployeeBMPKey ejbFindByPrimaryKey( ejb.empl.PhotoEmployeeBMPKey prikey) throws javax.ejb.FinderException { ejb.empl.PhotoEmployeeBMPKey pk = null; this.prikey = prikey; this.empno = prikey.empno; System.out.println( "++PhotoEmployeeBMPBean_ejbFindByPrimaryKey " + empno); //System.out.println("++PhotoEmployeeBMPBean_JNDIlookup connection OK"); java.sql.ResultSet rs = null; try { conn = ds.getConnection(); System.out.println( "++PhotoEmployeeBMPBean_ejbFindByPrimaryKey connection OK"); rs = selectByPrimaryKey(this.empno); if (rs != null) { if (!rs.next()) { if (this.debugOn) System.out.println( "++PhotoEmployeeBMPBean_ejbFindByPrimaryKey NO photo"); } else { rs.close(); pstmt.close(); pk = prikey; } } else { pstmt.close(); } conn.close(); } catch (java.sql.SQLException ex) { System.out.println( "++PhotoEmployeeBMPBean_ejbFindByPrimaryKey SQLException " + ex.toString()); throw new javax.ejb.EJBException( "++PhotoEmployeeBMPBean_ejbFindByPrimaryKey SQL error " + ex.getMessage()); } catch (Exception ex) { System.out.println( "++PhotoEmployeeBMPBean_ejbFindByPrimaryKey Exception " + ex.toString()); throw new javax.ejb.EJBException( "++PhotoEmployeeBMPBean_ejbFindByPrimaryKey error " + ex.getMessage()); } return pk;
287
} /** * ejbStore */ public void ejbStore() { System.out.println("++PhotoEmployeeBMPBean_ejbStore"); /*------------------------*/ if (!isModified) return; /*------------------------*/ ejb.empl.PhotoEmployeeBMPKey prikey = (ejb.empl.PhotoEmployeeBMPKey) myEntityCtx.getPrimaryKey(); String empno = prikey.empno; //String imagetype = prikey.photo_format; System.out.println( "++PhotoEmployeeBMPBean_ejbStore " + empno + " imagetype " + "N/A"); } private java.sql.ResultSet selectByPrimaryKey(String empno) throws java.sql.SQLException { java.sql.ResultSet rs = null; if (this.debugOn) System.out.println( "++PhotoEmployeeBMPBean_selectByPrimaryKey looking for photo for " + empno); pstmt = conn.prepareStatement(emplphotozos); pstmt.setString(1, empno); rs = pstmt.executeQuery(); if (this.debugOn) System.out.println( "++PhotoEmployeeBMPBean_selectByPrimaryKey returning resultset"); return rs; } public byte[] getImage() { //try { System.out.println("++PhotoEmployeeBMPBean_getImage"); return this.imagebytes; /* } catch (java.sql.SQLException ex) { System.err.println( "++PhotoEmployeeBean_getImage SQLException " + ex.toString()); return null; } */ } }
After the Java code has been completed, we still have some basic work to do.
288
Figure 11-52 displays the Beans panel inside the deployment descriptor of the BMP project. It shows the name of the BMP Bean that will be used for the lookup in the name space and the four classes that are part of the BMP.
We still miss a reference to the data source. To fix this, switch to the References tab of the deployment descriptor (Figure 11-53).
289
In this panel we establish the link between the symbolic data source name ITSODB2 used in the Bean code, and the logical data source name jdbc/ITSO1. During deployment we still can adapt this value. In reality we introduced an additional indirection. We set the container authorization type to container, which means that when the connection to DB2 takes place, the user ID is implicitely picked up from the thread under which the connection takes place. This user ID could be the server (servant) user ID, or if a sync to thread took place, it is the U(ser)token that was put on the thread by the J2EE authorization mechanism. The authorization type is set in the deployment descriptor ejb-jar.xml for this Bean. Each EJB also has a lookup name (JNDIName) with which it can be found in the name space. We simplify this name by taking off the first ejb (see Figure 11-52 on page 289). We now save the deployment descriptor. The last operation that has to be done for this project is the generation of the deployment code. This is the same as before. Highlight the project, right-click, and select Generate Deployment and RMIC code.
In the next window (Figure 11-55 on page 291), enter/select the name of the Enterprise project. We use ItsoEJB1.
290
Click Next, and go to a window like Figure 11-56. Select the type, Session Bean. (Note that Session Bean was automatically selected.) Enter the Bean name, the Source folder, and the Java Default package of the Bean.
Click Next, and we go to the next screen with Bean options (Figure 11-57 on page 292).
291
Our session Bean will be stateless; it behaves basically like a transaction without state, and we request a local interface (but also have the remote interface checked, as it is indeed possible to have both). Click Finish. Figure 11-58 shows the layout view of the new Bean. A session Bean also has life-cycle methods, those starting with ejb. We added four get methods (business) corresponding with the request that will emerge from the actions.
getEmployee() getImage() Each method returns a data transfer Bean with requested information, if the request went fine; otherwise the return is null. We always have three input parameters, as can be seen in Example 11-13, for getEmployee(). ParameterS 1 and 3 are obvious; parameter 2, a HashMap, can be used for communication between components, for example, for error information.
Example 11-13 getEmployee() method public Employee getEmployee( String empno, java.util.HashMap reqhm, boolean debugOn) { .................. }
The resulting data transfer Bean will then be passed to the view component. This part of the scenario is shown in Figure 11-59.
M odel
C on troller
ITS OA c c ess SessionEJ B
Employ ee Entity /C MP
Action s
To view
Put data transfer in Servlet Container
D epartment Entity /C MP
S ervlet
T4
P hotoEmploy ee E ntity /C MP
T2
D B2
EJBs
The deployment descriptor for the EJB project (ejb-jar.xml) contains specific parts for this Bean. Important information is the JNDIname of this Bean in its section. The convention is that this name should always start with ejb/. With this name, the Bean will be known in the name space, which, as we recall for WAS V5, is located in the HFS. The lookup of the Bean home via a direct name, or indirectly via a reference, will be for this name. Figure 11-60 on page 294 shows the Bean tab for the session Bean (ITSOAccess) of the deployment descriptor.
293
From within the session Bean ITSOAccessBean, the business methods will access the entity Beans. To look up the homes of those Beans, which is the first step in the access, we use reference names. Those names have to be connected to the real JNDI home names. This information is in the References section of the deployment descriptor, as shown in Figure 11-61 on page 295.
294
As an example let us have a quick look at the code to invoke the getEmployee() method on the CMP Bean ITSOEmpBean, shown in Example 11-14.
Example 11-14 getEmployee method public Employee getEmployee( String empno, java.util.HashMap reqhm, boolean debugOn) { empl.Employee employee = null; String ejbref = "ITSOEmp"; System.out.println( "++ITSOAccessBean_getEmployee looking_up " + ejbref + " for key " + empno); ITSOEmpLocal infoemployee = null; ITSOEmpKey infoprimarykey = new ITSOEmpKey(empno); /* fill primary ky */ infoemployee = (ITSOEmpLocal) itso.ejb.util.EjbFactory.singleton().findByRefPrimaryKey( ejbref, ITSOEmpLocal.class, infoprimarykey); if (infoemployee == null) { String infomsg = ++ITSOAccessBean_getEmployee Employee " + empno "NOT found"; doErr(infomsg, reqhm); return null; } else { if (debugOn) System.out.println( ++ITSOAccessBean_getEmployee handle to employee OK"); return infoemployee.getEmployee(); }
295
The steps are following: As parameters we get the empno and an HashMap for communication. The empno is used to set the primary key class. We use a utility class Ejbfactory, which: Does lookup of the home of the entity CMP via a reference Executes immediately a finder by primary key Returns the local object On the local object, we execute getEmployee() to get the data transfer Bean Employee. We return the data Bean to controller or null if unsuccessful, and error information is returned via the HashMap. The final preparation step for the session Bean is the generation of the deployment code. Highlight the ItsoEJB1 project, right-click, and select Generate Deployment and RMIC code. This takes you to a window like Figure 11-62.
Select the Beans for which you want to generate deployment code. Click Finish. After this, the Model component of our scenario is complete.
296
Browser
View
Model
Controller
EmpIndexJSP
ITSOAccess SessionEJB
Employee Entity/CMP
Actions
EmployeeJSP SVImage
Department Entity/CMP
PhotoEmployee Entity/BMP
DepartmentJSP
Servlet
EJBs
PhotoEmployee Entity/CMP
T4
DB2
T2
DepEmployeeListJSP
JSPs
Action control
As mentioned above, the view component consists of four JSPs and one presentation servlet. Before the controller dispatches the presentation to the JSPs, the data transfer Bean, which was returned from the session Bean in the model, has been put in the main servlet container. This happens in the actions in the controller with the following instruction:
request.setAttribute("infoemployee", employee);
The same instructions can be found for the other data transfer Beans. As a result, it is possible to use JSP tags for picking up the contents of the data transfer Beans. This is a common technique. To illustrate this, we use the JSP ITSOEmployee.jsp, shown in Example 11-15. jsp:useBean addresses a Bean of type empl.Employee located in the request container with label infoemployee. jsp:getProperty references infoemployee and pulls out the property, for example, empno. A getEmpno() is executed on the Bean. The code for all JSPs can be found in the additional material that is downloadable from the Web. See Appendix A, Additional material on page 319, for details.
Example 11-15 ITSOEmployee.jsp <BODY bgcolor="#ffff80" text="#0000ff" link="#00cc00"> <jsp:useBean id="infoemployee" class="empl.Employee" scope="request"/> <P><IMG src="goldengate.jpg" width="512" height="91" border="0"><BR> <BR> <FONT size="+3">Employee Information for <jsp:getProperty name="infoemployee" property="empno"/></FONT></P> <HR> Chapter 11. Sample application
297
<TABLE border="1"> <TBODY> <TR> <TD>empno</TD> <TD width="200"><jsp:getProperty name="infoemployee" property="empno"/></TD> <TD rowspan="8" width="152"><IMG src="/ItsoEmpl/employeeEJB.do?action=image&TRACE=YES&empno=<jsp:getProperty name="infoemployee" property="empno"/>&photobean=<jsp:getProperty name="infoemployee" property="photobean"/>" border="0"></TD> </TR> <TR> <TD>firstname</TD> <TD><jsp:getProperty name="infoemployee" property="firstnme"/></TD> </TR> <TR> <TD>lastname</TD> <TD><jsp:getProperty name="infoemployee" property="lastname"/></TD> </TR> ............ </TBODY> </TABLE> <hr> <TABLE width=100%> <TR> <TD width=50%> <A HREF=/ItsoEmpl/empIndex.do>BACK TO HOME PAGE</A> </TD> <TR> </TABLE> </BODY> </HTML>
The explanation of the view component here is only for completeness. For further reading about JSP techniques, it is best to consult more specialized documentation on this subject.
298
Browser
Model
View ?
Controller
ITSOAccess SessionE JB
E mployee E ntity/CMP
Department Entity/CMP
PhotoEmployee Entity/BMP
JSP's
T4 EJBs
DB2
T2
ActionServlet
StrutsConfig XML
The controller is built in a Web project ItsoWEB1. During the creation of the project we ask the inclusion of Struts support. Now we go over the sequence of actions to create the Web project. Create a new project (top left button in WSAD), and in the selection panel, select Web in the left column, and Dynamic Web Project on the right side of the window shown in Figure 11-65.
299
Click Next. In the next screen (Figure 11-66) give a name to the project (ItsoWEB1).
ItsoEmpl
This project is at J2EE level 1.3, and is also part of the Enterprise Application Itso1EAR, the same Application Project as the EJBs. An important element to specify here is the context root, which is the first part the URL requests for this Web application; for example, the original URL request would be like:
http://wtsc54.itso.ibm.com:9080/ItsoEmpl/empIndex.do
300
Click Next and a window for special support choices is displayed (Figure 11-68).
Check Add Struts support, and the struts.jar, JSP TLD files, belonging to the Struts framework will be included in the project. As a result the Struts framework will be automatically part of this Web project. This includes a Servlet called ActionServlet, and TLD files (Customer tag files for JSP). Click Next. The window in Figure 11-69 is shown next.
The deployment descriptor of the Web project will automatically indicate the presence of Struts. Struts exist in different versions. We select level 1.1. Accept the defaults, and click Finish. The project is now created. The heart of the struts framework is the Actionservlet, which is part of the included modules. All input is received by this servlet. Depending on a token in the URL request and mapping
301
information in the struts-config.xml file, the Actionservlet dispatches an action, as shown in Figure 11-70.
JS P
s e r v le t
A c tio n S e r v le t
a c t io n s A c t io n s
s tr u ts - c o n f ig . x m l
a c tio n s F o rm s
In general, an action is associated with a form. The form allows an easy retrieve and a verification of the input before the action is really linking to the model. A look at the struts-config.xml file can help to clarify things. This file is located under the Webcontent (document root) of the Web project. In a J2EE perspective, looking at the Project Navigator in the J2EE view, we observe the structure of the Webcontent for the project (ItsoWEB1). Note the location of the JSPs in there, and under the subdirectory WEB-INF, the deployment descriptor web-xml, struts tld files, and struts-config.xml (Figure 11-71 on page 303).
302
Double-click the struts-config.xml to open it, and select the Action Mappings tab. Your screen should look like Figure 11-72.
In the left part of Figure 11-72 we recognize the action token and in the right part the corresponding action module class. In the Form Bean Specification section, you can specify a form class if one is associated with this action. The action classes will invoke the model, while
303
the form class allows easy access to the input from the browser. The token mapping comes from the URL. For example, in the following URL:
http://wtsc54.itso.ibm.com:9080/ItsoEmpl/employeeEJB.do
ItsoEmpl is the context root as specified in the Application.xml of the EAR project. employeeEJB.do is composed of two parts:
*.do triggers the ActionServlet (URL specification in the deployment descriptor). employeeEJB is used for the mapping to the action.
Four tokens have been defined. All have an action and a form associated, except empIndex, which only drives the menu JSP. To understand how the *.do part leads us to the Actionservlet, we have a look in the file web.xml in the directory Webcontent/WEB-INF. We open the file by double-clicking. This opens the Servlets and JSPs window (Figure 11-73). On the left side in the window, we see the names of the Servlets, which are part of the Web project. Put the focus on action. On the right side, we see the name of the java class that corresponds with this Servlet; and under URL Mappings, the url *.do that leads to it. The other two Servlets are specialized; for example, the SVimage is required for sending images to the browser. JSP supports only text. This Servlet also has a URL mapping, which will be used from within the controller as a new forward action. The information on the action servlet was created automatically when we included Struts support with the Web project. .
The action Servlet forwards to actions, or to the View component. The actions in our case will direct the request to the models. The entry to the models is a session Bean, as mentioned before. Example 11-16 on page 305 shows the code for an action for the URL employee.do.
304
Example 11-16 Action class for employee.do package itsoweb1.actions; import ....... import org.apache.struts.action.ActionErrors; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import empl.Employee; import empl.AcquireEmpModel; public class EmployeeEJBAction extends Action { public ActionForward execute( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { ActionErrors errors = new ActionErrors(); ActionForward forward = new ActionForward(); EmployeeEJBForm employeeEJBForm = (EmployeeEJBForm) form; String action = employeeEJBForm.getAction(); String fw = "info"; boolean debugOn = true; try { String empno = employeeEJBForm.getEmpno(); HashMap reqhm = new HashMap(); if (action.equals("info")) { /* What type of Bean will be used for Employee? */ reqhm.put( "empaccess", employeeEJBForm.getEmpaccess()); /* lookup Local Home of Session bean, invoke getEmployee through Object interface */ Employee employee = (AcquireEmpModel.acquireLocal(debugOn)).getEmployee(empno, reqhm, debugOn); if (employee != null) { employee.setPhotobean(employeeEJBForm.getPhotobean()); request.setAttribute("infoemployee", employee); /* pass employee via request container */ } else { ........ request.setAttribute("ERRORMSG", errormsg); /* pass ERRORMSG via request container */ fw = "empIndex"; /* forward is index menu */ } forward = mapping.findForward(fw); /* set forward */ } else { /* What type of Bean will be used for Image? */ reqhm.put("photobean",employeeEJBForm.getPhotobean()); /* lookup Local Home of Session bean, invoke getEmployee through Object interface */ byte[] image = (AcquireEmpModel.acquireLocal(debugOn)).getImage(empno, reqhm, debugOn); if (image != null) { request.setAttribute("IMAGE", image); /* pass image via request container */ fw = "image"; /* forward is image */ forward = mapping.findForward(fw); /* set forward */ } else { System.out.println("++ImageOut_write NO image"); } } } catch (Exception e) { ............ request.setAttribute("ERRORMSG", errormsg); fw = "empIndex"; } } forward = mapping.findForward(fw); Chapter 11. Sample application
305
return (forward); } }
A user action class is an extension of the Action class of the Struts framework. The important method to consider and to write is perform. This method has an imposed signature and must return a forward class. This class will be used by the Action servlet to determine what to do next. The parameters passed on the call allows access to all required information, including the request. In our example we process two demands: Text information about the employee Image of the employee In both sections, after recuperating the params, the session Bean, entry to the model, is instantiated via a local home interface, and a business method is invoked through the returned local object. The response object is then stored in the container of the request as an attribute, which can be easily used by the view (JSP).
On the left side, we have the list of all Web and EJB projects included in the EAR project, and under Project Utility JARs, a list of additional jars with support/utility classes. The Web project ItsoWeb1 is highlighted, and as a result on the right we find the value of the Context Root,
306
which has to be included as the first token in the URL requests. After the context root, the
Where:
ItsoEmpl: Context root (selects the WebApplication) EmplIndex.do EmplIndex: Will be the action that is defined by the Struts config file .do: Is the URL matching that points to the Actionservlet
The .ear file can be exported directly from the WSAD development tool and used as input in the deployment process into WAS V5 for z/OS. To do so, highlight the project Itso1EAR, right-click, and select Export. In the Export panel, select the EAR file, click Next, and follow the instructions for selecting a name and a directory. At this stage it is not required to include the source files. We call our file Itso1EAR.ear.
307
As our EAR file is located on the workstation, so we use the Local path option, and specify the path name of the file. Click Next and accept the default binding and mappings, as shown in Figure 11-76.
Click Next and you will see an option list (Figure 11-77).
Use the options as indicated above. It is possible (if needed) to regenerate the deployment code for the EJBs, but this is not required in our case. Click Next. Figure 11-78 on page 309 is next. It lists the projects that are part of this J2EE Application.
308
Click Next. This takes you to Figure 11-79, a list of all the EJBs that are part of this J2EE application and their JNDIName, which can be changed if needed. We do not recommend this. Try to use the correct names in WSAD.
In our case there is no need to change the JNDInames, and we accept by clicking Next. A new window, Figure 11-80 on page 310, shows the datasource references as set in WSAD.
309
The right datasource name, which has been defined as a JDBC resource in WAS V5, has to be set here for default datasources. This can be a data source using T2 or T4 connectivity, as long as we can reach our DB2 tables through it. Simply override the values with the correct jdbc/ name. Click Next. The window in Figure 11-81 shows up next.
Again datasource JNDI names have to be overridden with real existing values. Resource authorization can also be changed. Click Next. Figure 11-82 on page 311, which is next, displays the references between the artifacts in the J2EE application.
310
What is shown here is the result of references from the Web application or the session EJB to the Beans. The proposed values are a result of information in the deployment descriptors. We can accept those values, and click Next. A new window, related to the PhotoBMP, pops up (Figure 11-83).
Change again to the right data source, and click Next. The next panel (Figure 11-84 on page 312) is related to the Virtual Host, on which this application can be reached.
311
This information is only related with the Web application. A J2EE Web server has the concept of Virtual Host being a distinct DNS address for a server. It also has a default_host associated. Our current Webapp in the EAR file is linked to the default Virtual Host. Click Next once more. This takes use to Figure 11-85, a final overview of all modules in this J2EE application, and gives you the possibility to indicate in which Application Server this J2EE application must be deployed.
Normally we would have a choice between several servers installed on WAS V5. However, in our case, only one is available. Accept and click Next. This takes us to Figure 11-86.
We do not consider protection settings in our application, and we click Next. A last summary overview is displayed (Figure 11-87 on page 313).
312
Click Finish. The application is now installed. When done, Figure 11-88 is displayed. The application was successfully installed, and you can now save to the master configuration.
313
000140
In this window we have three sections: Employee Department EmployeeList in Department For the selected option, we have to enter the key, and select the type of application we want to use (if available). For instance, when retrieving an Employee, we can indicate which type of entity Bean should be used for the Employee data and the Employee picture. We specify an empno, 000140, and keep CMP/JDBC for both Emp and Photo. The result is shown in Figure 11-90 on page 315.
314
315
316
Appendixes
317
318
Appendix A.
Additional material
This redbook refers to additional material that can be downloaded from the Internet as described below.
Select the Additional materials and open the directory that corresponds with the redbook form number, SG24-6319.
JCL used to create DB2 objects (DSNTEJ1).txt JCL used to create DB2 LOB objects (DSNTEJ7).txt
320
Related publications
The publications listed in this section are considered particularly suitable for a more detailed discussion of the topics covered in this redbook.
IBM Redbooks
For information on ordering these publications, see How to get IBM Redbooks on page 322. Note that some of the documents referenced here may be available in softcopy only. DB2 for z/OS Version 8 Everything you ever wanted to know, ... and more, SG24-6079 Squeezing the Most Out of Dynamic SQL with DB2 for z/OS and OS/390, SG24-6418 DB2 for z/OS and OS/390: Ready for Java, SG24-6435 IBM WebSphere Application Server V5.0 System Management and Configuration, SG24-6195 EJB 2.0 Development with WebSphere Studio Application Developer, SG24-6819 WebSphere Studio Application Developer Version 5 Programming Guide, SG24-6957 Distributed Functions of DB2 for z/OS and OS/390, SG24-6952
Other publications
These publications are also relevant as further information sources: DB2 Universal Database for z/OS Version 8 Administration Guide, SC18-7413 DB2 Universal Database for z/OS Version 8 SQL Reference, SC18-7426 DB2 Universal Database for z/OS Version 8 Command Reference, SC18-7416 DB2 Universal Database for z/OS Version 8 Application Programming and SQL Guide, SC18-7415 DB2 Universal Database for z/OS Version 8 Utility Guide and Reference, SC18-7427 DB2 Universal Database for z/OS Version 8 ODBC Guide and Reference, SC18-7423 DB2 Universal Database for z/OS Version 8 Application Programming Guide and Reference FOR JAVATM , SC18-7414 DB2 Universal Database for z/OS Version 8 Installation Guide, GC18-7418 WebSphere Application Server for z/OS V5.0.2 Performance Tuning and Monitoring, SA22-7962 WebSphere Studio Application Monitor Installation and Customizing Guide, SC31-6312 DB2 Universal Database for z/OS Version 7 Application Programming Guide and Reference FOR JAVA, SC26-9932-05 or later
321
Online resources
These Web sites and URLs are also relevant as further information sources: DB2 Universal Database for Linux, UNIX, and Windows Web site:
http://www.ibm.com/software/data/db2/udb/
Using DB2 for z/OS in WebSphere for z/OS Version 5, Techdoc TD101072:
http://www-03.ibm.com/support/techdocs/atsmastr.nsf/WebIndex/TD101072
Setting client information strings in WAS: Technical support document number 1142347:
http://www.ibm.com/software/webservers/appserv/was/support/
322
Index
Symbols
${DB2UNIVERSAL_JDBC_DRIVER_NATIVEPATH} 56 ${DB2UNIVERSAL_JDBC_DRIVER_PATH} 56 ${UNIVERSAL_JDBC_DRIVER_PATH} 56 *.do 304 .EAR file 38 .JAR file 38 .profile 26 .ser file 146, 171, 183 .so file 53 .sqlj extension 159 .WAR file 39 ? Parameter marker 114 PQ90211 22 PQ95284 23 PQ95881 30 Application Assembler 36 Application Component Provider 36 Application exceptions 157 Assembly descriptor 196 Assignment statement 144 Auditing 128, 136 Authentication 128 Authorization 128 Control 111 Type 290 -automaticbind NO 148 Auxiliary table 10
Numerics
1 Phase commit 79 1PC 80 2 phase commit 7980 4 tier programming model 37 4.x level data sources 80 64-bit mode 234 9672 G5 222
B
Base Application Server Node 41 BaseNode 51 Bean Managed Persistence 98, 151, 280 Bean Managed Transactions 194 Bind 118 Bind options DYNAMICRULES 120 ISOLATION 121 OWNER 120 QUALIFIER 120 BIND PACKAGE 18 BIND PLAN 18 BINDOPTIONS 276 BLOB 247, 249 BMP 100, 106, 151, 280 BMP vs. CMP 151 BMP with JDBC example 280 BMT 194 BN 51 Bottom-up approach 183, 249 Bottom-up mapping 259 Business integration 48
A
Abstract persistence schema 185 Access intent 218219 Access path 230 Accessors 263 Action token 303 Actionservlet 301, 304 activate() 96 Add SQLJ Support 274 Add Struts support 301 Additional Properties JVM 67 Administrative console 42, 45, 54, 307 Affinity routing 97, 99 Aged Timeout 225226 American National Standards Institute 15 ANSI 15, 20 ANSI X3.135-1999 15 Ant script 171, 275 APAR OW54622 233 PQ36011 22 PQ62695 29 PQ72453 29 PQ78165 29 PQ80079 24, 52 PQ80841 23, 26, 52 PQ83561 29 PQ90208 22 PQ90210 22
C
CACHEDYN 229 CAF 7 Call attachment facility 7 Call back methods 98 CallableStatement interface 115 CallableStatements 228 Callback methods 283 Call-level interface 140 CAST construct 146 Catalog database 9 CDB 202 Cell 51 Cell scope 81
323
CF 205 CGI 90 Checkbox SQLJ exploitation 100 Checked exception 157 CICS 38, 246 CICS attachment facility 6 Claim processing 206 ClassName_SJProfile0.ser 140 CLASSPATH 27, 113, 235 CLEAR_TEXT_PASSWORD_SECURITY 129 Client application modules 38 ClientAccountingInformation 137 ClientProgramName 136 ClientUser 136 ClientWorkstation 136 CLOB 247, 249 close() 115 CLUSTER 12 Clustering indexes 12 CMP 100, 107, 151, 229, 247 CMP 2.0 266 CMP generated SQL 218 CMP mapping 183 CMR 266 CMR fields 272 CMT 156, 194 Collection of objects 263 Collections 19 com.ibm.db2.jcc.* 112 com.ibm.db2.jcc.DB2BaseDataSource 125 com.ibm.db2.jcc.DB2ConnectionPoolDataSource 113, 125 com.ibm.db2.jcc.DB2DataSource 113, 125 com.ibm.db2.jcc.DB2Driver 26 com.ibm.db2.jcc.DB2SimpleDataSource 113 com.ibm.db2.jcc.DB2XADataSource 113 com.ibm.jcc.DB2RowID 33 com.ibm.websphere.rsadapter.WSCallHelper 137 Commit 194 commit() 195 Common Gateway Interface 90 Communication Database 202 Comparing SQLJ and JDBC 110 -compile=false 140 Component-managed Authentication Alias 135 CONDBAT 229 Configuring type 2 connectivity 53 Connection context 143144, 179 Connection definition 250 Connection pool maintenance 224 Connection pooling 140, 222 Best practices 228 Connection Pools option 227 Connection Timeout 226 Connections 140 Connections and transactions 144 ConnectionWaitTimeoutException 225226 Consistency token 147 Constructor 143 Container 279
Container managed persistence 93, 100, 151, 229 Container managed relation 266 Container Managed Transactions 156, 173, 194 Context 143 Context root 300, 306 Context switch 103 Controller 246 Controller component 298 Controller region 40, 233 Coprocessor 14 Coupling Facility 205 CREATE INDEX 12 CreateException 183 CREATEIN 19 Creating a new Application Server 73 Credentials 128 CRUD methods 272 CS 146, 187, 212, 220 CTHEAD 229 CURRENT PACKAGE PATH 124 CURRENT PACKAGESET 123124 CURRENT SCHEMA 122 CURRENT SQLID 121 CURRENTDATA 216 Cursor stability 146, 187, 212 Cursor update 216 Custom Properties 61, 121, 123 Customer tag files 301 Customizable Performance Monitoring Infrastructure 222 Customize the serialized profile 118119 Customized SQLJ 111 CVS 161
D
Daemon 75 Data access component 105 Data Control Language 14 Data Definition Language 14 Data integrity 2 Data Manipulation Language 14 Data perspective 249, 273 Data sharing considerations 216 Data Source 51, 57 Properties 58 Under the JDBC provider 53 Data structures 8 Data transfer Beans 264 Data transfer object 152 Database languages Standards 15 Database management system 2 Database request module 17 Database services address space 5 Databases 9 Data-partitioned secondary index 13 DataSource interface 22, 32, 113, 125, 140141 Datasource settings for authentication 134 DataSource versus datasource 141 DB Connect
324
Enterprise Edition 3 DB2 attachment facilities 6 DB2 bind options for Java applications 120 DB2 Connect 3 Application Server Edition 3 Personal Edition 3 Unlimited Edition 3 DB2 dynamic statement cache 229 DB2 federated database technology 10 DB2 Interactive 6 DB2 JDBC Legacy Type 2 driver 22 DB2 JDBC Legacy type 2 driver 22 DB2 locking 210 DB2 package 147 DB2 Performance Expert 230 DB2 precompiler 14 DB2 resource manager 204 DB2 Server for VSE & VM 4 DB2 transaction manager 202 DB2 UDB Enterprise Server Edition 3 Express Edition CPU Option 3 Personal Developers Edition 3 Personal Edition 3 Universal Developers Edition 3 Workgroup Server Edition 3 Workgroup Server Unlimited Edition 3 DB2 UDB for iSeries 4 DB2 UDB for z/OS and OS/390 Components 4 DB2 Universal Database Family 2 DB2 Universal Driver 21 DB2 Universal JDBC Driver Provider 51 DB2 Universal JDBC Driver Provider (XA) 51 db2.jcc.propertiesFile 68 DB2BaseDataSource 236 DB2Binder utility 29 DB2Connection 33 DB2Diagnosable 33 DB2-established stored procedure 5 db2jcc.jar 2627, 164 db2jcc_javax.jar 27 db2jcc_license_cisuz.jar 27, 164 db2jcc_license_cu.jar 164 db2profc 118, 147 DB2RowID 33 DB2Sqlca 33 db2sqljbind 32, 120, 148 db2sqljcustomize 32, 112, 119120, 147148, 213, 276 db2sqljprint 188 DB2T4XAIndoubtUtil 205 DB2T4XAIndoubtUtil utility 30 DB2UNIVERSAL_JDBC_DRIVER_PATH 83 DBRM 17, 118, 123 DDF 5, 22 Declarative query language 13 Default context 144 Default database 9 Deployer 37 Deployment and RMIC code 274, 290, 296
Deployment code 270 Deployment descriptor 51, 93, 132, 194, 265, 269, 279, 288, 293 Deployment of the EAR file 307 DESCRIBE 28 DESCRIBE SQLDA 28 DESCSTAT 2829, 116 Detailed application flow 153 DFSLI000 6 -DISPLAY DDF 30 -DISPLAY THREAD 136 Distributed data facility 129 Distributed data facility services address space 5 Distributed Relational Database Architecture 20 Distributed transaction support 24 DISTSERV 18, 112, 124 DLLs 27, 53 DNS address 312 Does Not Exist 224 DPSI 13 Drain processing 206 DRDA 18, 22, 204 DriverManager 125 DriverManager interface 22, 140 DriverManager.getConnection 125 DSN command processor 6 DSNALI 7 DSNCLI 6 DSNDB04 9 DSNDB06 9 DSNDB07 9 DSNELI 6 DSNHDECP 202 DSNL004I 30 DSNRLI 7 DSNTIJMS 29 DSNTIP4 29 DSNTIPE 229 DSNZPARM 9, 28 CACHEDYN 229 CONDBAT 229 CTHEAD 229 DESCSTAT 28 EDMDSMAX 230 EDMDSPAC 230 EDMSTMTC 230 MAXDBAT 229 TCPALVER 130 DTO 152153 Dynamic Application Environment 233 Dynamic SQL 14, 146 Statement caching 14 Dynamic statement caching 14 Dynamic Web Project 299 DYNAMICRULES(BIND) 120 DYNAMICRULES(RUN) 120
E
E.F. Codd 2 EA 254 Index
325
EAR 3738, 254 EAR file deployment 307 File 272 EAR project 306 EDMDSMAX 230 EDMDSPAC 230 EDMPOOL 230 EDMSTMTC 230 EJB 92 Summary 105 EJB 2.0 specification 247 EJB container 38 EJB module Enabling SQLJ support 184 EJB project 160, 253 EJB QL 185 EJB Query Language 185, 268 EJB to RDB mapping 260 EJBContext.getUserTransaction() 195 ejbCreate 183 EJBException 157, 182 Ejbfactory 296 ejb-jar.xml 279, 282, 288, 293 EJBQL 268, 272 ENCRYPTED _USER_AND _DATA_SECURITY 130 ENCRYPTED_PASSWORD_SECURITY 129 ENCRYPTED_USER_AND_PASSWORD_SECURITY 130 ENCRYPTED_USER_PASSWORD_AND _DATA 130 Enterprise achive 254 Enterprise Application 254 Enterprise application archive 3738 Enterprise Information System 38 Enterprise JavaBean 205 Enterprise JavaBeans 92 EntirePool 226 Entity Bean 106, 151 Entity Bean isolation level 218 Entity Beans 38, 98 Bean-Managed Persistence 98 Container-Managed Persistence 100 ENV parameter 70 Environment entries 71 Environment variables 26 CLASSPATH 27 LIBPATH 27 PATH 26 ESAME mode 234 Exception handling for EJBs 154 Exceptions 157 Exclusive lock 211 Executable statement 144 EXECUTE authority 112 executeQuery() 114 executeUpdate() 115 Execution context 158 ExecutionContext 159 EXPLAIN 230 export statement 27
F
FailingConnectionOnly 226 Federated capabilities 2 Finder 272 Finders 263 First contact subsystem 202 FixPak 5 22 FMID 23 FOR READ ONLY 216 FOR UPDATE 216 Forced data access abstraction 99 Foreign key 16, 248 Forward engineering 183 Function Module Identifier 23
G
Gateway subsystem 203 GENERATE_UNIQUE function 215 GENERATED ALWAYS 216 getBytes 33 getConnection 141 getConnection().setAutoCommit() 143 getDB2CurrentPackagePath 33 getDB2CurrentPackageSet 33 getJccLogWriter 33 getMessage 33 getSqlca 33 getSqlCode 33 getSqlState 33 getStatus() 195 Getters 272 getWarnings 159 Global security 135 Global transaction 192, 205 Global transaction support 205 Global unit of work 88 GUOW 88
H
Hardware configuration 222 HashMap 296 HDDA210 24 Heapsize 234 HTTP 104 HTTP clients 38 HTTP server 40
I
IBM DB2 Legacy Driver 21 IBM extensions 282 IEEE floating point 222 IFI 7 Imported tables 253 IMS 38, 246 IMS attachment facility 6 In Free Pool 224 In Use 224 Indexes 11
326
Indoubt 193 Indoubt transaction resolution 208 Industry standards 15 Initial Heap Size 235 INITIAL_CONTEXT_FACTORY 142 InitialContext 141 Instrumentation facility interface 7 Integrated Cryptographic Service Facility 222 Intent exclusive lock 211 Intent share lock 211 Internal resource lock manager 5 International Organization for Standardization 15 IRLM 5, 234 IS-lock 211 ISO 15, 20 ISOLATION 121 ISOLATION bind option 213 Isolation levels 187, 212 Iterator conversion statement 146 Iterator declaration 144 IVP tables 246 IX-lock 211
J
J2EE 19, 24, 3536 J2EE benefits 39 J2EE container 92 J2EE data access architecture 90 J2EE JTA/XA transaction 80 J2EE perspective 255256, 273 J2EE project 160 J2EE roles 36 JAAS security entries 163 Java 2 Enterprise Edition 19, 3536, 92 Java architecture guide 89 Java archive 38 Java Common Connectivity 22 Java Data Objects 104 Java Database Connectivity 19 Java identifiers 114 Java Interface Definition Language 40 Java Message Service 40 Java Naming and Directory Interface 32, 113, 141, 223 Java Naming Directory Interface support 93 Java Native Interface 53 Java packages 272 Java perspective 261 Java project 160 Java runtime environment 40 Java stand-alone program 150 Java Transaction API 24, 40, 155 Java Transaction Service 24 Java user-defined functions 24 Java Virtual Machine 40, 234 java.lang.Exception 158 java.lang.String 125 java.rmi.RemoteException 157 java.sql 113, 116 java.sql.Exception 33 java.util.HashMap 247
java.util.Properties 125 javac 117119 JavaMail 40 JavaServer Pages 38, 90 javax.ejb.EJBException 157 javax.naming 113, 116 javax.sql 113, 116 javax.transaction.UserTransaction 195 JCA Authentication 134 JCC 22 JCL INCLUDE statement 70 JDB7712 23 JDB8812 23 JDBC 19, 247 JDBC 1.2 specification 24 JDBC 2.0 specification 22, 24, 113 JDBC 3.0 specification 21, 24, 32 JDBC and SQLJ compared 110 JDBC authentication 129 JDBC driver 21 JDBC Driver Provider 54 JDBC Driver Provider (XA) 52, 80 JDBC driver types 21 Type 1 21 Type 2 21 Type 3 21 Type 4 21 JDBC fundamentals 20 JDBC packages 32 JDBC parameter markers 114 JDBC program preparation 117 JDBC provider 53 JDBC type 4 XA driver 24 JDBC/SQLJ 2.0 Driver 21 JDBC-ODBC bridge 21 JDO 104 JIT compiler 235 JMS 40 JNDI 32, 113, 141, 223 JNDI lookup 51 JNDI name 51, 166 JNDIName 59, 279, 290, 309 JNI 53 JSP 38, 90, 105, 153 Benefits 91 JTA 24, 40, 155 JTA/XA transaction 80 JTS 24, 40 Just In Time compiler 235 JVM 40, 151, 234, 282 JVM heap size 234 JVM System property db2.jcc.propertiesFile 72
K
Kerberos 128 KERBEROS_SECURITY 130 Key 16
Index
327
L
Last participant optimization 199 LDS 10 Lfecycle methods 283 libjava_g 235 LIBPATH 26, 235 Lifecycle methods 96 Limit key 12 Linear data sets 10 LINKLIST 70 Linklist 202 LOB 10, 249 LOB column 247 LOB locators 31 Local dynamic statement cache 18 Local interface 264 Local JDBC Provider (RRS) 51, 223 Local reference 262 Local transactions 192 LocalHome class 271 Lock duration 206 Lock mode 210 Lock mode compatibility 211 LOCKSIZE ANY 210, 217 PAGE 210 ROW 210 TABLE 210 TABLESPACE 210 Logical clustered environment 43 Logical Unit of Work 192 LPAR 22 LUW 192
MVC 150, 298 MVC model 253 MVC1 246 MVC2 246 MVS console 43
N
Namespace 290 Navigator view 273 ND 51 Network deployment 43, 51 NO WLM ENVIRONMENT 5 Node 81 Node scope 81 Nonpartitioned secondary index 13 non-XA JDBC provider 79 non-XA resource compliant 200 NPSI 13 Nullable columns 220 NULLID 272 NULLID collection 204 NULLID qualifier 249 NUMPARTS 10
O
Object Request Broker 282 ODBC 3, 21, 140 OLE DB 3 OLTP support 105 Omegamon 230 ON DELETE CASCADE 16 ON DELETE SET NULL 16 One-phase commit 79 Online checking 188 OSA Express 222 Overqualified predicates 215 Overriding lock mode 212 OW54622 233 OWNER 120
M
Manage WebSphere variables 64 Map.mapxmi 273 Max Connections 225 MAX REMOTE ACTIVE 229 MAX USERS 229 MAXDBAT 229 Maximum Heap Size 235 MAXROWS 1 217 MDB 101 Meet in the middle 183 Message Driven Beans 38 Message driven Beans 101 Metadata 260 Metadata stored procedures 2829 META-INF 282 META-INF folder 265 Method abstract declaration 263 Method signature 263 MIME types 246 Min Connections 225 Model View Controller 246 Models 246 Model-View-Controller 150 MSU 204
P
Package 17 Package lists 19 Package not found exception 187 Page locks 210 Parallel sysplex 206 Parameter marker 114 PARTITION BY 12 Partitioned table space Index-controlled partitioning 12 Limit key 12 Table-controlled partitioning 12 Partitioning clause 12 Partitioning indexes 12 passivate() 96 Password 128 PATH 26 Performance considerations 231
328
PKLIST 19 Plan 17 PMI 222 PQ36011 22 PQ62695 29 PQ72453 29 PQ78165 29 PQ80079 24, 52 PQ80841 23, 26, 52 PQ83561 29 PQ90208 22 PQ90210 22 PQ90211 22 PQ95284 23 PQ95881 30 PreparedStatement interface 115 PreparedStatements 228 Presentation servlet 297 Primary key 16 printTrace 33 Private protocol 18 Product Provider 36 Profile customization 146 Programmatic authentication 135 Project navigator 270 Promote to Local Interface 264 PROVIDER_URL 142 Purge Policy 226
Resource interfaces 198 Resource Managed Local Transaction 199 Resource manager 193 Resource recovery services 7 Resource transaction isolation 199 ResultSet 31, 146 ResultSet interface 114 ResultSet.getxxx 116 ResultSets 228 Resync IP port 208 Reverse engineering 183 RMI 93 RMLT 199 Rollback 194 rollback() 195 Root package name 171 Row locks 210 ROWID 216, 259 RR 146, 187, 212, 220 RRS 7, 22, 51, 198, 223 RRSAF 7 RS 146, 187, 212, 220 Run-as 132 RuntimeException 157
S
Sample scenario setup 50 SCA 205 Schemas 19 SDSNLOD2 70 Searched update 216 Secondary indexes 13 Security 2 Deployment descriptor 132 Security policy 128 securityMechanism 129, 131 SEGSIZE 10 Self-referencing constraint 16 SERIALIZABLE 146 Serializable interface 265 Serialized profile 118119, 146, 275 Servant 40 Servant region 233 server_region_dynapplenv_jclparms 233 server_region_dynapplenv_jclproc 233 Servlet 38, 90, 105, 179, 246 Benefits 91 Considerations 91 Session Bean 38, 93, 151, 182 Session facade 102 SessionContext 156 SET CURRENT PACKAGE PATH 124 SET CURRENT PACKAGESET 123 SET CURRENT SCHEMA 122 SET CURRENT SQLID 121 SET SCHEMA 122 -SET SYSPARM 28, 230 SET TRANSACTION ISOLATION LEVEL 187, 213 setAutoCommit 177 setDB2CurrentPackagePath 33 Index
Q
QUALIFIER 120, 122
R
RACF user ID 129 Rational Clearcase 161 RDB to EJB 259 RDBMS 38 READ COMMITTED 146 READ STABILITY 217 Read stability 146, 187, 212 READ UNCOMMITTED 145 Reap Time 224225 Recoverability 2 Recoverable Resource Services 198 Redbooks Web site 322 Contact us xxiii Referential constraint 16 Referential integrity definition 263 REGION 234 Relational database management systems 2 Relationship implementation 99 Remote interface 282 Remote Method Invocation 93 Remote vs. local interface 151 RemoteException 157 REPEATABLE READ 146, 217 Repeatable read 146, 187, 212 Res-auth 133, 135 Resource adapters 39
329
setDB2CurrentPackageSet 33 setJccLogWriter 33 setRollbackOnly 156157 setRollbackOnly() 196 Setters 272 Setting the client strings 137 setTransactionIsolation() 213 setXXX 125 Share lock 211 Shareable connection 224 Shared Communications Area 205 Simple Object Access Protocol 104 Single resource global transaction 199 SIX-lock 211 S-lock 211 SOAP 104 SOAP message 104 Software configuration 222 SP 102 Special registers 121 CURRENT PACKAGE PATH 124 CURRENT PACKAGESET 123 CURRENT SCHEMA 122 CURRENT SQLID 121 SQL 13 Data Control Language 14 Data Definition Language 14 Data Manipulation Language 14 SQL statement coprocessor 14 SQL warnings 158 SQL/Bindings 15 SQL/Foundation 15 SQL/Framework 15 SQL/JRT 15 SQL/OLB 15 SQL/PSM 15 SQL/XML 15 SQLAntScripts directory 171 SQLDA 28 SQLException 158 SQLJ 19, 79, 247 Deployment on WAS 189 Host variables 173 Java packages 116 Online checking 188 runtime 147 sqlj 112, 118, 140 SQLJ customization 187 SQLJ customization script 275 SQLJ customization script folder 161 SQLJ exploitation 100 SQLJ Java source folder 161 SQLJ program preparation 117 SQLJ runtime classes 27 SQLJ runtime library 146 SQLJ support 104 SQLJ translator 140 SQLJ translator class name 161 SQLJ translator JAR file 160 sqlj.customize.xml 277
sqlj.project.properties file 171 sqlj.runtime 116 sqlj.zip 2627 SQLJAntScripts 274 SQLSTATE 33 SQLWarning 158 ssnmDBM1 5 ssnmDIST 5 ssnmMSTR 4 ssnmSPAS 5 Stale connection 224 startCommandArgs 70 Stateful session Bean 96, 106 stateless Bean 232 Stateless failover 94 Stateless session Bean 106, 290 Stateless session Beans 94 Stateless vs. stateful 151 Statement cache size 227 Statement interface 114 Static SQL 14, 275 Static SQL vs. dynamic SQL 230 -staticpositioned 120 STEPLIB 202 Storage groups 10 Stored procedure 107 Stored procedures 102 Benefits 102 Considerations 103 Structured Query Language 13 Struts 299 struts-config.xml 302 Sun Microsystems 21 Symbolic environment variables 64 Sync to os 136 Sync to thread 290 SYSIBM.INDOUBT 30, 205 Sysplex 44 Sysplex Distributor 208 SYSSTC service class 234 System Administrator 37 System exception 157 System services address space 4
T
T4XAIndbtPkg 30 Table spaces 10 Large object 10 Partitioned 10 Segmented 10 Simple 11 Table-controlled partitioning 12 TCP/IP 78, 208, 234 TCPALVER 130 Team support 161 The big picture 152 Thread identity support 131, 135 Three part table name 203 TLD files 301 Tool provider 37
330
Top down 183 TRANSACTION _READ_UNCOMMITED 214 Transaction context 194 Transaction coordinator 193 Transaction demarcation 155, 194 Transaction deployment descriptors 217 Transaction isolation 210 Transaction isolation levels 218 Transaction management 97 Transaction types 196 TRANSACTION_NOT_SUPPORTED 232 TRANSACTION_READ_COMMITTED 214, 220 TRANSACTION_REPEATABLE_READ 214, 220 TRANSACTION_SERIALIZABLE 214, 220 TRANSACTION_SUPPORTS 232 Transactional locks 210 TSO attachment facility 6 Two phase commit 22, 24, 192 Two phase commit considerations 206 Type 2 Driver authentication 130 Type 4 Driver authentication 129 Type 4 XA connectivity 23, 80
W
W502002 223 WAS 35 WAS transaction manager 181, 204 was.env file 75, 77 Web application archives 39 Web container 38 Web modules 38 WEB project 160 Web services 93, 104 Web Services Definition Language 104 WebSphere Application Server Architecture 40 Cell 51 Scope 55 WebSphere bindings 270 WebSphere Commerce 47 WebSphere connection pooling 222 WebSphere Everyplace 48 WebSphere extensions 187 WebSphere family 47 WebSphere Flashes 45 WebSphere for z/OS Introduction 35 WebSphere Foundation 47 WebSphere Information Center 42 WebSphere Installer 42 WebSphere MQ 101 WebSphere Portal 47 WebSphere Studio Application Developer 37, 100, 112, 230 SQLJ support 159 WebSphere transaction isolation level 217 WebSphere transaction management 194 WebSphere Voice 48 WITH clause 214 WITH CS 214 WITH RR 212, 214 WITH RS 212, 214 WITH UR 214 Wizard 269 WLM 5, 40 WLM classification 232 WLM Dynamic Application Environment 233 WLM established stored procedure 5 Work file database 9 WSAD 37, 100, 112, 159, 185, 230, 249 Container managed transactions 173 Create a new server 161 Directory structure and files 170 Enable SQLJ support 168 JAAS entry 163 SQLJ CMP beans 166 Generate the custumization script 170 SQLJ Customization Script 168 User-managed persistence 172 WSAD preferences 160 WSAD wizard 290 WSDL 104
U
UDB for z/OS and OS/390 Address spaces 4 U-lock 211 Uncommitted read 145, 187, 212 Uncustomized SQLJ 146 Unique indexes 12 Universal Driver for SQLJ and JDBC 22 Universal JDBC Driver Provider 79, 200, 223 Universal JDBC Driver Provider (XA) 201, 223 UNIX System Services 110 Unshareable connection 224 Unused Timeout 226 Update cursor 215 Update lock 211 UQ85128 52 UR 145, 187, 212 USE AND KEEP EXCLUSIVE LOCKS 212 USE AND KEEP SHARE LOCKS 212 USE AND KEEP UPDATE LOCKS 212 user ID 128 USERID_ONLY_SECURITY 129 User-managed persistence 172 UserTransaction interface 155, 195 UserTransaction.begin() 195 Utility methods 173
V
Verbose Garbage Collection 235 View component 296 Views 246 Virtual Host 311 Virtual Storage Access Method 10 VSAM 10 VSAM control interval size 10 VTAM 234
Index
331
wsOptimisticRead 219 wsOptimisticUpdate 219220 wsPessimisticRead 219 wsPessimisticUpdate 219 wsPessimisticUpdate-Exclusive 219 wsPessimisticUpdateNo-Collisions 219 wsPessimisticUpdate-WeakestLockAtLoad 219
X
X/Open transaction 198 XA 51 XA distributed transaction support 24 XA driver 22, 24 XA specification 198 XA standard 198 XA transaction 80, 223 XID 205 X-lock 211 XML 38, 104, 267 XML enhancements 2 XML file 171
Z
Z parameter 77 z/Architecture mode 234 z/OS Application Connectivity to DB2 for z/OS and OS/390 24 z/OS security options 136 z/OS UNIX System Services 30, 110 z990 222 zAAP 103, 204 zSeries Application Assist Processors 103
332
Back cover