java application development for cics

254
ibm.com/redbooks Java Application Development for CICS Chris Rayns Scott Clee Ulrich Gehlert Vasilis Karras Debra Payne Bill Plowman Setting up CICS to run Java applications CICS Java problem determination and debugging Evolving a legacy application using Java

Upload: sai-ranga

Post on 08-Apr-2015

338 views

Category:

Documents


8 download

TRANSCRIPT

Page 1: Java Application Development for CICS

ibm.com/redbooks

Java Application Development for CICS

Chris RaynsScott Clee

Ulrich GehlertVasilis KarrasDebra PayneBill Plowman

Setting up CICS to run Java applications

CICS Java problem determination and debugging

Evolving a legacy application using Java

Page 2: Java Application Development for CICS
Page 3: Java Application Development for CICS

International Technical Support Organization

Java Application Development for CICS

August 2005

SG24-5275-02

Page 4: Java Application Development for CICS

© Copyright International Business Machines Corporation 1999, 2005. All rights reserved.Note to U.S. Government Users Restricted Rights -- Use, duplication or disclosure restricted by GSA ADP ScheduleContract with IBM Corp.

Third Edition (August 2005)This edition applies to CICS TS Version 2, Release 3.

Note: Before using this information and the product it supports, read the information in “Notices” on page vii.

Page 5: Java Application Development for CICS

Contents

Notices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . viiTrademarks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . viii

Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ixThe team that wrote this redbook. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ixBecome a published author . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .xComments welcome. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xi

Part 1. Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

Chapter 1. Introduction. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31.1 z/OS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41.2 CICS TS V2.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61.3 Java. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

1.3.1 Java language. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71.3.2 Java Virtual Machine. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91.3.3 Java for z/OS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91.3.4 Runtime Environment and tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

1.4 CICS TS Support for Java. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121.4.1 CICS Java applications using JCICS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131.4.2 CICS Support for the JVM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

Chapter 2. Java Virtual Machine support in CICS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162.2 History of JVM support in CICS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

2.2.1 CICS TS 1.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172.2.2 CICS TS 2.1 and 2.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172.2.3 CICS TS V2.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172.2.4 CICS TS 3.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

2.3 JVM operation modes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182.3.1 Single-use JVM. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182.3.2 Continuous JVM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192.3.3 Resettable JVM. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212.3.4 Summary of JVM modes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

2.4 JVMSets and the Shared Class Cache. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242.4.1 Benefits of the Shared Class Cache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242.4.2 Master JVM. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252.4.3 Worker JVM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252.4.4 Starting the Shared Class Cache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252.4.5 Inquiring the status of the Shared Class Cache . . . . . . . . . . . . . . . . . . . . . . . . . . 262.4.6 Changing the size of the Shared Class Cache . . . . . . . . . . . . . . . . . . . . . . . . . . . 282.4.7 Updating classes in the Shared Class Cache. . . . . . . . . . . . . . . . . . . . . . . . . . . . 29

2.5 Heap management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 292.5.1 Categories of classes in the IBM prJVM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 292.5.2 How the JVM identifies the category of a class. . . . . . . . . . . . . . . . . . . . . . . . . . . 302.5.3 Heap management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31

2.6 Sample program: Resettable versus continuous mode . . . . . . . . . . . . . . . . . . . . . . . . 33

Part 2. System programming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35

© Copyright IBM Corp. 2005. All rights reserved. iii

Page 6: Java Application Development for CICS

Chapter 3. Software and hardware requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 373.1 Hardware prerequisites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 383.2 z/OS operating system . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 383.3 External Security Manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 383.4 Java Language Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393.5 Java Client Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39

Chapter 4. Setting up CICS to run Java applications . . . . . . . . . . . . . . . . . . . . . . . . . . 414.1 Running a simple Java application in CICS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

4.1.1 Accessing the z/OS UNIX shell. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 424.1.2 Setting up the CICS sample Java application . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45

4.2 System configuration. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 484.2.1 UNIX System Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 484.2.2 Language Environment (LE) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 494.2.3 CICS Transaction Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50

4.3 Managing your CICS Java environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 574.3.1 CEMT INQUIRE CLASSCACHE. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 574.3.2 CEMT INQUIRE DISPATCHER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 584.3.3 CEMT INQUIRE JVM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 584.3.4 CEMT INQUIRE JVMPOOL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 594.3.5 CEMT INQUIRE PROGRAM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 594.3.6 CEMT PERFORM CLASSCACHE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 604.3.7 CEMT SET DISPATCHER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 614.3.8 CEMT SET JVMPOOL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61

Part 3. Java programming for CICS. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63

Chapter 5. Getting started . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 655.1 Coding your application in Rational Application Developer. . . . . . . . . . . . . . . . . . . . . . 665.2 Deploying and running the program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69

5.2.1 Deploying the code to CICS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 695.2.2 Setting up the transaction and program definitions. . . . . . . . . . . . . . . . . . . . . . . . 725.2.3 Running the program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 735.2.4 Troubleshooting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75

Chapter 6. The JCICS API. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 776.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 786.2 A short overview of the JCICS API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79

6.2.1 Program control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 806.2.2 File control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 806.2.3 Synchronization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 806.2.4 Scheduling services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 806.2.5 Unit of work . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 806.2.6 Document services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 806.2.7 Web and TCP/IP services. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 816.2.8 Transient storage queues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 816.2.9 Transient data queues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 816.2.10 Terminal control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 816.2.11 Miscellaneous services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 826.2.12 Services not supported by the JCICS API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83

6.3 JCICS basics. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 836.4 Input and output streams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 846.5 Exception handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 846.6 Calling other programs and passing data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89

iv Java Application Development for CICS

Page 7: Java Application Development for CICS

6.6.1 Calling other programs using LINK and XCTL . . . . . . . . . . . . . . . . . . . . . . . . . . . 906.6.2 Communicating via the COMMAREA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91

6.7 Remoteable resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 936.8 Using transient storage queues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 946.9 How to perform serialization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 976.10 Web, TCP/IP, and Document services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 996.11 File control. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1006.12 Interval control. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1096.13 Terminal services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110

Chapter 7. Evolving a legacy application using Java . . . . . . . . . . . . . . . . . . . . . . . . . 1217.1 The legacy trader application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1227.2 Adding a JCICS Web interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123

7.2.1 Wrapping the COMMAREA. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1247.2.2 Understanding COMMAREA request formats. . . . . . . . . . . . . . . . . . . . . . . . . . . 1267.2.3 A test Web application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1277.2.4 Designing the HTML interface. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1307.2.5 Implementing the design. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1317.2.6 Setting up TraderPL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1367.2.7 Web security . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138

7.3 Migrating TRADERBL to JCICS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1397.3.1 Mapping COBOL to Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1407.3.2 Using TraderBL with VSAM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1487.3.3 Setting up TraderBL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149

7.4 Moving to a DB2 back-end . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1497.4.1 Data migration. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1507.4.2 Using TraderBL with DB2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1517.4.3 Setting up TraderBL with DB2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154

Chapter 8. Problem determination and debugging . . . . . . . . . . . . . . . . . . . . . . . . . . . 1578.1 Debugging and problem determination . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158

8.1.1 First considerations. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1588.2 Where to look when you receive AJ07 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1608.3 Where to look for diagnostic information. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160

8.3.1 Javadumps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1618.3.2 JVM stdout and stderr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1658.3.3 Logging events in the JVM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1658.3.4 JVM method tracing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1688.3.5 JVM class loader tracing. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170

8.4 Interactive debugging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1728.4.1 Execution diagnostic facility . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1728.4.2 Java Platform Debugger Architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1728.4.3 The CICS JVM plug-in mechanism. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176

Chapter 9. Performance for Java in CICS TS V2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1799.1 Reusable JVM. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180

9.1.1 The Reusable JVM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1809.2 Shared Class Cache facility . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1819.3 Things to avoid . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183

9.3.1 Unresettable Event . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1849.3.2 JVM stealing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1849.3.3 Reset trace events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1859.3.4 Using application classpath . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1879.3.5 Excessive garbage collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187

Contents v

Page 8: Java Application Development for CICS

9.4 JVM startup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188

Part 4. Appendix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191

Appendix A. Channels and containers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193Creating channels and containers in JCICS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194Putting data into a container . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194Passing a channel to another program or task . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194

Link and xctl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194Return transid . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194Start transid. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195

Receiving the current channel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195Getting data from a container. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195Browsing the current channel. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195A JCICS example. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 196

Appendix B. Hints and tips . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197Priority of public static void main() methods. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198Getting transaction arguments using Java. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198Never use System.exit() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199

Appendix C. Output examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201

Appendix D. Program listings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203Scratchpad example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204VsamMap example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206JBMS (Java Basic Mapping Support) example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210

Component.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210Container.java. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212Field.java. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213Label.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219MenuScreen.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219Panel.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220PasswordText.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221PfKeyPanel.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221Screen.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222Text.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225Util.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225

Appendix E. Additional material . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227Locating the Web material . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227Using the Web material . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227

System requirements for downloading the Web material . . . . . . . . . . . . . . . . . . . . . . . 227How to use the Web material . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228

Related publications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229IBM Redbooks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229Other publications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229Online resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229How to get IBM Redbooks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230Help from IBM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230

Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231

vi Java Application Development for CICS

Page 9: Java Application Development for CICS

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.

© Copyright IBM Corp. 2005. All rights reserved. vii

Page 10: Java Application Development for CICS

TrademarksThe following terms are trademarks of the International Business Machines Corporation in the United States, other countries, or both:

AD/Cycle®AFS®AIX®C/370™CICS®CICSPlex®COBOL/370™DB2®DFS™ETE™eServer™Eserver®

Eserver®HiperSockets™IMS™Language Environment®Multiprise®MVS™MVS/ESA™OS/2®OS/390®OS/400®Parallel Sysplex®PR/SM™

Rational®Redbooks™Redbooks (logo) ™RACF®S/390®VisualAge®VTAM®WebSphere®z/Architecture™z/OS®zSeries®z/VM®

The following terms are trademarks of other companies:

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.

Microsoft, Windows, Windows NT, and the Windows logo are trademarks of Microsoft Corporation in the United States, other countries, or both.

Intel, Intel Inside (logos), MMX, and Pentium are trademarks of Intel Corporation in the United States, other countries, or both.

UNIX is a registered trademark of The Open Group in the United States and other countries.

Linux is a trademark of Linus Torvalds in the United States, other countries, or both.

Other company, product, and service names may be trademarks or service marks of others.

viii Java Application Development for CICS

Page 11: Java Application Development for CICS

Preface

This IBM Redbook is intended for clients who are implementing the Java™ language support provided by CICS® Transaction Server for z/OS® V2.3. Its prime audience is CICS and z/OS system programmers who provide support for Java application development, and Java application programmers who need a gentle introduction to Java development for CICS.

This book assumes a certain level of knowledge of z/OS, CICS, UNIX® System Services, and Java.

We start by reviewing the basic concepts of the z/OS, CICS TS V2.3, and Java environments, and introduce new terminology. We then discuss the software and hardware requirements for developing and executing Java applications in CICS TS V2.3 and the customization of the application development environment, UNIX System Services, MVS™, and CICS.

We briefly discuss three possible application development roadmaps: Java application programs that use CICS services, IIOP server applications, and CICS Enterprise Beans.

Subsequent chapters contain an expanded explanation and examples of Java application programs that use CICS services, and use of CICS-supplied Java class library and the Java Virtual Machine (JVM). We then present a CICS business application that has presentation and business logic.

As a special addition, we present a package called JBMS, which makes it possible to display and interact with 3270 screens from a CICS Java application.

Finally, we provide guidance on debugging and problem determination.

The team that wrote this redbookThis redbook was produced by a team of specialists from around the world working at the International Technical Support Organization, Poughkeepsie Center.

Chris Rayns is a CICS/Security Project Leader at Poughkeepsie and writes extensively on all areas of z/OS security. He is an IT Specialist at the International Technical Support Organization, Poughkeepsie Center. Before joining the ITSO, Chris worked in IBM Global Services in the UK as a CICS IT Specialist.

Vasilis Karras is a Project Leader/IT Specialist at the ITSO Center in Poughkeepsie. He has over 23 years of experience in zSeries, IBM Database, and Vendor products (Oracle, PeopleSoft). He has worked as a z/OS IT Support Specialist for 20 years with emphasis on database support. He holds a degree in Computer Science from Brooklyn College and a degree in Computer Programming from the College of Staten Island. His areas of expertise include DB2, CICS, zOS, MVS, and JES Technical Support. He has participated in many ITSO residencies during the past seven years as a resident, a project leader, a materials contributor, and an author.

Debra Payne is an independent consultant from the United States. She has over 25 years of experience in the IBM mainframe field, and over 20 with CICS, both in application development and system support. She holds a degree in Management Advisory Services from New Hampshire College and is currently pursuing a Masters Degree in Education from Plymouth State University. Her areas of expertise include CICS, DB2, OS/390, and MVS.

© Copyright IBM Corp. 2005. All rights reserved. ix

Page 12: Java Application Development for CICS

Ulrich Gehlert is an IT Architect with IBM Global Services, Germany. He has worked at IBM for ten years. His areas of expertise include the Java platform, with a strong focus on database and Web application server technologies, and the OS/390 and z/OS operating systems. He has previously co-authored the IBM Redbook DB2 for z/OS and OS/390: Ready for Java, SG24-6435. He holds a degree in Computing Science from University of Erlangen, Germany.

Scott Clee works as a CICS Tester for IBM in the UK. A senior member of his team, Scott is always looking at new ways to push automated test generation and execution, and for new and novel ideas that add a twenty-first century spin to the classy product that is the mainframe. He holds a degree in Mathematics and Computing from the University of Bath, UK. Areas of expertise include CICS, Java, COBOL, Linux, and Testing.

Bill Plowman is in his second spell as a CICS Change Team Programmer at IBM Hursley, UK. He joined IBM in 1988 and started work in the CICS change team. Between 1996 and 1998, he was part of the team that transferred CICSPlex SM development and service to IBM Hursley. He then moved to IBM North Harbour to work in IBM Global Services, providing CICS and MQ support to a variety of clients in EMEA. In 2001, he retrained as an AIX Systems Administrator and worked in the team supporting IBM and client systems. He rejoined the CICS change team in 2004, working in the area of CICS Java.

Thanks to the following people for their contributions to this project:

Mark CockerCICS Strategy and Project ManagementIBM Certified Solution Designer—CICS enablement for e-businessIBM Hursley, UK

Mike BrooksSenior IT Specialist, IBM Certified Solution Designer—CICS enablement for e-business, CICS Development 3IBM Hursley, UK

Bob HermanIBM Global Solutions—CICS System Support, Endicott

Jim CoolbaughCICS/390 Early Programs, Raleigh

Julie CzubikInternational Technical Support Organization, Poughkeepsie Center

Become a published authorJoin us for a two- to six-week residency program! Help write an IBM Redbook dealing with specific products or solutions, while getting hands-on experience with leading-edge technologies. You'll team with IBM technical professionals, Business Partners or clients.

Your efforts will help increase product acceptance and client satisfaction. As a bonus, you'll develop a network of contacts in IBM development labs, and increase your productivity and marketability.

x Java Application Development for CICS

Page 13: Java Application Development for CICS

Obtain more information about the residency program, browse the residency index, and apply online at:

ibm.com/redbooks/residencies.html

Comments welcomeYour 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

� Send your comments in an email to:

[email protected]

� Mail your comments to:

IBM Corporation, International Technical Support OrganizationDept. HYJ Mail Station P0992455 South RoadPoughkeepsie, NY 12601-5400

Preface xi

Page 14: Java Application Development for CICS

xii Java Application Development for CICS

Page 15: Java Application Development for CICS

Part 1 Overview

In this part of the book we familiarize you with the basic concepts of and developments in object-oriented (OO) technology in relation to the z/OS and CICS Transaction Server for z/OS (CICS TS). Java has rapidly grown in popularity throughout the Information Technology (IT) industry, and for many organizations is now their programming language of choice.

Part 1

© Copyright IBM Corp. 2005. All rights reserved. 1

Page 16: Java Application Development for CICS

2 Java Application Development for CICS

Page 17: Java Application Development for CICS

Chapter 1. Introduction

In this chapter we familiarize you with the basic concepts of and developments in object-oriented (OO) technology in relation to the z/OS and CICS Transaction Server for z/OS (CICS TS). Java has rapidly grown in popularity throughout the Information Technology (IT) industry, and for many organizations is now their programming language of choice. CICS has extended the support for Java-based workloads over a number of releases, in response to the uptake of the Java programming model. CICS Transaction Server for z/OS Version 2, Release 3 (CICS TS V2.3) adds further support for Java. This includes the provision of greater controls for the Runtime Environment used by Java application programs.

The main topics covered in this chapter are the positioning of z/OS, CICS TS, and Java, and the use of Java in a CICS environment.

1

© Copyright IBM Corp. 2005. All rights reserved. 3

Page 18: Java Application Development for CICS

1.1 z/OSz/OS is a highly secure, scalable, high-performance enterprise operating system on which to build and deploy Internet and Java-enabled applications, providing a comprehensive and diverse application execution environment.

z/OS:

� Provides a highly secure, scalable, high-performance base for on demand applications

� Can simplify IT infrastructure by allowing the integration of applications in a single z/OS image

� Takes advantage of the latest open software technologies to extend existing applications and add new on demand applications

� Incorporates world-class optimization features, security services, distributed print services, storage management, and Parallel Sysplex® availability

z/OS is the robust IBM Eserver™ zSeries® mainframe operating system designed to meet the demanding quality of service requirements for on demand business. With the IBM Eserver zSeries servers, z/OS serves as the heart of clients' on demand infrastructure.

z/OS takes advantage of the latest open and industry software technologies such as Enterprise JavaBeans, XML, HTML, C/C++, and Unicode. z/OS UNIX System Services allow you to develop and run UNIX programs on z/OS and exploit the reliability and scalability of the z/OS platform.

z/OS also incorporates world-class optimization features, security and IP networking services, distributed print services, storage management, and Parallel Sysplex availability.

Some of the unique classic strengths of z/OS are:

On demand infrastructure z/OS has optimization features to help provide the responsiveness needed for on demand applications. The z/OS Workload Manager (WLM) is at the heart of z/OS optimization, designed to manage the priority of mixed workloads based on business policies, defined in Service Level Agreement terms. Intelligent Resource Director (IRD) extends the z/OS Workload Manager to work with PR/SM™ on zSeries servers with features to dynamically manage resources across multiple logical partitions (LPARs). Based on business goals, WLM is designed to adjust processor capacity, channel paths, and I/O requests in real time across LPARs without human intervention.

Together with the IBM® zSeries servers, and with interoperability with Linux® for zSeries and z/VM®, z/OS can play a critical role in simplifying clients’ infrastructure. Both z/OS and Linux for zSeries support much of the server differentiation that sets the zSeries apart from other servers. With zSeries servers, z/OS provides the base for the z/Architecture™ with support for 64-bit storage, Intelligent Resource Director (IRD), and HiperSockets™ (for inter-partition communications).

Performance High-volume transaction processing and heavy batch processes are common on z/OS. z/OS is very efficient in managing its use of hardware and software resources.

4 Java Application Development for CICS

Page 19: Java Application Development for CICS

Availability The high availability of z/OS is a key reason why so many clients rely on z/OS for their most critical applications. To continue to improve this availability, z/OS provides automation capabilities in a new element, Managed System Infrastructure for Operations. This element provides automation for single system and sysplex operations to help simplify operations and improve availability.

Self-configuring z/OS Managed System Infrastructure for Setup (msys for Setup) is the z/OS solution for simplifying product installation, configuration, and function enablement. msys for Setup uses wizard-like configuration dialogs, thus helping to reduce configuration errors. msys for Setup provides multi-user and multi-system support. Also, msys for Setup can use the IBM Directory Server, OpenLDAP, on any IBM platform, including OpenLDAP on z/OS, which can simplify the initialization of msys for Setup.

Scalability z/OS is a highly scalable operating system that can support the integration of new applications. z/OS can scale up in a single logical partition and scale out in a Parallel Sysplex cluster for higher availability. With z/OS 1.6, up to 24 processors are supported in a single logical partition on the z990 server. In previous releases, z/OS supported up to 16 processors.

64-bit support The z/OS scale is extended with support for 64-bit real and virtual storage on zSeries servers, while continuing to support 24-bit and 31-bit applications. The 64-bit real support eliminates expanded storage, helps eliminate paging, and may allow you to consolidate your current systems into fewer LPARs or to a single native image. z/OS delivers 64-bit virtual storage management support. This 64-bit support is used by DB2® V8 and other middleware.

z/OS 1.5 delivers 64-bit shared memory support to allow middleware to share large amounts of 64-bit virtual storage among multiple address spaces. This is a significant capacity enhancement for relieving shared virtual storage constraints. z/OS 1.6 can improve the scale of new applications with 64-bit C/C++ support. In addition, the Java SDK for z/OS 1.4.1 is also available with 64-bit support.

Security z/OS extends its robust mainframe security features to address the demands of on demand enterprises. Technologies such as Secure Sockets Layer (SSL), Kerberos V5, Public Key Infrastructure, multilevel security, and exploitation of zSeries cryptographic features are available in z/OS. Integrated Cryptographic Service Facility (ICSF) is a part of z/OS, which provides cryptographic functions for data security, data integrity, personal identification, digital signatures, and the management of cryptographic keys. Together with cryptography features of the IBM zSeries servers, z/OS provides high-performance SSL, which can benefit applications that use z/OS HTTP

Chapter 1. Introduction 5

Page 20: Java Application Development for CICS

Server and WebSphere®, TN3270, and CICS Transaction Gateway server.

z/OS provides support for digital certificates, including the ability to provide full life-cycle management. With Public Key Services in z/OS, clients can create and manage digital certificates, leveraging their existing z/OS mainframe investments. This may provide significant cost savings over other digital certificate hosting options.

TCP/IP networking z/OS provides TCP/IP network support with high performance, security, and scale. High availability is provided across a Parallel Sysplex where TCP/IP traffic uses the Sysplex Distributor and Dynamic VIPA (virtual IP addressing). Together with the Workload Manager, these functions are designed to provide failure independence in the face of TCP/IP or system outages. Load balancing of network traffic can be self-optimized with z/OS, enabling consistent response times for critical traffic in a complex multiapplication network.

z/OS has evolved to a fully open operating system that supports:

� Internet Web serving� High security and integrity required for electronic commerce� Distributed object-oriented application architectures

This support, combined with the classic strengths of z/OS, makes it an excellent operating system for your current and future mission-critical applications and data.

1.2 CICS TS V2.3CICS Transaction Server for z/OS Version 2.3 provides an efficient and effective environment for applications written in COBOL, PL/I, C, C++, and Java. This version strengthens application development capabilities, enables enhanced re-use of 3270 applications, and enables applications to be accessed as Web Services within a services oriented architecture (SOA).

The transaction processing strengths of CICS in an enterprise computing environment are appreciated and exploited worldwide. CICS has always provided a reliable transaction processing environment that:

� Provides a robust, high-performance run-time environment for enterprise applications written in Java.

� Supports EJB session beans, providing another dimension for application architects. Where an EJB component needs to incorporate procedural logic modules to accomplish its business function, CICS enables this mixed-language component to run in a single execution environment with good isolation from other components, improving robustness and manageability.

� Provides a run-time environment optimized for business logic written as EJBs that can run alongside, and interoperate with, business logic written in languages such as COBOL. Both EJB applications and COBOL applications can access existing (and new) DB2, IMS™(TM) DB, and VSAM data concurrently and with complete integrity.

� Provides enhancements for applications that use TCP/IP communication for e-business enablement. These offer a range of benefits in terms of management and improved scalability and performance.

6 Java Application Development for CICS

Page 21: Java Application Development for CICS

� Provides enhanced DB2 facilities, which will provide a significant improvement in performance and a greater level of availability.

� Assists the evolution to on demand computing through integration, openness, autonomic computing and virtualization.

1.3 JavaJava is both an object-oriented programming language and a platform developed by Sun Microsystems. Java technology is based on the concept of a single Java virtual machine (JVM)—a translator between the language and the underlying software and hardware. All implementations of the programming language must emulate the JVM, thus enabling Java programs to run on any system that has a version of the JVM. In this section we introduce the technology, explain the basics, and position Java and Java technology.

Java started its life in 1991 as part of a Sun Microsystems project called OAK, a software environment (“virtual machine”) and programming language aimed at cable television “set-top” boxes. For various reasons the name OAK was dropped, and the name Java was adopted before the first release of the resulting technology.

To meet the objectives of this project, Java was designed from the outset to be small, portable, fast, and safe. These characteristics would later prove to be an essential part of Java's success, as they made Java an ideal language for the explosion in growth of the Web and the Internet.

The Java platform consists of the JVM and the Java Application Programming Interface (API), a large collection of ready-made software components to ease the development and deployment of applets and applications, including robust, secure, and interoperable enterprise applications. The Java API is grouped into libraries of related classes and interfaces; the libraries are known as packages.

1.3.1 Java languageThe Java programming language is unusual because Java programs are both compiled (translated into an intermediate language called Java bytecodes) and interpreted (bytecodes parsed and run by the JVM). Compilation occurs once, while interpretation happens each time the program is run. Compiled bytecode is a form of optimized machine code for the JVM; the interpreter is an implementation of the JVM.

Java is object oriented, but without all the complications. It has a single inheritance model, simple data types, and code that is organized into classes. These classes provide an excellent way of packaging functions.

As a language, Java is statically typed, and most type checking is done at compile time. However, runtime checks such as array bounds are still required. A key function of Java is that numeric precision is defined with the IEEE floating point notation, which ensures the same results everywhere for mathematical calculations.

The sample Java source code in Example 1-1 on page 8 shows some Java source code (the typical "Hello World" program) and the basic structure and elements of a Java application. It begins with block documentation comments that are started with /** and end with */. If this program were processed by the Java-Javadoc utility, a standard part of the SDK, these comments, along with the structure of the program, its methods, and other documentation comments, would be automatically included in a documentation file in HTML format.

Chapter 1. Introduction 7

Page 22: Java Application Development for CICS

A second form of comment can also be seen in the program: // display string. This is a private comment and will not be included in the HTML file that Javadoc produces.

Java also supports a third style of comment: The classical C comment starting with /* and ending with */. These are also private and are not included in Javadoc HTML files.

Example 1-1 Sample Java source code

/** * HelloWorldApp class implements an application that simply * displays "Hello World" to the standard output device. */public class HelloWorldApp { public static void main(String[] args) { System.out.println("Hello World!"); //display string }

After the documentation comment you can see the name of the class defined: HelloWorldApp. This part of the program gives us important information, such as whether this is an application, an applet, or a servlet. In this case the sample program is an application (it has a main() construct in its source code), and it can be executed from a command line.

The name of the class is case sensitive and must match the name of the file. The file type is .java, making the full file name HelloWorldApp.java. The file name (for example, javac HelloWorldApp.java) is used when you compile the program. A Java program is compiled into a .class file. The class name without its file type of .class (for example, java HelloWorldApp) is used when you run the program.

The next part of the program defines the properties of the Java program or class. In this case it is a public class that can be called by any other class. Our sample program returns no data, and it takes as input a character string of command line arguments.

Finally, our sample program performs its function: In this case to print out "Hello World" by creating an instance of a Java class. If you are only familiar with procedural programming, you could think of this as a call to a system-provided function. In reality it is very different, but that is beyond the scope of this introduction.

The source code shown in Example 1-1 would be compiled into machine-independent bytecode with the Java compiler, javac. The bytecode is conceptually similar to an object deck in z/OS terms. It is executable but still needs to be link-edited.

Java bytecode is dynamically linked; that is, functions external to the program are located and loaded at runtime rather than being statically bound to the Java bytecode. Thus, functions can be loaded on demand over the network when needed, with unused code never loaded. If the Java program is an application or servlet, it can still be dynamically linked by loading classes over a network-based file system such as network file system (NFS), distributed file system (DFS™), or Andrew file system (AFS®). Typically, however, all the required classes would be installed locally for applications and servlets.

Once loaded and linked, Java bytecodes are ready for execution. Originally Java bytecode was always interpreted (that is, translated) into native instructions. However, by default almost all JVMs include a just-in-time (JIT) compiler. The JIT compiler dynamically generates machine code for frequently used bytecode sequences in Java applications and applets while they are running.

The IBM Software Developer Kit for z/OS (SDK), Java 2 Technology Edition, Version 1.4 product, which became generally available in September, 2002, provides the SUN SDK1.4

8 Java Application Development for CICS

Page 23: Java Application Development for CICS

APIs and is periodically updated with cumulative service and improvements. The SDK for z/OS includes the JIT, which is enabled by default. You can disable the JIT to help isolate a problem with a Java application, an applet, or the compiler itself.

Because Java bytecode is in a machine-independent, architecture-neutral format, it can be run on any system with a standard Java implementation. An extensive library of underlying classes or functions can be used to do everything from graphics to network communication. Because these classes are Java bytecode, they too are machine independent.

1.3.2 Java Virtual MachineAt the core of the Java concept and implementation is the JVM, a complete software microprocessor with its own instruction set and operation (op)-codes. The JVM provides automatic memory management, garbage collection, and other functions for the programmer.

The IBM JVM, and most other JVMs, are implemented through licensed source code from Sun Microsystems. The source code is provided in C and Java and is highly portable. It has been ported by IBM to many platforms: IBM AIX®, OS/2®, OS/400®, z/OS, and others.

The JVM uses z/OS UNIX System Services for z/OS (USS) for base operating system functions. For this reason, USS must be correctly installed and tuned in order to get optimum performance from the JVM.

The JVM is the "essence" of Java; that is, it provides the machine independence that is the most significant advantage of Java. Although the JVM is not a unique concept and there have been other software microprocessors over the past 20 years, it is the first and only one to achieve broad acceptance. This acceptance is primarily a result of Sun Microsystems making the source code for the JVM available under license. It is much quicker to implement through the source code than from scratch working from a reference document.

For more information about the Java Virtual Machine see Chapter 2, “Java Virtual Machine support in CICS” on page 15.

1.3.3 Java for z/OSThe following Java products are full function products that have passed the Java compatible test suites, carry the Java compatible logo, and provide the Java language and function for z/OS.

� IBM Developer Kit for OS/390®, Java 2 Technology Edition, SDK1.3.1 (5655-D35)� IBM SDK for z/OS, Java 2 Technology Edition, V1.4 (5655-56)� IBM 64-Bit SDK for z/OS, Java 2 Technology Edition, V1.4 (5655-M30)

As of April 1, 2002, JDK 1.1.8 is no longer in service by the zSeries support team. In most cases, applications will run with no changes from JDK1.1. However, there are incompatibilities in some (particularly JNI) functions moving from Java 1.1 to Java 2.

The following Web site should be consulted for the latest on availability and service for products, and supersedes information in the announcements:

http://www-1.ibm.com/servers/eserver/zseries/software/java

Important: IBM SDK for z/OS, Java 2 Technology Edition, V1.4 with PTF for APAR PQ79281 is the minimum SDK level required for CICS TS V2.3.

CICS TS V2.3 does not support the 64-Bit SDK.

Chapter 1. Introduction 9

Page 24: Java Application Development for CICS

Products are available in both SMP/E and non-SMP/E format. You can order the product from IBM Software Manufacturing or you can download the identical code from the Web.

1.3.4 Runtime Environment and toolsThe SDK contains a Java Runtime Environment (JRE) and several development tools. This section describes the contents of the Runtime Environment and the SDK tools.

Runtime Environment In the Runtime Environment are:

� Core classes: These are the compiled class files for the platform and must remain zipped for the compiler and interpreter to access them. Do not modify these classes; instead, create subclasses and override where you need to.

� JRE tools: The following tools are part of the Runtime Environment and are in the /usr/lpp/java/J1.4/bins directory (where /usr/lpp/java/J1.4/ is the directory in which you installed the SDK).

– Java Interpreter (java) runs Java classes. The Java Interpreter runs programs that are written in the Java programming language.

– Java Interpreter (javaw) runs Java classes in the same way as the java command does, but does not use a console window.

– Key and Certificate Management Tool (keytool) manages a keystore (database) of private keys and their associated X.509 certificate chains that authenticate the corresponding public keys.

– Hardware Key and Certificate Management Tool (hwkeytool) works like keytool but also allows you to generate key pairs and store them in a keystore file of type JCA4758KS.

– Policy File Creation and Management Tool (policytool) creates and modifies the external policy configuration files that define your installation’s Java security policy.

– RMI activation system daemon (rmid) starts the activation system daemon so that objects can be registered and activated in a Java virtual machine (JVM).

– Common Object Request Broker Architecture (CORBA) Naming Service (tnameserv) starts the CORBA transient naming service.

– Java Remote Object Registry (rmiregistry) creates and starts a remote object registry on the specified port of the current host.

– Dump extractor (jextract) converts a system-produced dump into a common format that can be used by jdmpview. For more information see the relevant chapter in the IBM JVM Diagnostics Guide that is located at:

http://www.ibm.com/developerworks/java/jdk/diagnosis/index.html

Earlier versions of the IBM JRE shipped with a file called rt.jar in the jre/lib directory. From Java v1.4 onwards, this file has been replaced by multiple JAR files that reside in the jre/lib directory. Examples of these JAR files are:

� core.jar, which contains the majority of the class libraries, including the system, IO, and net class libraries.

� graphics.jar, which contains the awt and swing class libraries.

� security.jar, which contains the security framework code. For maintenance reasons, security.jar has been split up into smaller JAR files for this release.

� v server.jar, which contains the RMI class libraries.

10 Java Application Development for CICS

Page 25: Java Application Development for CICS

� xml.jar, which contains the xml and html class libraries.

This change should be completely transparent to the application. If an error is received about a missing rt.jar file in CLASSPATH, this error points to a setting that was used in Java V1.1.8 and was made obsolete in subsequent versions of Java. You can safely remove references to rt.jar in CLASSPATH.

SDK toolsThe following tools are part of the SDK and are located in the /usr/lpp/java/J1.4/bin directory:

� Java Compiler (javac) compiles programs that are written in the Java programming language into bytecodes (compiled Java code).

� Java Applet Viewer (appletviewer) tests and runs applets outside a Web browser.

� Class File Disassembler (javap) disassembles compiled files and can print a representation of the bytecodes.

� Java Documentation Generator (javadoc) generates HTML pages of API documentation from Java source files.

� C Header and Stub File Generator (javah) enables you to associate native methods with code written in the Java programming language.

� Java Archive Tool (jar) combines multiple files into a single Java Archive (JAR) file.

� JAR Signing and Verification Tool (jarsigner) generates signatures for JAR files, and verifies the signatures of signed JAR files.

� Native-To-ASCII Converter (native2ascii) converts a native encoding file to an ASCII file that contains characters encoded in either Latin-1 or Unicode, or both.

� Java Remote Method Invocation (RMI) Stub Converter (rmic) generates stubs, skeletons, and ties for remote objects. Includes RMI over Internet Inter-ORB Protocol (RMI-IIOP) support.

� IDL to Java Compiler (idlj) generates Java bindings from a given IDL file.

� Serial Version Command (serialver) returns the serialVersionUID for one or more classes in a format that is suitable for copying into an evolving class.

� Extcheck utility (extcheck) detects version conflicts between a target jar file and currently installed extension jar files.

� Cross-platform dump formatter (jdmpview) is a dump analysis tool that allows you to analyze dumps. For more information see the relevant chapter in the IBM JVM Diagnostics Guide located at:

http://www.ibm.com/developerworks/java/jdk/diagnosis/index.html

� INCLUDE FILES: C headers for JNI programs.

� DEMOS: The demo directory contains a number of subdirectories containing sample source code, demos, applications, and applets, that you can use.

� COPYRIGHT: Copyright notice for the SDK for z/OS software. Note that the user guides and the accompanying copyright files and demo directory are the only documentation that are included in this SDK for z/OS. You can view Sun’s software documentation by visiting the Sun Web site, or you can download Sun’s software documentation package from the Sun Web site:

http://java.sun.com

The following tools are not included in the IBM SDK:

� MIF doclet

Chapter 1. Introduction 11

Page 26: Java Application Development for CICS

� orbd� servertool

1.4 CICS TS Support for JavaCICS TS V2.3 makes use of the IBM Development Kit for z/OS, Java 2 Technology Edition (SDK), to provide the necessary Java Runtime Environment. Version 1.4 of the SDK extends the support for long-lived Java Virtual Machines (JVMs) by providing a new execution mode with a simplified storage heap structure. It also permits Java classes to be cached and shared by a number of JVMs running under the control of a single CICS region. CICS TS V2.3 provides infrastructure to allow both of these features to be used. In addition, CICS provides improvements to Java resource management by extending its storage protection mechanism to Java programs, and by refining the selection process it uses to match Java requests to the JVMs that run under its control.

CICS support for Java has evolved through a number of stages. With CICS TS V2.3, it now provides a robust, high-performance environment for enterprise applications written in Java. Its exploitation of the innovative IBM SDK for z/OS, Java Technology Edition, Version 1.4, together with an architecture that ensures that Java applications have a high degree of isolation from each other, allows it to achieve execution speed that is comparable with that of procedural languages. Further, CICS has enhanced Java execution by improving behavior under stress, reducing storage and start-up requirements for a JVM, and increasing the Java transaction throughput.

CICS provides optimized implementations of those parts of the J2EE specification that are appropriate to its role as a high-performance transaction server for core business applications and data. It also includes a copy of WebSphere Application Server V5.0 for Multiplatforms, which may be used for development, testing, and execution of J2EE applications in conjunction with CICS.

CICS exploits a completely new JVM specially designed to optimize performance for CICS transactions. Support for Java Enterprise APIs such as JDBC, JNDI, and RMI has been significantly enhanced. CICS applications can now use the Common Connector Interface (CCI) client API to allow portability between CICS and non-CICS servers of Java application classes that invoke CICS programs.

CICS TS V2.3 provides a new method for invoking the CICS function from a Java client. This function uses the Common Client Interface (CCI) Connector for CICS TS. It replaces the CICS Connector for CICS TS introduced in CICS TS V2.1. The CCI Connector for CICS TS enables clients to build powerful server components that exploit existing CICS programs. It enables Java programmers with little or no knowledge of CICS to reuse CICS applications. Java client applications should be portable between Java-enabled platforms with little or no modifications, and, in particular, should be portable from a non-CICS environment such as a WebSphere Applications Server into the CICS environment.

Depending upon the type of Java application being developed for CICS, there are three different roadmaps outlining the steps required to develop that particular type of Java application. These are:

� Java application in CICS� CICS IIOP application � CICS enterprise beans

Do do not discuss CICS IIOP applications or CICS EJBs in this book.

12 Java Application Development for CICS

Page 27: Java Application Development for CICS

1.4.1 CICS Java applications using JCICSYou can write Java application programs that use CICS services and execute under CICS control.

You can write Java programs on a workstation, or in the z/OS UNIX System Services shell. You can use any editor of your choice, or a visual composition environment such as Rational Application Developer.

CICS provides a Java class library, known as JCICS, supplied in the dfjcics.jar JAR file. JCICS is the Java equivalent of the EXEC CICS application programming interface (API) that you would use with other CICS supported languages, such as COBOL. It allows you to access CICS resources and integrate your Java programs with programs written in other languages. Most of the functions of the EXEC CICS API are supported. We discuss the JCICS API extensively in Part Part 3, “Java programming for CICS” on page 63, of this book.

The Java language is designed to be portable and architecture-neutral. The bytecode generated by compilation is portable, but requires a machine-specific interpreter for execution on different platforms. CICS provides this execution environment by means of a Java Virtual Machine (JVM) that executes under CICS control.

1.4.2 CICS Support for the JVMCICS provides the support you need to run a Java program in a z/OS Java Virtual Machine executing under the control of a CICS region. CICS support for JVMs allows you to run CICS application programs written in the Java language and compiled to bytecode by any standard Java compiler. You can find information about Java on the z/OS platform at:

http://www.ibm.com/servers/eserver/zseries/software/java/

CICS Transaction Server for z/OS Version 2 Release 3 supports the JVM provided by the IBM Software Developer Kit for z/OS, Java 2 Technology Edition, Version 1.4.1 at APAR PQ79281 or later, which features the persistent reusable JVM technology. This JVM includes several optimizations designed for the execution of CICS transactions. These are:

� The ability for JVMs to share a cache of commonly used class files that are already loaded, enabling faster JVM startup and reducing the cost of class loading. When a new JVM that shares the class cache is initialized, it can use these pre-loaded classes instead of reading them from the file system. Also, if the JVM performs just-in-time (JIT) compilation for any of the classes, it can write the results back to the Shared Class Cache, and other JVMs can then use the compiled classes. All the heap data (objects and static variables) are owned by the individual JVMs; this maintains the isolation between the applications being processed in the JVMs.

� The serial reuse of a JVM for multiple Java programs, avoiding most of the initialization costs.

� An optimized garbage-collection scheme, enabled by the clean separation of short-lived application objects from long-lived classes, objects, and native state (that is, non-Java or C language state), which are reset.

Java programs can execute in a JVM running on any supported platform through the ability of the JVM to interpret Java bytecode. You create Java bytecode class files using a Java compiler, such as Rational Application Developer, and these classes can be executed by a JVM without the need for any further translation.

This mode of executing Java classes is by interpretation, but a more efficient method in terms of performance is to convert the Java bytecode into z/OS machine code, like load modules. The JIT-compile function of the JVM provides this service. It produces JIT-compiled versions

Chapter 1. Introduction 13

Page 28: Java Application Development for CICS

of frequently used Java methods, normally at variable times during the usage of the methods. The JIT-compiling process incurs additional CPU time and uses extra Language Environment® storage, but provides more efficient executable code. The CPU cost of the Java applications reduces after the JIT-compiled code has been produced.

14 Java Application Development for CICS

Page 29: Java Application Development for CICS

Chapter 2. Java Virtual Machine support in CICS

In this chapter we talk about Java Virtual Machine (JVM) support in CICS. In particular, we discuss the various modes of operation a JVM can operate in, and the implications of choosing one of those modes. Also, we talk about different categories of classes loaded into a JVM, the rationale behind having those categories, and related performance and application design issues.

2

© Copyright IBM Corp. 2005. All rights reserved. 15

Page 30: Java Application Development for CICS

2.1 OverviewJava applications running in a server environment, such as CICS Transaction Server, have characteristics that are quite different from client applications. The latter tend to be long-lived, performing a variety of tasks (for example, a GUI application such as Rational® Application Developer). Server applications, on the other hand, typically perform a narrow set of functions in a more “predictable” way; they are designed for throughput and tend to be short-lived.

Also, in a transaction processing system, it is vital that no transaction effect the outcome of other transactions running in parallel or subsequently, other than by updating resources under transactional control.

This did not lend itself well to the JVM concept. The first problem is that the cost of creating and initializing a JVM is very high. Therefore, if a JVM was started and destroyed for each invocation of a transaction program, this would lead to an unacceptable throughput rate.

The obvious solution to this problem is to start up and initialize the JVM once, and then use it to run multiple programs sequentially. This is the approach found in today’s Web application servers, such as IBM WebSphere Application Server.

There is a new problem with this approach, however. A misbehaved program might change the state of the JVM in such a way that the outcome of subsequent program invocations on that JVM can be affected (a rather extreme example would be a change to the current time zone). In a transaction processing system, such situations must be avoided at all cost.

One way to get around this problem is a careful review of all application programs, making sure that they are “well-behaved.” Some global state changes may be all right, or even desired, such as reading configuration information that can be accessed by the next invocation of the same program without having to read it again. Other state changes, however, are potentially dangerous and must be avoided.

The other way of dealing with this problem is to reset the JVM to a state that is known to be safe to run the next program from. The idea is to categorize classes into levels of behavior: Classes that are known to be well-behaved can remain loaded and initialized, while classes that are not must be “thrown away” and re-loaded. In addition, application code needs to be monitored for potentially dangerous changes to the JVM state. If such a state change is performed, the JVM must not be reused; it must be terminated when the application program has finished, and a fresh one must be started.

There is another potential benefit of reusing the JVM for multiple program invocations: If classes are known to not affect the next program running on that JVM, then why not share those classes across JVMs? This would have two benefits: First, it reduces memory footprint; and second, it further reduces the JVM startup cost (in terms of both CPU and I/O) because shared classes will be loaded and initialized only once—the next JVM to start up can then use the shared version.

2.2 History of JVM support in CICSIn the next few sections we look at the history of JVM support in CICS, starting at CICS TS 1.3, going through to the current version CICS TS 3.1.

16 Java Application Development for CICS

Page 31: Java Application Development for CICS

2.2.1 CICS TS 1.3CICS TS 1.3 was the first level of CICS Transaction Server to support Java, at the JDK 1.1 level. Initially, however, Java programs were not run under a JVM; rather, they had to be compiled using the High Performance Java (HPJ) product, producing a Java Program Object. HPJ took the Java bytecodes and compiled them to S/390® machine code. A Java Program Object executes under the control of CICS Language Environment, just like a C application. Obviously, with this approach you lose platform independence.

Since the startup cost for an HPJ compiled application is very high, much like that of a JVM, a later PTF for CICS TS 1.3 introduced a technique called Hot Pooling. With Hot Pooling enabled, the HPJ environment is saved and reused between applications.

JVM support (for JDK 1.1 only) was introduced with another PTF to CICS TS 1.3. Because the JDK 1.1 JVM was not designed for reuse, a JVM is initialized, used, and then terminated for each CICS JVM program, making it very expensive in terms of path length. In other words, it suffered from the problems discussed in 2.1, “Overview” on page 16. Effectively, you could only use the JVM for programs that were either run very infrequently or were long-lived.

JVM support was only provided in CICS TS 1.3 to provide the ability to execute those parts of the Java API that are not supported by HPJ, to provide Java compliance.

2.2.2 CICS TS 2.1 and 2.2These two releases of CICS support the Java JDK 1.3. (The JDK 1.1 JVM is no longer supported.)

HPJ and Hot Pooling (discussed in 2.2.1, “CICS TS 1.3” on page 17) are still supported, but only for migration; you are encouraged to migrate to JVM (which really should not be more than setting up the JVM environment, and re-deploying you application as Java bytecodes instead of Java Program Objects).

Support for the resettable JVM (described in 2.3.3, “Resettable JVM” on page 21) was introduced.

One restriction for CICS programs running under the JVM, in these two releases, is that a JVM program cannot link, either directly or indirectly, to another JVM program in the same CICS region. This was true for CICS TS 1.3 as well.

2.2.3 CICS TS V2.3This level of CICS supports JDK 1.4.1 of the IBM Software Developer Kit for z/OS, Java 2 Technology Edition. It has support for the continuous JVM (see 2.3.2, “Continuous JVM” on page 19), and introduces the shareable class cache (see 2.4, “JVMSets and the Shared Class Cache” on page 24), allowing for classes and the results of JIT compilation to be shared between several JVMs.

Also, the restriction mentioned in 2.2.2, “CICS TS 2.1 and 2.2” on page 17, was lifted. You can now have more than one JVM program in the LINK stack, meaning that one JVM program can LINK to another JVM program (directly or indirectly).

2.2.4 CICS TS 3.1CICS Transaction Server V3.1 provides new Web Services capabilities to extend CICS applications to a Service Oriented Architecture (SOA), enabling them to be exposed directly as Web services.

Chapter 2. Java Virtual Machine support in CICS 17

Page 32: Java Application Development for CICS

Also, JCICS support was added for the new CHANNEL and CONTAINER mechanism for inter-program data transfer. See Appendix A, “Channels and containers” on page 193, for an example on how to use the new API.

2.3 JVM operation modesIn CICS TS 2.3 and 3.1, a JVM can run under one of the following modes, each of which is described in more detail in the following sections:

� Single use mode (2.3.1, “Single-use JVM” on page 18)� Continuous mode (2.3.2, “Continuous JVM” on page 19)� Resettable mode (2.3.3, “Resettable JVM” on page 21)

What mode a JVM runs in is determined by the REUSE parameter in the associated JVM profile. Table 2-1 on page 24 summarizes the different JVM modes.

In single use mode, the JVM always works “on its own,” while a JVM running in the resettable and continuous modes can run under the control of a dedicated master JVM. We explain this in more detail in 2.4.2, “Master JVM” on page 25, and 2.4.3, “Worker JVM” on page 25.

Continuous and resettable JVMs are commonly referred to as reusable JVMs.

Figure 2-1 illustrates the three different JVM modes.

Figure 2-1 Single-use, resettable, and continuous modes

2.3.1 Single-use JVMSingle use means that a JVM is created for each request, the Java application is run there, and then the JVM is thrown away. This effectively prevents the actions of one Java program from interfering with any other.

Obviously, this mode is expensive because every application incurs the cost of starting and initializing the JVM, loading of all classes needed by it, and destroying it once the program has terminated. Also, the results of JIT compilation are lost.

Create JVM Prog 1 Reset JVM Prog 2 Reset JVM Prog n Destroy JVM…

Create JVM Prog 1 Prog 2 Prog n Destroy JVM…Prog 3

Single use JVM (REUSE=NO)

Continuous JVM (REUSE=YES)

Resettable JVM (REUSE=RESET)

Create JVM Prog 1 Destroy JVM Create JVM Prog n Destroy JVM…

18 Java Application Development for CICS

Page 33: Java Application Development for CICS

The JVM has a single heap structure, unlike the one used by the resettable JVM, and does not undergo any reset processing. (Reset processing is discussed in 2.3.3, “Resettable JVM” on page 21.)

A typical use for this mode is testing changes to Java programs. Since no caching of classes is performed, you can be certain that when the program is restarted, the newly started JVM will reload any classes that have changed on the file system. It is not recommended for use in a production environment, other than to run applications that were originally designed for single-use JVMs and have not yet been reviewed for suitability to run in a reusable JVM.

2.3.2 Continuous JVMThis is a potentially long-lived JVM, which is started with a single storage heap.

In contrast to the resettable JVM mode described in 2.3.3, “Resettable JVM” on page 21, there is no mechanism for automatically resetting this storage when a Java program finishes execution.

This mode typically offers the best performance for running Java programs in CICS. However, this comes at a price: Application designers and implementors need to be aware that actions that change the JVM’s state can change the behavior of the next program (be it the same or another) that uses the same JVM. Therefore, applications whose behavior is not well understood are better run in the resettable JVM unless they can be extensively tested in this mode before putting into a production system.

On the other hand, the fact that applications can change and pass state can be put to good use. Suppose, for example, that an application, as part of its initialization, has to read configuration data. This may be an expensive operation—it might involve reading DB2 tables, parsing huge XML configuration files, or doing JNDI lookups. By taking advantage of the continuous JVM, you can cache this configuration information by anchoring it in static variables, thus avoiding the initialization overhead at subsequent invocations of the program. Any objects that are anchored in static, that is, that are reachable from a static variable, are never subject to garbage collection. Example 2-1 demonstrates the technique.

Example 2-1 Caching shared configuration data

package com.ibm.itso.sg245275.prjvm;

import java.io.IOException;import java.io.PrintWriter;import java.util.Collections;import java.util.Iterator;import java.util.Map;import java.util.Properties;

import com.ibm.cics.server.Task;

/** * Demonstrates how to keep initialization data across * program invocations when running in the continuous JVM. * * @author Ulrich Gehlert */public class MyApp {

/** * Our configuration data, or <code>null</code> if not read. */

Chapter 2. Java Virtual Machine support in CICS 19

Page 34: Java Application Development for CICS

private static Map configuration; // (1)

/** * Constructor. * * @param out * Stream for message output. */ public MyApp(PrintWriter out) { try { if (configuration == null) { // (2) // No cached configuration data, read them out.println("Reading configuration data"); readConfiguration(); } else { out.println("Using cached configuration data"); } showConfiguration(out); } catch (IOException e) { out.print("Unable to read configuration: " + e); } }

/** * Read the configuration data from a properties file. * In real life, this could be a much more expensive operation, * such as looking up a DB2 table or parsing a huge XML file. * * @throws IOException * Unable to read the configuration file. */ private void readConfiguration() throws IOException { Properties props = new Properties(); props.load(getClass().getResourceAsStream("myapp.properties")); // (3) configuration = Collections.unmodifiableMap(props); // (4) }

/** * Print the cached configuration, as a list of * key/value pairs. * * @param out * Stream on which to print. */ private void showConfiguration(PrintWriter out) { Iterator i = configuration.entrySet().iterator(); while (i.hasNext()) { Map.Entry entry = (Map.Entry) i.next(); out.print(entry.getKey()); out.print('='); out.println(entry.getValue()); } }

public static void main(String[] args) { new MyApp(Task.getTask().out); }}

20 Java Application Development for CICS

Page 35: Java Application Development for CICS

Notes on Example 2-1 on page 19:

1. This is the static variable where we store our configuration data.

2. Check for null to see if we have to initialize.

3. Read configuration data—in this example, from a properties file. In a real application, this could be a much more expensive operation, such as reading and parsing a complex XML document.

4. To make sure the configuration data cannot inadvertently be changed by the program, we wrap them in an unmodifiable collection. In general, it is good practice to make static variables final or immutable, if possible, when programming for the continuous JVM.

However, be aware that there is no guarantee that subsequent executions of an application will be assigned the JVM that contains the items created by the first execution of the application. In other words, there is no guarantee that the next invocation of the program will be able to see the data. Thus, your application should not rely on the presence of the persistent items that you create in the JVM; it should check for their presence in order to avoid unnecessary initialization, but it should be prepared to initialize them if they are not found in the present JVM.

If, on the other hand, you need to ensure that two applications that use a continuous JVM cannot see other's persistent state (for example, because you are not sure they will not interfere with each other), you should set up separate JVM profiles for the applications to use. You can specify the same options; just by using different names you make sure that they will run in distinct JVMs.

2.3.3 Resettable JVMThe resettable JVM can be started and used to run consecutive Java applications, resetting its storage areas between each program invocation. This mode of operation offers the same isolation as the single use mode, that is, it prevents that changes to the state of the JVM made by an application program affecting the operation of the next program run in that same JVM. However, it is much more efficient than single-use mode, for the following reasons:

� It avoids the overhead of destroying and starting the JVM.

� Classes and JIT-compiled code can be shared between JVMs, thus reducing I/O (for loading classes) and CPU time (for JIT compilation).

The JVM divides classes into categories of well-behavedness or trustworthiness, and it also monitors the behavior of application classes. If an application class changes the JVM state in a way that could potentially affect the next program run on that JVM, the JVM will be marked unresettable and will be destroyed once the program has terminated.

The storage heap is divided up into a number of areas, each with its own class loader. These areas are treated differently during reset processing.

There is a transient heap, which contains objects created by a Java application as it executes. All these objects are deleted at reset time. There is also a separate trusted middleware heap, used for middleware classes that are trusted to reset the object they create to some known state, as part of reset processing.

Resetting the JVM involves a check to see if any pointers exist from the middleware heap to the application heap. If there are none then the application heap is thrown away—in effect, this is a very cheap garbage collection operation.

If pointers do exist then a search similar to full garbage collection is performed to determine whether the pointers are live or not.

Chapter 2. Java Virtual Machine support in CICS 21

Page 36: Java Application Development for CICS

Resets can also fail for a number of application-related reasons, such as the changing of a system property or the loading of a native library. If the reset operation fails to complete, then CICS is informed of this and terminates the JVM. See “Unresettable actions” on page 22 for details.

To summarize, the resettable JVM provides the benefits of reuse while offering the greatest protection between program invocations.

Unresettable actionsAs discussed in the previous sections, a resettable JVM must be discarded after an application program has changed its state in a way that might affect another program running on that JVM. Therefore, in order to benefit from using the JVM in resettable mode, you must ensure that your applications stick to certain rules.

If an application program performs one of these actions, the JVM becomes unresettable:

� Writing to a static variable associated with a class loaded by either the bootstrap class loader or the extensions class loader

� Setting system properties

– java.lang.System.setProperty()– java.lang.System.setProperties()– java.lang.System.getProperties()

The first two of these are special cases of the modification of a static variable (in effect, they are write accesses to the static variable System.props).

� Closing or redirecting the standard input, output, or error streams

– System.err.close(), System.in.close(), System.out.close()– java.lang.System.setErr(), java.lang.System.setIn(), java.lang.System.setOut()

Again, these are special cases of writing to a global static variable.

� Loading a native library

– java.lang.System.loadLibrary()– java.lang.System.load()– java.lang.Runtime.loadLibrary()– java.lang.Runtime.load()

Since the JVM cannot know if native library code changes its state in one of the other ways described here, it marks itself as being unresettable.

� Using the Abstract Windowing Toolkit (AWT) or any of its derivatives to access a display or keyboard, or to print

� Several security-related actions, such as setting the security manager or attempting to access or modify the security configuration objects (Policy, Security, Provider, Signer, Identity)

� Using any of the thread methods to start, stop, resume, suspend, or interrupt threads

� Creating a new process using Runtime.exec()

Important: The resettable JVM is intended as an intermediate solution for running applications that are not known to be safe for running in continuous mode. Since the next release of the JDK (JDK 1.5) will no longer support resettable mode, support for this mode will be removed from a future version of CICS.

Therefore, you should design and code new applications to be able to run in continuous mode, and you should be prepared to migrate existing code.

22 Java Application Development for CICS

Page 37: Java Application Development for CICS

� Loading a nonchecked standard extension

Checked standard extensions are those extensions that have been checked for writable statics; the writable statics are either not exposed to application code, or checks have been added to the standard extension to detect any changes that are made.

Checked extensions are identified by the presence of a manifest entry in the main section of their JAR files:

IBM-Reusable-JVM-Compatible: True

� Using the JVM in debug mode (Xdebug option)

How to check for reset behaviorCICS provides logging facilities to assist you in finding out whether and why an application program has caused a JVM to become unresettable.

Logging of the events that cause a JVM to be marked as unresettable is controlled via the system properties file:

ibm.jvm.events.output=log file name

ibm.jvm.unresettable.events.level=max (Use this setting for development/test.)

or

ibm.jvm.unresettable.events.level=min (Use this setting for production.)

The three events to look out for are:

� UnresettableEvent

This is the worst type—it means the JVM has been marked unresettable and must be terminated. A textual description of the event tells you why that happened, and you will see a stack trace that tells you where in the application code it happened.

� ResetTraceEvent

This means there are cross-heap references from middleware objects to application objects. This is still bad, but not as bad as an UnresettableEvent since it does not necessarily mean the JVM has to be terminated.

For an in-depth discussion about ResetTraceEvents and how to get rid of them, refer to Persistent Reusable Java Virtual Machine User’s Guide, SC34-6201.

� ResetJVMEvent

This is the good one; it means the JVM reset cleanly.

2.3.4 Summary of JVM modesTable 2-1 on page 24 summarizes the different JVM modes.

Tip: This facility is not only useful for making your applications resettable-friendly, it is also a good start for migrating your applications from the resettable JVM to the continuous JVM. Many of the events that render a JVM unresettable can be potential problems when running in continuous mode.

Chapter 2. Java Virtual Machine support in CICS 23

Page 38: Java Application Development for CICS

Table 2-1 Comparison of JVM modes

2.4 JVMSets and the Shared Class CacheAs previously discussed in 2.1, “Overview” on page 16, another potential benefit of having long-lived JVMs, other than getting rid of JVM startup cost, is the possibility to share classes across multiple JVMs. This further cuts down the cost associated with loading the class files from the file system and initializing them; also, the results of JIT compilation can be shared so that each piece of code will be JIT compiled only once.

To support the Shared Class Cache, the JDK introduced the concept of a JVMSet, which is comprised of one master JVM and a set of multiple (one or more) worker JVMs.

2.4.1 Benefits of the Shared Class CacheThe benefits of having a Shared Class Cache can be summarized as follows:

� Worker JVMs start up more quickly.

A large proportion of JVM startup time was spent loading classes and JIT-compiling methods. With a Shared Class Cache, classes are loaded and JIT compiled only once.

� Worker JVMs have lower storage requirements than standalone JVMs.

The combined memory footprint of one master and several worker JVMs is less than for a set of standalone JVMs. Typically, this amounts to 20–40 MB per JVM; hence, you can have more JVMs in a single CICS region.

� The result is improved total system throughput (especially if combined with running in continuous mode).

IBM internal measurements have shown that the startup time for worker JVMs is at least 60 percent better than in CICS TS 2.2, and the storage footprint is down by 34 percent.

REUSE option in

profile

Can program invocations pass state?

Are programs allowed to

change characteristics

of the JVM?

Relative performance

Can be a master JVM?

Compatible with the Shared Class

Cache?

Single use NO N/A (JVM destroyed)

Yes Lowest (JVM initialized for

each use)

No No

Resettable RESET No No (JVM will be destroyed)

Medium Yes Yes

Continuous YES Yes Yes High Yes Yes

Important: There can be at most one active Shared Class Cache per CICS region.More precisely, there can be one or more old class caches that are in the process of termination, and there may be a new one that is being initialized but has not reached the point where it can take over from the current active one.

24 Java Application Development for CICS

Page 39: Java Application Development for CICS

2.4.2 Master JVMThe sole purpose of the master JVM is to initialize and to own the Shared Class Cache. It does not participate in any work once created; in other words, it cannot be used to run Java applications.

The JVM profile for the master JVM defines the trusted middleware classes and the shareable application classes for the Shared Class Cache.

The name of the JVM profile for the master JVM is set up in the JVMCCPROFILE system initialization parameter.

2.4.3 Worker JVMThe worker JVMs perform the actual Java workload (Java and CORBA applications, and EJBs). For classes that are shared across JVMs, a worker JVM uses the classes loaded in the Shared Class Cache instead of having to load them from the file system.

A worker JVM owns the working data for the applications that run in it (to maintain isolation between Java applications), and it also owns classes defined as being non-shareable. These classes will be loaded into each individual worker JVM, and will be reloaded every time the JVM is reset. We discuss this in more detail in FIXME.

The JVM profile for a worker JVM specifies the classpath for non-shareable classes. All other classpath settings are ignored for worker JVMs—they are inherited from the master JVM.

2.4.4 Starting the Shared Class CacheThe master JVM, and thus the Shared Class Cache, can be started in one of three ways, depending on the value of the JVMCCSTART CICS initialization parameter.

Important: The Shared Class Cache is no more and no less than what the name says—a cache for classes, that is, for bytecode (and JIT-compiled code). It is not a cache for data. For example, static member variables reside in one of each JVM’s own heaps, not in the Shared Class Cache.

Do not confuse this with JVMs running in continuous mode. A continuous JVM allows sharing data across program invocations; the Shared Class Cache, on the other hand, does not allow, or render possible, sharing data across several JVMs.

Important: There is at most one active Shared Class Cache, and therefore at most one master JVM per CICS region.

Important: The worker JVMs also inherit their reusability setting (whether they run in resettable or in continuous mode) from the master JVM. Since there can be only one master JVM, this implies that all worker JVMs run in either resettable or continuous mode—you cannot mix both modes in the same CICS region.

However, that does not mean you cannot use resettable JVMs in your region when the shared class in that region is set up for continuous mode, or vice versa. They just will have to be configured as standalone JVMs.

Chapter 2. Java Virtual Machine support in CICS 25

Page 40: Java Application Development for CICS

Possible settings are:

JVMCCSTART=AUTO The Shared Class Cache is started automatically as soon as a worker JVM starts up. Also, if you stop the Shared Class Cache manually, it will be restarted as soon as a worker JVM needs it.

JVMCCSTART=YES The Shared Class Cache is started automatically during CICS startup. Also, as in AUTO mode, it will be restarted automatically as needed after stopping it manually.

JVMCCSTART=NO You will have to start the Shared Class Cache manually, using the CEMT PERFORM CLASSCACHE START command. Also, there will be no automatic restart after stopping it; this means all attempts to create a new worker JVM will fail until you perform the restart.

2.4.5 Inquiring the status of the Shared Class CacheTo show the current status of the Shared Class Cache, use the CEMT INQUIRE CLASSCACHE command. You will get a summary display (Example 2-2); to see the details, tab on the first line of the summary and press Enter (Figure 2-3).

Figure 2-2 CEMT INQUIRE CLASSCACHE screen, short form

Figure 2-3 CEMT INQUIRE CLASSCACHE screen, long form

I CLASSCACHE STATUS: RESULTS - OVERTYPE TO MODIFY Cla Ena Sta Pro(DFHJVMCC) Dat(04/05/05) Tim(11:55:15) Tot(0001) Old(0000) Pha(0000) Reu Caches(24M )

SYSID=PJA7 APPLID=SCSCPJA7 RESPONSE: NORMAL TIME: 11.55.39 DATE: 04.05.05 PF 1 HELP 3 END 5 VAR 7 SBH 8 SFH 9 MSG 10 SB 11 SF

I CLASSCACHE RESULT - OVERTYPE TO MODIFY Classcache Autostartst( Enabled ) Status(Started) Profile(DFHJVMCC) Datestarted(04/05/05) Timestarted(11:55:15) Totaljvms(0001) Oldcaches(0000) Phasingout(0000) Reusest(Reuse) Cachesize(24M ) Cachefree(18389160 )

SYSID=PJA7 APPLID=SCSCPJA7 TIME: 11.56.16 DATE: 04.05.05 PF 1 HELP 2 HEX 3 END 5 VAR 7 SBH 8 SFH 10 SB 11 SF

26 Java Application Development for CICS

Page 41: Java Application Development for CICS

The following fields are displayed:

Autostartst This displays the status of autostart for the Shared Class Cache (see 2.4.4, “Starting the Shared Class Cache” on page 25).

Status This displays the status of the current Shared Class Cache. The values are:

StartedThe Shared Class Cache is ready, and it can be used by worker JVMs. This value in the CEMT display includes both the status STARTED and the transient status RELOADING, which occurs when a CEMT PERFORM CLASSCACHE Reload command has been issued, and a new Shared Class Cache is being loaded to replace the existing Shared Class Cache. While the Shared Class Cache is reloading, worker JVMs (both those that were already allocated to tasks and those that were allocated to tasks after the command was issued) continue to use the existing Shared Class Cache until the new Shared Class Cache is ready.

StoppedThe Shared Class Cache has either not been initialized on this CICS execution, or it has been stopped manually. If autostart is disabled, requests for worker JVMs will fail. If autostart is enabled, a new Shared Class Cache will be initialized as soon as CICS receives a request to run a Java application in a JVM whose profile requires the use of the Shared Class Cache. This value in the CEMT display includes both the status STOPPED and the transient status STARTING, which occurs when the Shared Class Cache is being initialized, either through the autostart facility or because an explicit CEMT PERFORM CLASSCACHE START command was issued. While the Shared Class Cache is starting, worker JVMs that require the use of the Shared Class Cache wait until the startup process is complete and the Shared Class Cache is ready. If initialization of the Shared Class Cache is unsuccessful, any waiting requests for worker JVMs fail.

Cachefree(value) This displays the amount of free space in the Shared Class Cache, in bytes.

Cachesize(value) This displays the size of the Shared Class Cache, in bytes, kilobytes (K), megabytes (M), or gigabytes (G). If the status of the Shared Class Cache is Stopped, this is the size that will be used by default when the Shared Class Cache is started. If the status of the Shared Class Cache is Starting or Started, this is the size of the current Shared Class Cache. If the status of the Shared Class Cache is Reloading, this is the size of the new Shared Class Cache that is being loaded.

Datestarted This displays the date on which the current Shared Class Cache was started. The format of the date depends on the value that you selected for the DATFORM system initialization parameter for your CICS region.

Oldcaches(value) This displays the number of old Shared Class Caches that are still present in the region because they are waiting for worker JVMs that are dependent on them to be phased out. If the status of the current Shared Class Cache is STOPPED, and worker JVMs are still dependent on it, then that Shared Class Cache is included in the number of old Shared Class Caches.

Chapter 2. Java Virtual Machine support in CICS 27

Page 42: Java Application Development for CICS

Phasingout(value) This displays the number of worker JVMs that are dependent on an old Shared Class Cache, and are being phased out. If the status of the current Shared Class Cache is Stopped, then any worker JVMs that are still dependent on it are included in the number of worker JVMs being phased out.

Profile(value) If the status of the Shared Class Cache is STOPPED, this displays the eight-character name of the JVM profile that will be used for a master JVM to start the Shared Class Cache. If the status of the Shared Class Cache is Started, Starting, or Reloading, this displays the eight-character name of the JVM profile that was used for the last valid request to start or reload the Shared Class Cache. This name is displayed even if the Shared Class Cache fails to start or reload. The displayed JVM profile is used next time you issue the command to start or reload the Shared Class Cache, unless you specify a different JVM profile using the Profile option.

Reusest This displays the level of reusability for the master JVM that initializes the Shared Class Cache. Recall from 2.4.2, “Master JVM” on page 25, that all the worker JVMs in a CICS region inherit their level of reusability from the master JVM. The values are:

ResetThe master JVM and worker JVMs are resettable.ReuseThe master JVM and worker JVMs are continuous.UnknownThe level of reusability for the master JVM and worker JVMs is not known, because the Shared Class Cache is not started.

Timestarted This displays the time, as an absolute value measured from midnight, that the current Shared Class Cache was started. The time is in the format hh:mm:ss.

Totaljvms(value) This displays the number of worker JVMs in the CICS region that are dependent on a Shared Class Cache. This includes both the worker JVMs that are dependent on the current Shared Class Cache, and any worker JVMs that are dependent on an old Shared Class Cache and are being phased out.

2.4.6 Changing the size of the Shared Class CacheWhen the master JVM initializes the Shared Class Cache, its amount of storage is fixed. To inquire the size of the Shared Class Cache, use the CEMT INQUIRE CLASSCACHE command, as explained in 2.4.5, “Inquiring the status of the Shared Class Cache” on page 26.

When you find the Shared Class Cache is too small, you can change its size by using the following commands. (Use START if the class cache is not currently started, or RELOAD if it is).

CEMT PERFORM CLASSCACHE [ START | RELOAD ] CACHESIZE(number)

The CACHESIZE parameter gives the new size of the class cache in bytes, kilobytes, megabytes, or gigabytes (use a suffix of K, M, or G, respectively).

As usual, subsequent CICS restarts will use the new value for the cache size unless you performed a COLD or INITIAL start of the CICS region, or the JVMCCSIZE parameter is specified as a SIT override.

28 Java Application Development for CICS

Page 43: Java Application Development for CICS

2.4.7 Updating classes in the Shared Class CacheSuppose you want to run a new version of an application running in your CICS region, for example, during development or to install a new release.

Merely copying the class files (or Jar files) to HFS does not suffice; since they are cached in the Shared Class Cache, the JVMs will not pick up the new copy unless you tell CICS about it using the CEMT PERFORM CLASSCACHE RELOAD command.

There are three levels of “gentleness” with this command:

� CEMT PERFORM CLASSCACHE RELOAD PHASEOUT

A new Shared Class Cache will be created, but until it is ready, both currently running worker JVMs and newly created worker JVMs will use the old cache. As soon as the new cache is ready, the currently running worker JVMs will be allowed to finish their work, but will then be terminated; newly created worker JVMs then use the new Shared Class Cache.

This is the default RELOAD mode (that is, the one that will be used if you omit the PHASEOUT keyword).

� CEMT PERFORM CLASSCACHE RELOAD PURGE

All tasks using the Shared Class Cache will be terminated using the PURGE mechanism; then the cache is deleted.

� CEMT PERFORM CLASSCACHE RELOAD FORCEPURGE

All tasks using the Shared Class Cache will be terminated using the FORCEPURGE mechanism; then the cache is deleted.

2.5 Heap managementIn order to provide for efficient garbage collection, and to support the reset mechanism, the JVM categorizes classes and objects to put them into different heaps.

In the next sections, we talk about the different categories of classes and objects, and explain how the JVM decides which heap to put an object in.

2.5.1 Categories of classes in the IBM prJVMAll classes loaded into the prJVM fall into one of three categories:

� Primordial classes

These are the classes that are part of the JVM distribution, for example, all classes in the java.lang.* hierarchy, and the classes implementing standard extensions to the JDK, such as the Java Naming and Directory Interface (JNDI) and the Lightweight Directory Access Protocol (LDAP).

Tip: During development (that is, when your application is updated very frequently), it may be a good idea not to use the Shared Class Cache at all, as suggested in 2.3.1, “Single-use JVM” on page 18. Sooner or later, you will forget to reload the Shared Class Cache, and will be scratching your head wondering why the bug you had spent all day finding still does not seem to be fixed. So, for development or debugging purposes, you should set up a JVM profile for a single-use JVM, which does not use the Shared Class Cache at all. Any new bytecode deployed to CICS will be picked up by a single-use JVM when it starts up.

Chapter 2. Java Virtual Machine support in CICS 29

Page 44: Java Application Development for CICS

� Trusted middleware classes

These are classes that are trusted to maintain a clean state (that is, one that does not adversely affect application classes) across a JVM reset. Examples of trusted middleware include:

– The JCICS interface classes– The IBM-supplied JDBC drivers– The CCI Connector for CICS– Enterprise Java Bean (EJB) containers

To be able to clean up during a JVM reset, middleware classes can request to be notified by the JVM whenever a reset occurs.

� Application classes

These are all the classes that do not fall into one of the categories above, such as Enterprise Java Beans (EJBs) and CICS programs written in Java.

Application classes fall into two subcategories: They can be either shareable or non-shareable. Shareable application classes, as the name suggests, are shared between different JVMs, using the Shared Class Cache as discussed in 2.4, “JVMSets and the Shared Class Cache” on page 24. Non-shareable classes, on the other hand, are loaded separately into each JVM. This can be useful during development, because there is no need to re-initialize the Shared Class Cache whenever a modified version of the application has been deployed to the CICS region.

Whether a class is loaded as shareable or not is purely a function of which class loader loads it, that is, which classpath it is found on. Nothing must be done when writing the class in Java.

2.5.2 How the JVM identifies the category of a classThe category of a class depends on the classloader by which it has been loaded; in other words, on the classpath on which it has been found. Figure 2-4 on page 31 illustrates this.

30 Java Application Development for CICS

Page 45: Java Application Development for CICS

Figure 2-4 Classpath determining class category

2.5.3 Heap managementAs already described in 2.4, “JVMSets and the Shared Class Cache” on page 24, the Shared Class Cache contains all classes (including JIT-compiled code) that are considered shareable, that is, those not loaded from the nonshareable application class loader.

Table 2-2 Characteristics of different heap types

Bootstrap class loader

Extension class loader

Extension class loaderTrusted middlewareclass loader (TMC)

Shareable applicationclass loader (SAC)

Default nonshareableapplication class loader

System default classpath

-Xbootclasspath

System default or java.ext dirs

ibm.jvm.trusted.middleware.class.path

java.class.path

ibm.jvm.shareable.application.class.pathShareableapplication classes

Non-shareable application classes

System classes

Standard extensionclasses

Shareable trustedmiddleware classes (in CICS: use TMPREFIX,

CICS_DIRECTORY, JAVA_HOME, TMSUFFIX)

System heap Middleware heap Transient heap

Lifetime Long (JVM lifetime) Medium–long, persistent Short, transactional

Allocation rate Low (mostly startup) Medium High

Garbage collection None Standard (for example, mark/sweep)

Quick clear of transactional data

Chapter 2. Java Virtual Machine support in CICS 31

Page 46: Java Application Development for CICS

The system heapThe system heap contains:

� System classes� Standard extension classes� Trusted middleware classes

Since those classes are never unloaded once initialized, the system heap is not subject to garbage collection. Its initial storage allocation is set by the Xinitsh parameter in the JVM profile. It can grow until it runs out of space in the LE enclave.

The Middleware heapThe middleware heap contains

� Objects having a lifetime greater than a single transaction so they are kept across JVM resets

� Objects constructed by middleware classes

� Objects constructed by system classes as a result of calls from middleware classes

� Static data for middleware and system classes

� Other string constant data

Its initial storage allocation is set by the Xms parameter in the JVM profile. It is allocated from low storage in the non-system heap and expands upwards until it meets the transient heap.

The application-class system heapThe application-class system heap (ACSH), which only exists in JVMs running in resettable mode, contains classes that have been declared as shareable application classes, that is, those that have been loaded from ibm.shareable.application.class.path (see Figure 2-4 on page 31).

Its initial storage allocation is set by the Xinitacsh parameter in the JVM profile. The ACSH is not subject to garbage collection.

The transient heapThe transient heap, which, like the ACSH, only exists in JVMs running in resettable mode, contains:

� Objects having a lifetime that is the same as the program using the JVM:

– Objects constructed by application classes

Objects � Class objects for shareable classes

� Objects reachable from the statics of primordial classes

� Non-shareable middleware classes

� Middleware objects� Primordial objects

created by middleware methods

� Arrays created by middleware methods

� Interned strings and the arrays for those strings

� Non-shareable application classes

� Application objects� Primordial objects

created by application methods

� Arrays created by application methods

System heap Middleware heap Transient heap

32 Java Application Development for CICS

Page 47: Java Application Development for CICS

– Objects constructed by system classes as a result of calls from application classes

� Class definitions and static data for non-shareable application classes

The transient heap is allocated from high storage in the non-system heap and expands downward until it meets the middleware heap. Its initial storage allocation is set by the Xinitth parameter in the associated JVM profile. During a successful JVM reset, the transient heap is completely deleted.

The other types of JVM do not have a transient heap. For single-use and continuous JVMs, objects that would be contained in the transient heap are allocated in the middleware heap. The master JVM cannot be used to run applications, and therefore does not need a transient heap.

2.6 Sample program: Resettable versus continuous modeIn this section, we demonstrate the difference between resettable and continuous modes. In addition, we show how to use extended system information (available in IBM JVMs only) to obtain whether a JVM runs in resettable mode.

Example 2-2 Sample program demonstrating resettable versus continuous JVM

package com.ibm.itso.sg245275.prjvm;

import java.io.PrintWriter;

import com.ibm.cics.server.Task;import com.ibm.jvm.ExtendedSystem;import com.ibm.jvm.classloader.Middleware;import com.ibm.jvm.classloader.Shareable;

/** * Demonstrates different behavior between the resettable and the continuous * JVM. * * @author Ulrich Gehlert */public class Demo1 {

private static int numInvocations; // (1)

public Demo1(PrintWriter out) { boolean isResettableJVM = ExtendedSystem.isResettableJVM(); // (2) out.println(); out.println("Running in a resettable JVM: " + isResettableJVM); if (isResettableJVM) { // (3) out.println("Has JVM been marked unresettable: " + ExtendedSystem.isJVMUnresettable()); // (4) } ClassLoader myClassloader = getClass().getClassLoader(); out.println("My classloader: " + myClassloader.getClass()); out.println("Is this a shareable classloader: " // (5) + (myClassloader instanceof Shareable)); out.println("Is this a middleware classloader: " // (6) + (myClassloader instanceof Middleware)); out.println("Number of invocations: " + numInvocations); // (7) }

public static void main(String[] args) {

Chapter 2. Java Virtual Machine support in CICS 33

Page 48: Java Application Development for CICS

numInvocations++; // (8) new Demo1(Task.getTask().out); }}

Notes on Example 2-2 on page 33:

1. This variable counts the number of times the program has been invoked in this JVM.

2. Find out if we are running in a resettable JVM. This API is available in IBM JVMs only.

3. If we are running in a resettable JVM…4. … we can find out if the JVM has been marked unresettable.

5. Shareable is a marker interface implemented by shareable classloaders.

6. Middleware classloaders implement the Middleware marker interface.

7. Print the number of times the program has been invoked in this JVM.

8. Increment invocation count.

34 Java Application Development for CICS

Page 49: Java Application Development for CICS

Part 2 System programming

This part of the book is intended for system programmers who will be setting up and configuring CICS to run Java applications. We list the software and hardware requirements to run Java applications in CICS. We then describe how to set up and run a very simple CICS Java application. Finally, we provide more detailed information about setting up and configuring CICS to run Java applications.

Part 2

© Copyright IBM Corp. 2005. All rights reserved. 35

Page 50: Java Application Development for CICS

36 Java Application Development for CICS

Page 51: Java Application Development for CICS

Chapter 3. Software and hardware requirements

Java application development for z/OS and CICS is supported by several components. In this chapter we discuss the major hardware and software requirements for executing Java programs in the CICS environment.

The following topics are addressed:

� Hardware prerequisites� z/OS operating system� External security manager� Java language support� Java client support

Use the documentation provided with each product for guidance on their installation.

For further information, see the following publications:

� CICS Transaction Server Program Directory, GI10-2560� Release Guide, GC34-6218� Migration Guide, GC34-6221

3

© Copyright IBM Corp. 2005. All rights reserved. 37

Page 52: Java Application Development for CICS

3.1 Hardware prerequisitesThe basic requirement is for a processor that supports z/OS Version 1 Release 4, and which has sufficient processor storage to meet the requirements of the operating system, CICS TS, the access methods, and all other software being run.

z/OS runs on the latest IBM mainframe servers—the z990, z900, z890, z800, G6, G5, and Multiprise® 3000 servers.

3.2 z/OS operating systemThe minimum required level of operating system for CICS Transaction Server for z/OS, Version 2 Release 3 is z/OS Version 1 Release 4 (5694-A01).

z/OS UNIX System Services z/OS UNIX System Services is a base element of z/OS that provides the standard command interface familiar to interactive UNIX users.

Language EnvironmentLanguage Environment is a base element of z/OS that provides the Runtime Environment for programs generated with:

� z/OS C/C++ � C/C++ for MVS/ESA™ � AD/Cycle® C/370™ � IBM Rational Software Development Platform (RAD)� COBOL for OS/390 &VM � COBOL for MVS &VM (formerly COBOL/370™) � VisualAge® PL/I for OS/390 � PL/I for MVS &VM (formerly PL/I MVS &VM) � VS FORTRAN and FORTRAN IV (in compatibility mode)

3.3 External Security ManagerIn this section we discuss External Security Manager.

Integrated security functionsSecurity Server, an optional feature of z/OS, can provide one-stop shopping for security needs. It is an integrated package that includes functions to help protect your z/OS e-business applications.

� RACF® provides user authentication and access control for z/OS and OS/390 resources and data. It includes support for digital certificate authentication as well as conventional user ID and password. RACF contains comprehensive administration, auditing, and logging capabilities.

� LDAP Server provides a generalized Lightweight Directory Access Protocol server supporting LDAP V1R4. LDAP clients in the network can search, extract, add, and delete information contained in the directory.

� Open Cryptographic Enhanced Plug-ins provide additional functions for z/OS and OS/390 applications that use Common Data Security Architecture (CDSA) cryptographic and certificate services.

38 Java Application Development for CICS

Page 53: Java Application Development for CICS

� Firewall Technologies supports e-business security with additional levels of protection for network applications. Included is Internet Key Exchange functions in support of IPSec VPN (Virtual Private Network).

� Network Authentication Services provides services (based on MIT Kerberos Version 5 reference implementation) for authentication, delegation, and data confidentiality. When combined with Kerberos-aware applications running across multiple platforms (with Kerberos implementations compatible with MIT Kerberos Version 5), this can help provide the basis of consistent user identification and authentication in a heterogeneous networked environment.

� DCE Security Server provides user and server authentication for applications using DCE client/server communications technology.

LDAP Server, Network Authentication Services, and Firewall Technologies are licensed with base z/OS and do not require a Security Server feature license to use them.

If you use Resource Access Control Facility (RACF) as your external security manager for CICS, you need the Security Server for z/OS feature, 56947-A01.

3.4 Java Language SupportCICS TS V2.3 supports the JVM provided by the IBM Software Developer Kit for z/OS, Java 2 Technology Edition, Version 1.4.2.

IBM SDK for z/OS Java 2 Technology Edition, V1.4.1 with PTF for APAR PQ79281 applied, can also be used, but IBM no longer provides technical support for this release.

To use the Java Naming and Directory Interface (JNDI), you need the LDAP server component of the Security Server feature of z/OS. Alternatively, you can use a COS naming directory server, such as that provided by WebSphere Application Server.

3.5 Java Client SupportTo enable connection to CICS server programs, the Common Client Interface (CCI) as defined by the J2EE Connector Architecture Specification and the CICS Transaction Gateway API are supported, the latter being an IBM proprietary interface. Support for the Common Connector Framework (CCF) Client Interface is retained only for backwards compatibility with CICS Transaction Server for z/OS Versions 2.1 and 2.2, and has been withdrawn with CICS TS 3.1.

Chapter 3. Software and hardware requirements 39

Page 54: Java Application Development for CICS

40 Java Application Development for CICS

Page 55: Java Application Development for CICS

Chapter 4. Setting up CICS to run Java applications

In this chapter we describe the tasks necessary to set up the environment for running Java applications in CICS and some of the commands to control your CICS Java setup once it is up and running. The information in this chapter is aimed at CICS systems programmers, though it may be useful background information for Java application developers.

In the first section, we give a brief overview of accessing the z/OS UNIX shell and then describe how you can build and run one of the Java application samples shipped with CICS. You will find this section useful if you are setting up a Java application in CICS for the first time. You may skip this section if you already have some experience with setting up a Java application in CICS.

In the second section we provide more detailed information about setting up CICS to run Java applications. We discuss configuring z/OS, USS, Language Environment, and CICS, and describe some of the options you can specify in the JVM profile and JVM properties file.

In the third section, we describe some of the commands you can use to manage your CICS Java setup once it is up and running.

4

© Copyright IBM Corp. 2005. All rights reserved. 41

Page 56: Java Application Development for CICS

4.1 Running a simple Java application in CICSIn this section we describe how you can set up and run a very simple Java application in CICS. It is aimed at systems programmers who are new to Java.

We have included a brief overview of accessing the z/OS UNIX shell. If you are already familiar with this you can go straight to 4.1.2, “Setting up the CICS sample Java application” on page 45.

4.1.1 Accessing the z/OS UNIX shellThe z/OS UNIX shell is the interactive interface to z/OS UNIX. You will need to access the shell to configure CICS to run Java applications. You will invoke shell commands and utilities and also run shell scripts.

There are several ways to access the z/OS UNIX shell. You can choose between a UNIX-like interface, a TSO interface, and an ISPF interface. You can choose the interface with which you are most familiar and get a quicker start on z/OS UNIX.

We describe three ways to access the shell in this book (Figure 4-1). See ABCs of z/OS System Programming Volume 9, SG24-6989, for more information about accessing the shell and USS in general.

Figure 4-1 Accessing the z/OS UNIX shell

If you are an experienced TSO user and new to UNIX, then we recommend that you use the ISPF shell. This is a menu-driven interface allowing you to work with the HFS and to enter some UNIX commands. You can use the ISPF editor to modify files in the HFS. If you need to type a UNIX command that is not available on the menus, then you can open a command prompt from the Tools option on the action bar (see Figure 4-2 on page 43).

Experienced UNIX user Experienced TSO user

UNIX InterfaceDirect login (telnet, ssh, rlogin)OMVS

Command line

ISPF basedISHELL

Menu interface

42 Java Application Development for CICS

Page 57: Java Application Development for CICS

To start the ISPF shell, enter TSO ISHELL at the ISPF command prompt or ISHELL from ISPF option 6.

Figure 4-2 ISPF shell

The other choice available from TSO is to use the OMVS command. This starts a UNIX-like interface with a command prompt. You can toggle between OMVS and the TSO/E command line. However, you cannot use the ISPF editor, nor can you use other ISPF functions such as the split screen.

To start OMVS enter TSO OMVS at the ISPF command prompt or enter OMVS from ISPF option 6.

Chapter 4. Setting up CICS to run Java applications 43

Page 58: Java Application Development for CICS

Figure 4-3 OMVS shell

If you are familiar with UNIX you may choose to log in directly to the shell. You could use the telnet, rlogin, or ssh command to log in. You then enter commands at the prompt. You cannot use the ISPF editor and cannot switch to TSO. However, you can use the TSO command to run a TSO command from your shell. You will need to be familiar with a UNIX editor such as vi or emacs if you want to modify the contents of a file.

You will need to know the host name or IP address of the z/OS LPAR to log in. You may also need to know the port number for the service you are using if it differs from the well known port number for that service.

Figure 4-4 Using telnet to access the shell

We used direct login to the UNIX shell using telnet while writing this book. Any screenshots or figures showing the z/OS UNIX shell in this book will be from a telnet session.

44 Java Application Development for CICS

Page 59: Java Application Development for CICS

4.1.2 Setting up the CICS sample Java applicationIn this section we cover the steps required to set up and run one of the CICS sample Java applications. The Java application selected is the HelloCICSWorld JCICS application supplied with CICS TS V2.3. A fuller explanation of how to set up and run this and the other sample Java applications can be found in Java Applications in CICS, SC34-6238.

You will:

1. Build the sample application using a makefile.2. Create directories and files in the HFS.3. Modify the JVM profile.4. Tailor the CICS system initialization parameters.5. Install the required CICS resource definitions.6. Run the Java application.

We assume that the following components are already installed, configured, and operational; that is, no further configuration is necessary:

� CICS Transaction Server V2.3� IBM SDK for z/OS, Java 2 technology Edition V1.4� Language Environment for z/OS� z/OS UNIX System Services

Build the sample application using a makefileCICS supplies makefiles containing instructions to compile the sample Java application source code. The UNIX make command executes the instructions in the makefile.

You need to set three environment variables before running the make command.

PATH USS search path.

CICS_HOME The installation directory for CICS Transaction Server V2.3. Typically this is /usr/lpp/cicsts/cicsts23. cicsts23 is defined by the USSDIR installation parameter when you installed CICS TS V2.3 (cicsts23 is the default).

JAVA_HOME The installation directory for IBM SDK for z/OS, Java 2 technology Edition V1.4. In our environment, the SDK is installed in /usr/lpp/java/J1.4.

The environment variables may be set in one or more of the following places:

� In the RACF user profile� In the file /etc/profile� In the file .profile in the shell user’s home directory� In the file named in the ENV environment variable in the user’s .profile� At the shell prompt� In a shell script

These environment variables may already be set. You can use the echo command to check whether they have been set (see Example 4-1).

Example 4-1 Displaying the environment variables

$ [SC66] /u/cicsrs1: echo $PATH/usr/lpp/java/J1.4/bin:/bin:.$ [SC66] /u/cicsrs1: echo $JAVA_HOME/usr/lpp/java/J1.4$ [SC66] /u/cicsrs1: echo $CICS_HOME

$ [SC66] /u/cicsrs1:

Chapter 4. Setting up CICS to run Java applications 45

Page 60: Java Application Development for CICS

We already have PATH and JAVA_HOME set correctly because the commands to set them are in the file /etc/profile (see Example 4-2).

Example 4-2 Commands to set the environment variables in /etc/profile

PATH=/usr/lpp/java/J1.4/bin:$PATHexport PATHexport JAVA_HOME=/usr/lpp/java/J1.4

The null response to echo $CICS_HOME shows that it is not set. You can either add the commands to set and export CICS_HOME to /etc/profile or your own .profile file or you can enter the command export CICS_HOME=/usr/lpp/cicsts/cicsts23 on the command line.

To build the Java samples, you need write permission for the HFS directory in which the samples are stored and for its subdirectories. These directories are part of the directory structure that includes the other CICS files that have been installed on HFS.

1. Type cd $CICS_HOME/samples/dfjcics to change directory.

2. Type make -f Helloworld.mak jvm to build the sample.

Example 4-3 Building the sample application

$ [SC66] /u/cicsrs1: export CICS_HOME=/usr/lpp/cicsts/cicsts23$ [SC66] /u/cicsrs1: cd $CICS_HOME/samples/dfjcics$ [SC66] /cicsts23/samples/dfjcics: make -f HelloWorld.mak jvmjavac -deprecation -classpath .:/usr/lpp/cicsts/cicsts23/lib/dfjcics.jar examples/HelloWorld/HelloWorld.javajavac -deprecation -classpath .:/usr/lpp/cicsts/cicsts23/lib/dfjcics.jar examples/HelloWorld/HelloCICSWorld.java$ [SC66] /cicsts23/samples/dfjcics:

You have now created two Java classes, HelloWorld and HelloCICSWorld. They are stored in the $CICS_HOME/samples/dfjcics/examples/HelloWorld directory.

Create directories and files in the HFSIn this section you copy the supplied JVM profile and JVM properties file used by the HelloCICSWorld application to a newly created directory. JVM profiles and JVM system properties are explained in more detail in “Setting up JVM profiles” on page 53 and “JVM system properties files” on page 55.

You also create a new working directory for the JVM. The CICS JVM uses this directory when creating the stdin, stdout, and stderr files for the JVM. The working directory is specified in the JVM profile.

Tip: In the UNIX shell, you prefix the environment variable with the dollar sign ($) to substitute the value of the variable. The echo command then displays the values of the variables on the screen.

Note: Example 4-2 shows two ways of exporting the environment variable. You can set the variable and then export it using two separate commands or you can set and export the variable using one command.

Exporting a variable makes it available to the current process (in this case the shell) and any other processes created by the current process.

Note: Adding the command to /etc/profile will affect all users. Any changes made in /etc/profile will take effect the next time a user invokes the shell.

46 Java Application Development for CICS

Page 61: Java Application Development for CICS

First you create new directories under the CICS region user ID’s home directory to hold the JVM profiles and properties files. You also create a new working directory. The commands we entered are shown in Example 4-4.

Example 4-4 Creating the new directories and copying files

$ [SC66] /u/cicsts23: export CICS_HOME=/usr/lpp/cicsts/cicsts23$ [SC66] /u/cicsts23: mkdir JVMProfiles$ [SC66] /u/cicsts23: cd JVMProfiles$ [SC66] /u/cicsts23/JVMProfiles: cp $CICS_HOME/JVMProfiles/* .$ [SC66] /u/cicsts23/JVMProfiles: cd ..$ [SC66] /u/cicsts23: mkdir props$ [SC66] /u/cicsts23: cd props$ [SC66] /u/cicsts23/props: cp $CICS_HOME/props/* .$ [SC66] /u/cicsts23/props: cd ..$ [SC66] /u/cicsts23: mkdir workdir

Modify the JVM profileYou need to check and possibly modify the values shown in Table 4-1 in the sample JVM profile DFHJVMPR.

Table 4-1 DFHJVMPR options

If you are using ISHELL to access the shell, then you can use the ISPF editor to update the profile. If you are using OMVS or direct login to the shell then you will need to use a UNIX editor such as vi.

Tailor the CICS system initialization parametersYou need to add the system initialization parameter JVMPROFILEDIR. This is the path to the directory holding the JVM profiles. Remember that case is significant when coding this parameter. We coded JVMPROFILEDIR=/u/cicsts23/JVMProfiles.

You will need to restart CICS to pick up the change.

Install the required CICS resource definitionsOnce CICS is back up, you can log on and install the CICS resource definitions.

Tip: The cp commands in Example 4-4 specify a period (.) as the target directory. In UNIX, this denotes the current directory.

Option Description What we coded

WORK_DIR Working directory for JVM

WORK_DIR=/u/cicsts23/workdir

CICS_DIRECTORY CICS TS installation path

CICS_DIRECTORY=/usr/lpp/cicsts/cicsts23

JAVA_HOME SDK installation path

JAVA_HOME=/usr/lpp/java/J1.4/

JVMPROPS Path and name of JVM properties file

JVMPROPS=/u/cicsts23/props/dfjjvmpr.props

CLASSPATH Directory search path for Java classes

CLASSPATH=/usr/lpp/cicsts/cicsts23/samples/dfjcics

Chapter 4. Setting up CICS to run Java applications 47

Page 62: Java Application Development for CICS

The definitions for the CICS Java sample applications are in group DFH$JVM. The transaction for the HelloCICSWorld Java application is JHE2 and the program is DFJ$JHE2.

Use CEDA to install the group.

Run the Java applicationEnter JHE2 at your CICS terminal. You see the response in Example 4-5.

Example 4-5 Running JHE2

JHE2Hello from a Java CICS application

The HelloCICSWorld class uses the JCICS Task class to send text to the terminal.

4.2 System configurationIn this section we look at the tailoring of your UNIX System Services (USS), Language Environment (LE), and CICS Transaction Server configuration required to support CICS Java applications.

Java application programs can be executed in either of two ways:

� Using a Java Virtual Machine (JVM) within CICS� Using VisualAge for Java, Enterprise Edition for OS/390 with the HPJ option

We do not discuss using HPJ-compiled Java application programs in this book. CICS TS 2.3 only supports these programs for compatibility reasons, and support for HPJ has been withdrawn in CICS TS 3.1. We recommend that you run Java applications in a JVM.

A JVM in CICS runs as a USS process in an LE enclave created using the LE pre-initialization module, CEEPIPI. This means that you will need to review and possibly modify your USS and LE configuration in addition to tailoring your CICS configuration to support running Java applications in CICS.

4.2.1 UNIX System ServicesYou specify USS parameters in the BPXPRMxx members of SYS1.PARMLIB. The default values are not sufficient when using the CICS JVM. Installation Guide, GC34-6224, suggests starting with the following values and adjusting them based on your experiences.

IPCSEMNSEMS 1000

MAXPROCSYS 500

MAXPROCUSER 512

MAXUIDS 500

MAXASSIZE 2000000000

MAXFILEPROC 512

MAXPTYS 256

Note: The first time you run JHE2 it will take a second or two to complete. This is because of the time spent initializing the JVM. You will not see this delay the second time you run the transaction. The JVM is reused.

You have just seen one of the benefits of using a reusable JVM.

48 Java Application Development for CICS

Page 63: Java Application Development for CICS

MAXTHREADS 10000

MAXTHREADTASKS 5000

MAXCPUTIME 2147483647

Java Applications in CICS, SC34-6238, also discusses the setting of IPCSEMNSEMS and an additional parameter IPCSEMNIDS when using the Shared Class Cache.

z/OS V1R6.0 UNIX System Services Planning, GA22-7800, discusses the settings of some of these parameters. You will find a description of all the BPXPRMxx parameters in z/OS MVS Initialization and Tuning Reference, SA22-7592.

You can change these values dynamically without re-IPLing using the SETOMVS or SET OMVS commands. For example:

SETOMVS MAXPROCUSER=256

You will need to edit the BPXPRMxx member to pick up the changes on the next IPL.

Pay special attention to the setting of MAXPROCUSER if you have several CICS regions with the same region user ID running multiple JVMs. There will be a large number of UNIX processes running under the CICS region user ID. You may need to increase MAXPROCUSER further. Message BPXI040 is issued when the process limit is reached.

You set system-wide limits when you specify the values in BPXPRMxx. You may want to set a lower system-wide limit and then set a higher limit for individual users (such as your CICS region user ID). You can do this by specifying limits in the OMVS segment of the user’s profile. Table 4-2 shows the RACF OMVS segment attribute names and the corresponding BPXPRMxx parameter names.

Table 4-2 RACF OMVS segment attributes

You use the RACF ADDUSER or ALTUSER command to specify these attributes on a per-user basis:

ALTUSER userid OMVS(PROCUSERMAX(nnnn)

4.2.2 Language Environment (LE)LE is a prerequisite for CICS JVM programs. However, unlike other languages, JVM programs do not require the CICS/LE interface. JVM programs run with LE support using MVS services (not CICS services). JVM programs require the LE support provided by the SCEERUN and SCEERUN2 libraries only.

SCEERUN and SCEERUN2 can either be defined in the CICS STEPLIB or included in the MVS linklist. SCEERUN also needs to be added to DFHRPL.

RACF OMVS segment attribute name BPXPRMxx parameter name

ASSIZEMAX MAXASSIZE

CPUTIMEMAX MAXCPUTIME

FILEPROCMAX MAXFILEPROC

PROCUSERMAX MAXPROCUSER

THREADSMAX MAXTHREADS

Chapter 4. Setting up CICS to run Java applications 49

Page 64: Java Application Development for CICS

The LE runtime options for the enclave in which the JVM runs are obtained from:

1. CEEDEOPT2. DFHJVMRO3. CICS JVM Launcher program

The options in Example 4-6 cannot be over-ridden and are set by the CICS JVM launcher program.

Example 4-6 LE runtime options that cannot be over-ridden

POS(ON)XPLINK(ON)TRAP(ON,NOSPIE)ABTERMENC(ABEND)

You can override all other runtime options for the JVM by assembling and linking a module called DFHJVMRO. The source code for a sample DFHJVMRO is provided in SDFHSAMP. A DFHJVMRO load module is not shipped.

If you assemble and link a new version of DFHJVMRO while CICS is running, you must use the command CEMT SET PROG(DFHJVMRO) NEW to load the new version of the program.

If DFHJVMRO cannot be loaded by the JVM launcher program, CICS builds the default runtime options programmatically. Example 4-7 shows the default runtime options.

Example 4-7 Default LE runtime options for the CICS JVM

ALL31(ON) LIBSTACK(8,900,FREE) STACK(128K,128K,ANY,KEEP) HEAP(4M,1M,ANY,FREE,0K,4080) BELOWHEAP(4096,2048,FREE) ANYHEAP(4K,8176,ANY,FREE) STORAGE(NONE,NONE,NONE,0K) TERMTHDACT(DUMP,,96)MSGFILE(CEEMSG) ENVAR(“_EDC_STOR_INITIAL=4K”)

4.2.3 CICS Transaction ServerThis section describes the tasks needed to configure CICS to run Java applications.

Security settings for the CICS region user IDTo create JVMs, CICS requires access to directories and files in the USS HFS. You need to give your CICS region user permission to access these resources in the HFS. This is covered in detail in “Setting up and using JVMs” in Java Applications in CICS, SC34-6238. The key points are summarized in this section.

� Assign a suitable UNIX user identifier (UID) and suitable UNIX group identifier (GID) for your CICS region user.

� Specify a home directory for your CICS region user.

Note: When coding options in DFHJVMRO remember to add a trailing blank.

50 Java Application Development for CICS

Page 65: Java Application Development for CICS

� Ensure that the HFS containing the home directory is mounted. We recommend using the automount facility of USS. Refer to z/OS V1R6.0 UNIX System Services Planning, GA22-7800, for further information about the automount facility.

� Give the CICS region user read and execute access to the directories and files that every CICS region needs to create JVMs. These files and directories are in /usr/lpp/cicsts/$CICS_HOME and its sub-directories and in /usr/lpp/java142/J1.4/bin and /usr/lpp/java142/J1.4/bin/classic.

� Give the CICS region user read, write, and execute access to the working directories you have specified for stdin, stdout, and stderr for the JVMs in each CICS region. The WORK_DIR option in the JVM profile specifies the working directory. If you redirect the output using the USEROUTPUTCLASS option in the JVM profile, then the CICS region user needs access to the directories to which the output is redirected.

� Give the CICS region user read and execute access to directories and files:

– Specified on the CLASSPATH option in the JVM profile.

– Specified on the ibm.jvm.shareable.application.class.path system property in a JVM properties file.

– You have added to the trusted middleware classpath using the TMPREFIX or TMSUFFIX option in the JVM profile.

– You have added to the LIBPATH in the JVM profile.

– Holding any JVM profiles or JVM properties files you have created.

CICS startup JCL You need to add the SDFJAUTH library to STEPLIB of your CICS startup JCL. This library must be APF authorized. The load modules in SDFJAUTH contain the CICS Java launcher code.

The storage used by the CICS JVM does not come from the CICS Dynamic Storage Areas (DSAs). You need to specify a region size for your CICS region that is sufficient both to accommodate the CICS DSAs and the storage required for your planned Java workload. CICS Performance Guide, SC34-6247, contains guidance on calculating and tuning the storage requirements for your Java workload. As a starting point we recommend setting a region size of at least 400 MB.

CICS system initialization parametersYou should review the CICS system initialization parameters discussed in this section when setting up CICS to run Java applications.

There are some additional system initialization parameters that control CICS tracing for the JVM. You may need to set these parameters for debugging purposes. These parameters are discussed in Chapter 8, “Problem determination and debugging” on page 157.

You can find more information about the system initialization parameters in CICS System Definition Guide, SC34-6226.

JVMPROFILEDIRJVMPROFILEDIR specifies the name (up to 240 characters long) of an HFS directory that contains the JVM profiles for CICS. CICS searches this directory for the profiles it needs to configure JVMs. The default value of JVMPROFILEDIR is /usr/lpp/cicsts/cicsts23/JVMProfiles.

If you chose a different name during CICS installation for the cicsts23 directory beneath which the sample JVM profiles are stored (that is, if you chose a non-default value for the

Chapter 4. Setting up CICS to run Java applications 51

Page 66: Java Application Development for CICS

CICS_DIRECTORY variable used by the DFHIJVMJ job), or if you want CICS to load the JVM profiles from a directory other than the samples directory, you need to do one of the following:

� Change the value of the JVMPROFILEDIR system initialization parameter.

� Link to your JVM profiles from the directory specified by JVMPROFILEDIR, by means of UNIX soft links. This method enables you to store your JVM profiles in any place in the HFS file system. Use the ln -s command to create a soft link.

JVMCCPROFILEJVMCCPROFILE specifies the JVM profile to be used for the master JVM that initializes the Shared Class Cache. The default is the supplied sample JVM profile, DFHJVMCC, which you can modify. The value specified by JVMCCPROFILE is used on an initial or cold start of CICS. Using CEMT, you can restart the Shared Class Cache with a different JVM profile while CICS is running.

JVMCCSIZEJVMCCSIZE specifies the size of the Shared Class Cache on an initial or cold start of CICS. The size of the Shared Class Cache can be between 1 MB and 2047 MB. You can specify the number in bytes, or as a whole number of kilobytes followed by the letter K, or as a whole number of megabytes followed by the letter M. The default value is 24 MB (specified as 24M).You can use the CEMT PERFORM CLASSCACHE START or RELOAD command (or the equivalent EXEC CICS command) to change the size of the Shared Class Cache while CICS is running.

JVMCCSTARTJVMCCSTART determines whether the Shared Class Cache is started during CICS initialization, and sets the status of autostart for the Shared Class Cache.

When autostart is enabled for the Shared Class Cache, if the Shared Class Cache has been stopped or has not yet been started, it is started as soon as CICS receives a request to run a Java application in a JVM whose profile requires the use of the Shared Class Cache.

When autostart is disabled, the Shared Class Cache can only be started by a CEMT PERFORM CLASSCACHE START command (or the equivalent EXEC CICS command).

Using CEMT, you can change the status of autostart while CICS is running.

Note: The JVM profiles DFHJVMPR and DFHJVMCD, and their associated JVM properties files, must always be available to CICS. DFHJVMPR is used if a Java program is defined as using a JVM but no JVM profile is specified, and it is used for sample programs. DFHJVMCD is used by CICS-defined programs, including the default request processor program and the program that CICS uses to publish and retract deployed JAR files. Both these JVM profiles must therefore be present in the directory that is specified.

Attention: On subsequent restarts, the value from the last CICS execution is used, unless you provide JVMCCPROFILE as a SIT override.

Attention: On subsequent restarts, the value from the last CICS execution is used, unless you provide JVMCCSIZE as a SIT override.

52 Java Application Development for CICS

Page 67: Java Application Development for CICS

MAXJVMTCBSCICS JVMs run on their own TCBs (see “CICS TCBs and the JVM” on page 180). MAXJVMTCBS limits the total number of TCBs in the pool of open TCBs that CICS uses for JVMs. Each JVM runs on a J8 or J9 TCB, so MAXJVMTCBS limits the number of JVMs that can be active in the CICS region.

The default is 5. The minimum permitted value is 1, meaning that CICS is always able to create at least one open TCB for use by a JVM, of either J8 or J9 mode.

Chapter 9, “Performance for Java in CICS TS V2” on page 179, provides information about setting MAXJVMCTBS. Refer to CICS Performance Guide, SC34-6247, for definitive guidance on setting and tuning your setting of MAXJVMTCBS.

You can change the setting for MAXJVMTCBS without restarting CICS by using the CEMT SET DISPATCHER MAXJVMCTBS command.

Setting up JVM profilesThe JVM is started by the CICS Java launcher, which uses a set of options known as a JVM profile. A JVM profile determines the characteristics of a JVM. The JVM profile that a Java application uses is specified in the CICS PROGRAM definition for that Java program. You can set up several JVM profiles that use different options to cater for the needs of different applications. JVM profiles are text files stored on HFS.

The Persistent Reusable JVM used by CICS has a set of standard options that are supported in the z/OS Runtime Environment. An additional set of non-standard options is specific to the z/OS virtual machine implementation. Persistent Reusable Java Virtual Machine User’s Guide, SC34-6201, contains detailed descriptions of all the options you can specify.

Typically you will set options in the profile that specify:

� Whether the JVM runs in continuous, resettable, or single-use mode

� Whether the JVM uses the Shared Class Cache, and if so whether it is the master JVM or a worker JVM

� Directory pathnames such as CICS_DIRECTORY and JAVA_HOME

� The location of the JVM systems properties file

� Class paths

� Stack and heap size settings for the JVM

� Where output from the JVM (System.out and System.in) is written

Attention: If you do this, subsequent CICS restarts use the changed setting, unless the system is INITIAL or COLD started, or the JVMCCSTART system initialization parameter is specified as an override at startup. In these cases, the setting from the system initialization parameter is used.

Note: JM TCBs, used for the master JVM that initializes the Shared Class Cache, do not count towards the MAXJVMTCBS limit.

Tip: If you need to set environment variables to control the behavior of the CICS JVM specify them in the JVM profile.

Chapter 4. Setting up CICS to run Java applications 53

Page 68: Java Application Development for CICS

CICS System Definition Guide, SC34-6226, lists the options that are of particular relevance to CICS. Table 4-3 shows the options that you are most likely to set. Each entry in the table shows the default value if not specified in the profile. It also shows for each type of JVM whether the option is required (must be specified), OK (may be specified), or ignored (CICS ignores the option if specified). If a particular setting for the option is required for a certain type of JVM, or if the option is only applicable to a certain type of JVM, then this information is given instead.

Refer to CICS System Definition Guide, SC34-6226, and Persistent Reusable Java Virtual Machine User’s Guide, SC34-6201, for descriptions of the options.

Table 4-3 JVM profile options

Tip: You can use the symbol &APPLID; in any value to indicate that the APPLID of the CICS region should be substituted at runtime. This allows the use of the same profile for all regions, even if a different WORK_DIR (for example) is required. APPLIDs are always upper case.

Option Default Master Worker Standalone

CLASSCACHE NO Ignored YES NO

REUSE RESET RESET or YES

Ignored REUSE or YES or NO

CICS_DIRECTORY None Required Ignored Required

JAVA_HOME None Required Ignored Required

WORK_DIR /tmp OK OK OK

CLASSPATH None Ignored OK OK

LIBPATH None Required OK OK

TMPREFIX, TMSUFFIX None Required Ignored Required

JVMPROPS None Required Required Required

Xinitacsh 128 KB OK Ignored Resettable only

Xinitsh 128 KB OK Ignored OK

Xinitth 500 KB Ignored Resettable only

Resettable only

Xmaxe 0 OK OK OK

Xmaxf 0.6 OK OK OK

Xmine 1 MB OK OK OK

Xminf 0.3 OK OK OK

CLASSCACHE_MSGLOG dfhjvmccmsg.log Required Ignored Ignored

STDERR dfhjvmerr OK OK Ok

STDIN dfhjvmin OK OK OK

STDOUT dfhjvmout OK OK OK

VERBOSE NO OK OK OK

54 Java Application Development for CICS

Page 69: Java Application Development for CICS

CICS supplies sample JVM profiles in /usr/lpp/cicsts/$CICS_DIRECTORY/JVMProfiles. You can use these profiles for your own applications, only adding your classes to the class path options. The CICS installation job, DFHIJVMJ, substitutes your values for the symbols &CICS_DIRECTORY and &JAVA_HOME in the sample JVM profiles.

The supplied sample JVM profiles are:

DFHJVMPR Resettable JVM. Shared Class Cache is not used. (This is the default JVM profile for a CICS PROGRAM definition.)

DFHJVMPC Resettable JVM using the Shared Class Cache.

DFHJVMPS Single-use JVM. (We do not recommend using this profile for Java applications running in production systems.)

DFHJVMCC Master JVM that initializes the Shared Class Cache.

DFHJVMCD Profile for CICS-supplied system programs written in Java. Do not use this profile for your own programs. Only make changes so that it is set up correctly for your CICS region to allow the CICS-supplied programs to run. For example, you may need to change JAVA_HOME.

Java Applications in CICS, SC34-6238, contains more detailed information about the CICS-supplied JVM profiles.

JVM system properties filesEach JVM profile references a JVM properties file, which is another text file containing the system properties for the JVM. The JVMPROPS option in the profile specifies the path of the systems properties file. System properties are key name and value pairs.

You specify the shareable application classpath (SAC) in the systems property file. The property name is ibm.jvm.shareable.application.classpath.

Persistent Reusable Java Virtual Machine User’s Guide, SC34-6201, contains a list of system properties you may need to specify. IBM Developer Kit And Runtime Environment, Java 2, Technology Edition, SC34-6358, describes system properties that you may need to set to gather diagnostic materials when working with IBM support personnel.

CICS supplies sample JVM system properties files in /usr/lpp/cicsts/&CICS_DIRECTORY/props to get you started. There is a corresponding system properties file for each supplied JVM profile.

Table 4-4 Supplied JVM system properties file

DUMP YES OK OK OK

Note: Any system property that you would specify using the -D option when launching a JVM from the command line should go in the JVM systems property file, without the -D prefix.

Supplied JVM profile name Corresponding JVM systems property file

DFHJVMCC dfjjvmcc.props

DFHJVMPC dfjjvmpc.props

DFHJVMPR dfjjvmpr.props

Option Default Master Worker Standalone

Chapter 4. Setting up CICS to run Java applications 55

Page 70: Java Application Development for CICS

CICS PROGRAM definition attributesYou use a PROGRAM resource definition to specify the control information that CICS requires to load and run an application program. Some attributes of the PROGRAM resource definition are applicable only to Java application programs, and other attributes require fixed values for Java application programs. You can find more information about PROGRAM attributes in CICS Resource Definition Guide, SC34-6228.

JVMYou must specify JVM(YES) for a Java application.

JVMCLASSJVMCLASS specifies the fully qualified name of the main class in a Java program to be run in a CICS JVM. The fully qualified name is the class name qualified by the package name. The name is case-sensitive and must be entered with the correct combination of upper and lower case letters.

JVMPROFILEJVMPROFILE specifies the name of a JVM profile to use for this program. The JVM profile must be in the directory specified by the system initialization parameter JVMPROFILEDIR.

DFHJVMPS dfjjvmps.props

DFHJVMCD dfjjvmcd.props

Note: As JVM profiles and JVM properties files are HFS files, case is important whenever you use their names in CICS. You must enter the name using the same combination of upper and lower case characters that is present in the HFS file name.

In the CEDA panels, any field where you enter an HFS file name accepts mixed case characters. This is not true if you enter the name in a CEDA command line or in another CICS transaction such as CEMT or CECI. Therefore, you may need to temporarily suppress upper case translation for your terminal when working with HFS file names. Enter CEOT NOUCTR at a CICS terminal to do this. CEOT UCTR restores upper case translation for your terminal.

Pay attention to case when specifying HFS file names in the source for your system initialization table (SIT) or SIT overrides.

Tip: The package name describes a hierarchical directory structure. You need to specify the path to the directory structure (which may be within a Java archive (JAR) file) on one of your classpaths. The JVMCLASS attribute then specifies how to locate the class within the directory structure.

For example, the CICS-supplied HelloCICSWorld class is in package examples.HelloWorld. The supplied sample creates the directory structure examples/HelloWorld below /usr/lpp/cicsts/cicsts23/samples/dfjcics. The HelloCICSWorld class file is created in /usr/lpp/cicsts/cicsts23/samples/dfjcics/examples/HelloWorld.

So you specify /usr/lpp/cicsts/cicsts23/samples/dfjcics on your classpath and examples.HelloWorld.HelloCICSWorld as your JVMCLASS attribute in the program definition.

Supplied JVM profile name Corresponding JVM systems property file

56 Java Application Development for CICS

Page 71: Java Application Development for CICS

LANGUAGEThis attribute is ignored for JVM programs. Specifying JVM(YES) tells CICS that this is a Java program.

CONCURRENCYJVM programs must be defined as threadsafe.

4.3 Managing your CICS Java environmentThe CICS CEMT transaction provides several commands to manage your CICS Java environment. This section lists and briefly describes the commands you are most likely to use. For more information about each of the commands refer to CICS Supplied Transactions, SC34-6230.

All of these commands are available in the system programming interface (SPI). You can write your own programs to use EXEC CICS commands to manage. Refer to CICS System Programming Reference, SC34-6233, for more information.

If you use CICSPlex® System Manager (CPSM) to manage your CICSplex then some of these commands are available using the CPSM Web User Interface (WUI) or CPSM Application Programming Interface (API). You can find more information about using the WUI in CICSPlex SM Web User Interface Guide, SC34-6461.

4.3.1 CEMT INQUIRE CLASSCACHEINQUIRE CLASSCACHE returns information about the Shared Class Cache in the CICS region and reports the presence of any old Shared Class Caches that are awaiting deletion.

Example 4-8 CEMT INQUIRE CLASSCACHE

I CL RESULT - OVERTYPE TO MODIFY Classcache Autostartst( Enabled ) Status(Started) Profile(DFHJVMCC) Datestarted(04/06/05) Timestarted(10:08:38) Totaljvms(0000) Oldcaches(0000) Phasingout(0000) Reusest(Reuse) Cachesize(24M ) Cachefree(19652770 )

You can modify the autostart status of the Shared Class Cache. Autostartst takes one of two values:

Enabled If the Shared Class Cache has been stopped or has not yet been started on this CICS execution, the Shared Class Cache is started as soon as CICS receives a request to run a Java application in a JVM whose profile requires the use of the Shared Class Cache.

Disabled If the Shared Class Cache has been stopped or has not yet been started on this CICS execution, an explicit CEMT PERFORM CLASSCACHE START command is required to start it. If the status of the Shared Class Cache is

Chapter 4. Setting up CICS to run Java applications 57

Page 72: Java Application Development for CICS

Stopped and autostart is disabled, and CICS receives a request to run a Java application in a JVM whose profile requires the use of the Shared Class Cache, the request fails.

4.3.2 CEMT INQUIRE DISPATCHERINQUIRE DISPATCHER returns information about the current state of the dispatcher. You can see the current number of active JVM TCBs (Actjvmtcbs). The value displayed includes both J8 and J9 TCBs, but not the JM TCB for the master JVM. You can also view and update the maximum number of JVM TCBs from this panel (Maxjvmtcbs).

Example 4-9 CEMT INQUIRE DISPATCHER

I DIS STATUS: RESULTS - OVERTYPE TO MODIFY Acthptcbs(000) Actjvmtcbs(000) Actopentcbs(0000) Aging( 00500 ) Maxhptcbs( 005 ) Maxjvmtcbs( 005 ) Maxopentcbs( 0130 ) Mrobatch( 001 ) Runaway( 0015000 ) Scandelay( 0100 ) Subtasks(000) Time( 0001000 )

4.3.3 CEMT INQUIRE JVMINQUIRE JVM displays all the JVMs in the CICS region. You cannot change the displayed values. You can also enter CEMT INQUIRE JVM with one of the values listed below, to display all the JVMs in the CICS region with a particular status. For example, you could enter CEMT INQUIRE JVM UEXECKEY to display all the JVMs that execute in user key, or CEMT INQUIRE JVM PROFILE(DFHJVMPC) to display all the JVMs that were created with the JVM profile DFHJVMPC.

The INQUIRE JVM command does not find the master JVM that initializes the Shared Class Cache. It only finds JVMs that are, or could be, allocated to tasks.

Example 4-10 CEMT INQUIRE JVM

I JVM STATUS: RESULTS - OVERTYPE TO MODIFY Jvm(0000000001) Age(0000001810) Allo(0000000000) Cla Res Uex Pro(DFHJVMPC) Tas(0000000) Jvm(0000000002) Age(0000001804) Allo(0000000000) Reu Uex Pro(DFHJVMPR) Tas(0000000) Jvm(0000000003) Age(0000001711) Allo(0000000000) Reu Uex Pro(DFHJVMPR) Tas(0000000) Jvm(0000000004) Age(0000001668) Allo(0000000000) Cla Res Uex Pro(DFHJVMPC) Tas(0000000)

58 Java Application Development for CICS

Page 73: Java Application Development for CICS

4.3.4 CEMT INQUIRE JVMPOOLINQUIRE JVMPOOL displays information about the JVM pool (if any JVMs exist) in the CICS region. Note that there is no identifier on this command—a CICS region supports only one pool of JVMs.

You can see the number of JVMs that have been initialized and are available for use or allocated to tasks. This total includes JVMs that are in the process of being terminated and removed from the region and included in the PHASINGOUT count.

You can enable or disable the JVM pool. A disabled JVM pool cannot accept new requests to service JVM programs. Programs can still be executing if they were started before the JVM pool became disabled.

Example 4-11 CEMT INQUIRE JVMPOOL

I JVMPO RESULT - OVERTYPE TO MODIFY Jvmpool Status( Enabled ) Total(0001) Phasingout(0000) Terminate( )

4.3.5 CEMT INQUIRE PROGRAMINQUIRE PROGRAM returns information about an installed program definition.

Example 4-12 CEMT INQUIRE PROGRAM

I PROG(TRADERPJ) STATUS: RESULTS - OVERTYPE TO MODIFY Prog(TRADERPJ) Jav Pro Ena Ced Res(000) Bel Uex Ful Thr Jvm

The expanded display shows the class name and JVM profile. You can change the class name and JVM profile from this display. You may need to disable upper case translation before specifying a new class name.

Example 4-13 CEMT INQUIRE PROGRAM (expanded display)

I PROG(TRADERPJ) RESULT - OVERTYPE TO MODIFY Program(TRADERPJ) Rescount(000) Usecount() Dataloc(Below) Execkey(Uexeckey) Executionset( Fullapi ) Concurrency(Threadsafe) Remotesystem() Runtime( Jvm ) Jvmclass( com.ibm.itso.sg245275.trader.SimpleTraderPL ) Jvmclass( ) Jvmclass( ) Jvmclass( ) Jvmclass( ) Hotpooling( Nothotpool )

Chapter 4. Setting up CICS to run Java applications 59

Page 74: Java Application Development for CICS

Jvmprofile( DFHJVMPR )

4.3.6 CEMT PERFORM CLASSCACHEYou can use the PERFORM CLASSCACHE command to initialize (start or reload) or terminate (phase out, purge, or forcepurge) the Shared Class Cache. While you are performing one of these operations, you can use other options on the command to set attributes of the Shared Class Cache, as follows:

� When you are initializing the Shared Class Cache (PERFORM CLASSCACHE START or RELOAD), you can change its size (Cachesize option), and change the JVM profile that is used for the master JVM (Profile option).

� When you are terminating the Shared Class Cache (PERFORM CLASSCACHE PHASEOUT, PURGE, or FORCEPURGE), you can set the status of autostart (Autostartst option). If you do not want the Shared Class Cache to start up again until you enter an explicit command, you can use this option to ensure that autostart is disabled.

Subsequent CICS restarts use the most recent settings that you made using the PERFORM CLASSCACHE command (or the SET CLASSCACHE command), unless the system is INITIAL or COLD started, or the system initialization parameters are specified as overrides at startup. In these cases, the settings from the system initialization parameters are used.

Example 4-14 CEMT PERFORM CLASSCACHE

PER CL STATUS: COMMAND SYNTAX CHECK CEMT Perform CLasscache ( Reload | Start ) ( Forcepurge | PHaseout | PUrge ) < ( Disabled | Enabled > ) < PRofile() > < Cachesize() >

You use one of the following options to terminate the Shared Class Cache.

Forcepurge All tasks using worker JVMs dependent on the Shared Class Cache are terminated by the SET TASK FORCEPURGE mechanism, and the worker JVMs are terminated. No more JVMs can use the Shared Class Cache, and it is deleted when all the worker JVMs that were dependent on it have been terminated.

Phaseout All worker JVMs using the Shared Class Cache are marked for deletion. The JVMs are actually deleted when they finish running their current Java programs. No more JVMs can use the Shared Class Cache, and it is deleted when all the worker JVMs that were dependent on it have been terminated.

Purge All tasks using worker JVMs dependent on the Shared Class Cache are terminated by the SET TASK PURGE mechanism, and the worker JVMs are terminated. No more JVMs can use the Shared Class Cache, and it is deleted when all the worker JVMs that were dependent on it have been terminated.

Note: The Phaseout, Purge, and Forcepurge operations also act on any old Shared Class Caches that are still present in the region because they are waiting for worker JVMs that are dependent on them to be phased out. For example, if you issue a CEMT PERFORM CLASSCACHE Forcepurge command, all tasks using worker JVMs dependent on a Shared Class Cache are forcepurged (both those dependent on the current Shared Class Cache and those dependent on old Shared Class Caches).

60 Java Application Development for CICS

Page 75: Java Application Development for CICS

4.3.7 CEMT SET DISPATCHERYou can use the SET DISPATCHER command to specify the maximum number of J8 and J9 mode open TCBs that can exist concurrently in the CICS region. The value specified can be in the range of 1 to 999. If you reduce MAXJVMTCBS from its previously defined value, and the new value is less than the number of open TCBs currently allocated, CICS detaches TCBs to achieve the new limit only when they are freed by user tasks. Transactions are not abended to allow TCBs to be detached to achieve the new limit. If there are tasks queued waiting for a J8 mode TCB and you increase MAXJVMTCBS from its previously defined value, CICS attaches a new TCB to resume each queued task, up to the new limit.

Example 4-15 CEMT SET DISPATCHER

SET DIS MAXJVMTCBS(6) STATUS: RESULTS - OVERTYPE TO MODIFY NORMAL Acthptcbs(000) Actjvmtcbs(000) Actopentcbs(0000) Aging( 00500 ) Maxhptcbs( 005 ) Maxjvmtcbs( 006 ) Maxopentcbs( 0130 ) Mrobatch( 001 ) Runaway( 0015000 ) Scandelay( 0100 ) Subtasks(000) Time( 0001000 )

4.3.8 CEMT SET JVMPOOLThe SET JVMPOOL command allows you to enable or disable the JVM pool, or to terminate the pool altogether. When you terminate the pool, all the JVMs in the pool, both worker JVMs using the Shared Class Cache and JVMs running independently of the Shared Class Cache, are terminated. No more JVMs can use the existing Shared Class Cache, and it is deleted when all the worker JVMs that were dependent on it have been terminated. If autostart is enabled for the Shared Class Cache, a new Shared Class Cache is started as soon as a new JVM requests it.

Example 4-16 CEMT SET JVMPOOL

SET JVMPO PHASE STATUS: COMMAND SYNTAX CHECK CEMT Set JVMPool < Enabled | Disabled > < PHASEout | PUrge | Forcepurge >

You use one of the following options to terminate a pool:

Forcepurge All tasks using JVMs in the pool are terminated by the SET TASK FORCEPURGE mechanism. The Shared Class Cache is deleted when all the worker JVMs that were dependent on it have been terminated.

Phaseout All JVMs in the pool are marked for deletion. The JVMs are actually deleted when they finish running their current Java program. The Shared Class Cache is deleted when all the worker JVMs that were dependent on it have been terminated.

Chapter 4. Setting up CICS to run Java applications 61

Page 76: Java Application Development for CICS

Purge All tasks using JVMs in the pool are terminated by the SET TASK PURGE mechanism, and the JVMs are terminated. The Shared Class Cache is deleted when all the worker JVMs that were dependent on it have been terminated.

Tip: If you change the JVM profile or JVM system properties file for a JVM currently in the pool and you want the changes to take effect you need to terminate the whole JVM pool.

62 Java Application Development for CICS

Page 77: Java Application Development for CICS

Part 3 Java programming for CICS

Part 3

© Copyright IBM Corp. 2005. All rights reserved. 63

Page 78: Java Application Development for CICS

64 Java Application Development for CICS

Page 79: Java Application Development for CICS

Chapter 5. Getting started

This chapter helps you get started with Java programming in a CICS environment, using Rational Application Developer.

We show how to create the Java code in Rational Application Developer, and how to deploy the code to the mainframe and run it under CICS.

5

© Copyright IBM Corp. 2005. All rights reserved. 65

Page 80: Java Application Development for CICS

5.1 Coding your application in Rational Application DeveloperNow let us get started creating our first JCICS application. Traditionally, the first program to write and run in a new environment prints something like Hello World!, and the example presented in this chapter is no exception.

Start Rational Application Developer and create a new Java project (File → New → Project, then select Java Project). Click Next and enter the project name SG245275. Then click Finish.

Create a Java package called com.ibm.itso.sg247275 (select File → New → Package, or use the New Java Package icon ), and then create a new Java class called HelloWorld.

We show the source code for our Hello World in Example 5-1. It is a bit longer than usual for a first-time example, but it demonstrates a lot of useful things. Now you should copy the program code from the PDF file (or the zip file available from the Redbooks Web site), and paste it into Rational Application Developer. You will get tons of compilation errors, but we will fix this in the next step.

Example 5-1 Hello World!

package com.ibm.itso.sg245275;

import java.io.PrintWriter;import com.ibm.cics.server.*;

public class HelloWorld {

public static void main(CommAreaHolder cah) { // (1) try {

PrintWriter out = getOutputWriter(); // (2)Task task = Task.getTask(); // (3)out.println();

out.println("Hello " + task.getUSERID() + ", welcome to CICS!"); // (4) out.println(); out.println("This is program " + task.getProgramName()); // (5) out.println("Transaction name is " + task.getTransactionName()); // (6) out.println("CICS region is " + Region.getSYSID()); // (7) } catch (Throwable e) {

System.err.printStackTrace(); // (8) } }

/** * Return the terminal principal facility, or <code>null</code> * if the transaction is not associated with a terminal. */ private static TerminalPrincipalFacility getTerminal() { Object principalFacility = Task.getTask().getPrincipalFacility(); // (9) if (principalFacility instanceof TerminalPrincipalFacility) return (TerminalPrincipalFacility) principalFacility; // (10) else return null; // (11) } /** Is the transaction associated with a terminal? */ private static boolean haveTerminal() { // (12) return getTerminal() != null; }

66 Java Application Development for CICS

Page 81: Java Application Development for CICS

/** * Return a PrintWriter that is either directed at the terminal, if * we have one, or to <code>System.out</code> if not. */ private static PrintWriter getOutputWriter() { if (haveTerminal()) return Task.getTask().out; // (13) else return new PrintWriter(System.out, true); // (14) }}

Notes on Example 5-1 on page 66:

1. The first thing to notice is that, unlike “regular” standalone Java applications, the main() method in CICS Java programs takes an argument of type CommAreaHolder, instead of the familiar String[]. A main method with a string array argument is supported as well, but if both are present, CICS will call the one with the CommAreaHolder argument. We talk about Commareas in 6.6, “Calling other programs and passing data” on page 89.

2. Get an output writer to print to. Depending on the environment, output will either go to the terminal if we have one; otherwise it will go to an HFS file. See notes 13 and 14 below.

3. Get a singleton instance of class Task, which has methods to inquire about information about our environment…

4. … such as the user ID that is signed on,

5. … the program name,

6. … and the transaction code under which we are running.

7. Print the system ID of our CICS region.

8. Any uncaught exceptions will be caught here, and a stack trace will be printed on System.err. Note that we could have decided to only catch checked exceptions; if an unchecked exception (such as NullPointerException) occurred, it would be caught by launcher code in CICS, which in turn causes the task to abnormally end (abend).

9. Get the principal facility associated with the task. CICS assigns the principal facility when it initiates the task, and the task owns the facility for its duration. No other task can use that terminal until the owning task ends.

10.Not all tasks have a principal facility. If we do have one, it will be an instance of TerminalPrincipalFacility.

11.If we do not have a terminal, return null.12.Return true if we have a terminal.

13.If we have a terminal, return a PrintWriter whose output goes to the terminal.

14.Otherwise, return a PrintWriter whose output goes to System.out. This stream is associated with a file on the HFS file system (see “Setting up JVM profiles” on page 53 for details). The boolean parameter to the PrintWriter constructor call causes the println() methods to flush the output buffer.

As we said before, you will get a lot of compilation errors since the Jar file implementing the JCICS API (dfjcics.jar) is missing from the project. Since it does not come with the Rational Application Developer product, we have to copy it from the mainframe. Open a command prompt, change to our project folder, and use the FTP command to get the file.

Chapter 5. Getting started 67

Page 82: Java Application Development for CICS

We list a sample FTP session in Example 5-2. This assumes that the Rational Application Developer workspace and the CICS library files are at their installation-default location.

Example 5-2 Sample FTP session to copy dfjcics.jar to the development workstation

C:\Documents and Settings\TOT195>cd C:\Documents and Settings\TOT195\IBM\rationalsdp6.0\workspace\SG24-5275C:\Documents and Settings\TOT195\IBM\rationalsdp6.0\workspace\SG24-5275>ftp wtsc66.itso.ibm.comConnected to wtsc66.itso.ibm.com.220-FTPMVS1 IBM FTP CS V1R6 at wtsc66.itso.ibm.com, 23:36:52 on 2005-04-05.220 Connection will close if idle for more than 5 minutes.User (wtsc66.itso.ibm.com:(none)): cicsrs3331 Send password please.Password: ********230 CICSRS3 is logged on. Working directory is "CICSRS3.".ftp> cd /usr/lpp/cicsts/cicsts23/lib250 HFS directory /usr/lpp/cicsts/cicsts23/lib is the current working directoryftp> bin200 Representation type is Imageftp> get dfjcics.jar200 Port request OK.125 Sending data set /usr/lpp/cicsts/cicsts23/lib/dfjcics.jar250 Transfer completed successfully.ftp: 139283 bytes received in 0.02Seconds 6964.15Kbytes/sec.ftp> quit221 Quit command received. Goodbye.

C:\Documents and Settings\TOT195\IBM\rationalsdp6.0\workspace\SG24-5275>

Now that dfjcics.jar has been copied to our project directory, we have to tell Rational Application Developer to include it on the compiler class path. Right-click the project name, and select Properties. Switch to the Java Build Path category and click Add Jars (Figure 5-1 on page 69).

Tip: If you do not know the place in the file system where the Rational Application Developer workspace, and therefore our project root folder, resides (the path name tends to be rather long), there is an easy way to find out. Right-click the project and select Properties. In the dialog that opens, select the Info category. The project root folder name appears in the dialog box, and you can copy it from there and paste it into the command prompt window.

68 Java Application Development for CICS

Page 83: Java Application Development for CICS

Figure 5-1 Setting up the Java build path in Rational Application Developer

In the dialog that opens, expand the project folder, select dfjcics.jar, then click OK. The “JARs and class folders on the build path” list box should now include dfjcics.jar. Click OK again to finish the build path setup.

Since the build path has changed, Rational Application Developer rebuilds your project. The compilation errors should be gone since all required libraries are included. In the next step, we deploy the code to the mainframe, and run it in CICS.

5.2 Deploying and running the programNow that the code is ready in Rational Application Developer, the next step is to deploy it to the mainframe and run it in CICS.

5.2.1 Deploying the code to CICSThe first step is to export the Java bytecode (the .class files) to the mainframe.

If your z/OS installation happens to run an SMB server such as DFS/SMB or Samba (http://www.samba.org), you are in luck. This enables you to access the HFS file system as a shared network drive. Otherwise, you can use FTP to transfer your code to HFS. We describe both methods in “Exporting to a shared file system” on page 70 and “Exporting via FTP” on page 71, respectively.

Note: If Rational Application Developer did not rebuild your project after you changed the build path, select Window → Preferences, select the Workbench category, and make sure that Build automatically is checked.

Chapter 5. Getting started 69

Page 84: Java Application Development for CICS

Exporting to a shared file systemTo export your code to a USS directory, you first have to map that directory as a drive on your PC. From Windows® Explorer, select Tools → Map Network Drive. Select a drive letter and enter the network path for the shared directory. In our case, the network path is \\wtsc66\u, which maps to the /u directory on HFS (see Figure 5-2).

Figure 5-2 Mapping the HFS file system as a shared network drive

After mapping the network drive, you should be able to browse it in Windows Explorer just like a regular local drive.

To export the code from Rational Application Developer to the mainframe, follow these steps:

1. Select the package (com.ibm.itso.sg245275), then select File → Export.

2. Select File System from the list of export destinations and click Next.

3. In the Directory field, type the drive letter to which you mapped the HFS file system, followed by a colon and a backslash. Select Create directory structure for files (see Figure 5-3 on page 71).

4. Click Finish.

5. To verify that the files have been exported correctly, use Windows Explorer to view the directory structure on the HFS file system.

Tip: For more information about DFS/SMB and Samba, refer to S/390 File and Print Serving, SG24-5330.

Note: The “Create directory structure for files” option tells Rational Application Developer to create the same directory structure on the export directory as it exists in the workspace. That is, in our example, the wizard will create a directory called SG24-5275 and create the directories corresponding to the Java package names below that directory. When you work with several projects at a time, this makes it easier to tell which file on the destination file system belongs to which project.

70 Java Application Development for CICS

Page 85: Java Application Development for CICS

Figure 5-3 Export to file system wizard

Exporting via FTPIf your installation does not offer SMB access to the HFS file system, you can use FTP to export your code. Fortunately, you do not have to do this manually; Rational Application Developer comes with built-in FTP support.

To export the code, follow these steps:

1. Select the package (com.ibm.itso.sg245275), then select File → Export.

2. Select FTP from the list of export destinations and click Next.

3. In the FTP host field, type the TCP/IP host name of your z/OS machine.

4. In the FTP folder field, type the name of the target HFS directory, in our example, /u/cicsrs3/SG24-5275 (see Figure 5-4 on page 72). Click Next.

5. Enter your user name and password. Click Finish.

Important: Since the HFS file system on Unix System Services uses EBCDIC, the SMB server software usually performs an ASCII-to-EBCDIC conversion for files whose content is known to be text (such as Java source code). Make sure that it does not perform that conversion for .class files, which are binary.

Chapter 5. Getting started 71

Page 86: Java Application Development for CICS

Figure 5-4 Export to an FTP server wizard

5.2.2 Setting up the transaction and program definitionsNext, we have to set up the CICS transaction and program definitions for our program. We assume that all JVM-related setup, such as creation of a JVM profile, has already been done (refer to FIXME for instructions). Also, we assume that a transaction and program definition has been created for you to use, and that you are authorized to view and change the program definition attributes.

In the following discussion, we use transaction ID HELO and program name HELOWRLD for our example; depending on your installation standards, your friendly CICS system programmer may have set up different names.

First, we verify that the transaction’s initial program is set up to be HELOWRLD. Clear the CICS screen and type CEMT INQUIRE TRANSACTION(HELO). CICS will show a screen that shows a summary of the HELO transaction’s attributes:

INQUIRE TRANSACTION(HELO) STATUS: RESULTS - OVERTYPE TO MODIFY Tra(HELO) Pri( 001 ) Pro(HELOWRLD) Tcl( DFHTCL00 ) Ena Sta Prf(DFHCICST) Uda Bel Iso Bac Wai

Thus, we have verified that the transaction’s initial program is indeed HELOWRLD.

Next, we look at the definition of program HELOWRLD.

INQUIRE PROGRAM (HELOWRLD) STATUS: RESULTS - OVERTYPE TO MODIFY

Note: Unfortunately, the FTP export does not allow you to do ASCII-to-EBCDIC translation—it always transfers files in binary. This is OK for the .class files, but not if you want to ship the source code to the mainframe.

72 Java Application Development for CICS

Page 87: Java Application Development for CICS

Prog(HELOWRLD) Jav Pro Ena Ced Res(001) Bel Uex Ful Thr Jvm

Expand the display by tabbing to the first line of the summary, and press Enter. Your display should look similar to Figure 5-5; however, we left out several attributes that are not relevant to this discussion.

Figure 5-5 Program definition attributes

Verify that the Runtime attribute is set to Jvm, and that the Jvmclass attribute is set to the Java class name of the program. If this is not the case, you can overtype the previous values and press Enter to apply the changes. Also, verify that the JVM profile name is correct.

5.2.3 Running the programNow, we are finally ready to run our program. Clear the CICS screen, and enter the transaction code:

HELO

After a moment, the program should print its output to the terminal (Example 5-3).

Example 5-3 Output from the Hello World program

HELO Hello CICSUSER, welcome to CICS! This is program HELOWRLD Transaction name is HELO CICS region is PJA7

If anything went wrong, refer to 5.2.4, “Troubleshooting” on page 75. If not, congratulations, you have successfully run your first program in the CICS Transaction Server.

Next, we invoke the transaction in a way such that it is not associated with a terminal (in CICS terms, it will not have a principal facility). If the program works right, output should go to an HFS file instead. To do this, we use the CICS-supplied CECI transaction.

INQUIRE PROGRAM (HELOWRLD) RESULT - OVERTYPE TO MODIFY Program(HELOWRLD) Language(Java) Progtype(Program) Status( Enabled ) Copystatus( Notrequired ) Cedfstatus( Cedf ) Dynamstatus(Notdynamic) Rescount(001) Usecount() Execkey(Uexeckey) Executionset( Fullapi ) Concurrency(Threadsafe) Remotesystem() Runtime( Jvm ) Jvmclass( com.ibm.itso.sg245275.HelloWorld ) Jvmprofile( DFHJVMUG )

Chapter 5. Getting started 73

Page 88: Java Application Development for CICS

You can use the command-level interpreter (CECI) transaction to check the syntax of CICS commands and to process these commands interactively on a 3270 screen. CECI allows you to follow through most of the commands to execution and display the results.

In 6.12, “Interval control” on page 109, we discuss Interval control services, which allow one transaction to asynchronously start another transaction. We will now do that manually, via CECI, to start our Hello program.

On the CICS screen, type CECI and press Enter. You get a list of all CICS commands (Figure 5-6).

Figure 5-6 CECI transaction: Initial screen

We want to use the START command, which starts another transaction. Type START TR(HELO) and press Enter. CECI will check the command syntax, and since it is valid, responds with the message ABOUT TO EXECUTE COMMAND. Press Enter again to actually execute the command. CECI responds with COMMAND EXECUTION COMPLETE.

This way of invocation causes the transaction to be run without a terminal being associated with it; therefore, the output from our program should have gone to an HFS file. The name and location of that HFS file are configured in the JVM profile under which the program has been set up to run.

Next, you could experiment with the debugging techniques we explain in Chapter 8, “Problem determination and debugging” on page 157. For example, you may want to try the execution diagnostic facility (CEDF), or you could run the program under control of the debugger to see what is going on.

Tip: For a full description of CECI, refer to CICS Supplied Transactions, SC34-6230.

STATUS: ENTER ONE OF THE FOLLOWING ABend DELAy FREE POP RETRieve SUspend ACquire DELETE FREEMain POSt RETUrn SYncpoint ADD DELETEQ GDs PURge REWInd TEst ADDRess DEQ GET PUSh REWRite TRace ALlocate DISAble GETMain PUT ROute UNlock ASKtime DISCard GETNext Query RUn UPdate ASSign DOcument Handle READ SENd Verify BIf DUmp IGnore READNext SET WAIT BUild ENAble INquire READPrev SIGNOFf WAITCics CAncel ENDBR ISsue READQ SIGNON WEb CHAnge ENDBROwse Journal RECeive SPOOLClose WRITE CHEck ENQ LInk RELease SPOOLOpen WRITEQ COLlect ENTer LOad REMove SPOOLRead Xctl CONNect EXtract MONitor RESET SPOOLWrite CONVerse FEpi MOVe RESETBr START CReate FORCe PErform RESUme STARTBR DEFine FORMattime POInt RESYnc STARTBROwse PF 1 HELP 2 HEX 3 END 4 EIB 5 VAR 6 USER 9 MSG

74 Java Application Development for CICS

Page 89: Java Application Development for CICS

5.2.4 TroubleshootingIf the program failed to run for whatever reason, a message similar to the following will be displayed on the bottom of the CICS screen:

DFHAC2206 20:56:01 SCSCPJA7 Transaction HELO failed with abend AJ07. Updatesto local recoverable resources backed out.

The most important piece of information is the abend code, which indicates what went wrong. (The abend code in itself is not exactly self-explanatory, but you can get an idea of what went wrong.)

In fact, abend code AJ07 is one that you may see quite often. It means that the class containing the main method of your application could not be found, probably because your classpath is set up incorrectly or you misspelled the main class name on the program definition. Refer to 8.2, “Where to look when you receive AJ07” on page 160, for more on this code.

Another common abend code is AJ05, which means that an unhandled exception has been caught by CICS code—that is, an exception was thrown but never caught by your application, all the way up and beyond your application’s main method.

See Chapter 8, “Problem determination and debugging” on page 157, for more information about problem determination.

Tip: See CICS Messages and Codes, GC34-6241, for a detailed explanation of each transaction abend code.

Chapter 5. Getting started 75

Page 90: Java Application Development for CICS

76 Java Application Development for CICS

Page 91: Java Application Development for CICS

Chapter 6. The JCICS API

This chapter gives you a gentle introduction to Java programming in a CICS environment.

First, we discuss the difference between traditional CICS programming and using CICS services from Java. Then we briefly introduce the main functional areas of the API, followed by a more in-depth discussion of each. Also, we show and explain some example code to help you get started.

6

© Copyright IBM Corp. 2005. All rights reserved. 77

Page 92: Java Application Development for CICS

6.1 IntroductionThere is one fundamental difference between using the CICS API from traditional languages such as COBOL, PL/1, and C, and using it from Java applications. In languages other than Java, CICS commands are implemented as a language extension, that is, they are embedded into the source program bracketed by EXEC CICS…END-EXEC clauses. Therefore, the source program cannot be compiled as it is, but must first be run through the CICS translator, which extracts all CICS calls and replaces them by calls into the CICS language interface module, producing a program that can be compiled by the respective language compiler. If you are familiar with database access using embedded SQL, you will notice this is pretty much the same concept.

Figure 6-1 shows the program preparation process for CICS applications by example of a COBOL program.

Figure 6-1 Preparing CICS programs in COBOL

In Java, however, things are much simpler. CICS commands are not implemented as a language extension, but rather as a regular Java API (the JCICS API), so no additional translation steps are necessary. In that sense, CICS programming in Java is no more difficult than using any other Java API.

CICS COBOL program

CICS translator

Translated COBOL program

COBOL compiler

Object code

Linkage editor

Language interfacemodule

Load module

EXEC CICS …END-EXEC

CALL “DFHEI1" USING …END-CALL

CICS commands bracketed by EXEC CICS ... END EXEC clauses

CICS translator generates calls into CICS language interface module

78 Java Application Development for CICS

Page 93: Java Application Development for CICS

6.2 A short overview of the JCICS APIIn this section, we give you a high-level overview of the CICS API, briefly describing its various categories. Later in this chapter, we describe most of the API in more detail.

Figure 6-2 shows a class diagram of the JCICS API. Due to limited space, we only show some particularly important classes; later sections show more detail.

Figure 6-2 Overview of the JCICS API

In the following sections, we briefly describe several functional areas of the API.

Chapter 6. The JCICS API 79

Page 94: Java Application Development for CICS

6.2.1 Program controlProgram control services allow one program to call another program in the same unit of work. Data can be passed to and received back from the called program, by means of a shared area of storage known as the COMMAREA.

6.2.2 File controlFile control services allow you to access VSAM files, which come in three different flavors:

� Key Sequenced Data Sets (KSDS) � Entry Sequenced Data Sets (ESDS) � Relative Record Data Sets (RRDS)

6.2.3 SynchronizationSynchronization services provide a mechanism to ensure mutual exclusion when dealing with shared resources that must not be modified (or even accessed) by more than one transaction at a time.

6.2.4 Scheduling servicesScheduling services allow a program to start other transactions asynchronously, either immediately or at some specified later time.

6.2.5 Unit of workThis is not only one of the easiest JCICS services to use, but also probably one of the most important. You use these services to commit or roll back the current unit of work, thus either making the results of the current transaction permanent, or backing them out.

There is no API to explicitly start a new unit of work; a new unit of work is considered active as soon as the previous one has ended.

To commit the current unit of work, you use the Task.commit() method:

Task.getTask().commit();

To back out the current unit of work, you use the Task.rollback() method:

Task.getTask().rollback();

6.2.6 Document servicesDocument services are most often used in conjunction with CICS Web support services (6.2.7, “Web and TCP/IP services” on page 81) to dynamically build HTML pages to be sent back to a Web browser.

You can work with document templates, which are portions of a document created offline (or by another program), and may contain symbols representing dynamic content. You can then replace those symbols to produce the actual document to be sent back.

We show an example of using the Document API in Chapter 7, “Evolving a legacy application using Java” on page 121.

80 Java Application Development for CICS

Page 95: Java Application Development for CICS

6.2.7 Web and TCP/IP servicesWeb services allow CICS programs to produce dynamic Web content, probably in response to a client request from a Web browser. In other words, they can act very much like CGI programs supported by most Web servers, or like Java servlets.

The following Web-related and TCP/IP-related services are provided by the JCICS API:

� Examining an HTTP request� Sending a response back to the client� Getting the client’s host name� Security-related services, such as getting authorization method and certificates

We show how to use Web services in conjunction with Document services in Chapter 7, “Evolving a legacy application using Java” on page 121.

6.2.8 Transient storage queuesTemporary storage is the primary CICS facility for storing data that must be available to multiple transactions. Data items in temporary storage are kept in queues whose names are assigned dynamically by the program storing the data. A temporary storage queue containing multiple items can be thought of as a small data set whose records can be addressed either sequentially or directly, by item number. If a queue contains only a single item, it can be thought of as a named scratch-pad area.

6.2.9 Transient data queuesTransient data queues (TD queues) are similar in some respects to transient storage queues, but there are some major differences:

� They cannot be created on-the-fly, but must be predefined.

� Items can only be read sequentially, and cannot be changed.

� Reading from TD queues is destructive, that is, each item can be read only once. After a transaction reads an item, that item is removed from the queue and is not available to any other transaction.

Today, TD queues are pretty much obsolete, because the preferred alternative is to use WebSphere MQ message queues. Therefore, we do not further discuss TD queues in this book. However, they are fully supported by the JCICS API.

6.2.10 Terminal controlTerminal control services allow an application program to interact with the user’s terminal, by displaying data on and retrieving user input from the terminal.

However, terminal control in Java is not widely used, because there is no JCICS support for an important feature called Basic Mapping Support (BMS). To put it simply, BMS is a set of CICS services and tools to create, display, and interact with screen forms from an application program. As you can imagine, BMS screens are much easier to use (and more portable) than direct interaction with the raw terminal.

That said, during the course of this residency we developed a small package boldly called JBMS (for Java Basic Mapping Support), which allows you to create and interact with screen forms, just like the real BMS does. Read all about it in 6.13, “Terminal services” on page 110.

Chapter 6. The JCICS API 81

Page 96: Java Application Development for CICS

6.2.11 Miscellaneous servicesThis section covers several services that do not fall into one of the categories above.

Specifically, you can:

� Inquire about the system name and VTAM® application ID of the CICS region, using Region.getSysId() and Region.getAPPLID(), respectively.

� Enable and disable tracing in the CICS region (Region.enableTrace(), Region.disableTrace()).

� Examine and modify the contents of the Common Work Area (CWA), using Region.getCWA() and Region.setCWA().

� Retrieve the transaction name and program name under which the current program is executing; this may be useful for logging purposes.

� Get the name of the user who started the transaction.

� Examine and modify the Transaction Work Area (TWA). The TWA is a small (up to 32 K) area of storage that is allocated when a transaction is initiated, and is initialized to binary zeros. It lasts for the entire duration of the transaction, and is accessible to all local programs in the transaction. Usage of the TWA is no longer recommended for new applications.

� Find out how the current program was started, using Task.getTask().getSTARTCODE(). Table 6-1 lists the different possible startcodes and their meanings.

Table 6-1 Startcodes as returned by Task.getTask().getSTARTCODE()

Startcode Meaning

D The task was initiated to process a distributed programming link (DPL) command that did not specify the SYNCONRETURN option. (The task is not allowed to issue syncpoints.)

DS The task was initiated to process a distributed programming link (DPL) command containing the SYNCONRETURN option. (The task is allowed to issue syncpoints.)

QD CICS initiated the task to process a transient data queue that had reached trigger level.

S Another task initiated this one, using a START command that did not pass data in the FROM option.

SD Another task initiated this one, using a START command that passed data in the FROM option.

SZ The task was initiated with a FEPI START command (see CICS Front End Programming Interface User’s Guide, SC34-6234, for further information).

TO The task was initiated to process unsolicited input from a terminal (or another system), and the transaction to be executed was determined from the input.

TP The task was initiated to process unsolicited input or in response to a RETURN IMMEDIATE command in another task. In either case, the transaction to be executed was preset (in the RETURN command or in the associated TERMINAL definition) without reference to input.

U CICS created the task internally.

82 Java Application Development for CICS

Page 97: Java Application Development for CICS

6.2.12 Services not supported by the JCICS APIThe following CICS services are not supported by JCICS:

� APPC unmapped conversations� CICS Business Transaction Services� DUMP services� Journal services� Storage services� Timer services� CICS Business Transaction Services� BMS services SEND MAP and RECEIVE MAP

6.3 JCICS basicsJCICS application programming classes enable you to invoke CICS services from Java. All you have to do to invoke a CICS service is to call a Java method. Methods provided by JCICS use Java exception classes to return error messages to the caller. The exception handling mechanism is internally based on the CICS API response codes, which are set after execution of the CICS commands.

CICS resources, such as files, programs, temporary storage queues, and transient data queues, are represented by instances of the appropriate Java class. Therefore, to work with, for example, a temporary storage queue (TSQ), you would first create an instance of a TSQ object. You would then assign it a name corresponding to the name of the TSQ you want to use and use its methods to manipulate the queue:

TSQ tsq = new TSQ();tsq.setName(“MYTSQ”);tsq.writeItem("Hello World!".getBytes());

Often, you will want to initialize the JCICS objects your program works with in a constructor, and use the initialized objects from regular methods. Consider the following snippet (an excerpt from 6.8, “Using transient storage queues” on page 94), where we declare a TSQ to be a blank final instance variable. The final keyword indicates that the variable must be initialized in the constructor, and cannot be reassigned once initialized.

public class Scratchpad {

public final TSQ tsq;

public Scratchpad(String tsqName) { this.tsq = new TSQ(); tsq.setName(tsqName); }

public void writeBytes(byte[] bytes) throws ItemErrorException, ... { try {

tsq.rewriteItem(1, bytes); } catch (InvalidQueueIdException e) {

tsq.writeItem(bytes);}

}...

}

The JCICS library structure and naming conventions are modelled to be fairly close to the traditional EXEC CICS programming interface, so translating the CICS calls in a traditional

Chapter 6. The JCICS API 83

Page 98: Java Application Development for CICS

CICS program to JCICS calls in a Java application should be fairly easy. The downside is that the JCICS way of doing things often does not quite “feel right” to a seasoned Java programmer. For example, to iterate over a set of related resources, CICS has the concept of browsing, similar to the Java idiom of using an Iterator. However, the relevant JCICS classes do not implement the Iterator interface; they stand entirely on their own.

6.4 Input and output streamsJust like any standalone Java application, JCICS applications can use the predefined streams System.in to read input, and System.out and System.err to print output.

In addition, the Task class has two fields, out and err, which are directed at the user’s terminal if the transaction was started from a terminal (in CICS parlance, if the principal facility associated with the transaction is a terminal). Otherwise, they are the same as System.out and System.err, respectively.

However, the standard input stream (System.in) is never connected to the terminal. Rather, it is associated with an HFS file, whose name is set up in the JVM profile (see “Setting up JVM profiles” on page 53 for more information). In other words, it is not interactive in the sense that you could read end user input from it. So, there is probably little use for the System.in stream, except maybe for reading configuration information at program startup.

System.out and System.err are connected to HFS files as well. Those files are created (or scratched) when the JVM starts up (again, see “Setting up JVM profiles” on page 53 and “JVM stdout and stderr” on page 165).

Note that, when using a resettable or continuous JVM, the terminal may change each time the JVM is reused, while System.in, System.out and System.err remain connected to the respective HFS files.

6.5 Exception handlingSince anything that can go wrong eventually does go wrong, you need to handle error conditions in your code.

As usual, error reporting and handling in JCICS is integrated into the standard Java exception handling mechanism.

In traditional languages, CICS indicates the success or failure of a CICS command by returning a condition code to your application program (sometimes called the RESP value because you use the RESP keyword to retrieve it). If everything went fine, the RESP value will be NORMAL; if it is some value other than NORMAL, you can test the value and find out what happened. Many RESP values also have an associated RESP2 value, which gives further detail about the error.

In Java, RESP codes are mapped to Java exception classes. For each RESP value that can occur in CICS, there is one corresponding Java exception class.

Figure 6-3 on page 85 shows part of the JCICS exception hierarchy.

Note: All JCICS classes representing CICS resources are designed to comply with the JavaBeans standard, so they can be used with a visual composition editor.

84 Java Application Development for CICS

Page 99: Java Application Development for CICS

Figure 6-3 Part of the JCICS exception hierarchy

In Java, exceptions fall into two major categories: Checked exceptions and unchecked exceptions. When you call a method that may throw a checked exception, you are required to either handle the exception in your method, or to declare your own method as throwing that exception. Unchecked exceptions, on the other hand, need not necessarily be handled or declared; they usually represent conditions that are so common (or so rare) that it is impractical to be forced to handle them.

Figure 6-1 on page 86 shows a first example of exception handling in JCICS. The sample program tries to count the number of items in a transient storage queue (we discuss transient storage queues in “Using transient storage queues” on page 94). Since there is no straightforward method in the CICS API, we have to do this by reading the items in order until CICS responds with an error after trying to read past the last item.

Chapter 6. The JCICS API 85

Page 100: Java Application Development for CICS

Example 6-1 Exception handling example, first version

package com.ibm.itso.sg245275;

import java.io.PrintWriter;

import com.ibm.cics.server.*;

public class ExceptionExample {

/** Count the number of items in a TS queue. */ private static int countItems(TSQ tsq) throws InvalidRequestException, IOErrorException, LengthErrorException, InvalidSystemIdException, ISCInvalidRequestException, NotAuthorisedException, InvalidQueueIdException // (1) { int count = 0; ItemHolder item = new ItemHolder(); try { while (true) { // (2) tsq.readNextItem(item); count++; // (3) } } catch (ItemErrorException e) { // (4) return count; } }

public static void main(String[] args) { TSQ tsq = new TSQ(); // (5) tsq.setName("MYTSQ");

PrintWriter out = Task.getTask().out; try { out.println("Number of items in TSQ " + tsq.getName() // (6)

+ ": " + countItems(tsq)); } catch (InvalidRequestException e) { // (7) out.println("Invalid request"); } catch (IOErrorException e) { out.println("I/O error"); } catch (LengthErrorException e) { out.println("Length error"); } catch (InvalidSystemIdException e) { out.println("Invalid system id"); } catch (ISCInvalidRequestException e) { out.println("Inter-system invalid request"); } catch (NotAuthorisedException e) { out.println("Not authorized to access queue"); } catch (InvalidQueueIdException e) { out.println("Invalid queue ID"); } }}

Notes on Example 6-1:

1. The countItems() method expects a parameter of type TSQ, and declares that it may throw several different exceptions—namely, all exceptions that may be thrown by invoking the TSQ.readNextItem() method except for the one we handle ourselves (see below).

86 Java Application Development for CICS

Page 101: Java Application Development for CICS

2. In a semi-infinite loop, we try to read the items in the transient storage queue. The loop is not really infinite because it will be eventually terminated when no more items are left in the queue (see Note 4).

3. At this point, the call to TSQ.readNextItem() succeeded, and we increment the number of items read.

4. When there are no more items left in the queue, JCICS raises an ItemErrorException. The loop is terminated, and control flow reaches the catch block. We return the number of items read so far.

If any other exception occurred, however, we do not catch it in the countItems() method; rather, the calling method will have to handle it. This is why we had to list all possible exception classes in the method declaration (see Note 1 on page 86), except ItemErrorException, which is handled in the countItems() method itself.

5. The main method creates a TSQ object, sets the queue name…

6. … and calls countItems() to print the number of items in the queue.

7. Since the countItems() method declares several checked exceptions, we either have to handle them, or declare them to be thrown from the main() method. In this example, we handle them by listing each possible exception in a catch block and printing a short error message corresponding to the exception type.

Note that we do not have to catch an ItemErrorException since it is already handled in the countItems() method—in fact, if we tried to handle it, we would see a compilation error.

Now, if we have a closer look at the long list of catch clauses in the main method of Example 6-1 on page 86, we see that several exceptions cannot actually be thrown. For example, an InvalidSystemIdException or ISCInvalidRequestException can only occur when dealing with remote TS queues (that is, they live in a different CICS region). The queue we use in this example, however, is local (we never invoked the setSysId() method).

Therefore, in a second version of the example, we chose to specifically handle only the exceptions that are somewhat likely to occur, and handle all others in a generic way, rendering them unexpected (Example 6-2).

Example 6-2 Exception handling example, second version

public static void main(String[] args) { TSQ tsq = new TSQ(); tsq.setName("MYTSQ"); createItems(tsq); PrintWriter out = Task.getTask().out; try { out.println("Number of items in TSQ " + tsq.getName() + ": " + countItems(tsq)); } catch (NotAuthorisedException e) { out.println("Not authorized to access queue"); // (1) } catch (InvalidQueueIdException e) { out.println("Invalid queue ID"); // (2) } catch (CicsException e) { out.println("Unexpected CICS exception: " + e); // (3) }}

Notes on Example 6-2:

1. In this version of the example, we chose to only handle NotAuthorisedException…

2. … and InvalidQueueIdException.

Chapter 6. The JCICS API 87

Page 102: Java Application Development for CICS

3. This catch clause will handle all other exceptions. Note that order is important: You will see a compilation error if a catch clause for a more generic exception textually appears before a catch clause for a more specific one (that is, for one of its subclasses).All checked exceptions thrown by the JCICS API are subclasses of CicsException, so this clause will handle all of them except the two we chose to handle specifically.

Exception handling in CICS (or generally in Java, for that matter) is seemingly easy but still often done wrong. It is important that your code does “the right thing,” not only if everything works smoothly, but also in case of failure. Consider Example 6-3. In this example, the intention is to protect a shared resource against concurrent updates, via the NameResource mechanism (more about NameResource in “Synchronization” on page 80). Basically, a NameResource is a global flag that indicates whether some resource is in use.

The code in Figure 6-3 looks simple enough: Acquire the lock on the shared resource, perform the update, and release the lock. If an error occurred (either when trying to acquire or release the lock, or when updating) an error message is logged.

Example 6-3 Incorrect exception handling - Resources held

// INCORRECT EXCEPTION HANDLING

private void doUpdate() throws CicsException { // ... code omitted }

private void updateSharedData() throws ResourceUnavailableException, LengthErrorException { NameResource lock = new NameResource(); lock.setName("SG245275.LOCK"); try { lock.enqueue(); // Lock the shared resource. doUpdate(); // Perform the update. lock.dequeue(); // Release the lock. } catch (CicsException e) { logError("Update failed: " + e); }}

However, there is one serious flaw in the code: What happens when the lock was acquired successfully, but the update failed? Control will be passed to the catch block, the lock.dequeue() call will never be executed, and the lock will still be held by the program. Obviously, that is a bad thing because other instances of the application might want to access the protected resource as well.

Of course, this problem is easy enough to fix, you say. Just release the lock in the catch block as well (Example 6-4).

Example 6-4 Still incorrect exception handling

try { lock.enqueue(); // Lock the shared resource. doUpdate(); // Perform the update. lock.dequeue(); // Release the lock. } catch (CicsException e) { logError("Update failed: " + e);

lock.dequeue(); // Release the lock.}

88 Java Application Development for CICS

Page 103: Java Application Development for CICS

But that is not much better. First, we have duplicate code, and second, what if the call to logError() fails? We still have the same problem. Swapping the two lines in the catch block is not much better either, because the dequeue() call might fail, and the error will never be logged.

The proper way to do it is via the try-catch-finally mechanism. Code in a finally block always gets control, no matter if the corresponding try block completed successfully, or raised an exception. Example 6-5 shows how it is done.

Example 6-5 Correct exception handling using try/catch/finally

private void doUpdate() throws CicsException { // ... code omitted }

private void updateSharedData() throws ResourceUnavailableException, LengthErrorException { NameResource lock = new NameResource(); lock.setName("SG245275.LOCK"); lock.enqueue(); // Lock the shared resource. try { doUpdate(); // Perform the update. } catch (CicsException e) { logError("Update failed: " + e); } finally { lock.dequeue(); // Release the lock. }}

In Example 6-5, the call to lock.dequeue() is in a finally block, and will therefore be executed no matter whether the doUpdate() call (or the logError() call, for that matter) succeeded or failed, ensuring that the lock will be released in any event. Also, we no longer have duplicate code.

6.6 Calling other programs and passing dataIn traditional CICS programming, it is very common to split an application into several programs, each handling a specific part of the application. For example, you could have one front-end program, which handles user interaction; and one or more subprograms that handle the business logic, such as retrieving data from and inserting data into a database or VSAM file. The front-end program would be responsible for displaying menus and data entry forms (maps in CICS parlance), possibly also for input verification, and would call one of the business logic subprograms, depending on the user’s input.

To call another program, you use the CICS LINK mechanism. A LINK causes the invoking program to be temporarily suspended and the linked-to program being invoked. When the linked-to program returns, control is given back to the original program. The invoked program is still part of the same unit of work. Therefore, any work done to recoverable resources by both programs is backed out if the task does not complete successfully. In other words, a CICS LINK works just like a subroutine call, except that the calling and called programs are not statically linked together.

To pass control to another program, you use the XCTL (transfer control) command. The program issuing an XCTL does not receive control back when the target program terminates; rather, the program one level up in the call hierarchy does. See Figure 6-4 on page 90 for an illustration of the program control flow with LINK and XCTL.

Chapter 6. The JCICS API 89

Page 104: Java Application Development for CICS

Figure 6-4 Program control flow with CICS LINK and XCTL

Of course, in most cases, the linking program has to communicate with the linked-to program, for example, to pass in a function code that tells it what specific function to perform, and to get results back from it. In CICS, this is done via the COMMAREA mechanism. A COMMAREA is simply a storage area that is owned by the linking program and is made available to the linked-to program.

In CICS Java applications, separation of logic into several distinct subprograms is not that common, primarily because of the fact that the Java language lends itself well enough to separate different aspects of the application into different parts of the code, namely, into different classes.

In practice, however, you probably will have to call existing programs from your Java code. For example, you may need to access legacy modules that would be too expensive to be reimplemented using Java.

6.6.1 Calling other programs using LINK and XCTLThe Java equivalents to EXEC CICS LINK and EXEC CICS XCTL are the methods Program.link() and Program.xctl(), respectively. There are several versions of each method, taking different parameters, depending on whether and how you want to pass a COMMAREA

90 Java Application Development for CICS

Page 105: Java Application Development for CICS

to the called program. So, to set up a LINK (or XCTL) to another program, you create an instance of class Program, call its setName() method to supply the name of the program you want to transfer control to, and call link() or xctl() as appropriate.

The usual pattern is to create and initialize the Program object in a constructor so it can be used from your individual methods (Example 6-6).

Example 6-6 Typical usage of Program.link()

public class LinkDemo {

private final Program okk850; public LinkDemo() { okk850 = new Program(); okk850.setName("OKK850"); } public void callOKK850() throws InvalidRequestException, LengthErrorException,

InvalidSystemIdException, NotAuthorisedException, InvalidProgramIdException, RolledBackException, TerminalException

{ okk850.link(); }

...

}

6.6.2 Communicating via the COMMAREATo pass data between a calling program and a called program, CICS programs use the COMMAREA mechanism. A COMMAREA is nothing more than an area of storage that is owned by the calling program, and is made available to the callee.

CICS does not care about the format or layout of the COMMAREA—this is entirely up to the two programs involved. Typically, the format of the COMMAREA is defined in a host language data structure, such as a COBOL Level-01 record or a C struct.

In JCICS, there are five different varieties of the Program.link() method:

� Program.link()

Performs a link without a COMMAREA.

� Program.link(byte[] commarea)

Performs a link with a COMMAREA. The linked-to program can modify the COMMAREA.

� Program.link(byte[] commarea, int datalength)

Performs a link with a COMMAREA, where only the first datalength bytes are passed to the linked-to program. The linked-to program can modify the entire COMMAREA, even if it is longer than datalength bytes.

� Program.link(IByteBuffer commarea)Program.link(IByteBuffer in, IByteBuffer out)

These methods have been retained for compatibility only; they were supplied for integration with the IBM Record Framework library, which came with VisualAge for Java. Since the Record Framework has not been carried over to Rational Application Developer, they can be considered deprecated.

Chapter 6. The JCICS API 91

Page 106: Java Application Development for CICS

We demonstrate the COMMAREA mechanism with a very simple program that just reverts the COMMAREA being passed (Example 6-7).

Example 6-7 Program to revert the passed COMMAREA

package com.ibm.itso.sg245275;

import com.ibm.cics.server.CommAreaHolder;

public class Revert {

public static void main(CommAreaHolder cah) { byte[] data = cah.value; int n = data.length - 1; for (int i = (n - 1) / 2; i >= 0; --i) { byte temp = data[i]; data[i] = data[n - i]; data[n - i] = temp; } }}

To test the program, we can write another little program (Example 6-8), which invokes it using Program.link().

Example 6-8 Linking to the Revert program

public class RevertTest { private static String revert(String s) throws CicsException { Program revert = new Program(); revert.setName("REVERT"); byte[] bytes = s.getBytes(); revert.link(bytes); return new String(bytes); }

public static void main(CommAreaHolder cah) { PrintWriter out = Task.getTask().out; try { String original = "Hello World!"; String reverted = revert(original); out.println(); out.println("Original: " + original); out.println("Reverted: " + reverted); } catch (CicsException ex) { out.println("Oops: " + ex); } }}

Alternatively, you can use the CECI transaction to test it, just like we did in 5.2.3, “Running the program” on page 73 (Example 6-9).

Example 6-9 Testing the Revert program using CECI

link program(REVERT) commarea('The quick brown fox') STATUS: COMMAND EXECUTION COMPLETE NAME= EXEC CICS LInk Program( 'REVERT ' ) < Commarea( 'xof nworb kciuq ehT' ) < Length( +00019 ) > < Datalength() > > < SYSid() >

92 Java Application Development for CICS

Page 107: Java Application Development for CICS

< SYNconreturn > < Transid() > < INPUTMSG() < INPUTMSGLen() > >

RESPONSE: NORMAL EIBRESP=+0000000000 EIBRESP2=+0000000000 PF 1 HELP 2 HEX 3 END 4 EIB 5 VAR 6 USER 7 SBH 8 SFH 9 MSG 10 SB 11 SF

6.7 Remoteable resourcesMost CICS resources, such as files, TS queues, and programs, need not actually reside in the CICS region from which they are accessed, but can live in another region connected to it. Resources can either be set up in a CICS region to be remote, in which case the program using the resource does not even know the resource is owned by a different region, or a program can explicitly access a resource in another region.

In JCICS, remoteable resources are subclasses of the abstract class RemotableResource (see Figure 6-5 on page 94). This class has two methods, setSysId() and getSysId(), to respectively set and retrieve the name of the region owning the resource. In fact, there are no other direct subclasses of the Resource class, so all resources can be considered remoteable.

The region accessing the resource and the region owning the resource must be set up to “know each other” on the network. We do not explain the details of setting up a connection between CICS regions in this publication; see CICS Intercommunication Guide, SC34-6243, or ask your CICS system programmer.

Example 6-10 demonstrates how to start a new transaction in a different CICS region, using the StartRequest class, which we briefly discussed in 6.12, “Interval control” on page 109.

Example 6-10 Starting a transaction in another CICS region

StartRequest startRequest = new StartRequest();startRequest.setName("TRN2"); // Name of transaction to be startedtry {startRequest.setSysId("PJA6"); // System ID of remote CICS regionstartRequest.issue(); // Issue request

} catch (CicsException e) {log("Error starting remote transaction: " + e);

}

Chapter 6. The JCICS API 93

Page 108: Java Application Development for CICS

Figure 6-5 The RemoteableResource class hierarchy

6.8 Using transient storage queuesTransient storage queues (TS queues for short) are a very simple mechanism for inter-process communication in CICS. Basically, a TS queue is simply an array of numbered slots, or items. You can either add a new item to a queue, or replace an existing item identified by its slot number. The maximum number of items is 32767, and each item can hold up to 32763 bytes of data.

One additional benefit of TS queues, other than being easy to use, is that they can be created dynamically. In other words, no additional setup is necessary in CICS to create a

94 Java Application Development for CICS

Page 109: Java Application Development for CICS

TS queue—if it did not exist before, it will be created automatically when a new item is added to it. A TS queue may also be predefined if the queue is to have special characteristics such as security or recoverability, or is remote.

A very common usage of a TS queue is a scratchpad functionality—a shared storage area that is available to all instances of an application running in the CICS region. In this section, we develop a simple Scratchpad class to demonstrate usage of TS queues with JCICS.

Example 6-11 shows a skeleton version of our Scratchpad class, just having a reference to the TS queue to use, and three constructors.

Example 6-11 Skeleton Scratchpad class

package com.ibm.itso.sg245275;

// Import declarations omitted...

/** * * Demonstrates how to use TS queues as a scratchpad. * * @author Ulrich Gehlert */public class Scratchpad {

/** Default TS queue name. */ public static final String DEFAULT_SCRATCHPAD_TSQ_NAME = "SCRATCH"; // (1)

/** The TS queue we are writing to. */ private final TSQ tsq; // (2)

/** Constructor using the default TS queue name. */ public Scratchpad() { // (3) this(DEFAULT_SCRATCHPAD_TSQ_NAME); }

/** Constructor using an explicit TS queue name. */ public Scratchpad(String tsqName) { // (4) this(new TSQ()); tsq.setName(tsqName); }

/** Constructor using an explicit TS queue (which may be remote). */ public Scratchpad(TSQ tsq) { // (5) this.tsq = tsq; }}

Notes on Example 6-11:

1. This is the default queue name if the user of the class chose to use the no-argument constructor.

2. The TS queue where the data goes to. The variable is declared final, so it has to be initialized, either directly or indirectly, by each constructor.

3. The no-argument constructor sets up a TS queue with the default name.

4. Constructor taking an explicit TS queue name.

Chapter 6. The JCICS API 95

Page 110: Java Application Development for CICS

5. Constructor taking an initialized TS queue object. Callers will use this constructor if they want to write to a remote TS queue, for example, because they want the scratchpad to be available across CICS regions.

Next, we implement methods for writing data into, and getting data from, the scratchpad (Examples Example 6-12 and Example 6-13, respectively).

Example 6-12 Writing data to the scratchpad

/** * Write a byte array into the scratchpad queue. * * @param bytes The byte array to be written. */public void writeBytes(byte[] bytes) throws ItemErrorException, InvalidRequestException,

IOErrorException, LengthErrorException, InvalidSystemIdException, ISCInvalidRequestException, NotAuthorisedException,

InvalidQueueIdException{ try { tsq.rewriteItem(1, bytes); // (1) } catch (InvalidQueueIdException e) { // The queue didn't exist -- add item to queue, thus creating the queue tsq.writeItem(bytes); // (2) }}

/** * Write a string to the scratchpad. * * @param s The string to be written to the scratchpad. */public void writeString(String s) throws InvalidRequestException, IOErrorException,

LengthErrorException, InvalidSystemIdException, ItemErrorException, ISCInvalidRequestException,

NotAuthorisedException, InvalidQueueIdException{ writeBytes(s.getBytes()); // (3)}

Notes on Example 6-12:

1. In this example, we never write into any TS queue slots other than the first one. Note that the slot numbers count from 1, not from 0.

2. If we got an InvalidQueueIdException when trying to write to the TS queue, it did not exist. So, we use the writeItem() method, which will cause the queue to be created.

Note that there is a possible race condition: Another task could have created the queue right between our failed call to rewriteItem() and our call to writeItem(). We could solve the problem by protecting this section of code with a NameResource. For the sake of brevity, we decided to ignore that possibility.

3. This convenience method allows us to write strings into the queue, by converting a String to a byte[] and writing that byte array to the queue. We will implement a corresponding readString() method to read a String back. Of course, users of the Scratchpad class have to agree upon what kind of data to put on the scratchpad.

Example 6-13 Reading data from the scratchpad

/**

96 Java Application Development for CICS

Page 111: Java Application Development for CICS

* Read a byte array from the scratchpad. * * @return The byte array on the scratchpad, or <code>null</code> if the * scratchpad is empty. */public byte[] readBytes() throws InvalidRequestException, IOErrorException,

LengthErrorException, InvalidSystemIdException, ISCInvalidRequestException, NotAuthorisedExceptionWriting data { try { ItemHolder item = new ItemHolder(); tsq.readItem(1, item); return item.value; } catch (InvalidQueueIdException e) { return null; } catch (ItemErrorException e) { return null; }}

/** * Read a string from the scratchpad. * * @return The string currently on the scratchpad. */public String readString() throws InvalidRequestException, IOErrorException,

LengthErrorException, InvalidSystemIdException, ISCInvalidRequestException, NotAuthorisedException, InvalidQueueIdException{ byte[] bytes = readBytes(); if (bytes == null) return null; else return new String(bytes);}

6.9 How to perform serializationWhen you need to make sure that a given resource cannot be accessed by more than one task at a time, you need some form of serialization mechanism.

A resource, in this context, may be a physical resource such as a TS queue or a file, or it may be a virtual resource such as a credit card number.

A well-known solution to ensure mutual exclusion is the semaphore mechanism, in z/OS and CICS referred to as ENQ/DEQ. A semaphore is simply an integer variable (a counter) with an associated queue. When a task has issued an ENQ for a given resource, other tasks that try to ENQ on the resource are suspended until the first task releases the resource using a DEQ operation.

A resource in the context of this command is any string of 1 through 255 bytes, established by in-house standards, to protect against conflicting actions between tasks or to cause single threading within a program. Therefore if you enqueue on the name of a file, another task attempting the enqueue() call on the same file name will be unsuccessful. This does not stop some other task from using the file. It simply means that the enqueue request will be unsuccessful if another task attempts an enqueue on the same character string, which in this case happens to be the same as the string of characters that make up the name of the file. If

Chapter 6. The JCICS API 97

Page 112: Java Application Development for CICS

more than one enqueue() call is issued for the same resource by a given task, the resource remains owned by that task until the task issues a matching number of dequeue() calls, finishes its current unit of work, or terminates.

You can enqueue by string or by address. The JCICS classes provide an AddressResource class and a NameResource class (see Figure 6-6).

Figure 6-6 JCICS synchronization support classes

The AddressResource class is supplied for compatibility with other languages that use an enqueue on address (or, in general, on any resource name that is binary). The address used would have to be passed to your Java program through a COMMAREA, TSQ, or other shared area. What you actually supply to the AddressResource class is a byte array.

The preferable enqueue method is the enqueue by (human-readable) name, that is, by string. From your Java program, you create a NameResource object and use the setName() method to supply a 1–255 character string. Then issue the enqueue() method.

Note that an enqueue is held only until the current unit of work finishes, that is, it will be released automatically when you call Task.getTask().commit() or Task.getTask().rollback(). Also, it is released if a task ends abnormally.

Restriction: The EXEC CICS ENQ command has an option that allows a task to hold an enqueue across unit-of-work boundaries (ENQ RESOURCE(…) TASK). Unfortunately, there is no corresponding option, or parameter, in the JCICS API.

98 Java Application Development for CICS

Page 113: Java Application Development for CICS

In z/OS, each ENQ has a given scope that determines the visibility of the ENQ. An ENQ may be visible:

� At local scope, that is, only in the address space issuing it (for CICS applications, the CICS region).

� At system scope, that is, only in the z/OS image where the program is executing.

� At sysplex scope, that is, in the entire sysplex.

In CICS, an application program cannot by itself determine the scope of an ENQ. By default, each ENQ has local scope only. If you want to ensure serialization across multiple CICS regions, you have to set up a special CICS resource called an ENQMODEL. For details, see CICS System Definition Guide, SC34-6226.

6.10 Web, TCP/IP, and Document servicesCICS Web support is a collection of CICS services that supports direct access to CICS application programs from Web browsers. You can use CICS Web support with:

� Web-aware application programs, which use the EXEC CICS WEB and EXEC CICS DOCUMENT application programming interfaces. See the CICS Application Programming Guide for more information.

� Programs that are designed to communicate with 3270 terminals using BMS.

� Programs that are designed to be linked to from another program, using a COMMAREA interface.

Applications can use the facilities of the CICS Web support to:

� Map a URL to a request for CICS services. � Interpret HTTP requests. � Construct HTTP responses.� Build HTML output for display by a Web browser.

Although CICS Web support is designed primarily to provide communication between a Web browser and CICS using HTTP, it also supports clients that send non-HTTP requests; the same components of CICS Web support are used to process HTTP and non-HTTP requests.

CICS has a facility that allows you to build up formatted data areas, known as documents. Some examples of how these formatted areas, or documents, can be used, are:

� Constructing a COMMAREA

� Creating standard formats for printing (for example, using your own letterhead, address, and so on)

� Sending HTML data to be displayed by a Web browser

We use CICS document support in Chapter 7, “Evolving a legacy application using Java” on page 121, for the latter purpose, namely, to populate predefined HTML templates.

Important: This is so important that we say it again. An ENQ is local to the CICS region by default. To achieve serialization across multiple regions, possibly running on different z/OS images in the sysplex, you have to set up an ENQMODEL definition.

Chapter 6. The JCICS API 99

Page 114: Java Application Development for CICS

6.11 File controlThe JCICS file control methods enable you to query and manipulate key-sequenced data set (KSDS), entry-sequenced data set (ESDS), and relative record data set (RRDS) VSAM files.

� Key-sequenced data set (KSDS)

A key-sequenced data set has each of its records identified by a key. (The key of each record is simply a field in a predefined position within the record.) Each key must be unique in the data set.

� Entry-sequenced data set (ESDS)

An entry-sequenced data set is one in which each record is identified by its relative byte address (RBA), that is, by the byte offset of its starting position within the file. Records are held in an ESDS in the order in which they were first loaded into the data set.

New records added to an ESDS always go after the last record in the data set. You may not delete records or alter their lengths. After a record has been stored in an ESDS, its RBA remains constant. When browsing, records are retrieved in the order in which they were added to the data set.

� Relative record data set (RRDS)

A relative record data set has records that are identified by their relative record number (RRN). The first record in the data set is RRN 1, the second is RRN 2, and so on.Records in an RRDS can be fixed or variable length records, and the way in which VSAM handles the data depends on whether the data set is a fixed or variable RRDS. A fixed RRDS has fixed-length slots predefined to VSAM, into which records are stored. The length of a record on a fixed RRDS is always equal to the size of the slot. VSAM locates records in a fixed RRDS by multiplying the slot size by the RRN (which you supply on the file control request), to calculate the byte offset from the start of the data set.

A variable RRDS, on the other hand, can accept records of any length up to the maximum for the data set. In a variable RRDS VSAM locates the records by means of an index.

A fixed RRDS generally offers better performance. A variable RRDS offers greater function.

The operations available on files fall into the following categories, all of which are supported by the JCICS API:

� Adding new records� Reading an existing record� Deleting an existing record� Changing an existing record� Browsing the file

Figure 6-7 on page 101 shows the JCICS class hierarchy for file control classes.

100 Java Application Development for CICS

Page 115: Java Application Development for CICS

Figure 6-7 JCICS classes for file control

Here we only discuss KSDS file access; using the other two types of file with JCICS is fairly similar.

In the rest of this section, we develop an implementation of the Java Map interface that is backed by a KSDS data set. Essentially, it is a kind of wrapper around the KSDS that allows manipulation of the data set in a way that looks more natural to Java programmers than raw JCICS API calls. This example is rather long, and many of the implementation details have nothing to do with JCICS per se, but we feel that it illustrates file access in JCICS quite nicely, and could prove to be a useful starting point for your own code.

If you are familiar with Java collection classes, you know that a map is a collection of name/value pairs. You can associate a value with a key (put), delete an association (remove), retrieve the value associated with a key (get), and iterate over the map in three different ways (keys only, values only, or key/value pairs).

The implementation does not always fulfill the Map contract. For example, the documentation for Map says that the remove() method returns the value previously associated with the key, or null if no value was previously associated with the key.

Chapter 6. The JCICS API 101

Page 116: Java Application Development for CICS

However, we chose not to return the previous value but just a Boolean that indicates there actually was a record in the file with the given key (or null if there was none). The reason is performance: If we wanted to return the previously associated value, we would have to perform an extra read operation. Since the value returned from remove() is not typically used anyway, we chose to consciously break the contract.

Class declaration and constructorsWe start with the class declaration, including fields and constructors (Example 6-14).

Example 6-14 VsamMap class skeleton

package com.ibm.itso.sg245275.vsam;

import java.util.AbstractMap;... more import statements ...

/** * An implementation of a Map that is backed by a * KSDS VSAM file. * * Note that, for simplicity and performance, this * implementation violates some of the Map interface's contracts. * For example, the {@link #remove(Object) remove()} method * does not return the value previously associated with the key. * * @author Ulrich Gehlert */public class VsamMap extends AbstractMap { // (1)

private class VsamIterator implements Iterator { ... see below ... // (2) }

static class SimpleEntry implements Entry { ... not shown here (copied from java.util.AbstractMap) }

/** Length of key. */ private final int keylength;

/** Underlying KSDS. */ private final KSDS ksds; // (3)

private final RecordHolder recordHolder = new RecordHolder();

/** * Constructor. */ public VsamMap(KSDS ksds, int keylength) { // (4) this.ksds = ksds; this.keylength = keylength; }

/** * Convenience constructor that accepts a KSDS name. */ public VsamMap(String ksdsName, int keylength) { // (5) this(new KSDS(), keylength); ksds.setName(ksdsName); }

102 Java Application Development for CICS

Page 117: Java Application Development for CICS

}

Notes on Example 6-14 on page 102:

1. Rather than implement all methods of the Map interface ourselves, we extend the AbstractMap class, which already provides a lot of the implementation.

In fact, the only abstract method in AbstractMap is entrySet(), so in theory we only need to implement that. However, the default implementations of several other operations are not terribly efficient, so we override them (for example, AbstractMap.get() iterates over all associations until it finds an entry with the given key).

2. Eventually, this will be an implementation of Iterator, which iterates over the entries in the KSDS (see Example 6-20 on page 106).

3. This is the object representing the VSAM KSDS by which this map is backed.

4. This constructor takes a KSDS and a key length. We need the key length later for iterating through the file.

5. For convenience, this is a constructor that takes a String argument (the KSDS name) rather than a pre-initialized KSDS object.

Getting a recordNext, we implement the get() method (Example 6-15), which accepts a key and returns the associated value, or null when no value is associated with the key (that is, if there is no record in the file having that key). Also, it is easy to implement containsKey() using get().

To get the value associated with the key, we try to read a record with the given key from the underlying VSAM KSDS.

Example 6-15 VsamMap.get()

public Object get(Object key) { try { ksds.read(keyToBytes(key), recordHolder); // (1) return valueFromBytes(recordHolder.value); // (2) } catch (RecordNotFoundException notfound) { return null; // (3) } catch (CicsException e) { throw new RuntimeException(e); // (4) }}

public boolean containsKey(Object key) { return get(key) != null; // (5)}

Notes on Example 6-15:

1. Read a record with the given key from the KSDS. The first argument to KSDS.read() is the key, as a byte array; the second argument is a RecordHolder object, which will contain the data after a successful read.

Since, in general, our keys and records will not have the form of byte arrays, we call helper methods to convert keys and records to byte arrays, and vice versa. The default implementations (see Example 6-16 on page 104) assume that both keys and records are String objects; subclasses can override these methods to provide their own conversions.

2. The KSDS read was successful; we return the record after converting it.

Chapter 6. The JCICS API 103

Page 118: Java Application Development for CICS

3. When the KSDS did not contain a record with the given key, JCICS raises a RecordNotFoundException. Since the Map interface states that get() return null when no value is associated with the key, we catch the exception and do so.

4. All other exceptions are wrapped into a RuntimeException. We cannot directly throw instances of CicsException since these are checked exceptions.

5. Implementing containsKey() is straightforward; check if get() returns non-null.

The next piece of code (Example 6-16) provides default implementations of the conversion methods we talked about in the notes on Example 6-15 on page 103.

Example 6-16 VsamMap - Conversion methods

protected byte[] keyToBytes(Object key) { return ((String) key).getBytes(); // (1)} protected byte[] valueToBytes(Object value) { return ((String) value).getBytes();} protected Object keyFromBytes(byte[] bytes) { return new String(bytes); // (2)}

protected Object valueFromBytes(byte[] bytes) { return new String(bytes);}

Notes on Example 6-16:

1. This default implementation assumes that both keys and records are strings. So, to convert the key to a byte array, we cast it to a String and convert that string to a byte array.

2. To convert back, we construct a new String object from the byte array.

As mentioned before, these methods are default implementations only and are meant to be overridden by subclasses as appropriate (that is why they have been declared protected).

Removing a recordNext, we implement remove(), which deletes a record from the underlying VSAM data set. It is fairly simple (Example 6-17).

Example 6-17 VsamMap.remove()

public Object remove(Object key) { try { ksds.delete(convertToBytes(key)); // (1) return Boolean.TRUE; // (2) } catch (RecordNotFoundException e) { return null; // (3) } catch (CicsException e) { throw new RuntimeException(e); }}

Notes on Example 6-17:

1. Again, we convert the key to a byte array; then we call KSDS.delete().

104 Java Application Development for CICS

Page 119: Java Application Development for CICS

2. We return Boolean.TRUE if the record was actually deleted. This is a deliberate violation of the Map contract, which says that delete() returns the value previously associated with the key. While fairly easy to implement, this would cause another CICS call, degrading performance.

3. If the record was not found, return null.

Adding a recordTo implement Map.put(), we try to write a record to the data set (Example 6-18).

Example 6-18 VsamMap.put()

public Object put(Object key, Object value) { byte[] keyBytes = convertToBytes(key); byte[] valueBytes = convertToBytes(value); try { ksds.write(keyBytes, valueBytes); // (1)} catch (DuplicateRecordException e) {throw new IllegalArgumentException("Duplicate key"); // (2)

} catch (CicsException e) { throw new RuntimeException(e); } return null;}

Notes on Example 6-18:

1. Try to write the record to the KSDS.

2. If we received a DuplicateRecordException, we throw an IllegalArgumentException. This is explicitly permitted by the documentation of java.util.Map (“some aspect of this key or value prevents it from being stored in this map”).

So, effectively, this implementation only allows you to add new records, but not to modify existing ones.

IterationFinally, we implement Map.entrySet(), the only abstract method in AbstractMap (Example 6-19). This adds support for iterating over the keys or values in the Map, in other words, to browse the file.

Example 6-19 VsamMap.entrySet()

public Set entrySet() { return new AbstractSet() { // (1) public Iterator iterator() { return new VsamIterator(); // (2) } public int size() { throw new UnsupportedOperationException(); // (3) } };}

Notes on Example 6-19:

1. Again, we use an abstract implementation provided by the collections framework. The methods we have to implement are iterator() and size().

Chapter 6. The JCICS API 105

Page 120: Java Application Development for CICS

2. See Example 6-20 for the implementation of VsamIterator.

3. Since there is no easy way to find out the number of records in a VSAM data set (other than counting), we chose not to support this operation.

The hardest part is implementing an iterator class (Example 6-20). It is implemented as an inner class of VsamMap, and so has access to VsamMap’s attributes.

Example 6-20 VsamMap.VsamIterator

public class VsamIterator implements Iterator { private final KeyedFileBrowse fb; private final KeyHolder kh = new KeyHolder(); private byte[] nextKey; private byte[] nextValue; private final RecordHolder rh = new RecordHolder();

public VsamIterator() { try { fb = ksds.startBrowse(new byte[keylength]); // (1) } catch (CicsException e) { throw new RuntimeException(e); } }

public boolean hasNext() { if (nextKey == null) { // (2) try { fb.next(rh, kh); // (3) nextKey = kh.value; nextValue = rh.value; } catch (EndOfFileException e) { close(); // (4) } catch (CicsException e) { close(); // (5) throw new RuntimeException(e); } } return nextKey != null; // (6) }

public Object next() { if (hasNext()) { // (7) Entry entry = new SimpleEntry(keyFromBytes(nextKey), valueFromBytes(nextValue)); nextKey = nextValue = null; return entry; } else { throw new NoSuchElementException(); } }

public void remove() { throw new UnsupportedOperationException(); // (8) }

public void close() { try { fb.end(); // (9) } catch (CicsException ignored) { } }

106 Java Application Development for CICS

Page 121: Java Application Development for CICS

}

Notes on Example 6-20 on page 106:

1. In CICS terms, to move through a data set sequentially, you start a BROWSE operation. In JCICS, this is implemented by the startBrowse() method, which returns an instance of class KeyedFileBrowse. This class, in turn, has methods to return the next record from the file.

2. To protect against multiple invocations of hasNext() without calling next() in between, we first check if the next record has already been read.

3. If not, we read it, using the next() method on the KeyedFileBrowse object we received in the constructor call. We remember both key and value.

4. If the end of file has been reached, end the browse.

5. If any other exception occurred, end the browse as well to free any resources held by it, and throw a RuntimeException.

6. At this point, either the next record has been successfully read, and nextKey (as well as nextValue) are non-null, or the end of file has been reached, in which case nextKey remained null.

7. The implementation of next() simply calls hasNext(). If there was another record, construct a key/value pair from it, and reset nextKey and nextValue to null so that hasNext() will try a physical read at the next invocation.

8. There is no KeyedFileBrowse method to delete the current record, so we do not support this operation. It would be fairly easy to implement, however, by remembering the last key retrieved and calling KSDS.delete() with that key.

9. This method ends the browse, cleaning up any resources held by it.

Testing the implementationTo test our VSAM-backed map, we run a small program (Example 6-21).

Example 6-21 Testing the VsamMap implementation

package com.ibm.itso.sg245275.vsam;

import java.util.Iterator;

public class VsamMapTest { private final VsamMap map;

public static void main(String[] args) { try { new VsamMapTest(); } catch (Exception e) { e.printStackTrace(); } }

private VsamMapTest() { String key = "66666"; String record = createRecord(key); this.map = new VsamMap("ACCTFILE", key.length()); System.out.println("Contains key " + key + ": " + map.containsKey(key)); testPutNew(key, record); System.out.println("Contains key " + key + ": " + map.containsKey(key)); testPutExisting(key, record);

Chapter 6. The JCICS API 107

Page 122: Java Application Development for CICS

testRemove(key); printAllValues(); }

private void testPutNew(String key, String record) { System.out.println("Adding record " + key); map.put(key, record); }

private void testPutExisting(String key, String record) { try { // (1) System.out.print("Trying to modify record with key " + key + "..."); map.put(key, record.toString()); System.out.println("Oops, should have caused an exception"); } catch (IllegalArgumentException expected) { System.out.println("Caught an IllegalArgumentException, as expected"); } }

private void testRemove(String key) { System.out.println("Removing record " + key); map.remove(key); } private String createRecord(String key) { // (2) StringBuffer buf = new StringBuffer(key + "DOE JOHN "); buf.setLength(383); // Pad to record length return buf.toString(); }

private void printAllValues() { Iterator iter = map.values().iterator(); while (iter.hasNext()) { System.out.println(iter.next().toString().substring(0, 35)); // (3) } }}

Notes on Example 6-21 on page 107:

1. Modifying an existing record via VsamMap.put() is not allowed. Check that an IllegalArgumentException is thrown, as expected.

2. This creates a record of the correct length for our example VSAM file, whose record length is 383 bytes. (The rest will be padded with zeros.)

3. In each iteration, we print the first 35 bytes of the record.

Note: There is one potential flaw in our implementation: Once you have started iterating over the map, there is no way to end the iteration prematurely (to end the BROWSE operation, in CICS parlance). This could potentially tie up resources.

In particular, the number of concurrent operations that can be processed against a VSAM file is limited by the value of the STRINGS attribute on the file definition (see CICS Resource Definition Guide, SC34-6228, for more information). So, when you open one iterator, and then at a later point open another one before the first one was at end-of-file, your program may block forever.

108 Java Application Development for CICS

Page 123: Java Application Development for CICS

6.12 Interval controlAn important facility in CICS is the ability to have one transaction start another transaction. You can have CICS start the transaction immediately (the default), at a specific time, or after a period of time. You can start the transaction on behalf of a specified terminal, and you can pass the started transaction some data. Additionally, the transaction can be started in another CICS region. The started transaction is asynchronous to the transaction that starts it. Thus, the started transaction is in its own unit of work.

Optionally, you can pass data to the started transaction. Other than being able to retrieve the data passed to it, the started transaction is independent of the originating transaction.

We used this facility in 5.2.3, “Running the program” on page 73, when we started the HelloWorld sample program using the START command from CECI. To do it from a JCICS program, you set up an instance of class StartRequest and call the issue() method.

Optionally, you can pass data to the transaction being started, similar to the COMMAREA mechanism explained in 6.2.1, “Program control” on page 80. The difference is that, since the starting transaction and the new transaction being started are independent from each other, the new transaction cannot pass data back to the originating transaction. Also, the mechanism to access the passed data is different: You use the Task.retrieve() method. Example 6-22 shows how it is done.

Example 6-22 Retrieving data passed from a START request

package com.ibm.itso.sg245275;

import java.util.BitSet;import com.ibm.cics.server.*;

public class RetrieveDemo {

public static void main(CommAreaHolder cah) { RetrievedDataHolder rdh = new RetrievedDataHolder(); BitSet whatToRetrieve = new BitSet(); // (1) whatToRetrieve.set(RetrieveBits.DATA); whatToRetrieve.set(RetrieveBits.QUEUE);

try { Task.getTask().retrieve(whatToRetrieve, rdh); System.out.println("Retrieved DATA: " + new String(rdh.value.data)); // (2) System.out.println("Retrieved QUEUE: " + new String(rdh.value.queue)); // (3)

} catch (EndOfDataException e) { // (4) System.err.println("No data to retrieve. Did you start me from a terminal?"); } catch (InvalidRetrieveOptionException e) { // (5) System.err.println("Expected option not set by START command"); } catch (CicsException e) { e.printStackTrace(); } }}

Notes on Example 6-22:

1. We have to indicate what to retrieve: Data, an RTRANSID, an RTERMID, a queue name, or some combination of these. (See CICS Application Programming Reference, SC34-6232, for more information about the meaning of the various options.)

To indicate what combination to retrieve, we have to instantiate a BitSet and set the corresponding bits (one of the constants in the RetrieveBits interface).

Chapter 6. The JCICS API 109

Page 124: Java Application Development for CICS

2. Print the data…

3. … and the queue name we received.

4. No data was passed.

5. We tried to retrieve a piece of information that was not present. That is, either no data or no queue name was passed from the transaction that started ours.

You can test the sample using CEMT, as we show in Example 6-23.

Example 6-23 CEDA dialog to test Example 6-22 on page 109

START TR(SMP1) From('Your data goes here') Queue(MYQUEUE) STATUS: ABOUT TO EXECUTE COMMAND NAME= EXEC CICS START TRansid( 'SMP1' ) < Interval( +0000000 ) | TIme() | ( AFter | AT ) < Hours() > < Minutes() > < SEconds() > > < FRom( 'Your data goes here' ) < Length( +00019 ) < FMh > > > < TErmid() | Userid() > < SYsid() > < RTRansid() > < RTErmid() > < Queue( 'MYQUEUE ' ) > < Nocheck > < Protect > < REqid() > < ATTach > < BRExit() < BRDATA() < BRDATALength() > > > PF 1 HELP 2 HEX 3 END 4 EIB 5 VAR 6 USER 7 SBH 8 SFH 9 MSG 10 SB 11 SF

You enter the data in the From clause of the START command (you have to use quotes if the data contains embedded blanks), and the queue name in the Queue clause. Try and omit one or both of them, and inspect the program’s output.

6.13 Terminal servicesJCICS terminal services allow interaction with the user terminal. You can send data to and receive data from the terminal, and send cursor and device control instructions to the terminal.

Alas, using these services is not for the faint of heart since they require intimate knowledge of the 3270 datastream format (see 3270 Data Stream Programmer’s Reference, GA23-0059).

There is one terminal service, however, that is relatively straightforward to use. If a JCICS program has been started from a terminal, the Task.out variable (an instance of PrintWriter) allows you to write to that terminal, much like the standard Java System.out stream:

Task.getTask().out.println("Hello World!");

That said, there is good news. During the residency, we developed a little package boldly called JBMS (Java Basic Mapping Support), which provides an easy-to-use interface to the 3270 terminal, much like the corresponding BMS service in traditional CICS programming. Be aware, however, that the usual Redbooks disclaimer applies: It is experimental code, not thoroughly tested, and certainly not ready for production purposes. It may come handy, however, if you want to develop a simple front-end for an application without going through all the effort to create a full-fledged Web interface.

110 Java Application Development for CICS

Page 125: Java Application Development for CICS

We only show some particularly interesting parts of the JBMS package in the remainder of this section. You can find the full source code in Appendix D, “Program listings” on page 203.

Figure 6-8 JBMS class hierarchy

A brief explanation of all classes follows.

ComponentThis is the abstract superclass for all classes that represent elements on the screen. All components except Screen have a parent Component that has to be passed to the constructor. A Component has a row/column position that is relative to its enclosing Component (if any), and a flag that indicates whether the component is visible, that is, should be displayed on the screen at all.

Chapter 6. The JCICS API 111

Page 126: Java Application Development for CICS

ContainerThis is an abstract superclass for all components that contain other components. The idea is that you add related items to a container using a relative position. So, if you later decide that you have to move a container to another position on the screen, you simply change the container’s position rather than the position of each individual item in the container.

PanelRight now, a panel does not have additional functionality over a container; the idea is that it could add visual elements, such as a border as an indication of grouping.

For convenience, we provide a subclass, PfKeyPanel, which you can use to show PF-key assignments.

ScreenThis container represents an entire 3270 screen. It is responsible for generating and sending the outbound 3270 data stream to the terminal, and for receiving and parsing the inbound data stream.

Again, there is a convenience subclass, MenuScreen, which can be used to easily create a menu screen showing several items and an input field for the user’s choice.

FieldThis is the abstract superclass of all basic components of a screen, that is, the actual fields that make up the screen.

LabelRepresents fields that are intended for display only, that is, that are not for data entry by the user. However, the text displayed need not be static but can also be changed during the dialogue with the end user, for example, to show an error message.

TextThis is a field for data entry. Optionally, you can set a formatter, that is, an instance of java.text.Format, to validate and format data entered by the user.

Next, we show you a sample screen created using the JBMS package (Figure 6-9 on page 113), and the program that created it (Example 6-24 on page 113).

112 Java Application Development for CICS

Page 127: Java Application Development for CICS

Figure 6-9 Sample screen produced by a JBMS program

The program to generate this screen is shown in Example 6-24.

Example 6-24 Sample JBMS program

package com.ibm.itso.sg245275;

import java.text.DecimalFormat;

import com.ibm.cics.server.*;

import com.ibm.itso.sg245275.jbms.*;import com.ibm.itso.sg245275.jbms.Field.Color;import com.ibm.itso.sg245275.vsam.VsamMap;

public class BmsDemo { private Text acctno; private Text firstname, lastname, midinit; private Text phone; private Text[] addr = new Text[3]; private PfKeyPanel pfkeys; private VsamMap accounts = new VsamMap("ACCTFILE", 5); // (1)

public BmsDemo(TerminalPrincipalFacility term) throws InvalidRequestException, LengthErrorException, NotAllocatedException, TerminalException { Screen screen = createScreen(); byte aid; String record = null; boolean end = false; term.clear(); while (!end) {

Chapter 6. The JCICS API 113

Page 128: Java Application Development for CICS

do { fillFields(record); // (2) aid = screen.displayAndReceive(term); // (3) } while (aid != AIDValue.PF3 && screen.validate() != null); // (4) switch (aid) { // ... omitted } } term.clear(); }

private String makeRecord() { // ... omitted } private void fillFields(String record) { // ... omitted }

private Screen createScreen() { // (5) Screen screen = new Screen(); Label label; label = new Label(screen, 1, 1, "Account management"); label.setForegroundColor(Color.PINK); label = new Label(screen, 4, 1, "Acct no:"); label.setForegroundColor(Color.TURQUOISE); acctno = new Text(screen, 4, 10, 5); // (6) acctno.setFormat(new DecimalFormat("00000")); // Name panel. Panel namePanel = new Panel(screen, 6, 0); // (7) label = new Label(namePanel, 0, 1, "Name: "); label.setForegroundColor(Color.TURQUOISE); lastname = new Text(namePanel, 0, 10, 18); label = new Label(namePanel, 0, 29, ","); label.setForegroundColor(Color.TURQUOISE); firstname = new Text(namePanel, 0, 31, 12); midinit = new Text(namePanel, 0, 44, 1); label = new Label(screen, 8, 1, "Phone: "); label.setForegroundColor(Color.TURQUOISE); phone = new Text(screen, 8, 10, 10); // Address panel. Panel addressPanel = new Panel(screen, 10, 0); label = new Label(addressPanel, 0, 1, "Address: "); label.setForegroundColor(Color.TURQUOISE); addr[0] = new Text(addressPanel, 0, 10, 24); addr[1] = new Text(addressPanel, 1, 10, 24); addr[2] = new Text(addressPanel, 2, 10, 24); // Create PF key bar. pfkeys = new PfKeyPanel(screen); pfkeys.setText(1, "HELP"); // ... (omitted)

// Initial cursor position. screen.setInitialField(acctno); // (8)

114 Java Application Development for CICS

Page 129: Java Application Development for CICS

return screen; }

public static void main(CommAreaHolder ca) { // ... omitted }}

Notes on Example 6-24 on page 113:

1. The data displayed on this screen comes from a VSAM file. We use the VsamMap class developed in 6.11, “File control” on page 100, to access the data.

2. Populate the fields with values from the record.

3. Display the screen, and receive the user response. The fields that make up the screen will be updated with the data entered by the user, and we get back an AID value that tells us what key the user pressed to send the data (for example, the ENTER key, or a PF key).

4. If the user entered invalid data (in this example, non-numeric data in the acctname field), start all over again, unless he pressed PF3 for exit.

5. This method creates the screen, adding labels for informative text, and fields for data entry.

6. This is the account number field. We set up a formatter that causes the data to be displayed with leading zeros, and validates the user input.

7. For easier maintenance, we group related fields such as the name and address fields together, with offsets relative to the enclosing container. To move a group of related fields, you need to only change the position of the container rather than of each contained element.

8. Set the initial field, that is, the one that the cursor is positioned on when the screen is displayed.

In the remainder of this section, we show you some implementation details. The most interesting parts are constructing the data to be sent to the 3270 terminal (in 3270 parlance, the outbound data stream), and parsing the data being sent back by the terminal (the inbound data stream).

Example 6-25 shows the method that creates the 3270 data stream and sends it to the terminal.

Example 6-25 Screen.display()

public void display(TerminalPrincipalFacility term) throws InvalidRequestException, LengthErrorException, NotAllocatedException, TerminalException{ ByteArrayOutputStream bos = new ByteArrayOutputStream(); // (1) bos.write(0); bos.write(0); to3270(bos); // (2) if (getInitialField() != null) { // (3) // Position cursor to initial field. initialField.insertBufferAddress(bos, true); bos.write(Order.INSERT_CURSOR); } term.send(bos.toByteArray()); // (4)}

Chapter 6. The JCICS API 115

Page 130: Java Application Development for CICS

Notes on Example 6-25 on page 115:

1. Create a ByteOutputStream to hold the outbound 3270 data stream.

2. Create the 3270 data stream (see Example 6-26).

3. If an initial field was specified, write a 3270 instruction to set the current buffer position and another one to move the cursor to that position.

4. This is the JCICS call to send the data stream to the terminal.

To generate the data stream, we recursively iterate over all components (Example 6-26).

Example 6-26 Container.to3270()

protected void to3270(ByteArrayOutputStream bos) { if (isVisible()) { // (1) for (Iterator iter = components.iterator(); iter.hasNext();) { // (2) Component component = (Component) iter.next(); component.to3270(bos); // (3) } }}

Notes on Example 6-26:

1. If this Container is visible at all…

2. … iterate over all contained components, …

3. … telling each in turn to generate its part of the data stream. This will be a recursive call if the current component is itself a container.

Finally, we have to generate the 3270 stream for a single field. This is the most complicated part, because here we finally have to know about the 3270 data stream format.

Basically, the outbound 3270 data stream consists of command bytes (orders) followed by parameters. To define a field, you use the Start Field (SF) or Start Field Extended (SFE) order. In our code below, we use SFE.

A field begins at the current buffer position, which can be changed with the Set Buffer Address (SBA) order, and ends right before the next field begins. SBA is followed by a two-byte buffer address.

Therefore, to start a new field, we first set the current buffer position, then define the field using SFE, and finally create an empty marker field.

A 3270 field can have several attributes, such color, intensity, and whether the field is protected (that is, no data can be entered into the field). Each attribute is recognized by an attribute type byte followed by an attribute value byte (see Table 6-2 on page 117). One of those attributes, the 3270 attribute, is always present, and is stored in the 3270 display buffer at the first position of the field (it will not display on the screen). The other attributes are optional.

The SFE order is followed by a single byte that indicates how many type/value byte pairs follow.

116 Java Application Development for CICS

Page 131: Java Application Development for CICS

Table 6-2 Some 3270 attributes and their possible values

Now we are ready to show how the data stream for a single field is generated (Example 6-27).

Example 6-27 Field.to3270()

protected void to3270(ByteArrayOutputStream bos) { if (isVisible()) { insertBufferAddress(bos, false); // (1) bos.write(Order.START_FIELD_EXT); // Start field extended // (2) bos.write(countExtendedAttributes()); // Number of extended attributes // (3) // Send extended attributes, as type/value byte pairs. // (4) writeAttribute(bos, AttributeType.STD3270, (byte) Util.encode(attributes)); writeAttributeConditional(bos, AttributeType.EXT_HILITE, extHilite); writeAttributeConditional(bos, AttributeType.FOREGROUND, foregroundColor); try { bos.write(text.getBytes()); } catch (IOException e) { // Can’t happen with a ByteArrayOutputStream } // Send a dummy marker field to indicate end of current field // (5) bos.write(Order.START_FIELD); bos.write(Util.encode(Attribute.AUTOSKIP)); }}

Notes on Example 6-27:

1. First we have to tell the terminal the position of the field. The 3270 expects the position as a buffer address, encoded in a rather peculiar format (see the full source code for details).

2. Next we indicate the start of a field, using the Start Field Extended (SFE) order.

Type code

Attribute type Values

0xC0 3270 Field attribute

Value is a combination of bits. Some combinations have special meanings (autoskip, nondisplay).Value must be EBCDIC encoded.

0x20 Field is protected

0x10 Field is numeric

0x30 Field is autoskip (no entry)

0x08 Intensified

0x0C Nondisplay (password)

0x41 Extended highlighting 0x00 Default

0xF0 Normal (as determined by 3270 field attribute)

0xF1 Blink

0xF2 Reverse video

0xF4 Underscore

0x42 Foreground color 0xF0 Neutral

0xF1 Blue

...

0xFF White

Chapter 6. The JCICS API 117

Page 132: Java Application Development for CICS

3. SFE expects the number of attribute/value pairs.

4. Write attribute/value pairs to the data stream.

5. The 3270 assumes that a field ends where the next field starts, so we write a dummy marker field to indicate the end of the current one, as described above.

To get end user input, we have to receive and parse the inbound 3270 data stream (Example 6-28).

Example 6-28 Screen.receive() - Receive input from terminal, parse response, and update fields

/** * Receive input from terminal, and parse data stream.

* * @return AID (Action Identifier) of the key pressed {one of the * {@link com.ibm.cics.server.AIDValue AIDValue}constants). */public byte receive(TerminalPrincipalFacility term) throws InvalidRequestException, LengthErrorException, NotAllocatedException, TerminalException{ DataHolder dah = new DataHolder(); try {

term.receive(dah); // (1) } catch (EndOfChainIndicatorException expected) { // Always thrown from TerminalPrincipalFacility.receive(). // (2) // We can safely ignore it. } parseResponse(dah.value); // (3) return term.getAIDbyte(); // (4)}

Notes on Example 6-28:

1. JCICS call to receive the response from the terminal.

2. Term.receive() always throws an EndOfChainIndicatorException (because the underlying EXEC CICS API always sets the corresponding RESP condition), and we can safely ignore it.

3. Parse the response…

4. … and return the AID that caused the screen to be sent.

The inbound 3270 consists of Set Buffer Address (SBA) orders that indicate which field is being sent next, followed by the actual data (that is, whatever the user entered into the field). So, we inspect the data stream, looking for SBA orders and finding the corresponding JBMS Field object for each order (Example 6-29). Then we extract the field data, and update the Field object accordingly.

Example 6-29 Parsing the response received from the 3270 terminal

private void parseResponse(byte[] resp) { // Start at index 1 (index 0 has a SET_BUFFER_ADDRESS for first field). for (int pos = 1; pos < resp.length; pos++) { // (1) // Get buffer address. int bufaddr = ((resp[pos++] << 8) | (resp[pos++] & 0xFF)) & 0xFFFF; // (2) // Find end of current segment (look for next SBA). int end; for (end = pos; end < resp.length && resp[end] != Order.SET_BUFFER_ADDRESS; end++) ; // Find the field this segment corresponds to. Field field = findFieldByAddress(bufaddr); // (3)

118 Java Application Development for CICS

Page 133: Java Application Development for CICS

if (field != null) { // Found field; set its contents to the data received. String fieldContents = new String(resp, pos, end - pos); // (4) field.setText(fieldContents); } pos = end; }}

Notes on Example 6-26 on page 116:

1. Scan the data stream, examining it for SBA orders.

2. Extract the buffer address (next two bytes after SBA).

3. Look up the field this buffer address refers to.

4. Extract the field data, and set the new field text.

Chapter 6. The JCICS API 119

Page 134: Java Application Development for CICS

120 Java Application Development for CICS

Page 135: Java Application Development for CICS

Chapter 7. Evolving a legacy application using Java

In this chapter we take a COBOL legacy application and describe ways it can be enhanced using the JCICS API. The stages of evolution are:

1. Implement a Web interface to co-exist alongside the original 3270 display, opening up the underlying business logic to a generation of Internet clients.

2. Fully implement the back-end business logic using Java, introducing a pluggable data storage component for future scalability.

3. Implement a DB2 back-end and migrate the application data from its existing VSAM setup.

You may find this section useful as both an approach for migrating legacy applications to JCICS and as a reference to example implementations of Web, file, and DB2 access using the JCICS API.

7

© Copyright IBM Corp. 2005. All rights reserved. 121

Page 136: Java Application Development for CICS

7.1 The legacy trader applicationThe COBOL trader sample is a 3270 application that allows users to buy and sell shares from a group of companies in real time. Written in COBOL, it has a CICS BMS interface and uses VSAM file access for data storage. The application is pseudo-conversational, meaning that a chain of related non-conversational CICS transactions is used to convey the impression of a “conversation” to the user as they go through a sequence of screens that constitute a business transaction.

The application consists of two modules:

� TRADERPL - The 3270 presentation logic. Invokes TRADERBL using an EXEC CICS LINK passing a COMMAREA structure for input and output.

� TRADERBL - The business logic. Data is persisted in VSAM files.

Figure 7-1 Breakdown of the legacy application

InstallationThe COBOL trader application requires the following resources.

FilesThe trader application uses two VSAM files:

� COMPFILE: Stores the list of companies and associated share prices. It can be created using the supplied JCL TRADERCOJCL.TXT, which requires as input the file TRADERCODATA.TXT.

� CUSTFILE: Stores the list of users and their share holding. It can be created using the supplied JCL TRADERCUJCL.TXT.

ProgramsTwo COBOL programs are used, TRADERPL and TRADERBL, which need to be compiled and placed in a data set in your CICS region’s DFHRPL concatenation. The programs are supplied as the files TRADERPL.TXT and TRADERBL.TXT, respectively.

MapsetTrader uses the mapset NEWTRAD, which comprises the maps T001, T002, T003, T004, T005, and T006. The mapset is supplied in the file NEWTRAD.TXT and needs to be assembled and placed in a dataset in your CICS region’s DFHRPL concatenation.

TRADERPL

PresentationLogic

COMMAREA

TRADERPL

PresentationLogic

COMMAREA

TRADERBL

BusinessLogic

BMS

Companyfile

Customerfile

LINK

VSAM

3270

122 Java Application Development for CICS

Page 137: Java Application Development for CICS

CICS definitionsThese CICS resources need to be defined in the TRADER group.

� MAPSET(NEWTRAD)

� PROGRAM(TRADERBL)LANGUAGE(COBOL)

� PROGRAM(TRADERPL)LANGUAGE(COBOL)

� TRANSACTION(TRAD)PROGRAM(TRADERPL)

� FILE(COMPFILE)DSNAME(DATASET.CONTAINING.COMPFILE)RLSACCESS(Yes)STRINGS(5)ADD(Yes)BROWSE(Yes)DELETE(Yes)READ(Yes)UPDATE(Yes)

� FILE(CUSTFILE)DSNAME(DATASET.CONTAINING.CUSTFILE)RLSACCESS(Yes)STRINGS(5)ADD(Yes)BROWSE(Yes)DELETE(Yes)READ(Yes)UPDATE(Yes)

For further information about creating the resource definitions for the trader application, refer to the supplied file TRADERRDO.TXT, which contains the output of a CSD extract for group TRADER.

7.2 Adding a JCICS Web interfaceThe trader application is comprised of a presentation component and a business component with requests transmitted between them using a COMMAREA. Given an understanding of the COMMAREA structure, additional interfaces can be written to run alongside, or instead of, the original 3270 display. Figure 7-2 on page 124 illustrates this.

Chapter 7. Evolving a legacy application using Java 123

Page 138: Java Application Development for CICS

Figure 7-2 A Web interface alongside the legacy application

Following this approach, you will implement a Web interface to the trader application using the JCICS Web API.

7.2.1 Wrapping the COMMAREAIn order to transmit data requests to the COBOL business component, the JCICS program needs an understanding of the COMMAREA data. The COMMAREA is an array of bytes, the data of which is formatted according to a COBOL data structure. Given this information, a wrapper class is written in Java allowing you to set and get the various values contained within the COMMAREA.

ExampleAs a starting point we discuss wrapping the first two lines of the COMMAREA, as shown in Example 7-1.

Example 7-1 The first two lines of the COMMAREA from TRADERBL

01 COMMAREA-BUFFER.03 REQUEST-TYPE PIC X(15).

The structure of the wrapper is a Java class containing the following:

� A byte[] for the COMMAREA data� A getter and setter method for the byte[]� Variables holding the index and length of each value in the COMMAREA� Getter and setter methods for each value� A utility method for formatting values

TRADERPL

PresentationLogic

COMMAREA

TRADERPL

PresentationLogic

COMMAREA

TRADERBL

BusinessLogic

BMS

Companyfile

Customerfile

LINK

VSAM

3270

TRADERPJ

JCICS Web Presentation

Logic

COMMAREA

HTTP

LINK

WebClient

Java

124 Java Application Development for CICS

Page 139: Java Application Development for CICS

Example 7-2 The structure of the wrapper class

public class CommareaWrapper {

// Values in the COMMAREAprivate final int[] COMMAREA_BUFFER = {0, 372}; // (1)private final int[] REQUEST_TYPE = {0, 15};

// Variable to hold the binary data in the COMMAREAprivate byte[] fData;

/* Instantiate the wrapper object and initialize its values */public CommareaWrapper() {

fData = new byte[COMMAREA_BUFFER[1]];setNewValue("", 0, fData.length); // (2)

}

/* Set the binary data of the COMMAREA */public void setByteArray(byte[] data) { fData = data; }

/* Get the binary data of the COMMAREA */public byte[] getByteArray() { return fData; }

/* Get the value of REQUEST-TYPE */public String getRequestType() {

return new String(fData, REQUEST_TYPE[0], REQUEST_TYPE[1]);}

/* Set the value of REQUEST-TYPE */public void setRequestType(String newValue) {

setNewValue(newValue, REQUEST_TYPE[0], REQUEST_TYPE[1]);}

/* * Inserts a value into the main byte[] and pads with spaces if necessary. * Note: values will be left justified */private void setNewValue(String newValue, int index, int length) { ... }

}

Notes on Example 7-2:

1. {0, 372} implies index=0 & length=372.

2. Resets all values in the array to the space character.

This provides you with a fully usable wrapper. To add further COMMAREA values create a new variable to hold its index and length settings and a corresponding getter and setter method. Generally the index is set to the index of the previous value plus its size, but sometimes it can also overlay a previous value depending on the COMMAREA structure.

Character-based valuesThe code so far applies to character-based non-numeric values. For character-based numeric values an alternative setNewValue() needs to be implemented, which right justifies and pads with zeros if required.

Important: COBOL character types can be quite flexible so pay close attention during the creation of the wrapper. Feel free to modify and create new versions of the setNewValue() method as required.

Chapter 7. Evolving a legacy application using Java 125

Page 140: Java Application Development for CICS

Binary-based valuesCOBOL types that are binary based (COMP1, COMP3, etc.) need further processing.

The suggested approach is to write a getter method that converts the binary data into a Java primitive number (short, int, long) and gives it to the user. The setter method does the opposite and takes a Java primitive number, which it converts to the corresponding COBOL binary representation and inserts it into the byte[].

ArraysThe COBOL statement OCCURS X TIMES refers to an array structure of size X. To allow for values that exist in arrays, the getter and setter methods need to take an extra parameter, the index in the array.

� public String getValue(int arrayIndex)� public void setValue(String newValue, int arrayIndex)

The code for finding the index of a value in the array then becomes index = value-index + (value-length * array-index), as shown in Example 7-3.

Example 7-3 getter and setter methods for an array value

/* Get the value of ARRAY_VAL. Note: arrayIndex starts at 0 */public String getArrayVal(int arrayIndex) {

return new String(fData, ARRAY_VAL[0] + (ARRAY_VAL[1] * arrayIndex), ARRAY_VAL[1]);}

/* Set the value of ARRAY_VAL. Note: arrayIndex starts at 0 */public void setCompanyNameTab(String newValue, int arrayIndex) {

setNewValue(newValue, ARRAY_VAL[0] + (ARRAY_VAL[1] * arrayIndex), ARRAY_VAL[1]);}

7.2.2 Understanding COMMAREA request formatsHaving written CommareaWrapper we now need to understand how to format the requests to send to TRADERBL. Observing the link commands in TRADERPL, the requests can be broken down to the following settings in the COMMAREA structure:

� Get list of companies.

– REQUEST-TYPE = “Get_Company”

� Get a company quote.

– REQUEST-TYPE = “Share_Value”– RETURN-VALUE = “00” – USER-ID = User ID of current user– COMPANY-NAME = Company selected for previous menu

� Buy shares.

– REQUEST-TYPE = “Buy_Sell”– RETURN-VALUE = “00” – USER-ID = User ID of current user– COMPANY-NAME = Company selected for previous menu– UPDATE-BUY-SELL = “1”

� Sell shares.

Note: COBOL arrays can get quite complex, but it is still possible to wrapper them using indexing techniques similar to above.

126 Java Application Development for CICS

Page 141: Java Application Development for CICS

– REQUEST-TYPE = “Buy_Sell”– RETURN-VALUE = “00” – USER-ID = User ID of current user– COMPANY-NAME = Company selected for previous menu– UPDATE-BUY-SELL = “2”

If you set these values in the CommareaWrapper and link to TRADERBL the data returned will be exactly the same as that for TRADERPL.

7.2.3 A test Web applicationTo test the CommareaWrapper class, we write a simple JCICS Web program to interface with the COBOL application TRADERBL. The program retrieves a list of companies and displays them in a Web page.

SimpleTraderPLUsing the JCICS Web API create a Java class called SimpleTraderPL. As with all JCICS programs, it needs a public static void main(CommAreaHolder commAreaHolder) method, which in this case gets called by the CICS Web transaction CWBA.

The flow of the program is as follows:

1. Build the COMMAREA data.2. Link to TRADERBL passing the COMMAREA.3. Build the HTML from the returned COMMAREA data.4. Send the HTTP response.

Building the COMMAREA is a matter of creating a CommareaWrapper object instance and setting the requestType value to "Get_Company", as shown in “Understanding COMMAREA request formats” on page 126. To alleviate any potential errors that may occur should this value be referenced in multiple places, it is stored as a static variable GET_COMPANY_REQ in the class TraderConstants.

Next the request is sent using a CICS program link to TRADERBL. A call to getByteArray() extracts the byte[] from CommareaWrapper and passes it to the JCICS link() command. Any COMMAREA data changed by TRADERBL will be reflected back in this byte[].

If the link command fails for any reason, the exception data is output to Java’s stderr; see 8.3.2, “JVM stdout and stderr” on page 165, for more info on this.

The program now has the list of companies and begins building the HTML response. Dynamic HTML content is built using documents that allow a user to insert HTML line-by-line or in one big chunk. In JCICS a document object is instantiated and HTML added using the appendText() method. In SimpleTraderPL, company names are extracted from the COMPANY-NAME-TAB array value in the CommareaWrapper and inserted into the HTML. Lastly, the document is sent back in the HTTP response. If anything should fail, an attempt is made to send back a HTTP 500 error response.

Important: Program names specified for the JCICS link() command are case sensitive and so need to be presented in uppercase.

Note: The parameters to the HttpResponse.sendDocument() method supply HTTP response values such as status code, status response, and client code page.

Chapter 7. Evolving a legacy application using Java 127

Page 142: Java Application Development for CICS

Example 7-4 The SimpleTraderPL main() method

public static void main(CommAreaHolder commAreaHolder) {final CommareaWrapper commareaWrapper = new CommareaWrapper();

// Prepare COMMAREA for request to COBOL program TRADERBLcommareaWrapper.setRequestType(TraderConstants.GET_COMPANY_REQ);

// Send the data request to TRADERBLfinal Program program = new Program();

HttpResponse response = null;Document document = null;

try {// Link to TRADERBLprogram.setName("TRADERBL");program.link(commareaWrapper.getByteArray());

// Build the HTML responseresponse = new HttpResponse();document = new Document();

document.appendText("<H1>SimpleTraderPL</H1>");document.appendText("<P>List of companies:</P>");document.appendText("<UL>");document.appendText("<LI>" + commareaWrapper.getCompanyNameTab(0) + "</LI>");document.appendText("<LI>" + commareaWrapper.getCompanyNameTab(1) + "</LI>");document.appendText("<LI>" + commareaWrapper.getCompanyNameTab(2) + "</LI>");document.appendText("<LI>" + commareaWrapper.getCompanyNameTab(3) + "</LI>");document.appendText("</UL>");

// Send the responseresponse.sendDocument(document, (short) 200, "OK", "iso-8859-1"); // (1)

}catch (Exception e) { sendErrorResponse(); e.printStackTrace(); }

}

private static void sendErrorResponse() {try {

final Document doc = new Document();doc.appendFromTemplate("Internal Error");new HttpResponse().sendDocument(doc, (short) 500, "Internal Error","iso-8859-1");

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

}

Notes on Example 7-4:

1. 200 is the HTTP status code for OK. iso-8859-1 is the name of the Latin-1 (ascii) character set.

Further features of documents are used in “Display next page” on page 134.

InstallationThe source code and compiled classes for this example are in Trader-1.jar. Follow the instructions in Chapter 4, “Setting up CICS to run Java applications” on page 41, and make sure this jar file is added to the CICS Java classpath.

128 Java Application Development for CICS

Page 143: Java Application Development for CICS

Two new CICS resources need to be defined alongside the existing definitions in the TRADER group:

� PROGRAM(TRADERPS)CONCURRENCY(Threadsafe)JVM(Yes)JVMCLASS(com.ibm.itso.sg245275.trader.SimpleTraderPL)

� TCPIPSERVICE(TCPIPS)URM(DFHWBADX)PORTNUMBER(<portnumber>)PROTOCOL(Http)TRANSACTION(CWXN)AUTHENTICATE(No)

For the TCPIPSERVICE definition make sure you choose a port number that is available and not already open. Also ensure the group DFHWEB is installed to pick up the necessary Web transactions.

Running SimpleTraderPLBring up your favorite Web browser and type in a URL similar to the following:

http://wtsc66.itso.ibm.com:5275/cics/cwba/traderps

Ensure the port number matches up to that in your TCPIPSERVICE definition and that the program name at the end is traderps.

The browser now displays the list of companies, as shown in Figure 7-3.

Figure 7-3 SimpleTraderPL’s browser display

Congratulations. You have implemented your first JCICS Web interface.

Note: The DFHWEB group is in DFHLIST, so if you have this in your CICS startup then the Web transactions will be installed by default.

Note: The program name at the end of the URL is not case sensitive.

Chapter 7. Evolving a legacy application using Java 129

Page 144: Java Application Development for CICS

7.2.4 Designing the HTML interfaceAfter successfully running the sample you could go ahead and begin developing JCICS Web applications; but before jumping in feet first with the coding let us take a look at the Web site’s navigation design.

The BMS displayThe 3270 BMS display allowed users to traverse through menus while making navigation decisions along the way. From each menu they can always get back to the previous one. A graphical representation of the navigation paths is shown in Figure 7-4.

Figure 7-4 Navigation of the trader application

The HTML designThe HTML pages navigation follows a similar design to the 3270 display although a couple of changes can be made to increase usability. An explicit login page is no longer needed since CICS has the option of handling Web security implicitly for you. For more information about Web security, see “Web security” on page 138.

Utilizing the flexibility of HTML navigation, the company selection and share trading options pages are combined to provide a single interface for showing the companies and actions that can be performed upon them. For further convenience the company quotes page contains direct links to the share buying and selling pages for that company. As a usability enhancement, the buy and sell pages will also display some of the company information available from the company quotes page.

The new navigation design is shown in Figure 7-5 on page 131.

Logon

Select a company

Quote, buy or sell

Real-time quote Buy Sell

130 Java Application Development for CICS

Page 145: Java Application Development for CICS

Figure 7-5 Web interface navigation

7.2.5 Implementing the designWith design in hand you can go right ahead and implement the code. For the purpose of maintainability, the HTML Web pages are stored in PDS members and accessed using the CICS document’s API, which is fully supported in JCICS. Documents allow dynamic HTML to be built using CICS templates and symbols.

TraderPLThe JCICS Web program TraderPL is a single point of entry to all Web requests. Parameters received through HTTP GET and POST requests control the response of the program.

The main flow of logic through the program is:

1. Get HTTP input fields.2. Perform buying and selling.3. Get request details.4. Display next page.

Get HTTP input fieldsFor convenience, the program actions are stored as static strings. These values must match the form field values specified in the HTML.

Example 7-5 Action constants

private static final String PERFORM_BUY = "performbuy";private static final String PERFORM_SELL = "performsell";private static final String SHOW_LIST = "showlist";private static final String SHOW_DETAILS = "Details"; // (1)private static final String SHOW_BUY = "Buy";private static final String SHOW_SELL = "Sell";private static final String LOGOFF = "Logoff";

Note on Example 7-5:

1. The HTML equivalent for this is:

<INPUT type='submit' name='action' value='Details'>

If the action is to buy or sell shares, then once this is performed the user is redirected to the company details page. When no parameter is supplied, the default action is to show the

Quote, buy or sell from company list

Buy SellReal-time quote

Note: PDS members have a fixed width, so HTML files uploaded using FTP should be checked to ensure that long lines are not truncated.

Chapter 7. Evolving a legacy application using Java 131

Page 146: Java Application Development for CICS

company list page; or if an unknown action is specified, then a message is sent back to the user.

Example 7-6 The main flow of logic in TraderPL

private String fCompanyName;private String fNumShares;private String fMessage;

public TraderPL() {

// Get HTTP datafinal HttpRequest request = HttpRequest.getHttpRequestInstance();

String action = null;

try { action = request.getFormField("action");fCompanyName = request.getFormField("companyname");fNumShares = request.getFormField("numshares"); // Used when buying/selling shares

}catch (InvalidRequestException e) {}

// If action is not set then default to show company list screen if (action == null) action = SHOW_LIST;// Buy/sell shares and then redirect to show company details screen else if (PERFORM_BUY.equals(action)) {

performBuy();action = SHOW_DETAILS;

}else if (PERFORM_SELL.equals(action)) {

performSell();action = SHOW_DETAILS;

}

// Show desired pageif (SHOW_LIST.equals(action)) showList();else if (SHOW_DETAILS.equals(action)) showDetails();else if (SHOW_BUY.equals(action)) showBuy();else if (SHOW_SELL.equals(action)) showSell();else if (LOGOFF.equals(action)) logoff();else {

// Notify the user of the unknown action fMessage = "Unknown action: '" + action + "'"; // (1)

// Invalid page requested so show company list page insteadshowList();

}}

Note on Example 7-6:

1. This message will be output as part of the HTTP response.

Note: By default, HTTP parameters are case sensitive. To bypass this your Java program can use the String.toLowerCase() function for string comparisons.

132 Java Application Development for CICS

Page 147: Java Application Development for CICS

Perform buy/sellThe performBuy() and performSell() methods are virtually identical, the only difference being the value for UPDATE-BUY-SELL in the COMMAREA, as shown in 7.2.2, “Understanding COMMAREA request formats” on page 126.

The method structure is:

1. Build request COMMAREA.2. Send request.3. Check return value.

A non-zero return value will generate a message that is returned in the HTTP response. For convenience, static constants for the return values and their corresponding messages have been added to the TraderConstants class, which was first mentioned in “SimpleTraderPL” on page 127. It also has a utility method for passing a return code and getting back its corresponding message; see Appendix D, “Program listings” on page 203.

Example 7-7 The performBuy() method

private void performBuy() {// Prepare commarea for request to COBOL program TraderblfCommareaWrapper.setRequestType(TraderConstants.BUY_SELL_REQ);fCommareaWrapper.setReturnValue(TraderConstants.CLEAN_RETURN);fCommareaWrapper.setCompanyName(fCompanyName);fCommareaWrapper.setNoOfSharesDec(fNumShares);fCommareaWrapper.setUpdateBuySell(TraderConstants.SUBTYPE_BUY);

// Send the data request to TRADERBLsendLinkRequest();

// If the link failed then a message was set by sendLinkRequest.// If it worked then check the return value from TRADERBLif (fMessage == null)

fMessage = TraderConstants.getMessage(fCommareaWrapper.getReturnValue());}

Get request detailsAll the show*() functions follow a common design:

1. Build request COMMAREA.2. Send request.3. Check return value.4. Build symbol list.5. Send HTTP response.

The appropriate values are set in the CommareaWrapper and the request sent to TRADERBL. When the request returns, the symbol list is built using a series of name/value pairs (see CICS Application Programming Guide, SC34-6231, for more information about symbols). As you can see in Example 7-8 on page 134, values are extracted from the CommareaWrapper and inserted into the symbol list. For any numerical values that are displayed on pages such as the company quotes page, a custom utility method strip() is used to remove any leading zeros (see Appendix D, “Program listings” on page 203) for the code of this method.

Note: The Get_Company request to TRADERBL does not produce a return value and so is not checked.

Chapter 7. Evolving a legacy application using Java 133

Page 148: Java Application Development for CICS

Example 7-8 The showList() method

private void showList() {// Prepare COMMAREA for request to COBOL program TraderblfCommareaWrapper.setRequestType(TraderConstants.GET_COMPANY_REQ);

// Send the data request to TRADERBLsendLinkRequest();

// Return value is not checked as none are returned from a GET_COMPANY_REQ request

// Set appropriate symbol valuesfinal String symbolList =

"company1=" + fCommareaWrapper.getCompanyNameTab(0) + "&" +"company2=" + fCommareaWrapper.getCompanyNameTab(1) + "&" +"company3=" + fCommareaWrapper.getCompanyNameTab(2) + "&" +"company4=" + fCommareaWrapper.getCompanyNameTab(3) + "&" +"message=" + (fMessage != null ? fMessage : ""); // (1)

// Send the responsesendResponse(symbolList, "TRADCOML"); // (2)

}

Notes on Example 7-8:

1. If a message was generated, its symbol value is set, or else it is left blank.

2. TRADCOML is a DOCTEMPLATE definition that needs to exist in CICS; see “Installation” on page 136 for more information about this.

The sendLinkRequest() method is identical to the code in “SimpleTraderPL” on page 127 other than a single addition. Most requests to TRADERBL require a user ID, and since there is no longer an explicit login page, as discussed in “Designing the HTML interface” on page 130, the user ID is retrieved using the JCICS method Task.getTask().getUSERID().

Example 7-9 The sendLinkRequest() method

private void sendLinkRequest() {final Program program = new Program();

program.setName("TRADERBL");

try { // Set the UserId value in the COMMAREAfCommareaWrapper.setUserId(Task.getTask().getUSERID());

program.link(fCommareaWrapper.getByteArray()); }catch (Exception e) { System.err.println(e); e.printStackTrace(); fMessage = "Error - "

+ e; }}

Display next pageThe sendResponse() method completes the HTTP request by building the document object, adding the symbol list to it, appending the corresponding DOCTEMPLATE, and sending the HTTP response. Should anything go wrong while setting up the document object, then the

Note: If security is disabled, the user ID defaults to CICSUSER. See “Web security” on page 138 for enabling security in Web applications.

134 Java Application Development for CICS

Page 149: Java Application Development for CICS

exception data is outputted to Java’s stderr and an error message sent back to the user in the HTTP response. An error will occur if the template it is trying to append has not been installed in CICS.

As discussed in “SimpleTraderPL” on page 127, the same parameter options are used in the HttpResponse.sendDocument() method.

Example 7-10 The sendResponse() method

private void sendResponse(String symbolList, String template){final HttpResponse response = new HttpResponse();

Document document = null;boolean appendTemplateWorked = false;

try{// Create a new document and set the symbol listdocument = new Document();document.setSymbolList(new SymbolList(symbolList)); // (1)

// Append the template// Note this needs to have been defined in cics as a DOCTEMPLATE resourcedocument.appendTemplate(template);

// If we get here then the append succeededappendTemplateWorked = true;

}catch (Exception e) { sendErrorResponse(); e.printStackTrace(); }

// If the append failed then send back a message using the document objectif (!appendTemplateWorked && document != null) {

try { document.appendText("Problem loading template. See Java stderr for more info");

}catch (Exception e) {}

}

try { response.sendDocument(document, (short) 200, "OK", "iso-8859-1"); }catch (Exception e) { sendErrorResponse(); e.printStackTrace(); } // (2)

}

Notes on Example 7-10:

1. To set the symbol list, the API specifies that it must be wrapped using a SymbolList object.

2. The sendErrorResponse() method is the same as in Example 7-4 on page 128.

For more information about documents and templates, see CICS Application Programming Guide, SC34-6231.

Tip: Use CEMT INQUIRE DOCTEMPLATE to ensure your DOCTEMPLATE has been installed.

Note: Since the buy and sell HTML pages are so similar they use a common template, values specific to both are substituted in using symbols.

Chapter 7. Evolving a legacy application using Java 135

Page 150: Java Application Development for CICS

7.2.6 Setting up TraderPLFollow these instructions to install and run TraderPL.

InstallationSimilar to “Installation” on page 128, the source code and compiled classes for this example are in Trader-1.jar. Following the instructions in Chapter 4, “Setting up CICS to run Java applications” on page 41, make sure this jar file is added to the CICS Java classpath.

The new CICS resources that need to be defined alongside the existing definitions in the TRADER group are:

� PROGRAM(TRADERPJ)CONCURRENCY(Threadsafe)JVM(Yes)JVMCLASS(com.ibm.itso.sg245275.trader.TraderPL)

� DOCTEMPLATE(TRADBYSL)TEMPLATENAME(TRADBYSL)DDNAME(DFHHTML)MEMBERNAME(TRADBYSL)

� DOCTEMPLATE(TRADCOMD)TEMPLATENAME(TRADCOMD)DDNAME(DFHHTML)MEMBERNAME(TRADCOMD)

� DOCTEMPLATE(TRADCOML)TEMPLATENAME(TRADCOML)DDNAME(DFHHTML)MEMBERNAME(TRADCOML)

� DOCTEMPLATE(TRADLOGF)TEMPLATENAME(TRADLOGF)DDNAME(DFHHTML)MEMBERNAME(TRADLOGF)

Make sure the corresponding HTML templates exist in CICSSYSF.APPL.TEMPLATE.

To polish up the look of the Web pages, a CICS hosted image is added to the HTML that uses the ImageLoader program to load the file RBHOME.gif. Ensure the relevant DOCTEMPLATE has been installed and the image exists in the template data set (it will need to be uploaded as a binary file). Notice that for images the attributes APPENDCRLF(No) & TYPE(Binary) have to be set in the DOCTEMPLATE definition.

� DOCTEMPLATE(RBHOME)TEMPLATENAME(RBHOME)DDNAME(DFHHTML)MEMBERNAME(RBHOME)APPENDCRLF(No)TYPE(Binary)

Note: DFHHTML is the DD card for template data sets in the startup JCL. In our example it is set to CICSSYSF.APPL.TEMPLATE.

136 Java Application Development for CICS

Page 151: Java Application Development for CICS

Running TraderPLSimilar to “Running SimpleTraderPL” on page 129, bring up a Web browser and type in the URL:

http://wtsc66.itso.ibm.com:5275/cics/cwba/traderpj

Ensure the port number matches up to that in your TCPIPSERVICE definition and that the program name at the end is traderpj.

You will now see the display shown in Figure 7-6.

Figure 7-6 The company selection screen

If an error should occur, for example, if TRADERBL is not installed, then a message will be displayed as shown in Figure 7-7 on page 138.

Tip: You can use the ImageLoader program to host images in CICS by adding the following statement to your HTML:

<IMG src='imageldr?filename=<filename>&filetype=<filetype>' border='0'>

Where:

� filename: Case sensitive name of the DOCTEMPLATE definition for the image file.� filetype: Image type of the file, for example, gif, jpg, bmp.

Chapter 7. Evolving a legacy application using Java 137

Page 152: Java Application Development for CICS

Figure 7-7 The message received if TRADERBL has not been installed

Congratulations. You have implemented a Web interface to your existing COBOL legacy application.

7.2.7 Web securityEnabling security in the TraderPL program does not require any additional coding since CICS takes all the pain out of it by handling it for us. All that is needed is to set the AUTHENTICATE attribute to Basic is the TCPIPSERVICE definition.

Now when TRADERPJ is accessed over the Web you get prompted with a login box. Ensure you enter a valid user name and password combination.

Tip: To prove there are no smoke and mirrors involved, try running the Web interface and the original 3270 display side-by-side and watch the figures get updated in both.

Note: For information about basic authentication and other forms of Web security, see CICS Internet Guide, SC34-6245.

138 Java Application Development for CICS

Page 153: Java Application Development for CICS

Figure 7-8 Log in to run TraderPL

The JCICS call Task.getTask().getUSERID() picks up this user ID, and TRADERPJ continues seamlessly with security enabled.

Since there is no explicit way of closing an authenticated Web session in CICS, the browser window must be closed to perform a logoff.

7.3 Migrating TRADERBL to JCICSA Web front-end introduces an application to a world-wide client base. Originally, the COBOL legacy application was probably written for an intended user base of no more than a few hundred people; through the Web this could become millions. Knowing this, it may be the case that the back-end code might not handle as well when scaled up to this factor. In anticipation of this, the approach is to re-implement the back-end using JCICS and separate out the logic and data access functionality into two components. Then should the need require, the data access can be migrated to a DB2 back-end or even a workload balanced solution.

Note: For enhanced levels of Web security refer to CICS RACF Security Guide, SC34-6249.

Chapter 7. Evolving a legacy application using Java 139

Page 154: Java Application Development for CICS

Figure 7-9 Migrating the back-end to JCICS

7.3.1 Mapping COBOL to JavaInstead of re-architecting the code in a pure object-oriented (OO) setup, the alternative is to re-code it with a procedural Java equivalent, that is, to write Java in a procedural and not OO manner. In this way, should a problem occur in the code, then it can be debugged through comparison with the original working COBOL version.

Fundamentally, COBOL was designed to be written in a human understandable form, so reading the code is just like reading an instruction manual. By migrating the back-end logic to Java you will get an understanding of how the languages can be mapped.

Working storageThe first section in TRADERBL is the working storage; the various COBOL data structures defined in it can be categorized as:

� Error messages� Input/output buffers� Constants� Conversion fields� Miscellaneous

TRADERPL

PresentationLogic

COMMAREA

TRADERPL

PresentationLogic

COMMAREA

TRADERBL

BusinessLogic

BMS

Companyfile

Customerfile

3270

TRADERPJ

JCICS Web Presentation

Logic

COMMAREA

HTTP

WebClient

Java

TRADERPL

PresentationLogic

COMMAREA

TRADERBJ TRADERPL

PresentationLogic

TraderDataAccess

VSAM

TRADERBLCOMMAREA

Java

JCICSBusiness

Logic

Note: Converting COBOL to an object-oriented Java setup is possible, but requires a complete understanding of the code. This may not be a trivial task, since if there is a lot of code, there is also a lot to understand.

Attention: To understand this section better it might be useful to print out the COBOL source code. You can find the TRADERBL source code in Appendix D, “Program listings” on page 203.

140 Java Application Development for CICS

Page 155: Java Application Development for CICS

Error messagesThese are used to feed debug information to the user. The COMPANY-NOT-FOUND message is shown in Example 7-11. Conveniently these map directly to Java static constants, as can be seen in Example 7-12 on page 142.

Example 7-11 The company not found message

03 COMPANY-NOT-FOUND-MSG.05 FILLER PIC X(25) VALUE 'COMPANY #CCCCCCCCCCCCCCCC'.05 FILLER PIC X(25) VALUE 'CCC NOT FOUND '.

Input/output buffersThe following data areas are used to read and write data using CICS API:

� CUSTOMER-IO-BUFFER� COMPANY-IO-BUFFER� COMMAREA-BUFFER

With the same approach as “Wrapping the COMMAREA” on page 124, the classes CustomerIOWrapper and CompanyIOWrapper are written and the class CommareaWrapper is reused from SimpleTraderPL. These become instance variables in TraderBL, as shown in Example 7-12 on page 142.

ConstantsVarious constants are defined to represent return values for actions in the code. The same values were used in TraderPL and so will be reused here to minimize code and alleviate any potential errors when passing the values between TraderPL and TraderBL. The TraderConstants class was first mentioned in “SimpleTraderPL” on page 127.

Conversion fieldsOne of the powerful features of COBOL is its ability to convert between and format multiple data types. The conversion fields in TRADERBL, a sample of which is shown in Example 7-21 on page 147, show how data areas can be redefined to allow convenient conversions between character-based numeric types.

To replicate this behavior in Java you can either:

� Wrap the conversion fields using the approach in “Wrapping the COMMAREA” on page 124, and implement specific conversion and formatting rules in the various getters and setters.

� Utilize the powerful conversion and formatting facilities available to Java.

To reduce the number of wrapper classes, and fundamentally the amount of code, TraderBL uses the second option and inserts explicit Java code to perform the conversions; see Example 7-22 on page 147 for an example of this.

MiscellaneousWhat remains are helper values that can easily be mapped to Java types and instantiated as local variables when needed. The tracing fields are not implemented since Java exception data will provide enough information about problems.

Putting it togetherFollowing a similar naming convention to TraderPL, the Java code for the back-end is in the class TraderBL. The Java version of the working storage is shown in Example 7-12 on page 142.

Chapter 7. Evolving a legacy application using Java 141

Page 156: Java Application Development for CICS

Example 7-12 TraderBL’s equivalent to WORKING-STORAGE

private static final String COMPANY_NOT_FOUND_MSG ="COMPANY #CCCCCCCCCCCCCCCCCCC NOT FOUND"; // (1)

private static final String REQUEST_NOT_FOUND_MSG = "REQUEST CODE OF #RRRRRRRRRRRRRR INVALID";

private static final String SUB_FUNCTION_NOT_FOUND_MSG = "FUNCTION BUY/SELL CALLED WITH AN INVALID SUBCODE";

private static final String OVERFLOW_MSG ="OVERFLOW WHEN CALCULATING SHARE VALUE";

private static final String TOO_MANY_SHARES_MSG ="CUSTOMER TRIED TO SELL MORE SHARES THAN THEY OWN";

private static final String NO_SHARES_MSG = "CUSTOMER HAS NO SHARES TO SELL IN SELECTED COMPANY";

private static final String VALIDATE_MSG ="VALIDATING COMPANY #CCCCCCCCCCCCCCCCCCC";

private static final String TOO_MANY_MSG ="TOO MANY SHARES REQUESTED, MAX OWNERSHIP IS 9999";

private final CommareaWrapper fCommareaWrapper = new CommareaWrapper();private final CustomerIOWrapper fCustomerIOWrapper = new CustomerIOWrapper();private final CompanyIOWrapper fCompanyIOWrapper = new CompanyIOWrapper();

Note on Example 7-12:

1. A further expansion would be to externalize these strings and provide internationalized versions that can returned depending on the language preference in the HTTP header.

Abstracting the data accessWith the wrappers written, we have everything needed to design the data access interface. There are five sections in the COBOL program that use file access for retrieving data. They are replaced with a call to an object that implements the Java interface TraderDataAccess. This interface, shown in Example 7-13, provides an individual method for each type of data access required in the program.

As Java does not have an equivalent to EIBRESP, the methods return the type int, which contains the response value. If a class that implements the interface does not directly support these values then it should map them back to ensure compatibility with TraderBL. The response values used in TraderBL are included as static constants, and DFHRESP_UNKNOWN is used for values that are not listed.

An implementation of this interface for VSAM data access is discussed in “Using TraderBL with VSAM” on page 148.

Example 7-13 The TraderDataAccess interface

public interface TraderDataAccess {public static final int DFHRESP_UNKNOWN = -1; public static final int DFHRESP_NORMAL = 0; public static final int DFHRESP_NOTFND = 13;

public int getCompanyNames(CommareaWrapper wrapper, String key);

142 Java Application Development for CICS

Page 157: Java Application Development for CICS

public int readCustfile(CustomerIOWrapper wrapper, String key);public int readCustfileForUpdate(CustomerIOWrapper wrapper, String key);public int writeCustfile(CustomerIOWrapper wrapper, String key);public int readCompfile(CompanyIOWrapper wrapper, String key);public int rewriteCustfile(CustomerIOWrapper wrapper); // (1)

}

Note on Example 7-13 on page 142:

1. Does not need a key since the file should already be opened from a previous readCustfileForUpdate() call.

Main sectionThis is the equivalent of public static void main() in a Java class; that is, it gets executed upon startup of the program. Since TraderBL is written procedurally to reflect the COBOL code, this is the likely place to put the MAINLINE section. Observing the recommended approach (2.3.2, “Continuous JVM” on page 19), the code instead is placed in TraderBL’s constructor and the object instantiated from this method. This minimizes the need for static variables.

To allow for pluggable data access, a class that implements the TraderDataAccess interface is passed to the object constructor as well as the supplied COMMAREA data.

Example 7-14 Instantiating the TraderBL object in the main method

public static void main(CommAreaHolder commAreaHolder) {new TraderBL(commAreaHolder, new TraderVSAMAccess()); // (1)

}

Note on Example 7-13 on page 142:

1. For more information about TraderVSAMAccess see “Using TraderBL with VSAM” on page 148.

Mainline sectionIn TRADERBL the MAINLINE section evaluates the request passed in the COMMAREA and executes the relevant code section before exiting the program.

Writeq-TSAt the start of MAINLINE, and in many places throughout the code, messages are sent to a TSQ by moving text to a variable and then calling WRITEQ-TS. In the Java implementation this is collapsed to a single call to writeMessage() and the message passed as a parameter. Similar to WRITEQ-TS, the text is formatted and pre-pended with a timestamp. Instead of having separate sections for doing, this they are included in-line instead.

For convenience, the message is output to Java’s stdout instead of a TSQ. This allows an unlimited length log to be used. Should you still want the output in a TSQ, then this can be done using the fully supported temporary storage JCICS API discussed in 6.8, “Using transient storage queues” on page 94.

Example 7-15 The writeMessage() method

private void writeMessage(String comment) {

Note: Not all EXEC CICS calls have a JCICS equivalent. In some cases, such as EXEC CICS ASKTIME, you will need to implement a Java equivalent.

Chapter 7. Evolving a legacy application using Java 143

Page 158: Java Application Development for CICS

// Get a time stampfinal String timeStamp = new SimpleDateFormat("h:mm:ss a").format(new Date());

// If they exist, replace fields in the comment with COMMAREA values comment =

comment.replaceFirst("#CCCCCCCCCCCCCCCCCCC", fCommareaWrapper.getCompanyName());

comment = comment.replaceFirst("#RRRRRRRRRRRRRR", fCommareaWrapper.getRequestType());

comment = comment.replaceFirst("#UUUUUUUUUUUUUU", fCommareaWrapper.getUserId().substring(0, 15));

comment = comment.replaceFirst("#R", fCommareaWrapper.getReturnValue());

// Remove spaces from the commentcomment.trim();

// Original wrote to TSQ, for Java we'll use stdout System.out.println(timeStamp + " TraderBL: " + comment);

}

Evaluate statementEvaluate statements in COBOL allow for multiple outcomes to be coded dependant on a variable’s value, as shown in Example 7-16.

Example 7-16 A COBOL evaluate statement

EVALUATE REQUEST-TYPEWHEN GET-COMPANY-REQ

PERFORM GET-COMPANYWHEN SHARE-VALUE-REQ

PERFORM GET-SHARE-VALUEEND-EVALUATE.

The Java equivalent to evaluate statements are switch statements, the only difference being that switch statements are limited to integer-based or character-based comparisons and so cannot be used with string-based values. Instead, a series of if-then-else statements can be used; this is shown in Example 7-17 on page 145.

Perform <section>Depending on the request type, different actions are performed in the evaluate statement, as shown in Example 7-16. The PERFORM GET-COMPANY call executes code that resides in the GET-COMPANY section. In Java this equates to calling a method with return type void. So any PERFORM <section> calls in the COBOL code are converted such that PERFORM GET-COMPANY becomes getCompany().

Tip: Use tail -f <filename> to continually display Java stdout or stderr in a ssh or telnet terminal.

Tip: Good practice for Java string comparisons is to call equals on the constant and not the variable (for example, CONSTANT.equals(astring)). This protects against null pointer exceptions should astring be set to null.

144 Java Application Development for CICS

Page 159: Java Application Development for CICS

Putting it togetherFollowing the directions discussed so far, the MAINLINE code in TraderBL becomes the code shown in Example 7-17.

Example 7-17 The TraderBL constructor

private final TraderDataAccess fTraderDataAccess; // (1)

public TraderBL(CommAreaHolder commAreaHolder, TraderDataAccess traderDataAccess) {// Set the traderDataAccess referencefTraderDataAccess = traderDataAccess;

writeComment("Entry");

// Get the commarea byte[] and put in wrapperfCommareaWrapper.setByteArray(commAreaHolder.value);

// Evaluate the request typefinal String requestType = fCommareaWrapper.getRequestType();

if (TraderConstants.GET_COMPANY_REQ.equals(requestType)) getCompany();else if (TraderConstants.SHARE_VALUE_REQ.equals(requestType)) getShareValue();else if (TraderConstants.BUY_SELL_REQ.equals(requestType)) buySell();else {

fCommareaWrapper.setReturnValue(TraderConstants.UNKNOWN_REQUEST);writeComment(REQUEST_NOT_FOUND_MSG);

}

writeComment("Exit");

// EXEC CICS RETURN END-EXEC // (2)}

Notes on Example 7-17:

1. This holds a reference to the pluggable data access component passed in during object construction.

2. See the following note.

Get companyThe GET-COMPANY section is the first to include file access functionality. It also has a few other commands worth mentioning.

MoveTo move a value into a variable is to set its value. In Java this is the same as using the = operator. Pay close attention to the code, since COBOL will implicitly convert values according to the data type they are being inserted into. In Java this needs to be done explicitly. Also, double check the value you are setting, since sometimes it is not obvious

Note: COBOL allows the hyphen character (-) in identifiers, while Java does not. The Java convention is to use inner capitalization, so GET-COMPANY in COBOL becomes getCompany() in Java.

Note: There is no JCICS equivalent to EXEC CICS RETURN. Java programs running in CICS should always run to the end and terminate cleanly to allow for appropriate cleanup.

Chapter 7. Evolving a legacy application using Java 145

Page 160: Java Application Development for CICS

which wrapper the variable is in and you might need to check the working-storage section for clarification.

Perform varyingAlthough not used in the Java version of getCompany(), since file access is abstracted out to a TraderDataAccess implementation, it is still worth mentioning the PERFORM VARYING command. This is a flexible statement that is essentially the super set of the Java iteration statements, that is, both for and while loops can be represented with the PERFORM statement. The main identifier as to whether a for loop or a do while loop should be used are the WITH TEST BEFORE and WITH TEST AFTER modifiers, respectively. The default action is to use WITH TEST BEFORE.

The Java versionWith the use of the pluggable data access component, the Java getCompany() method becomes substantially smaller than the COBOL version.

Example 7-18 The getCompany() method

private void getCompany() {fCommareaWrapper.setCompanyName("");

fTraderDataAccess.getCompanyNames(fCommareaWrapper);}

Calculate shares boughtThe CALCULATE-SHARES-BOUGHT section shown in Example 7-19 takes the number of shares bought and adds it to the amount of shares owned. Both these numbers are character-based numerics. By looking at a specific character in the total value, it is determined whether there is an overflow.

Example 7-19 The calculate-shares-bought section

CALCULATE-SHARES-BOUGHT SECTION.ADD NO-OF-SHARES-DEC TO DEC-NO-SHARES GIVING SHARES-WORK1EVALUATE SHARES-OVERFLOW

WHEN 0MOVE SHARES-NORMAL TO NO-OF-SHARES-DECMOVE SHARES-NORMAL TO DEC-NO-SHARESPERFORM UPDATE-BUY-SELL-FIELDS

WHEN OTHERMOVE INVALID-BUY TO RETURN-VALUEMOVE TOO-MANY-MSG TO COMMENT-FIELDPERFORM WRITEQ-TS

END-EVALUATE.

CALCULATE-SHARES-BOUGHT-EXIT. EXIT.

As mentioned in “Conversion fields” on page 141, COBOL can convert and format values implicitly based on their definitions. Building on this, it also allows basic arithmetic to be performed on values that differ in type; that is, character-based numbers can be added or subtracted to binary-based numbers without the user having to implement additional conversion code.

In Java, the share values are stored internally as strings, so numeric addition is not directly possible. Instead, the numbers are converted to integers, using the Integer.parseInt() method, and then added together. To determine if the value has overflowed, the integer total

146 Java Application Development for CICS

Page 161: Java Application Development for CICS

is evaluated using an if statement. This gives the calculateSharesBought() method shown in Example 7-20.

Example 7-20 The calculateSharesBought() method

private void calculateSharesBought() {int sharesWork =

Integer.parseInt(fCommareaWrapper.getNoOfSharesDec()) +Integer.parseInt(fCustomerIOWrapper.getDecNoShares());

if (sharesWork <= 9999) {fCommareaWrapper.setNoOfSharesDec("" + sharesWork); // (1)fCustomerIOWrapper.setDecNoShares("" + sharesWork);updateBuySellFields();

}else {

fCommareaWrapper.setReturnValue(TraderConstants.INVALID_SALE_OR_BUY);writeMessage(TOO_MANY_MSG);

}}

Note on Example 7-20:

1. To insert the values into the wrappers they are converted to strings first. The Java compiler implicitly converts ““ + sharesWork to new String(sharesWork).

Calculate share valueThis is where values are moved between different data types to perform arithmetic operations and number formatting. The code in Example 7-21 allows a number to be inserted into NUM-VALUE, replacing any leading spaces with the 0 character. When CHAR-VALUE is referenced it picks up this number formatting.

Example 7-21 COBOL values used for conversions

03 CONVERSION-FIELDS.05 CHAR-VALUE.

07 CHAR-INT-PART PIC X(09).07 FILLER PIC X VALUE '.'.07 CHAR-DEC-PART PIC X(02).

05 NUM-VALUE REDEFINES CHAR-VALUE.07 NUM-INT-PART PIC 9(09).07 GUB92 PIC X.07 NUM-DEC-PART PIC 9(02).

Since arithmetic in Java is done using binary-based numbers, the DecimalFormat class is used to format it similar to the COBOL code. The result is placed in the COMMAREA wrapper.

Example 7-22 Formatting a number as a string

final DecimalFormat decimalFormat = new DecimalFormat("000000000.00");fCommareaWrapper.setTotalShareValue(decimalFormat.format(totalShareValue));

HousekeepingIt is most likely that TRADERBL is an application that has evolved over many years. Through writing its JCICS equivalent you will notice that various statements have been commented out, and sections such as BUY-SELL-UPDATE are no longer used by the presentation layer. This allows for a little spring cleaning, and so redundant code is removed along the way.

Chapter 7. Evolving a legacy application using Java 147

Page 162: Java Application Development for CICS

7.3.2 Using TraderBL with VSAMThe result of “Mapping COBOL to Java” on page 140 gives us a JCICS version of TRADERBL that has a pluggable interface for accessing the client and company data. To access the VSAM data, the class TraderVSAMAccess is used, which implements the TraderDataAccess interface. This gives direct access to the existing VSAM data using the JCICS file access API.

The VSAM data access componentThe methods that need implementing are shown in Example 7-13 on page 142. Each method takes as a parameter a wrapper data area within which to return the results, and a key for accessing a specific record. Similar to the REWRITE-CUSTFILE COBOL code, rewriteCustfile() does not take a key since the file must already have been opened using a readCustfileForUpdate() call. Example 7-23 shows CICS file access code from the READ-COMPFILE section in TRADERBL.

Example 7-23 File access code in the read-compfile section

EXEC CICS READFILE('COMPFILE')INTO(COMPANY-IO-BUFFER)LENGTH(LENGTH OF COMPANY-IO-BUFFER)RIDFLD(COMPANY-NAME OF COMMAREA-BUFFER)NOHANDLE

END-EXEC

Since TraderVSAMAccess is explicitly written to access the files CUSTFILE and COMPFILE, the file names are stored inside the class as static constants. The appropriate value is then set on the JCICS KSDS object to access the data, as shown in Example 7-24.

Example 7-24 The readCompfile() method

public int readCompfile(CompanyIOWrapper wrapper, String key) {int result = DFHRESP_NORMAL;

final RecordHolder recordHolder = new RecordHolder();final KSDS ksds = new KSDS();

ksds.setName(COMPFILE);

try { ksds.read(key.getBytes(), recordHolder); wrapper.setByteArray(recordHolder.value);

}catch (RecordNotFoundException e) { result = DFHRESP_NOTFND; }catch (Exception e) {

result = DFHRESP_UNKNOWN; System.err.println("Exception: " + e); e.printStackTrace();

}

return result;}

All the methods in TraderVSAMAccess are implemented similar to this, using the JCICS file API. Observe that, as specified in the design, no business logic is performed in this class; it is solely used to provide access to the VSAM data files.

148 Java Application Development for CICS

Page 163: Java Application Development for CICS

7.3.3 Setting up TraderBL

Follow these instructions to install and run TraderPL with TraderBL as the back-end.

InstallationThe source code and compiled classes for this example are in Trader-2.jar. Following the instructions in Chapter 4, “Setting up CICS to run Java applications” on page 41, make sure this jar file replaces Trader-1.jar in the CICS Java classpath. In CICS, run the command CEMT SET JVMPOOL PHASE to phase out any JVMs that still may reference the old code.

Re-define the existing TRADERBL CICS resource definition such that it has the following properties:

� PROGRAM(TRADERBL)CONCURRENCY(Threadsafe)JVM(Yes)JVMCLASS(com.ibm.itso.sg245275.trader.TraderBL)

Run CEMT SET PROGRAM(TRADERBL) NEWCOPY to pick up the new program definition.

Running TraderBLSince there is no change to the front-end code, bring up a Web browser and type in the URL:

http://wtsc66.itso.ibm.com:5275/cics/cwba/traderpj

Ensure the port number matches up to that in your TCPIPSERVICE definition and that the program name at the end is traderpj.

You will see the same results as shown in Figure 7-6 on page 137. This time, however, the back-end code being driven is that of the Java class TraderBL. To prove this, look at Java’s stdout to observe the various messages output during the run. Example 7-25 shows the message’s output for a getCompany() call.

Example 7-25 Messages for a getCompany() call

12:07:49 PM TraderBL: Entry12:07:49 PM TraderBL: Entry to GET-SHARE-VALUE12:07:49 PM TraderBL: Reading record from customer file12:07:49 PM TraderBL: Reading record from company file12:07:49 PM TraderBL: Building return commarea12:07:49 PM TraderBL: Exit

Now try the same thing with the original 3270 front-end. Nothing appears to have changed, but by watching the Java stdout messages you can see that the TraderBL implementation of the business logic is being driven under the covers instead.

Congratulations. You have migrated your COBOL legacy application to a JCICS environment with a scalable back-end.

7.4 Moving to a DB2 back-endWith the Web interface and JCICS back-end in place, the next stage is to replace the existing VSAM data setup with a DB2 implementation. The pluggable design implemented in

Note: Before deploying your newly developed back-end on a live system, ensure it has been thoroughly tested against sample or replica data.

Chapter 7. Evolving a legacy application using Java 149

Page 164: Java Application Development for CICS

“Migrating TRADERBL to JCICS” on page 139, combined with an understanding of DB2 JDBC, aids this in being a trivial task.

Figure 7-10 Implementing a DB2 back-end

7.4.1 Data migrationThe client and company data in the VSAM files are stored as flat data; databases, on the other hand, generally store elements in structured columns.

Database tablesThe data in the VSAM file COMPDATA is broken down into the columns shown in Table 7-1.

Table 7-1 The TRADER_COMPANY table

TRADERPL

PresentationLogic

COMMAREA

BMSCompany

file

Customerfile

3270

TRADERPJ

JCICS Web Presentation

Logic

COMMAREA

HTTP

WebClient

Java

TRADERPL

PresentationLogic

COMMAREA

TRADERBJ TRADERPL

PresentationLogic

TraderDataAccess

DB2

TRADERBLCOMMAREA

Java

TraderDataAccess

VSAM

DB2

Datamigration

JCICSBusiness

Logic

Column name Column type Length Nulls

name Character 20 No

unitprice Double 8 No

price1dayago Double 8 No

price2daysago Double 8 No

price3daysago Double 8 No

price4daysago Double 8 No

price5daysago Double 8 No

price6daysago Double 8 No

150 Java Application Development for CICS

Page 165: Java Application Development for CICS

Similarly, the data in the VSAM file CUSTDATA is stored using the columns shown in Table 7-2.

Table 7-2 The TRADER_CUSTOMER table

The TRADER_CUSTOMER table contains the minimum fields required to perform share transactions.

Data migration SQLTo simplify the data migration in this example, the company information is manually inserted into the appropriate table using the SQL statements shown in Example 7-26. The client information is not migrated, and so all share holdings are reset to zero. For a real-life migration, one might consider the CICS VSAM Transparency tool for transferring the data; see http://www.ibm.com/software/htp/cics/vt/ for more information about this tool.

Example 7-26 SQL statements for inserting the data into TRADER_COMPANY

INSERT INTO TRADER_COMPANY VALUES('Casey_Import_Export',79, 77, 78, 72, 70, 65, 63, 59, 100, 0);

INSERT INTO TRADER_COMPANY VALUES('Glass_and_Luget_Plc',19, 22, 25, 20, 16, 20, 22, 17, 200, 0);

INSERT INTO TRADER_COMPANY VALUES('Headworth_Electrical',124, 131, 133, 133, 133, 137, 138, 141, 300, 0);

INSERT INTO TRADER_COMPANY VALUES('IBM',163, 163, 162, 160, 161, 159, 156, 157, 400, 0);

7.4.2 Using TraderBL with DB2With the pluggable architecture discussed in “Abstracting the data access” on page 142, the act of moving TraderBL to a DB2 back-end involves creating a Java class that implements the TraderDataAccess interface. The class, called TraderDB2Access, provides implementations of the methods shown in Example 7-13 on page 142, which perform DB2 calls for accessing the data.

Opening and closing the database connectionA common function shared amongst the methods in TraderDB2Access is that of opening and closing a DB2 connection. The code for this is put into two utility methods, as shown in Example 7-27.

Example 7-27 The openConnection() and closeConnection() methods

private Connection fConnection = null; // (1)

price7daysago Double 8 No

sellcommission Double 8 No

buycommission Double 8 No

Column name Column type Length Nulls

username Character 8 No

companyname Character 20 No

sharesheld Decimal 19,0 No

Column name Column type Length Nulls

Chapter 7. Evolving a legacy application using Java 151

Page 166: Java Application Development for CICS

private int openConnection() {int result = DFHRESP_NORMAL;

try {final String jdbcUrl = "jdbc:default:connection"; // (2)

fConnection = DriverManager.getConnection(jdbcUrl);fConnection.setAutoCommit(false);

}catch (Exception e) {

result = DFHRESP_UNKNOWN; System.err.print("Exception: " + e); e.printStackTrace();

}

return result;}

private int closeConnection() {int result = DFHRESP_NORMAL;

try {fConnection.close();fConnection = null;

}catch (Exception e) {

result = DFHRESP_UNKNOWN; System.err.print("Exception: " + e); e.printStackTrace();

}

return result;}

Notes on Example 7-27 on page 151:

1. Holds a reference to the connection object, which is used for database access.

2. The default JDBC connection is used.

The SQL statementsSQL statements are needed to extract and update information in the database tables. For convenience, the SQL is stored as static variables in TraderDB2Access. Use the prepared statement functionality to update the values dynamically.

Example 7-28 SQL to extract and update the data

private static final String SQL_GET_COMPANY_NAMES = "SELECT name FROM trader_company";

private static final String SQL_GET_COMPANY_DATA = "SELECT * FROM trader_company WHERE name=?"; // (1)

private static final String SQL_GET_CUSTOMER_DATA = "SELECT sharesheld FROM trader_customer WHERE username=? AND companyname=?";

private static final String SQL_UPDATE_CUSTOMER_DATA = "UPDATE trader_customer SET sharesheld=? WHERE username=? AND companyname=?";

private static final String SQL_INSERT_CUSTOMER_DATA =

152 Java Application Development for CICS

Page 167: Java Application Development for CICS

"INSERT INTO trader_customer(username, companyname, sharesheld) VALUES(?,?,?)";

Note on Example 7-28 on page 152:

1. Values get inserted into the place of the question mark symbol (?).

Running a queryAll the methods in TraderDB2Access follow the similar pattern:

1. Open database connection.2. Prepare SQL statement.3. Run the query.4. If required, extract the results and insert into supplied data wrapper.5. Close database connection.6. Return response code.

One of the methods, readCompfile(), which implements this structure, is shown in Example 7-29. To see all the methods in TraderDB2Access go to Appendix D, “Program listings” on page 203.

Note that when values are inserted into the CompanyIOWrapper in the readCompfile() method, they need to be formatted first. This is because the original COMPANY-IO-BUFFER did not enforce formatting; instead, the format was picked up from the way the data was stored in the VSAM files. This means the data must be formatted up front using a DecimalFormat object in order to provide data consistency. If COMPANY-IO-BUFFER had specified the format of these values then it would not need to be done here; instead, they would automatically be converted upon insertion.

Example 7-29 The readCompfile() method

public int readCompfile(CompanyIOWrapper wrapper, String key) {int result = openConnection();;

// If everything's ok then get the dataif (result == DFHRESP_NORMAL) {

PreparedStatement prepStmt = null;ResultSet resultSet = null;

try {prepStmt = fConnection.prepareStatement(SQL_GET_COMPANY_DATA);prepStmt.setString(1, key);resultSet = prepStmt.executeQuery(); // (1)

if (resultSet.next()) {final DecimalFormat df1 = new DecimalFormat("00000.00");final DecimalFormat df2 = new DecimalFormat("000");

wrapper.setShareValue(df1.format(resultSet.getDouble("unitprice")));wrapper.setValue1(df1.format(resultSet.getDouble("price1dayago")));wrapper.setValue2(df1.format(resultSet.getDouble("price2daysago")));wrapper.setValue3(df1.format(resultSet.getDouble("price3daysago")));wrapper.setValue4(df1.format(resultSet.getDouble("price4daysago")));wrapper.setValue5(df1.format(resultSet.getDouble("price5daysago")));wrapper.setValue6(df1.format(resultSet.getDouble("price6daysago")));wrapper.setValue7(df1.format(resultSet.getDouble("price7daysago")));wrapper.setCommissionSell(df2.format(resultSet.getDouble("sellcommission")));wrapper.setCommissionBuy(df2.format(resultSet.getDouble("buycommission")));

}else result = DFHRESP_NOTFND; // (2)

Chapter 7. Evolving a legacy application using Java 153

Page 168: Java Application Development for CICS

}catch (SQLException e) {

result = DFHRESP_NOTFND; System.err.print("Exception: " + e); e.printStackTrace();

}finally {

try { resultSet.close();prepStmt.close();

} catch (Exception e) {}}

}

closeConnection();

return result;}

Notes on Example 7-29 on page 153:

1. To retrieve information the executeQuery() method is used. For updating data the executeUpdate() method must be used.

2. If no results were found, then set the response value accordingly.

Plugging in TraderDB2AccessThe final step in the migration is to replace the code in TraderBL that instantiates a TraderVSAMAccess object with that of a TraderDB2Access object. The swap works seamlessly since both classes implement the TraderDataAccess interface.

Example 7-30 The new main() method in TraderBL

public static void main(CommAreaHolder commAreaHolder) {new TraderBL(commAreaHolder, new TraderDB2Access());

}

You are now ready to try out the DB2 back-end.

7.4.3 Setting up TraderBL with DB2Follow these instructions to install and run TraderPL with TraderBL using DB2 for data access.

InstallationThe source code and compiled classes for this example are in Trader-3.jar. Following the instructions in Chapter 4, “Setting up CICS to run Java applications” on page 41, make sure this jar file replaces Trader-2.jar in the CICS Java classpath. In CICS, run the command CEMT SET JVMPOOL PHASE to phase out any JVMs that still may reference the old code.

Do not forget to set up DB2 as discussed in “Data migration” on page 150.

The new CICS resources that need to be defined alongside the existing definitions in the TRADER group are:

� DB2ENTRY(TRADER)PLAN(DSNJDBC)

154 Java Application Development for CICS

Page 169: Java Application Development for CICS

� DB2TRAN(TRADCOBL)ENTRY(TRADER)TRANSID(TRAD)

� DB2TRAN(TRADJAVA)ENTRY(TRADER)TRANSID(CWBA)

Run CEMT SET PROGRAM(TRADERBL) NEWCOPY to pick up the new program definition that uses the TraderDB2Access object.

Running TraderBLSince there is no change to the front-end code, bring up a Web browser and type in the URL:

http://wtsc66.itso.ibm.com:5275/cics/cwba/traderpj

Ensure the port number matches up to that in your TCPIPSERVICE definition and that the program name at the end is traderpj. You will see the same results as shown in Figure 7-6 on page 137.

Use the Web interface to buy some shares and open up your favorite DB2 query tool. Input and run the following SQL:

SELECT * FROM trader_customer;

The resulting data shows the shares that you just bought. Sample output is shown in Example 7-31.

Example 7-31 Query results

---------+---------+---------+---------+---------+---------USERNAME COMPANYNAME SHARESHELD ---------+---------+---------+---------+---------+---------CICSUSER Glass_and_Luget_Plc 42. CICSUSER Casey_Import_Export 100.

Do the same thing with the original 3270 display to see that the back-end is fully implemented using DB2.

Congratulations. You have migrated your JCICS trader application to a DB2 back-end.

Chapter 7. Evolving a legacy application using Java 155

Page 170: Java Application Development for CICS

156 Java Application Development for CICS

Page 171: Java Application Development for CICS

Chapter 8. Problem determination and debugging

In this chapter we describe some tools and techniques that will help you discover and fix problems in your application or configuration.

The first section describes some of the tools and techniques for problem determination. This section is aimed primarily at CICS systems programmers who are familiar with traditional problem determination tools such as the message, trace, and dump facilities of CICS. We describe some of the additional facilities you can use to gather diagnostics for the JVM.

In the second section, we describe some interactive debugging tools that help an application developer find and correct problems in the Java application.

8

© Copyright IBM Corp. 2005. All rights reserved. 157

Page 172: Java Application Development for CICS

8.1 Debugging and problem determinationThere will be times when your CICS Java application does not display the expected or desired behavior. Your application may:

� Not start at all.� Produce incorrect output.� Enter a loop.� Wait indefinitely for another resource.� Perform badly.� Result in a system message, abend, or dump.

There may be a problem with the application itself that you can discover and correct yourself. The configuration may be in error, preventing the application from executing correctly. Fixing the configuration allows the application to execute as expected.

We will discuss some tools and techniques to help you resolve these issues.

You may encounter a problem with the SDK, LE, or CICS. You will require assistance from IBM to resolve these problems. One aim of this section is to describe how to gather the documentation IBM is likely to require and how to identify which area of IBM support is required.

CICS provides an extensive set of problem determination aids for systems and application programmers. Many of the usual sources of CICS diagnostic information, such as abend codes, error messages, dumps, and trace, can be useful in resolving a CICS Java problem.

However, there are extra considerations when diagnosing a problem in a CICS Java application. Because of the nature of the JVM, you may need to look at diagnostic information from UNIX System Services, Language Environment, and IBM SDK for z/OS.

The Web site below contains useful hints and tips for IBM SDK for z/OS problem solving. You can use this along with other sources of information such as this book and CICS Problem Determination Guide, SC34-6239, to develop a strategy for carrying out problem determination for CICS Java applications.

http://www-1.ibm.com/servers/eserver/zseries/software/java/javafaq.html

The JVMs own diagnostic tools and interfaces give you more detailed information about what is happening within the JVM than CICS can, because CICS is unaware of many of the activities within a JVM. You can download the diagnostics guide for the IBM SDK from:

http://www-128.ibm.com/developerworks/java/jdk/diagnosis/

8.1.1 First considerationsBefore looking in detail at some of the diagnostic tools, we describe some points you should consider if you encounter a problem with CICS Java. There may be a straightforward explanation for the problem. For example, the wrong JVM profile or properties file may have been changed or a typing error may have been made when entering a path to a file or directory. You may save a lot of time by carrying out these initial checks.

Which version of Java are you usingIBM provides regular service updates to the SDK. We recommend that you install the latest service level to take advantage of improved service, performance, and stability. More

158 Java Application Development for CICS

Page 173: Java Application Development for CICS

information about the PTF numbers, build date, and availability can be found on the Java Service Summary Web site:

http://www-1.ibm.com/servers/eserver/zseries/software/java/servicesum14.html

Information APAR II13519 contains a table that lists the SDK service levels and their corresponding PTFs. Table 8-1 shows the SDK 1.4.2 service releases at the time of writing.

Table 8-1 SDK 1.4.2 service releases

Is the JVM failing to startIs the JVM failing to start?

� Does the RACF profile for the CICS region user ID have an OMVS segment?

� Does the directory specified for WORK_DIR exist and does the CICS region user ID have read and write permissions to it?

� Are the path names to the Java directory correct and in sync on the JAVA_HOME and LIBPATH options?

� Does the CICS region user ID have read permission to all directories on the path?

� Is the value specified for the CICS_DIRECTORY correct?

Which JVM mode is in useWhich JVM mode is in use?

� Is the JVM using the expected JVM profile?

� Is the JVM running in resettable or continuous mode?

� Is the JVM using the Shared Class Cache?

� Is the JVM running in the correct key (CICS or USER)?

Has the JVM abendedIf you see the following message in the CICS log, the JVM (or some native code running under the JVM) has abended but all CICS knows is that the call to CEEPIPI has returned an error code.

DFHSJ0203 A call to CEEPIPI with function code CALL_SUB hasfailed. (Return code was - X’0000001C’)

Service release PTF number Build date

SR1a (142) UK00802 20050209

SR1 (142) UQ93743 20040917

Base 1.4.2 UQ90449 20040626

Tip: The system property java.fullversion tells you the build level of the SDK you are using. This is written to the event log along with the other system properties if event logging is enabled.

If you specify the system property com.ibm.cics.showJavaVersion=true, CICS will write message DFHSJ0901 to CSMT when the JVM initializes. The message text contains the Java version (including the build date) used for that invocation of the JVM.

Chapter 8. Problem determination and debugging 159

Page 174: Java Application Development for CICS

You will require assistance from IBM in resolving this type of problem. You will need to gather any diagnostics produced by the JVM. There should be a JAVADUMP in the working directory.

8.2 Where to look when you receive AJ07You receive abend AJ07 when CICS cannot find your program’s main method. This is a very common error and can have several causes:

� Check the name of the main class on the program definition (CEMT INQUIRE PROGRAM), making sure it is spelled correctly.

� Double-check the main class name. It is very easy to miss a typo.

� Check the classpath settings in the JVM profile.

� Make sure your program definition uses the correct JVM profile.

� Check that your main class does actually have a public static void main(String []) or public static void main(CommAreaHolder) method.

� Make sure CICS has access to the directories and files in the classpath (see “Security settings for the CICS region user ID” on page 50).

� When deploying the Java bytecode to the mainframe, make sure it is transmitted in binary mode. SMB server software, such as Samba, can automatically perform character set conversions, based on the file name extension. Make sure no such conversion takes place for .class and .jar files.

� When using file system export from Rational Application Developer, it is a very common mistake to use the “Create directory structure for files” and “Create only selected directories” options inconsistently (especially when using the latter). Check that your .class files ended up on the HFS file system where you want them.

8.3 Where to look for diagnostic informationYou may need to look in many places to gather all the diagnostic information to solve a problem. The various components required to provide CICS Java support will write diagnostics to different locations.

You may find diagnostic information in familiar places:

� MVS console messages� CICS messages written to TD queues or terminal end user� CICS transaction abend codes� CICS trace

You can use standard problem determination techniques in this case. For example, you can look in CICS Messages And Codes, GC34-6442, for an explanation of a CICS message or transaction abend code. A suggested course of action that you can take to resolve the problem might also be included with the explanation. However, for a fault in the JVM you may need to inspect additional diagnostic information. You may get some of this information by default; however, you may have to specify JVM options to obtain the information you need to resolve a problem.

The extra information could come from any of the following:

� Javadumps

160 Java Application Development for CICS

Page 175: Java Application Development for CICS

– Transaction dump - An unformatted dump requested by the MVS IEATDUMP service. This dump can be post-processed with Interactive Problem Control System (IPCS).

– CEEDUMP - Formatted application level dump, requested by the LE service CEE3DMP.

– JAVADUMP - Formatted internal state data produced by the IBM JVM.

� Binary or formatted trace data from the JVM internal high-performance trace

� Debugging messages written to stderr or stdout (for example, the output from the JVM when switches like -verbose:gc, -verbose, or -Xtgc are used)

� Java stack traces when exceptions are thrown

� SVC dumps obtained by the MVS Console DUMP command (typically for loops or hangs)

� Trace data from other products or components (for example, LE traces or the Component trace for z/OS UNIX)

In the following sections we provide more information about the diagnostics that may not be familiar to those from a traditional CICS background.

8.3.1 JavadumpsThe JVM has code to create Javadumps when the JVM terminates or crashes unexpectedly. You can control the code by using environment variables and runtime switches. A Javadump is a file that attempts to summarize the state of the JVM at the instant the signal occurred.

The crash may be the result of an error in JVM code or JNI code. If the error is in JVM code or JNI code supplied by IBM, then you will need to contact IBM for assistance. The information in this section will help you identify the source of the error and to gather the correct documentation for IBM support.

On z/OS, you control the behavior of the Javadump using the JAVA_DUMP_OPTS environment variable. You can specify this variable in your JVM profile.

If you do not specify JAVA_DUMP_OPTS in your profile, CICS uses the following default:

JAVA_DUMP_OPTS=”ONANYSIGNAL(JAVADUMP,CEEDUMP,SYSDUMP),ONINTERRUPT(NONE)”

If a CICS JVM crashes you will get a formatted Javadump, an LE dump, and an unformatted transaction dump.

You can find the full syntax for JAVA_DUMP_OPTS on z/OS in SDK DIagnostics Guide, SC34-6358. You should not need to change the dump options unless advised to do so by IBM support.

If the JVM crashes a JAVADUMP, LE CEEDUMP and Java transaction dump will be produced. Any one of the dumps produced may be enough on its own to find the cause of the problem.

JAVADUMPA JAVADUMP is a formatted text file providing information about the JVM at the time of the failure. The JVM checks each of the following locations for existence and write-permission, and stores the Javadump in the first one available. Note that you must have enough free disk space (possibly up to 2.5 MB) for the Javadump file to be written correctly.

� The location specified by the _CEE_DMPTARG environment variable, if set� The current working directory of the JVM processes� The location specified by the TMPDIR environment variable, if set

Chapter 8. Problem determination and debugging 161

Page 176: Java Application Development for CICS

� The /tmp directory

The file name is JAVADUMP.yyyymmdd.hhmmss.&PID.txt, where PID is the process ID (for example, JAVADUMP.20050330.074905.txt).

Each line of the JAVADUMP starts with a tag. This tag can be used to parse the JAVADUMP.

There is a lot of information contained in a JAVADUMP. There is more information about interpreting a JAVADUMP in SDK DIagnostics Guide, SC34-6358. We provide some of the information you can use to obtain from the JAVADUMP here.

At the top of the file you will find information such as:

� The date and time of the dump

� The build level of the SDK

� The OS level

� The signal that caused the dump to be taken (In Example 8-1, a SIGSEGV (signal 11) has been received.)

Example 8-1 shows the first two sections of a JAVADUMP. Each line of the Javadump starts with a tag that can be up to 15 characters long. This metadata can be used to parse and perform simple analysis of the contents of a Javadump.

Example 8-1 JAVADUMP title and operating environment sections

NULL ------------------------------------------------------------------------0SECTION TITLE subcomponent dump routine NULL =============================== 1TISIGINFO signal 11 received 1TIDATETIME Date: 2005/03/30 at 07:49:05 1TIFILENAME Javacore filename: /tmp/JAVADUMP.20050330.074905.16778293.txt NULL ------------------------------------------------------------------------0SECTION XHPI subcomponent dump routine NULL ============================== 1XHSIGRECV SIGSEGV received at fc1363d8 in (unknown Module) 1XHTIME Wed Mar 30 07:49:05 2005 1XHFULLVERSION JNI J2RE 1.4.2 IBM z/OS Persistent Reusable VM build cm142-20040917 NULL 1XHOPENV Operating Environment NULL --------------------- 2XHHOSTNAME Host : mlp1:10.0.32.42 2XHOSLEVEL OS Level : z/OS V01 R05.00 Machine 2084 Node MLP1 2XHCPUS Processors - 3XHCPUARCH Architecture : (not implemented) 3XHNUMCPUS How Many : (not implemented) 3XHCPUSENABLED Enabled : 4 NULL

You can find the environment variables for the JVM by searching for the tag 2XHENVVARS in the JAVADUMP. This shows the options such as CLASSPATH, CICS_DIRECTORY, and JVMPROPS set in the JVM profile.

The section “Current Thread Details” contains information that will help you identify the failing CICS task and program at the time of the failure. Search for the tag 1XHTHDDETAILS to find this section. The CICS program name, task number, and transaction identifier of the failing task can be found on the line with the tag 2XHCURRENTTHD (see Example 8-2 on page 163).

162 Java Application Development for CICS

Page 177: Java Application Development for CICS

Example 8-2 Current thread information from JAVADUMP

2XHCURRENTTHD "DFJIIRP.TASK14008.CIRP" (sys_thread_t:47b59290)

You will find stack traces throughout the JAVADUMP by searching for the tag 3XHNATIVESTACK. Each stack frame visible contains the name and library of the function involved (this information is not always complete). The failing function will be immediately before the LE error handling routine CEEHRNUH in the stack.

Example 8-3 shows the stack from the CEEPIPI call to invoke the JVM to the failure and LE error handling. In this example the failing function is buildPinnedFreeList in gc_free.c.

Example 8-3 Native stack in JAVADUMP

CEEHDSP CEEHDSP CEEHRNUH CEEHRNUH /u/sovbld/cm142/cm142-20040917/src/jvm/sov/st/msc/gc_free.c buildPinnedFreeList 1406 /u/sovbld/cm142/cm142-20040917/src/jvm/sov/st/msc/gc_mwmain.c gc0_locked 4353 /u/sovbld/cm142/cm142-20040917/src/jvm/pfm/st/msc/gc_md.c gc_locked 74 /u/sovbld/cm142/cm142-20040917/src/jvm/sov/st/msc/gc_mwmain.c gc0 5073 /u/sovbld/cm142/cm142-20040917/src/jvm/sov/st/msc/gc_mwmain.c gcMiddlewareHeap 2000 /u/sovbld/cm142/cm142-20040917/src/jvm/sov/st/msc/gc_main.c gc 699 /u/sovbld/cm142/cm142-20040917/src/jvm/sov/ci/jvm.c JVM_GC 2117 /u/sovbld/cm142/cm142-20040917/src/java/sov/Runtime.c Java_java_lang_Runtime_gc 74 /u/sovbld/cm142/cm142-20040917/obj/mvs390_oe_2/jvm/sov/xe/c_mmi/custom_invokers.c mmipInvoke_V_V 816 /u/sovbld/cm142/cm142-20040917/src/jvm/sov/xe/c_mmi/mmi_invoke_cmmi.c mmipInvokeLazyJniMethod 650 /u/sovbld/cm142/cm142-20040917/src/jvm/sov/xe/c_mmi/mmi_execute.c mmipExecuteJava 2478/u/sovbld/cm142/cm142-20040917/src/jvm/sov/xe/common/run.c xeRunJniMethod 1085/u/sovbld/cm142/cm142-20040917/src/jvm/sov/ci/jni.c jni_CallStaticVoidMethod 507 sjcscall dfhsjcsl @@FECB CEEVROND CEEPIPI CEEPIPI

CEEDUMPThe CEEDUMP is produced after any SYSDUMP processing, but before a JAVADUMP is produced. A CEEDUMP is a formatted summary system dump that shows stack traces for each thread that is in the JVM process, together with register information and a short dump of storage pertaining to each register. The CEEDUMP is written to the CESE transient data queue.

Use the traceback information in the CEEDUMP to find the source of the problem. The entry immediately before the entry for CEEHDSP shows the problem program. CEEHDSP is the LE

Chapter 8. Problem determination and debugging 163

Page 178: Java Application Development for CICS

module responsible for scheduling the CEEDUMP. Example 8-4 shows traceback data from a CEEDUMP.

Example 8-4 CEEDUMP traceback

TRACEBACK: DSA ADDR PROGRAM UNIT PU ADDR PU OFFSET ENTRY E ADDR E OFFSET STATEMENT LOAD MOD SERVICE STATUS 2E63E178 /u/sovbld/hm131s/hm131s-20020723/src/hpi/pfm/threads_utils.c 2EB098A0 +000006AA ThreadUtils_CoreDump 2EB098A0 +000006AA 1662 *PATHNAM h020723 CALL 2E63E068 /u/sovbld/hm131s/hm131s-20020723/src/hpi/pfm/interrupt_md.c 2EAEC108 +000004B0 userSignalHandler 2EAEC108 +000004B0 376 *PATHNAM h020723 CALL 2E63DFB8 /u/sovbld/hm131s/hm131s-20020723/src/hpi/pfm/interrupt_md.c 2EAEC670 +000000B6 intrDispatch 2EAEC670 +000000B6 642 *PATHNAM h020723 CALL 2E63DF00 2DED9938 +0000001A @@GETFN 2DED9890 +000000C2 CEEEV003 CALL 2E63DE80 CEEVASTK 2DCCC420 +00000126 CEEVASTK 2DCCC420 +00000126 CEEPLPKA CALL 2E32BCC0 2DFF2B80 +00000736 __zerros 2DFF2B80 +00000736 CEEEV003 DRIVER9 CALL 2E329128 CEEHDSP 2DC16848 +00000C0C CEEHDSP 2DC16848 +00000C0C CEEPLPKA CALL 2E3286A8 /u/sovbld/hm131s/hm131s-20020723/src/zip/sov/ZipEntry.c 31F6EB38 +00000252 Java_java_util_zip_ZipEntry_initFields 31F6EB38 +00000252 99 *PATHNAM h020723 EXCEPTION 2E3285C8 java/util/zip/ZipEntry.java 32CEE95C +000000E4 java/util/zip/ZipEntry.initFields(J)V 32CEE95C +000000E4 0 CALL

You can change the level of information produced by LE when a JVM crash occurs by overriding the TRAP and TERMTHDACT runtime options in DFHJVMRO. We recommend that you do not override these values unless advised to do so by IBM. The default values set by CICS for the enclave in which the JVM runs are TERMTHDACT(DUMP,,96) and TRAP(ON,NOSPIE).

SYSDUMPA sysdump is captured using the MVS IEATDUMP service. This produces a dataset containing an unformatted transaction dump. You use MVS Interactive Problem Control System (IPCS) to format the dump.

The default name for the dataset produced is &userid.SYSTDUMP.&date.T&time. You can use the environment variable JAVA_DUMP_TDUMP_PATTERN to set your own name.

You will see messages in stderr when the JVM requests a sysdump. Example 8-5 shows the messages we saw. You can see that we use JAVA_DUMP_TDUMP_PATTERN to set our own name for the dump dataset.

Example 8-5 Messages in stderr when a dump is captured

JVMDG217: Dump Handler is Processing Signal 4 - Please Wait.JVMHP002: JVM requesting System Transaction DumpJVMHP012: System Transaction Dump written to PLOWMAN.JVM.TDUMP.COMKZCES.D050419.T231519JVMDG303: JVM Requesting Java core fileJVMDG304: Java core file written to /u/plowman/cics630/workdir/JAVADUMP.20050419.231606.83886118.txtJVMDG215: Dump Handler has Processed Exception Signal 4.

You use IPCS to format the dump. VERBX LEDATA ‘CEEDUMP’ will format the LE traceback information. You can also use the appropriate CICS formatting exit to format CICS data such as the internal trace table. CICS Operations & Utilities Guide, SC34-6431, tells you how to use IPCS to format CICS dumps.

164 Java Application Development for CICS

Page 179: Java Application Development for CICS

8.3.2 JVM stdout and stderrThe JVM and the applications it is running may write data to stdout and stderr. The JVM will write informational and error messages to stdout and stderr. For example, if the JVM abends, messages will be written to stderr. The application itself may write messages to stdout and stderr. These may provide important clues in resolving a problem.

The location of these files is specified in the JVM profile using the options STDOUT and STDERR (“Setting up JVM profiles” on page 53). Look in the JVM profile to find where stdout and stderr are written.

The default names for stdout and stderr are dfhjvmout and dfhjvmerr, respectively. By default they are created in the WORK_DIR directory. You can use your own file name or specify a full path name. Remember, you can also use the symbol &APPLID; in the JVM profile to substitute the CICS region applid in any name at runtime.

The name of the stdout and stderr files may be further modified by using the -generate option in the JVM profile (for example, STDOUT=dfhjvmerr -generate. There must be a space before the -generate). This tells CICS to generate a specific file for the JVM by appending the following information to the specified file name:

region The applid of the CICS region

time The current time in the form yydddhhmmss

.txt A literal string suffix to indicate that the file contains readable data

An example of a generated name is dfhjvmout.SCSCPJA7.05101150145.txt.

We do not recommend using the -generate option in a production environment because it can affect JVM performance. However, you may want to use it in a test environment to keep output from different test cases separate.

8.3.3 Logging events in the JVMYou enable event logging to log actions and events during the lifetime of the JVM. This is particularly useful during development of an application for use in a resettable JVM. Logging of unresettable actions allows the developer to determine why a JVM was flagged as unresettable. Typically the application is tested with full logging enabled to capture all unresettable events (UREs). Once these are fixed, the application can be run in an environment where full logging is not enabled. If a JVM reset fails once the application is deployed then logging can be re-enabled to capture the required diagnostics to determine why the JVM failed a reset action.

You must first enable general event logging in the JVM by using the following system property, which specifies where to log the events, either in a specified file or on one of the standard system output streams.

ibm.jvm.events.output={event.log | path/file_name | stderr | stdout}

Note: The USEROUTPUTCLASS option in the JVM profile specifies the name of a class that is used to redirect output from the JVM. If this option is set in the JVM profile then you will need to know how the specified class deals with output from the JVM. Java Applications in CICS, SC34-6238, contains more information about redirecting JVM output using these classes.

Chapter 8. Problem determination and debugging 165

Page 180: Java Application Development for CICS

If you specify event.log or a file name, the event log is written to WORK_DIR. If you want to store the event log in another directory you can specify a full path name as the value for this property. Make sure the CICS region user ID has write permission to the directory.

Whenever the JVM writes to the event log, an event log file header is written. This header shows the system properties. This can provide vital information for problem determination. Information such as the Java version, classpath, trusted middleware classpath, and shareable application classpath are written to the event log. An example of a header is shown in Appendix C, “Output examples” on page 201.

You must specify additional system properties to log reset events, unresettable actions, reset trace events, and cross-heap events.

Logging reset eventsYou use the system property ibm.jvm.reset.events to log each successful and unsuccessful JVM reset. Example 8-6 shows the output produced by running the HelloCICSWorld sample.

Each event begins with a header [EVENT <eventnum>] and ends with [END EVENT]. Between these is a description, class, thread name, and timestamp. This syntax is used because it is easy to parse.

Example 8-6 JVM reset event logging

[EVENT 0x1]TIME=12/05/2005 at 10:55:51.881THREAD=DFJ$JHE2.TASK479.JHE2 (0:349a7f98)CLASS=ResetJVMEventDESCRIPTION=JVM reset number 1 completed successfully[END EVENT][EVENT 0x1]TIME=12/05/2005 at 10:55:55.227THREAD=DFJ$JHE2.TASK480.JHE2 (0:349a7f98)CLASS=ResetJVMEventDESCRIPTION=JVM reset number 2 completed successfully[END EVENT][EVENT 0x1]TIME=12/05/2005 at 10:55:57.294THREAD=DFJ$JHE2.TASK481.JHE2 (0:349a7f98)CLASS=ResetJVMEventDESCRIPTION=JVM reset number 3 completed successfully[END EVENT][EVENT 0x1]TIME=12/05/2005 at 10:55:59.203THREAD=DFJ$JHE2.TASK482.JHE2 (0:349a7f98)CLASS=ResetJVMEventDESCRIPTION=JVM reset number 4 completed successfully[END EVENT][EVENT 0x1]TIME=12/05/2005 at 10:56:01.333THREAD=DFJ$JHE2.TASK483.JHE2 (0:349a7f98)CLASS=ResetJVMEventDESCRIPTION=JVM reset number 5 completed successfully[END EVENT]

Logging unresettable actionsAn application class must follow a set of rules to avoid making the JVM unresettable. The Persistent Reusable Java Virtual Machine User’s Guide, SC34-6201, describes these rules. If

166 Java Application Development for CICS

Page 181: Java Application Development for CICS

your application does cause a JVM reset to fail then you may need to enable logging of unresettable actions to determine why the JVM became unresettable.

The system property ibm.jvm.unresettable.events.level=(min|max) enables the logging of unresettable events and specifies the level of information recorded in the event record. The minimum level contains only the name of the unresettable action (see Example 8-7). The maximum level also includes a stack trace to help identify the class causing the unresettable action.

Example 8-7 Unresettable action log record with minimum detail

[EVENT 0x1]TIME=12/05/2005 at 13:51:32.555THREAD=URECLAS2.TASK513.CECI (0:349a7fb8)CLASS=UnresettableEventDESCRIPTION=Modified defaultLocale in Locale.setDefault()[END EVENT]

We wrote a class that uses the java.util.Locale.setDefault() method to modify the default locale. If an application uses this method the JVM cannot be reset. (Persistent Reusable Java Virtual Machine User’s Guide, SC34-6201, lists the Java methods that cause a JVM to become unresettable when used by an application class.) The output with minimum event logging enabled is shown in Example 8-7. With the maximum level of output a stack trace is also produced that pinpoints the line of code using Locale.setDefault(). The example shows that method myCICSPrograms.UREClass2.main contains the call to Locale.setDefault.

Example 8-8 Unresettable action log record with maximum detail

[EVENT 0x1]TIME=12/05/2005 at 11:39:49.934THREAD=URECLAS2.TASK495.CECI (0:349a8028)CLASS=UnresettableEventDESCRIPTION=Modified defaultLocale in Locale.setDefault()STACK= at com.ibm.jvm.ExtendedSystem.setJVMUnresettableConditionally0(Native Method) at com.ibm.jvm.ExtendedSystem.setJVMUnresettableConditionally(ExtendedSystem.java:646) at java.util.Locale.setDefault(Locale.java:391) at myCICSPrograms.UREClass2.main(UREClass2.java:17) at java.lang.reflect.Method.invoke0(Native Method) at java.lang.reflect.Method.invoke(Method.java:374) at com.ibm.cics.server.Wrapper.call_main(Wrapper.java:611) at com.ibm.cics.server.Wrapper.callUserClass(Wrapper.java:740) at com.ibm.cics.server.Wrapper.main(Wrapper.java:1277)[END EVENT]

Logging reset trace and cross-heap eventsOne of the checks that must be performed prior to resetting the transient heap is to see whether there are any live references from objects in the middleware heap to objects in the transient heap (a cross-heap reference). Sometimes a reference is found from a middleware object to a transient heap object, but it is unclear whether the middleware object is still active. In this case, the JVM initiates a trace-for-unresettability check (reset trace) to determine whether such references are live. This may not necessarily result in the JVM becoming unresettable, but the check is expensive and may not be desirable.

By logging reset trace and cross-heap events you will be able to identify where the links between the middleware object and transient object is set up. You can then correct the code to remove the link.

Chapter 8. Problem determination and debugging 167

Page 182: Java Application Development for CICS

To enable logging of reset trace events and cross-heap events, you specify the system properties ibm.jvm.resetttrace.events and ibm.jvm.crossheap.events. You also need to turn off the JIT compiler to get the cross-heap reference events. You turn off the JIT compiler using system property java.compiler=NONE.

Chapter 7 of Persistent Reusable Java Virtual Machine User’s Guide, SC34-6201, lists some scenarios that may lead to a reset trace event and unresettable event. To demonstrate the scenario where there is a direct link from a live middleware object to an instance of an application object, we code a simple Java class. The class assigns a PrintWriter application object directly to the static variable fixedOutForJVMLifetime of the middleware Task class. We run the class in a resettable JVM with logging enabled. The JVM cannot be reset because of the live cross-heap reference.

Example 8-9 shows the event records logged for the unresettable event. You need to match the URE event with the corresponding cross-heap event. This is very simple case so it is easy to spot. The link must be made in myCICSPrograms.UREClass.main.

Example 8-9 Unresettable event due to live cross-heap reference

[EVENT 0x1]TIME=12/05/2005 at 15:07:46.747THREAD=URECLASS.TASK526.CECI (0:349a8128)CLASS=CrossHeapReferenceEventDESCRIPTION=Transient or Shared heap object(0x435FBC88) being referenced in Middleware heap at 0x3D3895A8. 0x435FBC88 is an instance of java/io/FileOutputStreamSTACK= at java.lang.ref.Reference.constructReference(Reference.java:209) at java.lang.ref.Reference.<init>(Reference.java:231) at java.lang.ref.FinalReference.<init>(FinalReference.java:31) at java.lang.ref.Finalizer.<init>(Finalizer.java:85) at java.lang.ref.Finalizer.register(Finalizer.java:91) at myCICSPrograms.UREClass.main(UREClass.java:27) at java.lang.reflect.Method.invoke0(Native Method) at java.lang.reflect.Method.invoke(Method.java:374) at com.ibm.cics.server.Wrapper.call_main(Wrapper.java:611) at com.ibm.cics.server.Wrapper.callUserClass(Wrapper.java:740) at com.ibm.cics.server.Wrapper.main(Wrapper.java:1277)[END EVENT][EVENT 0xf]TIME=12/05/2005 at 15:07:46.881THREAD=URECLASS.TASK526.CECI (0:349a8128)CLASS=UnresettableEventDESCRIPTION=0x435FBBB8 is an instance of java/io/PrintWriter from 0x35B3B940, field fixedOutForJVMLifetime in com/ibm/cics/server/Task[END EVENT]

You may have many more event records in the log. There will be many cross-heap reference events that are no longer valid (that is, they have already been nulled out), so the main task is to match the address in a reset trace event (or unresettable event) with a corresponding cross-heap event. Ideally, you will want to sort this event log into groups, headed by each reset trace event, where each group lists all the cross-heap events that might be associated.

8.3.4 JVM method tracingMethod trace is a powerful tool that allows you to trace method entry and exit in any Java code. You do not have to add any hooks or calls to existing code. Using method trace provides a complete (and potentially large) diagnosis of code paths inside your application

168 Java Application Development for CICS

Page 183: Java Application Development for CICS

and also inside the system classes. Use wild cards and filtering to control method trace so that you can focus on the sections of code that interest you.

You control method trace by specifying system properties. All the method trace properties are of the format ibm.dg.trc.<something>. The set of these properties is quite large and is fully described in SDK DIagnostics Guide, SC34-6358.

If you want method trace to be formatted, set two properties:

� ibm.dg.trc.print: Set this property to ’mt’ to invoke method trace. � ibm.dg.trc.methods: Set this property to decide what to trace.

Use the methods parameter to control what is traced. To trace everything, set it to methods=*.*. This is not recommended because you are certain to be overwhelmed by the amount of output. The methods parameter is formally defined as follows:

ibm.dg.trc.methods=[[!]method_spec[,...]]

Where method_spec is formally defined as:

{*|[*]classname[*]}.{*|[*]methodname[*]}[()]

Note that the delimiter between parts of the package name is a forward slash (/). The exclamation point (!) in the methods parameter is not an operator that allows you to tell the JVM not to trace the specified method or methods. The parentheses () that are in the method_spec define whether to trace method parameters.

The formatted trace output is written to stderr.

We traced the method calls in the HelloCICSWorld sample program by setting the properties ibm.dg.trc.print=mt and ibm.dg.trc.methods=examples/HelloWorld/HelloCICSWorld.*(). Example 8-10 shows the information written to stderr. Message JVMDG200 shows the diagnostics properties set. The HelloCICSWorld class only has a main method so the output shows entry and exit to main.

Example 8-10 Formatted method trace in stderr

JVMDG200: Diagnostics system property ibm.dg.trc.print=mtJVMDG200: Diagnostics system property ibm.dg.trc.methods=examples/HelloWorld/HelloCICSWorld.*()JVMDG200: Diagnostics system property ibm.jvm.events.output=event.log10:11:59.353*0x349A8280 40011 > examples/HelloWorld/HelloCICSWorld.main Bytecode static method, Signature: (Lcom/ibm/cics/server/CommAreaHolder;)10:11:59.355 0x349A8280 40022 < examples/HelloWorld/HelloCICSWorld.main Bytecode static method

Writing trace data to stderr in realtime is fine for low volume and non-performance-critical instances. For larger volumes and performance-critical tracing you should not write formatted output to stderr. You can direct unformatted trace output to in-storage buffers or to one or more external files using buffered I/O.

Writing trace to buffersThe use of in-storage buffers for trace is a very efficient method of running trace because no explicit I/O is performed until either a problem is detected, or an API is used to snap the buffers to a file. To examine the trace data, you must snap or dump, then format the buffers. Buffers are snapped when:

� An uncaught Java exception occurs.� An operating system signal or exception occurs.� The com.ibm.jvm.Trace.snap() Java API is called.� The JVMRI TraceSnap function is called.

Chapter 8. Problem determination and debugging 169

Page 184: Java Application Development for CICS

The resulting snap file is placed in the current working directory with a name in the format Snapnnnn.yyyymmdd.hhmmssth.process.trc, where nnnn is a sequence number starting at 0001 (at JVM startup), yyyymmdd is the current date, hhmmssth is the current time, and process is the process identifier.

You use the ibm.dg.trc.buffers system property to specify the size of the buffers allocated for each thread that makes trace entries. See SDK DIagnostics Guide, SC34-6358, for more information.

Writing trace to an external fileYou can write trace data to a file continuously as an extension to the in-storage trace, but, instead of one buffer per thread, at least two buffers per thread are allocated. This allows the thread to continue to run while a full trace buffer is written to disk. Depending on trace volume, buffer size, and the bandwidth of the output device, multiple buffers might be allocated to a given thread to keep pace with trace data that is being generated.

A thread is never stopped to allow trace buffers to be written. If the rate of trace data generation greatly exceeds the speed of the output device, excessive memory usage might occur and cause out-of-memory conditions. To prevent this, use the nodynamic option of the ibm.dg.trc.buffers system property. For long-running trace runs, a wrap option is available to limit the file to a given size. See the ibm.dg.trc.output property in SDK DIagnostics Guide, SC34-6358, for details. You must use the trace formatter to format trace data from the file.

Formatting traceThe trace formatter is a Java program that runs on any platform and can format a trace file from any platform. The formatter, which is shipped with the SDK in core.jar, also requires a file called TraceFormat.dat, which contains the formatting templates. This file is shipped in jre/lib.

You invoke the trace formatter by typing:

java com.ibm.jvm.format.TraceFormat input_filespec [output_filespec] [options]

Where com.ibm.jvm.format.TraceFormat is the traceformatter class, input_filespec is the name of the binary trace file to be formatted, and output_filespec is the optional output file name. If it is not specified, the default output file name is input_filespec.fmt.

8.3.5 JVM class loader tracingThe z/OS Persistent Reusable JVM used by CICS has three classpaths on which classes can be included:

� Trusted middleware class path� Shareable application class path� Standard class path

There is a class loader for each of these class paths. The status of a class within the JVM is dictated by its class loader. If a class is loaded by the wrong class loader, the behavior of the application could change. For example, a JVM could become unresettable.

Note: Because of the buffering of trace data, if the normal JVM termination is not performed, residual trace buffers might not be flushed to the file. Snap dumps do not occur, and the trace bytes are not flushed except when a fatal operating-system signal is received. The buffers can, however, be extracted from a system dump if that is available.

170 Java Application Development for CICS

Page 185: Java Application Development for CICS

There could be a large number of class and jar files on the classpaths, and you may not be able to easily identify on which classpath a class is included. JVM class loader tracing allows you to find out which class loader is responsible for loading a class.

You enable class loader tracing by specifying the system property ibm.verbose.cl in the properties file for the JVM. The output is written to stdout. You can trace loading for just one class or for many classes. You can use wildcard characters in the class name. For example:

� ibm.cl.verbose=examples.HelloWorld.HelloCICSWorld� ibm.cl.verbose=examples.HelloWorld.HelloCICSWorld,com.ibm.cics.server.Task� ibm.cl.verbose=com.ibm.cics.server.T*

We trace the loading of the sample CICS class HelloCICSWorld by adding ibm.cl.verbose=examples.HelloWorld.HelloCICSWorld to the systems properties file for the JVM. The output is shown in Example 8-11. The output shows that HelloCICSWorld is loaded by the standard Java class loader. You can also find out in which jar file or directory the class was found.

Example 8-11 JVM class loader trace output

ExtClassLoader attempting to find examples.HelloWorld.HelloCICSWorldExtClassLoader using classpath /usr/lpp/java142s/J1.4/lib/ext/dumpfmt.jar:/usr/lpp/java142s/J1.4/lib/ext/gskikm.jar:/usr/lpp/java14rExtClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/lib/ext/dumpfmt.jarExtClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/lib/ext/gskikm.jarExtClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/lib/ext/ibmjcefips.jarExtClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/lib/ext/ibmjceprovider.jarExtClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/lib/ext/ibmjce4758.jarExtClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/lib/ext/ibmjsseprovider2.jarExtClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/lib/ext/ibmpkcs11impl.jarExtClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/lib/ext/indicim.jarExtClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/lib/ext/jaccess.jarExtClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/lib/ext/ldapsec.jarExtClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/lib/ext/oldcertpath.jarExtClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/lib/ext/recordio.jarExtClassLoader could not find examples.HelloWorld.HelloCICSWorld

MiddlewareClassLoader attempting to find examples.HelloWorld.HelloCICSWorldMiddlewareClassLoader using classpath /SYSTEM/cicsts/cics630/lib/dfjcicsras.jar:/SYSTEM/cicsts/cics630/lib/ras.jar:/SYSTEM/cicsts/crMiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/dfjcicsras.jarMiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/ras.jarMiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/dfjwrap.jarMiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/dfjorb.jarMiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/dfjcont.jarMiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/dfjcsi.jarMiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/dfjcics.jarMiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/dfjcdmn.jarMiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/dfjjts.jarMiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/dfjadjr.jarMiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/omgcos.jarMiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/dfjname.jarMiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/websphere.jarMiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/dfjcci.jarMiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/ctg/ctgclient.jarMiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/ctg/ctgserver.jarMiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/ctg/ccf.jarMiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/dfjejbdd.jarMiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/standard/ejb/2_0/ejb20.jarMiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/standard/jta/1_0_1/jta-specrMiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/standard/jca/connector.jarMiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/db2710/db2710/jcc/classes/db2jcc.jarMiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/db2710/db2710/jcc/classes/db2jcc_javax.jarMiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/db2710/db2710/jcc/classes/db2jcc_license_rMiddlewareClassLoader could not find examples.HelloWorld.HelloCICSWorld

AppClassLoader attempting to find examples.HelloWorld.HelloCICSWorldAppClassLoader using classpath /u/plowman/cics630/myprogs/myCICSPrograms.jar:/u/plowman/cics630/samples/dfjcics:/u/plowman/cics630/sAppClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /u/plowman/cics630/myprogs/myCICSPrograms.jarAppClassLoader found examples/HelloWorld/HelloCICSWorld.class in /u/plowman/cics630/samples/dfjcicsAppClassLoader found examples.HelloWorld.HelloCICSWorld

Note: The fully qualified class name must be specified.

Chapter 8. Problem determination and debugging 171

Page 186: Java Application Development for CICS

8.4 Interactive debuggingIn this section we discuss interactive debugging.

8.4.1 Execution diagnostic facilityYou can use the execution diagnostic facility (EDF) to test an application program online, without modifying the program or the program-preparation procedure. The CICS execution diagnostic facility is supported by the CICS-supplied transaction, CEDF.

EDF intercepts the execution of CICS commands in the application program at various points, allowing you to see what is happening. Each command is displayed before execution, and most are displayed after execution is complete. Screens sent by the application program are preserved, so you can converse with the application program during testing, just as a user would on a production system.

CICS Application Programming Guide, SC34-6231, has more information about EDF and user instructions for EDF.

When used with a JCICS program, CEDF intercepts the CICS commands invoked by the Java Native Interface (JNI) programs, which provide the interface between JCICS classes and CICS. There may not be an obvious relationship between the JCICS class method and the CICS command. For example, the HelloCICSWorld sample uses the Task.out.println method to send a message to the user terminal. The JNI program invokes the SEND command to write to the screen. Example 8-12 shows the line of Java source code to write to the screen (t is an instance of Task) and the image from CEDF showing the intercepted SEND command.

Example 8-12 Writing to the screen using Task.out.println method

Task.getTask().out.println("Hello from a Java CICS application");

TRANSACTION: JHE2 PROGRAM: DFJ$JHE2 TASK: 0006530 APPLID: SCSCPJA7 DISPLAY: 00 STATUS: ABOUT TO EXECUTE COMMAND EXEC CICS SEND FROM ('.A&Hello from a Java CICS application..') LENGTH (39) NOHANDLE

8.4.2 Java Platform Debugger ArchitectureThe JVM in CICS supports the Java Platform Debugger Architecture (JPDA), which is the standard debugging mechanism provided in the Java 2 Platform. This architecture provides a set of APIs that allow the attachment of a remote debugger to a JVM. A number of third-party debug tools are available that exploit JPDA and can be used to attach to and debug a JVM that is running a Java program. Typically, the debug tool provides a graphical user interface that runs on a workstation and allows you to follow the application flow, setting breakpoints and stepping through the application source code, as well as examining the values of variables.

Note: You can also invoke CEDF indirectly through another CICS-supplied transaction, CEDX, which enables you to specify the name of the transaction you want to debug. When this section refers to the CEDF transaction (for example, when it explains about CICS starting a new CEDF task below) remember that it may have been invoked by the CEDX command.

172 Java Application Development for CICS

Page 187: Java Application Development for CICS

When you start the JVM in debug mode, the JVMDI interface is activated and additional threads are started in the JVM. One of these threads handles communication with the remote debugger; the others monitor the application that is running in the JVM. You can issue commands in the remote debugger, for example, to set break points or to examine the values of variables in the application. These commands are activated by the listener and event handler threads in the JVM.

We use the debugger provided in IBM Rational Software Development Platform to show how to attach a debugger to a CICS JVM. We chose the CICS-supplied JCICS sample program HelloCICSWorld as the application to be debugged.

JVM profile changesTo run a JVM in debug mode and allow a JPDA remote debugger to be attached, you need to set some options in the JVM profile for the JVM.

� Xdebug=YES

This is needed to start the JVM in debug mode (that is, with the JPDA interfaces active).

� Xrunjdwp=(suboption=...,suboption=...)

This option specifies the details of the connection between the debugger and the CICS JVM. These details include the TCP/IP address to be used for the connection, and the sequence in which connection occurs. Different debuggers have different connection requirements and capabilities; refer to the documentation provided with the debugger.

We specify the following suboptions for the connection between IBM Rational Software Development Platform and the CICS JVM.

Xrunjdwp=(transport=dt_socket,server=y,address=9876)

This set of suboptions specifies that:

– The standard TCP/IP socket connection mechanism is used. – The JVM starts first (server=y) and waits for the debugger to attach to it. – The CICS JVM listens on TCP/IP port 9876 for a debugger to attach to it.

� REUSE=NO

A JVM that has been run in debug mode is not a candidate for reuse. Set this option to NO to ensure that the JVM is discarded after the debug session.

When you set these options in a JVM profile, any CICS JVM program that uses that profile runs in debug mode (and waits for attach from, or attempts to attach to a debugger). You should therefore ensure that the JVM profile applies only to programs that you wish to debug.

Instead of configuring any of the CICS-supplied sample profiles for debug, you should create a separate JVM profile specifically for debug use, and set the appropriate CICS PROGRAM resource definition to use this debug JVM profile.

We recommend copying the existing JVM profile to a new file and adding the options to enable remote debugging. Change the PROGRAM definition to use the new profile. This ensures that the JVM options (which will influence the behavior of the Java application) are identical.

Important: Never configure for debug the JVM profiles that are involved with the Shared Class Cache; that is, the JVM profiles for worker JVMs that specify CLASSCACHE=YES and the JVM profile for the master JVM that initializes the Shared Class Cache. JVM debugging is not supported for shared classes, and if you configure these JVM profiles for debug, CICS ignores your setting.

Chapter 8. Problem determination and debugging 173

Page 188: Java Application Development for CICS

CICS resource definition changesYou must specify the name of the JVM profile with the debug options set in the PROGRAM definition for the Java application you wish to debug.

For our example, we use CEDA to copy PROGRAM(DFJ$JHE2) from GROUP(DFH$JVM) to our own group. We modify the PROGRAM definition and install the new group.

You could also change the profile name temporarily using the expanded CEMT INQ PROGRAM display.

IBM Rational Software Development Platform configurationWe use the debugger in IBM Rational Software Development Platform. Refer to your product documentation if you are using a different development platform.

The source code for the application you wish to debug must be loaded into the IBM Rational Software Development Platform. We use one of the CICS-supplied JCICS samples in our example so we create a new Java project called JCICS Samples and a new package called examples.HelloWorld (this must match the package name in the JCICS sample). We then create a new Java class called HelloCICSWorld and import the source code. The source code is in /usr/lpp/cicsts/cicsts23/samples/dfjcics/examples/HelloWorld/HelloCICSWorld.java.

Figure 8-1 on page 175 shows the Java perspective within IBM Rational Software Development Platform displaying the JCICS Samples project. The package explorer pane on the left shows the project, package, and class hierarchy. It also shows dfjcics.jar on the build path. The center pane shows the source code of HelloCICSWorld. We have set a breakpoint at line 23 of the source. This is indicated by the blue button to the left of the pane. Hovering over the button displays the text shown. Double clicking in the left-hand edge of the pane toggles a line breakpoint on and off.

Note: You need to add dfjcics.jar to the Java build path for your project.

174 Java Application Development for CICS

Page 189: Java Application Development for CICS

Figure 8-1 JCICS Samples project

You must create a Remote Java Application configuration within the Debug Perspective that specifies:

� The IP address (or host name) of the z/OS system that hosts the CICS region.

� The TCP/IP port number that the CICS JVM is using. (This is the same number specified to CICS on the Xrunjdwp option in the JVM profile.)

� That a standard TCP/IP socket connection (Socket Attach) is to be used.

To open the “Create, manage and run” configuration window, click the arrow to the right of the icon in the toolbar to display the pull-down menu and then click the icon in the menu.

The window in Figure 8-2 on page 176 is displayed.

Debugging the applicationYou are now ready to start the interactive debugging session.

Enter the transaction identifier on CICS to run the Java program to be debugged. For our example, we enter JHE2. This will start the JVM in debug mode. Your terminal session will hang. The JVM is waiting for the connection from the remote debugger.

Start the debug configuration created previously in the IBM Rational Software Development Platform. The debugger connects to the JVM in CICS, the debug perspective opens, and you can start debugging. Figure 8-3 on page 177 shows the debug perspective. From the debug perspective you can step through the code of your class, inspect and change variables, and set new breakpoints. If the source code is available, you can also debug interactively other classes invoked during execution of your application program.

Chapter 8. Problem determination and debugging 175

Page 190: Java Application Development for CICS

Figure 8-2 Configuring remote Java application

8.4.3 The CICS JVM plug-in mechanismIn addition to the standard JPDA debug interfaces in the JVM, CICS provides a set of interception points (or plug-ins) in the CICS Java middleware, which can be of value to developers of debugging applications. These interception points allow additional Java programs to be inserted immediately before and after the application Java code is run. Information about the application (for example, classname and method name) is made available to the plug-in programs. The plug-in programs can also use the JCICS API to obtain information about the application. These interception points can be used in conjunction with the standard JPDA interfaces to provide additional CICS-specific debug facilities. They can also be used for purposes other than debugging, in a similar way to user exit points in CICS.

The programming interface consists of two Java interfaces.

DebugControl Defines the method calls that can be made to a user-supplied implementation

Plugin Provides a general purpose interface for registering the plug-in implementation

These interfaces are supplied in dfjwrap.jar, and documented in JAVADOC HTML.

These plug-ins are not described further in this book. Refer to Java Applications in CICS, SC34-6238, for more information.

Attention: Be careful to keep the byte code and the source code in sync, that is, make sure that you re-export the byte code to the host after changing the source code on the development workstation.

176 Java Application Development for CICS

Page 191: Java Application Development for CICS

Figure 8-3 Debug perspective

Chapter 8. Problem determination and debugging 177

Page 192: Java Application Development for CICS

178 Java Application Development for CICS

Page 193: Java Application Development for CICS

Chapter 9. Performance for Java in CICS TS V2

In this chapter we first look at the Continuous JVM, describing this in detail. We look at the potential problems and the things you need to avoid that may impact performance. We recommend that you review Chapter 20, “Java applications using a Java virtual machine (JVM): improving performance,” of the CICS Performance Guide, for some good performance tips.

9

© Copyright IBM Corp. 2005. All rights reserved. 179

Page 194: Java Application Development for CICS

9.1 Reusable JVMIn this section we discuss reusable JVM.

CICS TCBs and the JVMCICS has a small number of Task Control Blocks (TCBs), which it uses when running application programs. Of these, the Quasi Reentrant (QR) TCB is used to single thread the entire workload. At any point in time there may be a number of transactions running in a CICS region. Only one of these will have use of the QR TCB at any time. If that application needs to pause for some reason, for example, when writing to a data set or waiting for a resource lock, it becomes suspended by CICS. This allows another applications to gain control of the QR TCB and carry out some work. This permits CICS to serialize the execution of all the applications it has concurrently running, preventing the actions of one from interfering with those of any others.

This mechanism was developed for applications written in fully compiled languages such as COBOL, PL/1, or C. However, the introduction of support for Java programs presented some additional challenges, which CICS has had to address.

Pure Java requires an execution environment provided by a JVM written for the operating system on which it runs. On z/OS, a JVM can sometimes issue blocking calls, such as MVS waits, which cause the TCB used by the JVM to go into a wait state. If a JVM was started on the QR TCB, then blocking calls would cause the entire CICS workload to pause. To address this issue, CICS TS 1.3 introduced a new type of TCB, known as the J8 TCB. CICS uses one of these for each JVM it starts. As we will see later, with CICS TS V2.3 there is now a J9 TCB as well.

The JVM that is used by CICS supports multithreaded applications. However, only one application can run in a JVM at any one time. More than one TCB can be used when a single CICS region has to support multiple concurrent Java applications. In this way a CICS region can have a single pool of J8 and J9 TCBs to support its Java workloads.

All new CICS transactions start on the QR TCB. If the transaction makes use of a Java program, then CICS switches to either a J8 or a J9 TCB and runs the program under the control of a JVM there. When the program terminates, or if it needs to access a CICS-managed resource, then CICS switches control back to the QR TCB for that piece of processing. In this way the JVM can pause without interrupting the rest of the CICS workload, so serialization of access to CICS resources and the management of the start and end of all transactions is done using the QR TCB.

9.1.1 The Reusable JVMThere are significant CPU costs in starting and stopping a JVM. Often these are greater than those incurred from the running of an application within a JVM. If a JVM can be serially reused by a number of CICS programs, then the overhead of starting and stopping the JVM is confined to the first and last program in the sequence, and those in between gain significant performance benefits from this.

However, if a JVM is reused then the potential exists for one Java application program to leave around objects whose state may interfere with the successful execution of programs that later reuse the same JVM. EJBs are inherently self-contained and as such cannot leave state around after their execution. Individual Java applications, on the other hand, tend to treat the JVM where they run as something to which they have exclusive use. They may assume that the JVM will be destroyed when the application finishes, and that all object

180 Java Application Development for CICS

Page 195: Java Application Development for CICS

instances, created during program execution, will be removed as a result of the termination of the JVM. This assumption is not valid when a JVM is serially reused and side effects, resulting from objects remaining in the JVM’s storage heap following the termination of one application, may interfere with other applications that later reuse the same JVM.

To address this issue, the IBM Development Kit for z/OS, Java 2 Technology Edition (SDK) provides a JVM with a modified heap structure; this JVM can be driven in an attempt to reset its storage areas between separate program invocations. CICS TS V2 can be configured to make use of this mechanism. Reset processing extends the operation of the JVM but does have some adverse effect on its performance characteristics.

Not all applications cause these problems and, for them, this reset processing is an unnecessary overhead. CICS TS V2.3 and the SDK 1.4.1 provide support for another JVM configuration, which offers the potential for reuse, but which places responsibility for reset processing onto the applications that run there. This provides significant performance benefits but does present opportunities for badly behaved programs to interfere with others that reuse the same JVM.

9.2 Shared Class Cache facilityIn this section we discuss the Shared Class Cache facility.

The Shared Class Cache facility We begin by providing an overview of the Shared Class Cache and then we describe the benefits of using it.

OverviewThe SDK V1.4 provides a mechanism that allows Java classes to be cached centrally and shared between different JVMs. CICS TS V2.3 introduces a Shared Class Cache facility, which extends this function to some, or all, of the JVMs that it controls. See Figure 9-1.

Figure 9-1 One view of the Shared Class Cache

WorkerN JVMWorker1 JVMMaster JVM

Shared Memory

Nonsystem Heap

System Heap

Nonsystem Heap

NonsystemHeap

ACSH

JIT compiled code

JIT compiled code

Chapter 9. Performance for Java in CICS TS V2 181

Page 196: Java Application Development for CICS

The collection of JVMs that use this facility is referred to as a JVMset. This consists of a single JVM, known as the master, whose role is to manage the Shared Class Cache, together with other JVMs, called workers, which service individual Java requests. These requests can be to run a Java program, an EJB, or an IIOP application. Figure 9-2 shows another view of the relationship between master and worker JVMs within a CICS region’s JVM pool; in this figure DFHJVMPR, DFHJVMPC, USERJVM1, and USERJVM2 are the names of JVM profiles.

Figure 9-2 Another view of the Shared Class Cache

A CICS region can only have a single active Shared Class Cache that uses this feature. CICS controls the launching of the master JVM and any workers that are needed to service requests to run Java components. Individual worker JVMs in a JVMset can have different characteristics, defined in their associated JVM profiles and JVM properties files. These may be used to define the size of a JVM’s storage heaps, to set the trace options it uses, or to add some security controls.

Some characteristics of a JVMset are common to all of its JVMs. They are taken from the JVM profile of the master JVM and include the REUSE option discussed earlier. A master JVM is potentially long-lived and as such must be started in either resettable or continuous mode. The master JVM cannot be configured with REUSE=NO and, as a result, worker JVMs cannot run in this mode either. Figure 9-3 on page 183 shows a master JVM running with REUSE=RESET. Therefore, the worker JVMs must also run with REUSE=RESET. However, the standalone JVMs (JVM8 and JVM10) may run with any of the REUSE options.

J9 TCB

J8 TCB

J8 TCB

J9 TCB

Availablefor reuse

Allocatedto task

Allocatedto task

Allocatedto task

DFHJVMPRUser key

USERJVM1CICS key

USERJVM2CICS key

DFHJVMPCUser key

JVM PoolMAXJVMTCBS=5

JVM6JVM10

JVM9

JVM8

Sharedclass cache

JM TCB

MasterJVM

DFHJVMCCUser key

J9 TCB

Availablefor reuse

DFHJVMPCUser key

JVM7worker

worker

worker

182 Java Application Development for CICS

Page 197: Java Application Development for CICS

Figure 9-3 REUSE and the Shared Class Cache

Benefits of using the Shared Class CacheThe Shared Class Cache facility offers a number of benefits to clients. Java classes are loaded once per CICS region rather than once per JVM, reducing the class loading overhead for all the workers in a JVMset. It also reduces the overall storage requirement for the JVMset, by having one copy of each class in the cache area, instead of one in each worker JVM’s storage heap. Because worker JVMs run in either resettable or continuous mode they receive the performance benefits described earlier, when the JVM is reused for a number of programs. Early internal IBM testing showed that startup for worker JVMs is at least 60 percent better than for CICS TS V2.2 standalone JVMs, and the storage footprint is down by over 30 percent.

9.3 Things to avoidThis section looks at the potential problems and the things you need to avoid that may impact performance. These include:

� Unresettable events

– JVM has to restart. This is relatively expensive.– The application runs using None JITed Code.– The code has to be JITed again after frequent usage. (The method is run about 2000

times.)

� Application abends that are not handled

– JVM becomes unresettable.

� JVM stealing

– JVM has to restart. This is similar in cost to becoming unresettable.

� Reset Trace Events

– This is an expensive reset at the transaction end.

� CICS Master Trace flag being set on

– If this is not required, make sure it is set off at JVM startup.

JVM PoolMAXJVMTCBS=5

Sharedclass cache

Allocatedto task

USERJVM3REUSE=YES

JVM10

Availablefor reuse

USERJVM2REUSE=NO

JVM8

Allocatedto task

DFHJVMPCREUSE=RESET

JVM6

Allocatedto task

USERJVM1REUSE=RESET

JVM9

MasterJVM

DFHJVMCCREUSE=RESET

Availablefor reuse

DFHJVMPCREUSE=RESET

JVM7

Chapter 9. Performance for Java in CICS TS V2 183

Page 198: Java Application Development for CICS

– Turning off inflight helps, but not completely.

� Using Application Classpath

– Use the Shareable classpath; otherwise classes are physically reloaded each time.

� Excessive garbage collection

– Make sure heaps are big enough for 101 trans when CICS does GC anyway.

9.3.1 Unresettable Event Unresettalbe events:

� High CPU usage by transactions� High JVMITIME in CICS Monitoring records� Set JVM properties

If an application is using a resettable JVM, you need to make sure that the Java programs are not performing unresettable actions, because this causes the JVM to be destroyed instead of being reset, which greatly reduces the performance of your application. In the CICS statistics for JVM profiles, the field “Number of times JVMs were unresettable for this profile” shows the number of unresettable JVMs for each JVM profile and execution key. If the statistics show that there were unresettable JVMs for a JVM profile that specifies the option REUSE=RESET, then it is probable that some of the applications requesting that JVM profile are performing unresettable actions. You can identify those applications by looking at byte 6, bit 0 of the transaction flags field, TRANFLAG (field 164 in group DFHTASK), in the CICS performance class monitoring record for each transaction.

To determine the cause of an unresettable event, you need to specify a value for ibm.jvm.events.output in the JVM properties file; this value will tell the JVM where to log three kinds of events:

� Unresettable events� Reset trace events� Cross heap events

Then you must specify a value of min or max for ibm.jvm.unresettable.events.level in the JVM properties file to enable the logging of unresettable events and to specify the level of logging detail. The event types are documented in the manual Persistent Reusable Java Virtual Machine User’s Guide, SC34-6201.

9.3.2 JVM stealingIf a JVM is required to execute a Java program, then CICS will choose to reuse a JVM not currently in use but initialized with the same JVM profile as the new request.

If no such JVM is available and the CICS region is not a MAXJVMTCB, then CICS will attach a new J8 TCB and initialize a new JVM.

If no such JVM is available and the CICS region is at MAXJVMTCB, then CICS will steal a currently unused JVM; but because this JVM is not using the same profile, it must be reinitialized.

If all the MAXJVMTCB JVMs were being used, then the new request would have to wait for a JVM to become available.

J8 TCBs used for Java do not come out of the MAXJVM pool; JVM Pool is separate.

184 Java Application Development for CICS

Page 199: Java Application Development for CICS

Figure 9-4 JVM stealing

9.3.3 Reset trace eventsThe existence of references from a middleware object to an object in the transient heap causes a reset trace event. When the JVM finds one of these references, it has to determine if the middleware object that contains it is actually dead and hence eligible for garbage collection. This process is expensive in terms of CPU costs. If the middleware object is actually alive, the JVM is marked unresettable. Figure 9-5 shows an example of an active cross heap reference.

Figure 9-5 Active cross heap reference

Figure 9-6 on page 186 shows an example of an inactive cross heap reference.

JVM Stealing

Not-in-useJVM withmatching profile?

Yes

Reuse JVM

No At MaxJVM TCB?

No Init a newJVM to match

JVM with other profilenot-in-use?

Yes

Yes

Steal andreinitialiseit

No Wait for anavailable JVM

High TCB Mismatch in CICS Stats

Middleware heap

Transient heap

Object A Object B

Object D

Object C

Active cross heapreference found at reset

JVM reset fails andJVM destroyed

Chapter 9. Performance for Java in CICS TS V2 185

Page 200: Java Application Development for CICS

Figure 9-6 Inactive cross heap reference

Figure 9-7 No heap cross references

Setting ibm.jvm.resettrace.events=on will log the presence of these traces at reset time and indicate the object that has the reference.

Setting ibm.jvm.crossheap.events=on will only work when the JVM is in debug mode and will trace every time a cross heap reference is actually created. Many of these trace entries will be innocent, as they may well have been set to null by the time the reset happens. The trick here is to match up the reset trace event to the rogue cross heap reference event. The cross heap reference entry will have a stack trace to identify the creator.

Figure 9-6 shows an example of the message written to the ibm.jvm.events.ouput destination in response to the detection of a reset trace event. The event types are documented in Persistent Reusable Java Virtual Machine User’s Guide, SC34-6201.

In this example, 0x1 is a RESETTRACEEVENT_REFERENCE_TO_TH condition. A middleware object contained a current reference to an application object when a reset was requested and it is necessary to determine whether the middleware object is live or unreferenced.

Middleware heap

Transient heap

Object A Object B

Object D

Object C

Inactive cross heapreference found at reset

JVM reset ok but costly

Nulledreference

Middleware heap

Transient heap

Object A Object B

Object D

Object C

No cross heapreferences found at reset

JVM reset okNo performance hit

Nulledreference

186 Java Application Development for CICS

Page 201: Java Application Development for CICS

Figure 9-8 Example of a reset trace event message

9.3.4 Using application classpathClass path is where we have put out application programs on the Classpath and not the Shareable classpath.

Figure 9-9 Classpath problems

9.3.5 Excessive garbage collectionExcessive garbage collection:

� CICS forces GC every 101 transactions per JVM.

� When heaps are too small:

– Additional GC is triggered.– This shows as a spike in JVMRTIME.

� Use VERBOSE=GC to investigate.

� More details on GC and heap sizing are provided later.

� The base is a normal, well-performing, small Java application.

� GC is where the heap is too small to support 101 transactions, so there is additional garbage collection going on.

[EVENT 0x1]TIME=14/03/2001 at 12:03:58.439THREAD=TRGQIIRP.TASK29685.TRGQ (0:17129580)CLASS=ResetTraceEventDESCRIPTION=0x18C24D70 is an instance of zc01/_callcobolImplfrom address 0x1809Fd80 within obj or array at 0x1809FD78.0x1809FD78 is an instance of vendor/io/ObjectClass/cache[END EVENT]

0 200 400 600 Transactions per Second

0

20

40

60

80

100

Tot

al C

PU%

(of 1

eng

ine)

No JITBase

Too much GCJava tracing

Steal 1:500Classpath

Debug=Yes

Things to avoid

Ave CPU per tranBase 1.67msGC (heap too small)

2.14ms

No JIT 2.66msDebug 23.5msJava tracing 3.14msSteal (1:500) 6.47msClass.path 3.04ms

Chapter 9. Performance for Java in CICS TS V2 187

Page 202: Java Application Development for CICS

� No JIT is where java.compile=none has been specified.

� Debug is where USE_LIBJVM_G=YES has been left in the JVM Profile.

� Java tracing is where we have left ibm.dg.trc.maximal=mt in the property file and activated method level java tracing.

� Steal is where we force the JVM to be stolen so that the TCB could be used by another JVM with a different profile.

� Class path is where we have put out application programs on the Classpath and not the Shareable classpath.

9.4 JVM startupJVM startup has improved significantly since CTS 2.2. Worker JVMs are the most efficient. The sharing of classes and JITed means that each JVM does not have to go through the same loading and building process. The use of -xquickstart can also help startup time by only doing a partial compile of Java code at this time. If the code is seen to be used a large number of times, later on it is recompiled to give more efficient JITed code. The initial compile under these circumstances is cheaper but the JITed code is not as efficient to run. Prior to JDK 1.4.1, the second compile would not happen, so although startup was quicker, subsequent runtime would be compromised.

JVM startup time, although expensive, should not be a hindrance in a well-behaved system. Once a JVM is started it should be able to stay initialized for long periods of time, so effectively the startup should be a one-off cost.

� Should be a one-off cost unless:

– JVM is made unresettable.– Stolen.– JVM has timed out through inactivity.

� Significant improvements since 2.2 GA:

– PTFs UQ76199, UQ76243 (CTS 2.2)– Xquickstart in 1.4.1 (CTS2.3)– Worker JVMs (CTS 2.3)

Figure 9-10 on page 189 shows the improvements that have been made to JVM startup within CICS since CTS 2.2 GA. This will vary depending on first application, but this should be a good guide as to what to expect.

188 Java Application Development for CICS

Page 203: Java Application Development for CICS

Figure 9-10 JVM startup

JVM startup

0

0.5

1

1.5

2

2.5

CPU

sec

onds

CTS 2.2 GACTS 2.2 PTFsCTS 2.3 ContCTS 2.3 ResetCTS 2.3 Worker

Chapter 9. Performance for Java in CICS TS V2 189

Page 204: Java Application Development for CICS

190 Java Application Development for CICS

Page 205: Java Application Development for CICS

Part 4 Appendix

Part 4

© Copyright IBM Corp. 2005. All rights reserved. 191

Page 206: Java Application Development for CICS

192 Java Application Development for CICS

Page 207: Java Application Development for CICS

Appendix A. Channels and containers

CICS has always been confined to a 32k COMMAREA limit when passing data between applications. With the release of CICS TS 3.1, a new functionality has been introduced that allows a theoretically unlimited amount of data to be passed between programs. This is the Channels and Containers API.

A channel provides an interface to many containers. Each container can hold character or binary data of an unlimited size, or at least up to where the underlying resource available to CICS is saturated.

Similar to performing an EXEC CICS LINK or an EXEC CICS XCTL with a COMMAREA, the same is used while passing a channel reference, allowing large amounts of data to flow between programs.

In this section you will see examples of how channels and containers are used with the JCICS API.

A

© Copyright IBM Corp. 2005. All rights reserved. 193

Page 208: Java Application Development for CICS

Creating channels and containers in JCICSTo create a channel, use the createChannel() method of the Task class. The string supplied to the createChannel() method is the name by which the Channel object is known to CICS. To create a container in the channel, call the createContainer() method on the Channel object. If a container of the same name already exists in the channel, a ContainerErrorException is thrown. The channel and container names are limited to 16 characters.

Example: A-1 Creating a channel and container

Task task = Task.getTask();Channel custData = task.createChannel("Customer_Data");Container custRec = custData.createContainer("Customer_Record");

Putting data into a containerTo add data to a container use the put() method. The API allows for data to be added as either a byte array or a string.

Example: A-2 Adding data to a container

String custNo = "00054321";byte[] custRecIn = custNo.getBytes();custRec.put(custRecIn);

// Or alternativelycustRec.put("00054321");

Passing a channel to another program or taskSimilar to the ways COMMAREAs can be passed to programs or tasks, the facility to pass a channel instead exists also.

Link and xctlTo pass a channel on a program-link or transfer program control (XCTL) call, use the link() and xctl() methods of the Program class.

Example: A-3 Passing a channel on a link() or xctl()

programX.link(custData);programY.xctl(custData);

Return transidTo set the next channel on a program-return call, use the setNextChannel() method of the TerminalPrincipalFacility class.

Example: A-4 Setting the next channel on a return transid call

terminalPF.setNextChannel(custData);terminalPF.setNextTransaction("TRAD");

194 Java Application Development for CICS

Page 209: Java Application Development for CICS

Start transidTo pass a channel on a START request, use the issue() method of the StartRequest class.

Example: A-5 Passing a channel on a start transid call

startRequest.issue(custData);startRequest.setTransId("TRAD");

Receiving the current channelIt is not necessary for a program to receive its current channel explicitly; see “Browsing the current channel” on page 195. However, a program can get its current channel from the task, enabling it to extract containers by name.

Example: A-6 Getting the current channel explicitly

Task task = Task.getTask();Channel custData = task.getCurrentChannel();

if (custData != null) { Container custRec = custData.getContainer("Customer_Record");} else { System.out.println("There is no Current Channel");}

Getting data from a containerUse the get() method to retrieve the data in a container as a byte array. If you know this data is String data then it can be passed to the String constructor to instantiate as a String. If the data was originally set as character data, then it is returned in the default codepage of the CICS region.

Example: A-7 Getting the data from a container

byte[] custInfo = custRec.get();String custString = new custString(custInfo);

Browsing the current channelA JCICS program that is passed a channel can access all of the Container objects without receiving the channel explicitly. To do this, it uses a ContainerIterator object, which implements the java.util.Iterator interface. The Task object from the current task returns an Iterator for the current channel, or null if there is no current channel.

Example: A-8 Browsing the containers in the current channel

Task task = Task.getTask();ContainerIterator iterator= task.containerIterator();

While (iterator.hasNext()) { Container custData = iterator.next(); // Process the container...

Appendix A. Channels and containers 195

Page 210: Java Application Development for CICS

}

A JCICS exampleExample A-9 shows a Java class called Payroll that calls a COBOL server program named PAYR. The Payroll class uses the JCICS Channel and Container classes to do the same things that a non-Java client program would use EXEC CICS commands to do.

Example: A-9 A JCICS program that passes a channel with containers to another program

import com.ibm.cics.server.*;public class Payroll { ... Task task = Task.getTask();

// create the payroll_2004 channel Channel payroll_2004 = task.createChannel("payroll-2004"); // create the employee container Container employee = payroll_2004.createContainer("employee"); // put the employee name into the container employee.put("John Doe"); // create the wage container Container wage = payroll_2004.createContainer("wage"); // put the wage into the container wage.put("2000"); // Link to the PAYROLL program, passing the payroll_2004 channel Program program = new Program(); program.setName("PAYR"); program.link(payroll_2004); // Get the status container which has been returned Container status = payroll_2004.getContainer("status"); // Get the status information byte[] payrollStatus = status.get(); ...}

196 Java Application Development for CICS

Page 211: Java Application Development for CICS

Appendix B. Hints and tips

Here are some tips through the evolution of what a typical Java program in CICS might look like.

B

© Copyright IBM Corp. 2005. All rights reserved. 197

Page 212: Java Application Development for CICS

Priority of public static void main() methodsCICS allows the use of two alternative main() methods for executing Java programs. They are prioritized as follows:

1. public static void main(CommAreaHolder commAreaHolder)2. public static void main(String[] args)

The first is passed COMMAREA data in a CommAreaHolder, which holds the data in a byte array. If this version of the main() method does not exist, then CICS attempts to call the “typical” second version (note that with this main() method, no data is passed with the arguments and so the supplied String array is empty).

Getting transaction arguments using JavaWhen a Java program in CICS is executed by typing a transaction definition in the terminal, it is possible to pass values after the transaction name for use as parameters in the program. Using the JCICS implementation of EXEC CICS RECEIVE, the terminal data is got as a byte array and wrapped in a String object before returning.

Example: B-1 Return transaction arguments as a String

public static String getTerminalString() {final DataHolder dataHolder = new DataHolder();final Object principalFacility = Task.getTask().getPrincipalFacility();

String result = null;

if (principalFacility instanceof TerminalPrincipalFacility) {try { ((TerminalPrincipalFacility)principalFacility).receive(dataHolder); }catch (EndOfChainIndicatorException e) {}catch (Exception e) { System.err.println(e.toString()); e.printStackTrace(); }

}

return dataHolder.value != null ? new String(dataHolder.value) : null;}

Using this facility you can go a step further and “chop up” the parameters and return them in a String array. The default separating character between the parameters is the “ “ (space) character. Since the transaction name is also part of the String data, this becomes the first element in the array.

Example: B-2 Separate transaction arguments into a String array

public static String[] getTerminalStringAsArray() {String[] result = null;int count = 0;

final String args = getTerminalString();

if (args != null) {final java.util.StringTokenizer tokenizer =

new java.util.StringTokenizer(args, " "); // (1)

result = new String[tokenizer.countTokens()];

while (tokenizer.hasMoreTokens()) result[count++] = tokenizer.nextToken();}

198 Java Application Development for CICS

Page 213: Java Application Development for CICS

return result;}

Notes on Example B-2 on page 198:

1. To include spaces in the resulting string array elements, change ‘ ‘ to something like ’,’.

Never use System.exit()When Java applications are run in CICS, the public static void main() method is called through the use of another Java program called the Java wrapper (that is how functionality like that described in “Priority of public static void main() methods” on page 198 can happen). The use of the wrapper allows CICS to initialize the environment for Java applications, but more importantly, it performs cleanup for any processes that are used during the life of the application. Killing the JVM, even with a “clean” return code of 0, does not allow this cleanup process to run, and may lead to data inconsistency.

From an additional perspective, by using a System.exit() call, the continuous and resettable JVM modes become unusable since it terminates the JVM instance.

The recommended and only approach is to allow the program to run to the end of the public static void main() method and the JVM to terminate cleanly.

Appendix B. Hints and tips 199

Page 214: Java Application Development for CICS

200 Java Application Development for CICS

Page 215: Java Application Development for CICS

Appendix C. Output examples

In this appendix we have included some examples of the event log.

Example: C-1 System properties in the event log

******************* SYSTEM PROPERTIES **********************java.assistive=ONplatform.notASCII=truejava.runtime.name=Java(TM) 2 Runtime Environment, Standard Editionsun.boot.library.path=/usr/lpp/java/J1.4/binjava.vm.version=1.4.2ibm.dg.trc.resettable=onjava.vm.vendor=IBM Corporationjava.vendor.url=http://www.ibm.com/path.separator=:gateway.T.trace=offjava.vm.name=Classic VMfile.encoding.pkg=sun.iosun.os.patch.level=gateway.T.stack=onDB2SQLJJDBCPROGRAM=GMBJDBCgateway.T.exit=offjava.vm.specification.name=Java Virtual Machine Specificationuser.dir=/u/cicsts22/workdirjava.runtime.version=1.4.2java.fullversion=J2RE 1.4.2 IBM z/OS Persistent Reusable VM build cm142sr1a-20050209 (JIT enabled: jitc)java.awt.graphicsenv=sun.awt.X11GraphicsEnvironmentgateway.T=offjava.endorsed.dirs=/usr/lpp/java/J1.4/lib/endorsedos.arch=390com.ibm.vm.bitmode=32java.io.tmpdir=/tmpline.separator=

gateway.T.entry=offjava.vm.specification.vendor=Sun Microsystems Inc.java.awt.fonts=gateway.T.lines=off

C

© Copyright IBM Corp. 2005. All rights reserved. 201

Page 216: Java Application Development for CICS

gateway.T.timing=onos.name=z/OSsun.java2d.fontpath=java.library.path=/usr/lpp/cicsts/cicsts23/lib:/usr/lpp/cicsts/cicsts23/ctg:/usr/lpp/java/J1.4/bin:/usr/lpp/java/J1.4/bin/classic:/SC66/mqm/java/lib/:/usr/libibm.jvm.events.output=event.logjava.class.version=48.0java.specification.name=Java Platform API Specificationibm.jvm.unresettable.events.level=maxibm.system.encoding=Cp1047java.util.prefs.PreferencesFactory=java.util.prefs.FileSystemPreferencesFactoryos.version=01.06.00user.home=/u/cicsts22user.timezone=java.awt.printerjob=sun.print.PSPrinterJobjava.specification.version=1.4file.encoding=Cp1047user.name=CICSTSjava.class.path=/usr/lpp/cicsts/cicsts23/samples/dfjcics:/SC66/mqm/java/lib/com.ibm.mq.jar:/u/cicsts22/jars/Trader-1.jarjava.vm.specification.version=1.0sun.arch.data.model=32java.home=/usr/lpp/java/J1.4java.specification.vendor=Sun Microsystems Inc.user.language=enjava.vm.info=J2RE 1.4.2 IBM z/OS Persistent Reusable VM build cm142sr1a-20050209 (JIT enabled: jitc)java.version=1.4.2java.ext.dirs=/usr/lpp/java/J1.4/lib/extsun.boot.class.path=/usr/lpp/java/J1.4/lib/core.jar:/usr/lpp/java/J1.4/lib/graphics.jar:/usr/lpp/java/J1.4/lib/security.jar:/usr/lpp/java/J1.4/lib/server.jar:/usr/lpp/java/J1.4/lib/xml.jar:/usr/lpp/java/J1.4/lib/charsets.jar:/usr/lpp/java/J1.4/classes:/usr/lpp/java/J1.4/lib/ibmcertpathprovider.jar:/usr/lpp/java/J1.4/lib/ibmjcefw.jar:/usr/lpp/java/J1.4/lib/ibmjgssprovider.jar:/usr/lpp/java/J1.4/lib/ibmjssefips.jar:/usr/lpp/java/J1.4/lib/ibmjsseprovider.jar:/usr/lpp/java/J1.4/lib/ibmorb.jar:/usr/lpp/java/J1.4/lib/ibmorbapi.jar:/usr/lpp/java/J1.4/lib/ibmpkcs.jarjava.vendor=IBM Corporationfile.separator=/java.vendor.url.bug=java.compiler=jitcsun.io.unicode.encoding=UnicodeBigibm.jvm.trusted.middleware.class.path=/usr/lpp/cicsts/cicsts23/lib/dfjcicsras.jar:/usr/lpp/cicsts/cicsts23/lib/ras.jar:/usr/lpp/cicsts/cicsts23/lib/dfjwrap.jar:/usr/lpp/cicsts/cicsts23/lib/dfjorb.jar:/usr/lpp/cicsts/cicsts23/lib/dfjcont.jar:/usr/lpp/cicsts/cicsts23/lib/dfjcsi.jar:/usr/lpp/cicsts/cicsts23/lib/dfjcics.jar:/usr/lpp/cicsts/cicsts23/lib/dfjcdmn.jar:/usr/lpp/cicsts/cicsts23/lib/dfjjts.jar:/usr/lpp/cicsts/cicsts23/lib/dfjadjr.jar:/usr/lpp/cicsts/cicsts23/lib/omgcos.jar:/usr/lpp/cicsts/cicsts23/lib/dfjname.jar:/usr/lpp/cicsts/cicsts23/lib/websphere.jar:/usr/lpp/cicsts/cicsts23/lib/dfjcci.jar:/usr/lpp/cicsts/cicsts23/ctg/ctgclient.jar:/usr/lpp/cicsts/cicsts23/ctg/ctgserver.jar:/usr/lpp/cicsts/cicsts23/ctg/ccf.jar:/usr/lpp/cicsts/cicsts23/lib/dfjejbdd.jar:/usr/lpp/java/J1.4/standard/ejb/2_0/ejb20.jar:/usr/lpp/java/J1.4/standard/jta/1_0_1/jta-spec1_0_1.jar:/usr/lpp/java/J1.4/standard/jca/connector.jar:

202 Java Application Development for CICS

Page 217: Java Application Development for CICS

Appendix D. Program listings

This appendix contains the full code of the examples we developed for this book.

D

© Copyright IBM Corp. 2005. All rights reserved. 203

Page 218: Java Application Development for CICS

Scratchpad examplepackage com.ibm.itso.sg245275;

import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutput;import java.io.ObjectOutputStream;import java.io.Serializable;

import com.ibm.cics.server.IOErrorException;import com.ibm.cics.server.ISCInvalidRequestException;import com.ibm.cics.server.InvalidQueueIdException;import com.ibm.cics.server.InvalidRequestException;import com.ibm.cics.server.InvalidSystemIdException;import com.ibm.cics.server.ItemErrorException;import com.ibm.cics.server.ItemHolder;import com.ibm.cics.server.LengthErrorException;import com.ibm.cics.server.NotAuthorisedException;import com.ibm.cics.server.TSQ;

/** * * Demonstrates how to use TS queues as a scratchpad. * * @author Ulrich Gehlert */public class Scratchpad {

/** Default TS queue name. */ public static final String DEFAULT_SCRATCHPAD_TSQ_NAME = "SCRATCH";

/** The TS queue we are writing to. */ private final TSQ tsq;

/** * Constructor using the default TS queue name. */ public Scratchpad() { this(DEFAULT_SCRATCHPAD_TSQ_NAME); }

/** * Constructor using an explicit TS queue name. */ public Scratchpad(String tsqName) { this(new TSQ()); assert tsqName != null; tsq.setName(tsqName); }

/** * Constructor using an explicit TS queue (which may be remote). */ public Scratchpad(TSQ tsq) { assert tsq != null; this.tsq = tsq; }

204 Java Application Development for CICS

Page 219: Java Application Development for CICS

/** * Write a byte array into the scratchpad queue. * * @param bytes * The byte array to be written. */ public void writeBytes(byte[] bytes) throws ItemErrorException, InvalidRequestException, IOErrorException, LengthErrorException, InvalidSystemIdException, ISCInvalidRequestException, NotAuthorisedException, InvalidQueueIdException { try { tsq.rewriteItem(1, bytes); } catch (InvalidQueueIdException e) { // The queue didn't exist -- add item to queue, thus creating the queue tsq.writeItem(bytes); } }

/** * Read a byte array from the scratchpad. * * @return The byte array on the scratchpad, or <code>null</code> if the * scratchpad is empty. */ public byte[] readBytes() throws InvalidRequestException, IOErrorException, LengthErrorException, InvalidSystemIdException, ISCInvalidRequestException, NotAuthorisedException { try { ItemHolder item = new ItemHolder(); tsq.readItem(1, item); return item.value; } catch (InvalidQueueIdException e) { return null; } catch (ItemErrorException e) { return null; } }

/** * Write a string to the scratchpad. * * @param s * The string to be written to the scratchpad. */ public void writeString(String s) throws InvalidRequestException, IOErrorException, LengthErrorException, InvalidSystemIdException, ItemErrorException, ISCInvalidRequestException, NotAuthorisedException, InvalidQueueIdException { writeBytes(s.getBytes()); }

/** * Read a string from the scratchpad. * * @return The string currently on the scratchpad. */ public String readString() throws InvalidRequestException, IOErrorException, LengthErrorException, InvalidSystemIdException, ISCInvalidRequestException, NotAuthorisedException, InvalidQueueIdException {

Appendix D. Program listings 205

Page 220: Java Application Development for CICS

byte[] bytes = readBytes(); if (bytes == null) return null; else return new String(readBytes()); }

/** * Write any serializable object to the scratchpad. * * @param obj * The object to be written to the scratchpad. */ public void writeObject(Serializable obj) throws InvalidRequestException, IOErrorException, LengthErrorException, InvalidSystemIdException, ItemErrorException, ISCInvalidRequestException, NotAuthorisedException, InvalidQueueIdException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutput oos; try { oos = new ObjectOutputStream(bos); oos.writeObject(obj); oos.close(); } catch (IOException ignored) { // Can't happen because we use in-memory streams only. } writeBytes(bos.toByteArray()); }

/** * Read a previously serialized object from the scratchpad. * * @return Object on the scratchpad, or <code>null</code> if the scratchpad * was empty. * * @throws IOException * Data on the scratchpad was not in serialized format (for example, * because the last call was writeString()). */ public Object readObject() throws ClassNotFoundException, InvalidRequestException, IOErrorException, LengthErrorException, InvalidSystemIdException, ISCInvalidRequestException, NotAuthorisedException, InvalidQueueIdException, IOException { byte[] bytes = readBytes(); if (bytes == null) { return null; } else { ObjectInputStream oos = new ObjectInputStream(new ByteArrayInputStream(bytes)); return oos.readObject(); } }}

VsamMap examplepackage com.ibm.itso.sg245275.vsam;

import java.util.AbstractMap;import java.util.AbstractSet;

206 Java Application Development for CICS

Page 221: Java Application Development for CICS

import java.util.Iterator;import java.util.Map;import java.util.NoSuchElementException;import java.util.Set;import com.ibm.cics.server.CicsException;import com.ibm.cics.server.DuplicateRecordException;import com.ibm.cics.server.EndOfFileException;import com.ibm.cics.server.KSDS;import com.ibm.cics.server.KeyHolder;import com.ibm.cics.server.KeyedFileBrowse;import com.ibm.cics.server.RecordHolder;import com.ibm.cics.server.RecordNotFoundException;

/** * An implementation of a Map that is backed by a * KSDS VSAM file. * * Note that, for simplicity and performance, this * implementation violates some of the Map interface's contracts. * For example, the {@link #remove(Object) remove()} method * does not return the value previously associated with the key. * * @author Ulrich Gehlert */public class VsamMap extends AbstractMap { private class VsamIterator implements Iterator { private final KeyedFileBrowse fb; private final KeyHolder kh = new KeyHolder(); private byte[] nextKey; private byte[] nextValue; private final RecordHolder rh = new RecordHolder();

public VsamIterator() { try { fb = ksds.startBrowse(new byte[keylength]); } catch (CicsException e) { throw new RuntimeException(e); } }

public boolean hasNext() { if (nextKey == null) { try { fb.next(rh, kh); nextKey = kh.value; nextValue = rh.value; } catch (EndOfFileException e) { close(); } catch (CicsException e) { close(); throw new RuntimeException(e); } } return nextKey != null; }

public Object next() { if (hasNext()) { Entry entry = new SimpleEntry(keyFromBytes(nextKey), valueFromBytes(nextValue));

Appendix D. Program listings 207

Page 222: Java Application Development for CICS

nextKey = nextValue = null; return entry; } else { throw new NoSuchElementException(); } }

public void remove() { throw new UnsupportedOperationException(); } public void close() { try { fb.end(); } catch (CicsException ignored) { } } }

static class SimpleEntry implements Entry { final Object key; Object value;

private static boolean eq(Object o1, Object o2) { return (o1 == null ? o2 == null : o1.equals(o2)); }

public SimpleEntry(Object key, Object value) { this.key = key; this.value = value; }

public SimpleEntry(Map.Entry e) { this.key = e.getKey(); this.value = e.getValue(); }

public boolean equals(Object o) { if (!(o instanceof Map.Entry)) return false; Map.Entry e = (Map.Entry) o; return eq(key, e.getKey()) && eq(value, e.getValue()); }

public Object getKey() { return key; }

public Object getValue() { return value; }

public int hashCode() { return ((key == null) ? 0 : key.hashCode()) ^ ((value == null) ? 0 : value.hashCode()); }

public Object setValue(Object value) { Object prevValue = this.value; this.value = value;

208 Java Application Development for CICS

Page 223: Java Application Development for CICS

return prevValue; }

public String toString() { return key + "=" + value; } }

/** Length of key. */ private final int keylength;

/** Underlying KSDS. */ private final KSDS ksds; private final RecordHolder recordHolder = new RecordHolder();

/** * Constructor. */ public VsamMap(KSDS ksds, int keylength) { this.ksds = ksds; this.keylength = keylength; }

/** * Convenience constructor that accepts a KSDS name. */ public VsamMap(String ksdsName, int keylength) { this(new KSDS(), keylength); ksds.setName(ksdsName); }

public Set entrySet() { return new AbstractSet() { public Iterator iterator() { return new VsamIterator(); }

public int size() { throw new UnsupportedOperationException(); } }; }

public Object get(Object key) { try { ksds.read(keyToBytes(key), recordHolder); return valueFromBytes(recordHolder.value); } catch (RecordNotFoundException notfound) { return null; } catch (CicsException e) { throw new RuntimeException(e); } }

public boolean containsKey(Object key) { return get(key) != null; }

public Object put(Object key, Object value) {

Appendix D. Program listings 209

Page 224: Java Application Development for CICS

byte[] keyBytes = keyToBytes(key); byte[] valueBytes = valueToBytes(value); try { ksds.write(keyBytes, valueBytes); } catch (DuplicateRecordException e) { throw new IllegalArgumentException("Duplicate key"); } catch (CicsException e) { throw new RuntimeException(e); } return null; }

public void replace(Object key, Object value) { byte[] keyBytes = keyToBytes(key); try { ksds.readForUpdate(keyBytes, recordHolder); ksds.rewrite(valueToBytes(value)); } catch (CicsException e) { throw new RuntimeException(e); } }

public Object remove(Object key) { try { ksds.delete(keyToBytes(key)); return Boolean.TRUE; } catch (RecordNotFoundException e) { return null; } catch (CicsException e) { throw new RuntimeException(e); } } protected byte[] keyToBytes(Object key) { return ((String) key).getBytes(); } protected byte[] valueToBytes(Object value) { return ((String) value).getBytes(); } protected Object keyFromBytes(byte[] bytes) { return new String(bytes); }

protected Object valueFromBytes(byte[] bytes) { return new String(bytes); }}

JBMS (Java Basic Mapping Support) example

Component.javapackage com.ibm.itso.sg245275.jbms;

import java.io.ByteArrayOutputStream;

210 Java Application Development for CICS

Page 225: Java Application Development for CICS

/** * Superclass for all JBMS elements. * * @author Ulrich Gehlert */public abstract class Component { /** Row position of this component. */ private final int row;

/** Column position of this component. */ private final int col; /** Parent component. */ private final Component parent; /** Should component be displayed? */ private boolean visible = true; /** * Constructor. * * @param parent Parent component. * @param row Row position relative to parent. * @param col Column position relative to parent. */ protected Component(Container parent, int row, int col) { // Screen is the only component with no parent. if (! (this instanceof Screen) && parent == null) { throw new IllegalArgumentException("No parent component"); } if (parent != null) { parent.addComponent(this); } this.parent = parent; this.row = row; this.col = col; } /** * @return Returns the column index relative to the screen. */ public int getAbsoluteCol() { return col + parent.getAbsoluteCol(); } /** * @return Returns the row index relative to the screen. */ public int getAbsoluteRow() { return row + parent.getAbsoluteRow(); } /** * @return Returns the column index relative to the parent.. */ public int getCol() { return col; }

/**

Appendix D. Program listings 211

Page 226: Java Application Development for CICS

* @return Returns the row index relative to the parent. */ public int getRow() { return row; } /** * Write 3270 data stream for this component. * * @param bos 3270 data stream. */ protected abstract void to3270(ByteArrayOutputStream bos);

/** * Will the component be displayed? */ public boolean isVisible() { return visible; }

/** * Controls whether the component will be displayed. */ public void setVisible(boolean visible) { this.visible = visible; }}

Container.java/* * Created on Apr 17, 2005 * * TODO To change the template for this generated file go to * Window - Preferences - Java - Code Style - Code Templates */package com.ibm.itso.sg245275.jbms;

import java.io.ByteArrayOutputStream;import java.util.ArrayList;import java.util.Collections;import java.util.Iterator;import java.util.List;

/** * A container for other components. * * @author Ulrich Gehlert */public abstract class Container extends Component { /** Child components. */ private final List components = new ArrayList();

/** * Constructor. * * @param parent * This container's parent Container. * @param row * Row position relative to parent.

212 Java Application Development for CICS

Page 227: Java Application Development for CICS

* @param col * Column position relative to parent. */ public Container(Container parent, int row, int col) { super(parent, row, col); }

void addComponent(Component c) { components.add(c); }

/** * If this Container is visible, create a 3270 data stream * from its Components. */ protected void to3270(ByteArrayOutputStream bos) { if (isVisible()) { for (Iterator iter = components.iterator(); iter.hasNext();) { Component component = (Component) iter.next(); component.to3270(bos); } } }

/** * Get a list of all Components that make up this Container. * * @return An unmodifiable list of all Components. */ public List getComponents() { return Collections.unmodifiableList(components); }

/** * Get a list of all Fields that make up this Container. * Contained Containers are expanded recursively. * * @return An unmodifiable list of all Fields. */ public List getFields() { List fields = new ArrayList(); Iterator iter = getComponents().iterator(); while (iter.hasNext()) { Component component = (Component) iter.next(); if (component instanceof Container) fields.addAll(((Container) component).getFields()); else fields.add(component); } return Collections.unmodifiableList(fields); }}

Field.javapackage com.ibm.itso.sg245275.jbms;

import java.io.ByteArrayOutputStream;import java.io.IOException;import java.text.Format;

Appendix D. Program listings 213

Page 228: Java Application Development for CICS

import java.text.ParsePosition;

/** * A displayable 3270 field. * * @author Ulrich Gehlert */public abstract class Field extends Component { /** Standard 3270 attributes. */ public interface Attribute { byte BRIGHT = 0x08; byte HIDDEN = 0x0C; byte MODIFIED = 0x01; byte NUMERIC = 0x10; byte PROTECTED = 0x20; byte AUTOSKIP = PROTECTED | NUMERIC; }

/** 3270 color constants. */ public interface Color { byte BLUE = (byte) 0xF1; byte RED = (byte) 0xF2; byte PINK = (byte) 0xF3; byte GREEN = (byte) 0xF4; byte TURQUOISE = (byte) 0xF5; byte YELLOW = (byte) 0xF6; byte BLACK = (byte) 0xF8; byte DEEP_BLUE = (byte) 0xF9; byte ORANGE = (byte) 0xFA; byte PURPLE = (byte) 0xFB; byte PALE_GREEN = (byte) 0xFC; byte PALE_TURQUOISE = (byte) 0xFD; byte GREY = (byte) 0xFE; byte WHITE = (byte) 0xFF; }

/** 3270 highlighting constants. */ public interface Hilite { byte BLINK = (byte) 0xF1; byte REVERSE = (byte) 0xF2; byte UNDERSCORE = (byte) 0xF4; }

/** Constants for 3270 extended attribute types. */ interface AttributeType { byte EXT_HILITE = (byte) 0x41; byte FOREGROUND = (byte) 0x42; byte STD3270 = (byte) 0xC0; }

/** 3270 commands ("orders"). */ interface Order { byte SET_ATTRIBUTE = 0x28; byte SET_BUFFER_ADDRESS = 0x11; byte INSERT_CURSOR = 0x13; byte START_FIELD = 0x1D; byte START_FIELD_EXT = 0x29; }

protected static String blanks(int length) {

214 Java Application Development for CICS

Page 229: Java Application Development for CICS

StringBuffer sb = new StringBuffer(length); sb.setLength(length); for (int i = 0; i < length; i++) sb.setCharAt(i, ' '); return sb.toString(); }

private static final byte UNSET = 0; /** Standard 3270 attributes. */ private byte attributes = UNSET; /** Extended highlighting. */ private byte extHilite = UNSET; /** Foreground color. */ private byte foregroundColor = UNSET; /** Field length. */ private int length; /** Text. */ private String text; /** Optional formatter. */ Format format;

/** * Construct a field at the given position, having the specified length. * * @param row * Row position * @param col * Column position * @param length * Field length */ protected Field(Container parent, int row, int col) { super(parent, row, col); }

/** * Construct a field at the given position, having the specified length. * * @param row * Row position * @param col * Column position * @param length * Field length */ protected Field(Container parent, int row, int col, int length) { this(parent, row, col, blanks(length)); }

/** * Construct a field at the given position, having the specified initial text * (and implied length). * * @param row * Row position * @param col * Column position * @param text * Initial field text */

Appendix D. Program listings 215

Page 230: Java Application Development for CICS

protected Field(Container parent, int row, int col, String text) { this(parent, row, col); this.length = text.length(); setText(text); }

/** * Get standard 3270 attributes for this field. * * @return The standard 3270 attributes. */ public byte getAttributes() { return attributes; }

/** * Get extended highlighting attribute. * * @return Extended highlighting. */ public byte getExtHilite() { return extHilite; }

/** * Get the foreground color. * * @return The foreground color. */ public byte getForegroundColor() { return foregroundColor; }

/** * @return Returns the format. */ public Format getFormat() { return format; }

/** * @return Returns the length. */ public int getLength() { return length; }

/** * @return Returns this field's text. */ public String getText() { return text; }

/** * If a format has been set, parse the text using the specified format, and * return the value; else, return the field text. If the text could not be * parsed, return null. * */

216 Java Application Development for CICS

Page 231: Java Application Development for CICS

public Object getValue() { Object value; if (getFormat() == null) { value = getText(); } else { String txt = getText().trim(); ParsePosition pos = new ParsePosition(0); value = getFormat().parseObject(getText(), pos); if (pos.getErrorIndex() >= 0 || pos.getIndex() != txt.length()) return null; setValue(value); } return value; }

/** * Sets standard 3270 attributes. * * @param attributes * One of the Attribute constants. */ public void setAttributes(byte attributes) { this.attributes = attributes; }

/** * Set extended highlighting. * * @param extHilite * One of the Hilite constants. */ public void setExtHilite(byte extHilite) { this.extHilite = extHilite; }

/** * Set the foreground color. * * @param foregroundColor * The foreground color to set. */ public void setForegroundColor(byte foregroundColor) { this.foregroundColor = foregroundColor; }

/** * @param format * The format to set. */ public void setFormat(Format format) { this.format = format; }

/** * Set a new text to display in this field. Right truncation occurs if too * long for the field. * * @param text * The text to set. */

Appendix D. Program listings 217

Page 232: Java Application Development for CICS

public void setText(String text) { if (text.length() > getLength()) text = text.substring(0, getLength()); this.text = text; }

public void setValue(Object value) { if (getFormat() == null) { setText(value == null ? blanks(getLength()) : value.toString()); } else { setText(format.format(value)); } }

protected void to3270(ByteArrayOutputStream bos) { if (isVisible()) { insertBufferAddress(bos, false); bos.write(Order.START_FIELD_EXT); // Start field extended bos.write(countExtendedAttributes()); // Number of extended attributes // Send extended attributes, as type/value byte pairs. writeAttribute(bos, AttributeType.STD3270, (byte) Util.encode(attributes)); writeAttributeConditional(bos, AttributeType.EXT_HILITE, extHilite); writeAttributeConditional(bos, AttributeType.FOREGROUND, foregroundColor); try { bos.write(text.getBytes()); } catch (IOException e) { // Can’t happen with a ByteArrayOutputStream } // Send a dummy marker field to indicate end of current field bos.write(Order.START_FIELD); bos.write(Util.encode(Attribute.AUTOSKIP)); } }

/** * @return The number of extended attributes, that is, the number of key/value * pairs to write to the 3270 data stream. */ private byte countExtendedAttributes() { byte numExtAttr = 1; // We always send the standard 3270 attributes if (extHilite != UNSET) numExtAttr++; if (foregroundColor != UNSET) numExtAttr++; return numExtAttr; }

private void writeAttribute(ByteArrayOutputStream bos, byte attrtype, byte value) { bos.write(attrtype); bos.write(value); }

private void writeAttributeConditional(ByteArrayOutputStream bos, byte attrtype, byte value) { if (value != UNSET) { writeAttribute(bos, attrtype, value); } }

/**

218 Java Application Development for CICS

Page 233: Java Application Development for CICS

* Append encoded buffer address to stream. * * @param bos * 3270 data stream. * @param skipAttributeByte * Skip attribute byte? */ void insertBufferAddress(ByteArrayOutputStream bos, boolean skipAttributeByte) { bos.write(Order.SET_BUFFER_ADDRESS); int bufpos = getEncodedBufferAddress(skipAttributeByte); bos.write(bufpos >>> 8); bos.write(bufpos & 0xFF); }

/** * Returns the 3270 buffer address, in 3270 encoded format. * * @param skipAttributeByte * Skip the 3270 attribute byte (adds 1 to buffer address)? * * @return Encoded buffer address. */ int getEncodedBufferAddress(boolean skipAttributeByte) { return Util.encodeBufpos(getAbsoluteRow(), getAbsoluteCol(), skipAttributeByte); }}

Label.javapackage com.ibm.itso.sg245275.jbms;

/** * An autoskip 3270 field (no data can be entered by the user). * * @author Ulrich Gehlert */public class Label extends Field {

public Label(Container parent, int row, int col, String text) { super(parent, row, col, text); setAttributes(Attribute.AUTOSKIP); }

public Label(Container parent, int row, int col, int length) { this(parent, row, col, blanks(length)); }}

MenuScreen.javapackage com.ibm.itso.sg245275.jbms;

import java.util.ArrayList;import java.util.Iterator;import java.util.List;

import com.ibm.itso.sg245275.jbms.Field.Color;

Appendix D. Program listings 219

Page 234: Java Application Development for CICS

/** * A simple menu screen. * * @author Ulrich Gehlert */public class MenuScreen extends Screen { Label titleLabel; Label promptLabel; Text promptText; List choiceLabels = new ArrayList(); List itemLabels = new ArrayList(); Panel selectionPanel;

public MenuScreen(String title) { titleLabel = new Label(this, 1, 1, title); titleLabel.setForegroundColor(Color.BLUE); promptLabel = new Label(this, 22, 1, ">>>"); promptLabel.setForegroundColor(Color.GREEN); promptText = new Text(this, 22, 6, 3); promptText.setForegroundColor(Color.TURQUOISE); setInitialField(promptText); selectionPanel = new Panel(this, 3, 1); } public void addItem(String choice, String text) { int numItems = choiceLabels.size(); Label choiceLabel = new Label(selectionPanel, 2*numItems, 1, choice); choiceLabel.setForegroundColor(Color.YELLOW); Label itemLabel = new Label(selectionPanel, 2*numItems, 4, text); itemLabel.setForegroundColor(Color.TURQUOISE); choiceLabels.add(choiceLabel); itemLabels.add(itemLabel); }

public void addItem(int choice, String text) { addItem(Integer.toString(choice), text); } public Field validate() { String choice = promptText.getText().trim(); for (Iterator iter = choiceLabels.iterator(); iter.hasNext();) { Label label = (Label) iter.next(); if (label.getText().equals(choice)) { return null; } } return promptText; } public String getChoice() { return promptText.getText().trim(); }}

Panel.javapackage com.ibm.itso.sg245275.jbms;

/**

220 Java Application Development for CICS

Page 235: Java Application Development for CICS

* A container for other components. * * @author Ulrich Gehlert */public class Panel extends Container {

/** * Constructor. * * @param parent This panel's parent Container. * @param row Row position relative to parent. * @param col Column position relative to parent. */ public Panel(Container parent, int row, int col) { super(parent, row, col); }}

PasswordText.javapackage com.ibm.itso.sg245275.jbms;

/** * A Text whose contents are not echoed on the screen. * * @author Ulrich Gehlert */public class PasswordText extends Text {

public PasswordText(Container parent, int row, int col, int length) { super(parent, row, col, length); setAttributes(Attribute.HIDDEN); }}

PfKeyPanel.javapackage com.ibm.itso.sg245275.jbms;

/** * A panel which displays PF key assignments. * * @author Ulrich Gehlert */public class PfKeyPanel extends Panel { Label pfLabel; Label[] labels = new Label[9]; Label[] texts = new Label[9]; /** * Constructor. * * @param parent This panel's parent container. * @param row This panel's relative row position. */ public PfKeyPanel(Container parent, int row) { super(parent, row, 0); pfLabel = new Label(this, 0, 0, "PF");

Appendix D. Program listings 221

Page 236: Java Application Development for CICS

pfLabel.setForegroundColor(Field.Color.RED); for (int pf = 1; pf <= 8; pf++) { labels[pf] = new Label(this, 0, 3 + 9*(pf-1), Integer.toString(pf)); labels[pf].setForegroundColor(Field.Color.BLUE); labels[pf].setVisible(false); texts[pf] = new Label(this, 0, 3 + 9*(pf-1) + 2, 6); texts[pf].setForegroundColor(Field.Color.RED); texts[pf].setVisible(false); } }

/** * Constructor using the default row position (24). * * @param parent This panel's parent (a Screen). */ public PfKeyPanel(Screen parent) { this(parent, 23); }

public void setEnabled(int pf, boolean enabled) { labels[pf].setVisible(enabled); texts[pf].setVisible(enabled); }

public void setText(int pf, String text) { setEnabled(pf, true); texts[pf].setText(text); }}

Screen.javapackage com.ibm.itso.sg245275.jbms;

import java.io.ByteArrayOutputStream;import java.util.Iterator;import com.ibm.cics.server.DataHolder;import com.ibm.cics.server.EndOfChainIndicatorException;import com.ibm.cics.server.InvalidRequestException;import com.ibm.cics.server.LengthErrorException;import com.ibm.cics.server.NotAllocatedException;import com.ibm.cics.server.TerminalException;import com.ibm.cics.server.TerminalPrincipalFacility;import com.ibm.itso.sg245275.jbms.Field.Order;

/** * Represents an entire 3270 screen. * * @author Ulrich Gehlert */public class Screen extends Container { /** Field which initially receives cursor. */ private Field initialField;

public Screen() { super(null, 0, 0); }

222 Java Application Development for CICS

Page 237: Java Application Development for CICS

/** * Display screen on the terminal. * * @param term The terminal. */ public void display(TerminalPrincipalFacility term) throws InvalidRequestException, LengthErrorException, NotAllocatedException, TerminalException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); bos.write(0); bos.write(0); to3270(bos); if (getInitialField() != null) { // Position cursor to initial field. initialField.insertBufferAddress(bos, true); bos.write(Order.INSERT_CURSOR); } term.send(bos.toByteArray()); }

/** * Display screen and receive user response. * * @param term The terminal. * @param asis Receive without upper case translation? * * @return * Action Identifier of key pressed to send data, * one of the constants in {@link com.ibm.cics.server.AIDValue AIDValue}. */ public byte displayAndReceive(TerminalPrincipalFacility term) throws InvalidRequestException, LengthErrorException, NotAllocatedException, TerminalException { display(term); return receive(term); }

/** * Find a field by its 3270 buffer address. */ private Field findFieldByAddress(int bufaddr) { for (Iterator i = getFields().iterator(); i.hasNext();) { Field field = (Field) i.next(); if (bufaddr == field.getEncodedBufferAddress(true)) { return field; } } return null; }

public int getAbsoluteCol() { return 0; }

public int getAbsoluteRow() { return 0; }

/** * @return Returns the initialField.

Appendix D. Program listings 223

Page 238: Java Application Development for CICS

*/ public Field getInitialField() { return initialField; }

/** * Parse response from 3270 terminal. * * * The 3270 response has the following format: <code> * +----+---+---+--------------------+----+---+---+----------------------+... * |SBA1|BPH|BPL|Data for first field|SBA1|BPH|BPL|Data for second field |... * +----+---+---+--------------------+----+---+---+----------------------+... * </code> * * We extract each segment (beginning with the SBA order, ending with the byte * before the next SBA order). Then, we find the field this segment * corresponds to, and set its text. */ private void parseResponse(byte[] resp) { // Start at index 1 (index 0 has a SET_BUFFER_ADDRESS for first field). for (int pos = 1; pos < resp.length; pos++) { // Get buffer address. int bufaddr = ((resp[pos++] << 8) | (resp[pos++] & 0xFF)) & 0xFFFF; // Find end of current segment (look for next SBA). int end; for (end = pos; end < resp.length && resp[end] != Order.SET_BUFFER_ADDRESS; end++) ; // Find the field this segment corresponds to. Field field = findFieldByAddress(bufaddr); if (field != null) { // Found field; set its contents to the data received. String fieldContents = new String(resp, pos, end - pos); field.setText(fieldContents); } pos = end; } }

/** * Receive input from terminal, and parse data stream. * * @return AID (Action Identifier) of the key pressed {one of the * {@link com.ibm.cics.server.AIDValue AIDValue}constants). */ public byte receive(TerminalPrincipalFacility term) throws InvalidRequestException, LengthErrorException, NotAllocatedException, TerminalException { DataHolder dah = new DataHolder(); try { term.receive(dah); } catch (EndOfChainIndicatorException expected) { // Always thrown from TerminalPrincipalFacility.receive(). // We can safely ignore it. } parseResponse(dah.value); return term.getAIDbyte(); }

/**

224 Java Application Development for CICS

Page 239: Java Application Development for CICS

* @param initialField * The initialField to set. */ public void setInitialField(Field initialField) { this.initialField = initialField; }

/** * Validate all fields, by calling getValue() for each field. * * @return The first field that could not be parsed, or <code>null</code> if * all fields are valid. */ public Field validate() { for (Iterator iter = getFields().iterator(); iter.hasNext();) { Field field = (Field) iter.next(); if (field.getValue() == null) return field; } return null; }}

Text.javapackage com.ibm.itso.sg245275.jbms;

/** * A text-entry field. * * @author Ulrich Gehlert */public class Text extends Field {

public Text(Container parent, int row, int col, String text) { super(parent, row, col, text); setExtHilite(Hilite.UNDERSCORE); }

public Text(Container parent, int row, int col, int length) { this(parent, row, col, blanks(length)); }}

Util.javapackage com.ibm.itso.sg245275.jbms;

/** * Contains utility methods. * * @author Ulrich Gehlert */class Util { private static final int[] encode3270 = { 0x40, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F

Appendix D. Program listings 225

Page 240: Java Application Development for CICS

, 0x50, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F , 0x60, 0x61, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F , 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F }; static int encode(int by) { return encode3270[by]; } static int encodeBufpos(int bufpos) { return encode(bufpos >>> 6) << 8 | encode(bufpos & 0x3F); }

static int encodeBufpos(int row, int col, boolean skipAttributeByte) { return encodeBufpos(80*row + col + (skipAttributeByte ? 1 : 0)); }}

226 Java Application Development for CICS

Page 241: Java Application Development for CICS

Appendix E. Additional material

This redbook refers to additional material that can be downloaded from the Internet as described below.

Locating the Web materialThe Web material associated with this redbook is available in softcopy on the Internet from the IBM Redbooks Web server. Point your Web browser to:

ftp://www.redbooks.ibm.com/redbooks/SG245275

Alternatively, you can go to the IBM Redbooks Web site at:

ibm.com/redbooks

Select the Additional materials and open the directory that corresponds with the redbook form number, SG245275.

Using the Web materialThe additional Web material that accompanies this redbook includes the following files:

File name DescriptionSG245275.zip Zipped Code Samples

System requirements for downloading the Web materialThe following system configuration is recommended:

Hard disk space: 3 MB minimumOperating System: Windows/z/OS/CICS

E

© Copyright IBM Corp. 2005. All rights reserved. 227

Page 242: Java Application Development for CICS

How to use the Web materialCreate a subdirectory (folder) on your workstation, and unzip the contents of the Web material zip file into this folder.

228 Java Application Development for CICS

Page 243: Java Application Development for CICS

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 RedbooksFor information about ordering these publications, see “How to get IBM Redbooks” on page 230. Note that some of the documents referenced here may be available in softcopy only.

� ABCs of z/OS System Programming Volume 9, SG24-6989

� DB2 for z/OS and OS/390: Ready for Java, SG24-6435

Other publicationsThese publications are also relevant as further information sources:

� Java Applications in CICS, SC34-6238

� CICS Messages and Codes, GC34-6241

� CICS Supplied Transactions, SC34-6230

� CICS Intercommunication Guide, SC34-6243

� CICS Resource Definition Guide, SC34-6228

� CICS Internet Guide, SC34-6245

� CICS RACF Security Guide, SC34-6249

� z/OS V1R6.0 UNIX System Services Planning, GA22-7800

� 3270 Data Stream Programmer’s Reference, GA23-0059

� Persistent Reusable Java Virtual Machine User’s Guide, SC34-6201

� z/OS MVS Initialization and Tuning Reference, SA22-7592

� CICS Performance Guide, SC34-6247

� CICS System Definition Guide, SC34-6226

� CICSPlex SM Web User Interface Guide, SC34-6461

� CICS Application Programming Reference, SC34-6232

� CICS Problem Determination Guide, SC34-6239

� SDK DIagnostics Guide, SC34-6358

� CICS Operations & Utilities Guide, SC34-6431

Online resourcesThese Web sites and URLs are also relevant as further information sources:

� IBM JVM Diagnostics Guide

© Copyright IBM Corp. 2005. All rights reserved. 229

Page 244: Java Application Development for CICS

http://www.ibm.com/developerworks/java/jdk/diagnosis/index.html

� Java on the z/OS platform

http://www-1.ibm.com/servers/eserver/zseries/software/java

� The Sun Web site

http://java.sun.com

How to get IBM RedbooksYou can search for, view, or download Redbooks, Redpapers, Hints and Tips, draft publications and Additional materials, as well as order hardcopy Redbooks or CD-ROMs, at this Web site:

ibm.com/redbooks

Help from IBMIBM Support and downloads

ibm.com/support

IBM Global Services

ibm.com/services

230 Java Application Development for CICS

Page 245: Java Application Development for CICS

Index

Numerics3270 13064-bit Support 5

AAD/Cycle C/370 38AddressResource 98AJ07 abend 160APAR II13519 159APAR PQ79281 39Application abends that are not handled 183application-class system heap 32ASKTIME 143Autostartst 27

BBasic Mapping Support 81Binary based values 126BMS 81, 130BPXI040 49BPXPRMxx 49BPXPRMxx parameter 49

MAXASSIZE 49MAXCPUTIME 49MAXFILEPROC 49MAXPROCUSER 49MAXTHREADS 49

BUY-SELL-UPDATE 147

CC/C++ 4Cachefree 27Cachesize 27CALCULATE-SHARES-BOUGHT 146calculateSharesBought() 147CECI 73CEDA 48CEDX 172CEE3DMP 161CEEDUMP 161, 163CEEHRNUH 163CEEPIPI 48, 159CEMT INQUIRE CLASSCACHE 57CEMT INQUIRE DISPATCHER 58CEMT INQUIRE JVM 58CEMT INQUIRE JVMPOOL 59CEMT INQUIRE PROGRAM 59CEMT PERFORM CLASSCACHE 60CEMT SET DISPATCHER 61CEMT SET JVMPOOL 61Channels & containers 193Character based values 125

© Copyright IBM Corp. 2005. All rights reserved.

CHAR-VALUE 147CICS Dynamic Storage Areas (DSAs) 51CICS JVM plug-in mechanism 176CICS language interface module 78CICS LINK 89CICS Master Trace flag being set on 183CICS PROGRAM definition attributes 56

CONCURRENCY 57JVM 56JVMCLASS 56JVMPROFILE 56LANGUAGE 57

CICS terminal 48CICS Transaction Gateway server 6CICS translator 78CICS using HTTP 99CICSUSER 134Class declaration and constructors 102COBOL 6, 122COMMAREA 91, 124, 133COMMAREA-BUFFER 124, 141CommareaWrapper 125, 133, 141Common Client Interface (CCI) 39Common Work Area 82Common Work Area (CWA) 82COMPANY-IO-BUFFER 141CompanyIOWrapper 141COMPFILE 122Component 111Container 112Continuous JVM 180conversion 141CUSTFILE 122CustomerIOWrapper 141CWBA 127

DData migration SQL 151Database tables 150Datestarted 27DB2 5, 139Debugging 158

JVM abended? 159JVM failing to start? 159

Debugging the application 175DecimalFormat 147Deploying code to CICS 69DFH$JVM 48DFHJVMCC 52DFHJVMCD 52DFHJVMPC 182DFHJVMPR 52, 182DFHWEB 129DFJ$JHE2 48

231

Page 246: Java Application Development for CICS

diagnostic information 160DOCTEMPLATE 134, 136Document 128Document API 80Document services 80Documents 131dynamic HTML 131Dynamic VIPA (virtual IP addressing) 6

EEIBRESP 142ENQ/DEQ 97Enterprise JavaBeans 4Entry Sequenced Data Sets (ESDS) 80entry-sequenced data set 100ESDS 100EVALUATE 144exceptions

checked 85unchecked 85

Excessive garbage collection 184EXEC CICS DOCUMENT 99EXEC CICS WEB 99Execution diagnostic facility 172External Security Manager 38

DCE Security Server 39Firewall Technologies 39Lightweight Directory Access Protocol 38Network Authentication Services 39Open Cryptographic Enhanced Plug-ins 38RACF 38

Fformatting 141Formatting trace 170FORTRAN IV 38

GG5 38G6 38GET 131getByteArray() 127GET-COMPANY 144–145getCompany() 144, 146GID 50GUI 16

HHeap management 29

The application-class system heapapplication-class system heap 32

The Middleware heap 32The system heap 32The transient heap 32

HelloCICSWorld Java application 48HFS 46High Performance Java 17HiperSockets 4

Hot Pooling 17HPJ 17HTML 4, 130HTML design 130HTTP input fields 131HttpResponse 128

IIBM Directory Server 5IBM eServer zSeries 4IBM Rational Software Development Platform (RAD). 38ImageLoader 136IMS(TM) 6Integrated Cryptographic Service Facility (ICSF) 5Intelligent Resource Director (IRD) 4IPCSEMNSEMS 48–49ISPF shell 43

JJ2EE Connector Architecture Specification 39Java 140Java Build Path 68Java Client Support 39Java for z/OS 9Java Language 7Java Language Support 39Java Platform Debugger Architecture 172Java Program Objects 17Java SDK 5Java servlets 81Java Virtual Machine 9Java Virtual Machines (JVMs) 12JAVA_DUMP_OPTS 161Javadumps 160–161JBMS 81JCICS API 79JCICS Web interface 123, 129JCICS Web program 127JDBC 12JHE2 48JNDI 12, 19JVM class loader tracing 170JVM method tracing 168JVM operation modes 18

Continuous mode 18Resettable mode 18Single use mode 18

JVM profile 47JVM profile options 54

CICS_DIRECTORY 54CLASSCACHE 54CLASSCACHE_MSGLOG 54CLASSPATH 54DUMP 55JAVA_HOME 54JVMPROPS 54LIBPATH 54REUSE 54STDERR 54

232 Java Application Development for CICS

Page 247: Java Application Development for CICS

STDIN 54STDOUT 54TMPREFIX, TMSUFFIX 54VERBOSE 54WORK_DIR 54Xinitacsh 54Xinitsh 54Xinitth 54Xmaxe 54Xmaxf 54Xmine 54Xminf 54

JVM profile options table 54JVM Startup 188JVM stdout and stderr 165JVM stealing 183JVM support in CICS 16

CICS TS 1.3 17CICS TS 2.1 and 2.2 17CICS TS 2.3 17CICS TS 3.1 17

JVM system properties files 55JVMCCPROFILE 25, 52JVMCCSIZE 52JVMCCSTART 52JVMCCSTART PARAMETERS

JVMCCSTART=NO 26JVMCCSTART=YES 26

JVMPROFILEDIR 47, 51JVMSet 24JVMSets and the shared class cache 24

Benefits of the shared class cache 24JVMCCSTART=AUTO,JVMCCSTARTPARAME-TERS

JVMCCSTART=AUTO 26JVMCCSTART=NO 26JVMCCSTART=YES 26Master JVM 25Worker JVM 25

KKey Sequenced Data Sets (KSDS) 80key-sequenced data set 100KSDS 100

LLanguage Environment 49

CEEDEOPT 50DFHJVMRO 50SCEERUN 49SCEERUN2 49

LDAP 38legacy trader application 122LIBPATH 51Linux for zSeries 4Logging reset events 166Logging unresettable actions 166logoff 139LPARs 5

Mmain() 143MAINLINE 143master JVM 24MAXASSIZE 48MAXCPUTIME 49MAXFILEPROC 48MAXJVMTCBS 53MAXPROCSYS 48MAXPROCUSER 48–49MAXPTYS 48MAXTHREADS 49MAXTHREADTASKS 49MAXUIDS 48Middleware heap 32move 145Multiprise 3000 servers 38MVS IEATDUMP 161

NNameResource 98Network Authentication Services 39NEWTRAD 122non-shareable 25NUM-VALUE 147

Oobject-oriented (OO) 3OCCURS X TIME 126Oldcaches 27OpenLDAP 5

PParallel Sysplex 4PERFORM 144, 146performBuy() 133performSell() 133Phasingout 28PL/I 6POST 131Program control 80PTFs 159

UK00802 159UQ90449 159UQ93743 159

Public Key Services in z/OS 6

RRACF 38RACF ADDUSER 49RACF OMVS 49

ASSIZEMAX 49CPUTIMEMAX 49FILEPROCMAX 49PROCUSERMAX 49THREADSMAX 49

Rational Application Developer 65

Index 233

Page 248: Java Application Development for CICS

RBHOME 136Redbooks Web site 230

Contact us xirelative record data set 100Relative Record Data Sets (RRDS) 80request formats 126Reset Trace Events 183RETURN 145Return transid 194Reusable JVM 18, 180REUSE=RESET 182Reusest 28rlogin 44RRDS 100

SSDFJAUTH 51SDK tools 11sendErrorResponse() 128, 135sendLinkRequest() 134sendResponse() 135Service Oriented Architecture (SOA) 17services oriented architecture (SOA) 6SETOMVS 49Shared Class Cache Facility 181showList() 134SimpleTraderPL 128SQL statements 152ssh 44standard extensions 29Start transid 195strip() 133symbol list 133SymbolList 135symbols 131SYSDUMP 164Sysplex Distributor 6system heap 32

Ttail 144TCP/IP network support 6TCPIPS 129TCPIPSERVICE 129telnet 44templates 131, 136Terminal control 81Terminal services 110Timestarted 28TMPREFIX 51TMSUFFIX 51TN3270 6Totaljvms 28TRADER 123Trader-1.jar 128TRADERBL 122, 140TraderConstants 127, 133TraderDataAccess 142TRADERPJ 136

TRADERPL 122TraderPL 131–132TRADERPS 129Transaction Work Area 82Transaction Work Area (TWA) 82Transient data queues 81transient heap 32Transient storage queues 81Troubleshooting 75TSO ISHELL 43TSO OMVS 43

UUID 50Unicode 4Unknown RefID_ijava

bytecode 8dynamically loading classes 8

Unresettable Event 184Unresettable events 183UPDATE-BUY-SELL 133URL 129, 137userid 134USEROUTPUTCLASS 51Using Application Classpath 184

VVisualAge for Java 91VS FORTRAN 38VTAM 82

WWeb 127Web and TCP/IP services 81Web pages 131Web security 138WebSphere Application Server 12WebSphere MQ message queues 81worker JVM 24Working storage 140WORKING-STORAGE 142wrapper 124writeMessage() 143WRITEQ-TS 143Writeq-TS 143Writing trace to buffers 169

XXCTL (“transfer control”) 89Xdebug=YES 173XML 4

Zz/Architecture 4z/OS 3

4z/OS HTTP Server 5

234 Java Application Development for CICS

Page 249: Java Application Development for CICS

z/OS LPAR 44z/OS Managed System Infrastructure 5z/OS UNIX System Services for z/OS (USS) 9z/VM 4z800 38z890 38z900 38z990 38

Index 235

Page 250: Java Application Development for CICS

236 Java Application Development for CICS

Page 251: Java Application Development for CICS

Java Application Development for CICS

Java Application Development for

CICS

Java Application Development for

CICS

Java Application Development for CICS

Page 252: Java Application Development for CICS

Java Application Development for

CICS

Java Application Development for

CICS

Page 253: Java Application Development for CICS
Page 254: Java Application Development for CICS

®

SG24-5275-02 ISBN 0738493791

INTERNATIONAL TECHNICALSUPPORTORGANIZATION

BUILDING TECHNICAL INFORMATION BASED ON PRACTICAL EXPERIENCE

IBM Redbooks are developed by the IBM International Technical Support Organization. Experts from IBM, Customers and Partners from around the world create timely technical information based on realistic scenarios. Specific recommendations are provided to help you implement IT solutions more effectively in your environment.

For more information:ibm.com/redbooks

Java Application Development for CICS

Setting up CICS to run Java applications

CICS Java problem determination and debugging

Evolving a legacy application using Java

This IBM Redbook is intended for clients who are implementing the Java language support provided by CICS Transaction Server for z/OS V2.3. Its prime audience is CICS and z/OS system programmers who provide support for Java application development, and Java application programmers who need a gentle introduction to Java development for CICS.

This book assumes a certain level of knowledge of z/OS, CICS, UNIX System Services, and Java.

We start by reviewing the basic concepts of the z/OS, CICS TS V2.3, and Java environments, and introduce new terminology. We then discuss the software and hardware requirements for developing and executing Java applications in CICS TS V2.3 and the customization of the application development environment, UNIX System Services, MVS, and CICS.

We briefly discuss three possible application development roadmaps: Java application programs that use CICS services, IIOP server applications, and CICS Enterprise Beans.

Subsequent chapters contain an expanded explanation and examples of Java application programs that use CICS services, and use of CICS-supplied Java class library and the Java Virtual Machine (JVM). We then present a CICS business application that has presentation and business logic.

As a special addition, we present a package called JBMS, which makes it possible to display and interact with 3270 screens from a CICS Java application.

Finally, we provide guidance on debugging and problem determination.

Back cover