0% found this document useful (0 votes)
816 views

Java Application Development For CICS

This edition applies to CICS TS Version 2, Release 3. This edition does not Support the latest version of the Java programming language. Before using this information and the product it supports, read the information in "Notices" on page vii.

Uploaded by

Sai Ranga
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
816 views

Java Application Development For CICS

This edition applies to CICS TS Version 2, Release 3. This edition does not Support the latest version of the Java programming language. Before using this information and the product it supports, read the information in "Notices" on page vii.

Uploaded by

Sai Ranga
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 254

Java Application

Development for CICS


Setting up CICS to run Java
applications

CICS Java problem determination


and debugging

Evolving a legacy application


using Java

Chris Rayns
Scott Clee
Ulrich Gehlert
Vasilis Karras
Debra Payne
Bill Plowman

ibm.com/redbooks
International Technical Support Organization

Java Application Development for CICS

August 2005

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

Third Edition (August 2005)


This edition applies to CICS TS Version 2, Release 3.

© 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 Schedule
Contract with IBM Corp.
Contents

Notices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . vii
Trademarks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . viii

Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ix
The team that wrote this redbook. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ix
Become a published author . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .x
Comments welcome. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xi

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

Chapter 1. Introduction. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.1 z/OS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.2 CICS TS V2.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.3 Java. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.3.1 Java language. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.3.2 Java Virtual Machine. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.3.3 Java for z/OS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.3.4 Runtime Environment and tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.4 CICS TS Support for Java. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.4.1 CICS Java applications using JCICS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.4.2 CICS Support for the JVM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

Chapter 2. Java Virtual Machine support in CICS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15


2.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.2 History of JVM support in CICS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.2.1 CICS TS 1.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.2.2 CICS TS 2.1 and 2.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.2.3 CICS TS V2.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.2.4 CICS TS 3.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.3 JVM operation modes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.3.1 Single-use JVM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.3.2 Continuous JVM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
2.3.3 Resettable JVM. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
2.3.4 Summary of JVM modes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
2.4 JVMSets and the Shared Class Cache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
2.4.1 Benefits of the Shared Class Cache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
2.4.2 Master JVM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
2.4.3 Worker JVM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
2.4.4 Starting the Shared Class Cache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
2.4.5 Inquiring the status of the Shared Class Cache . . . . . . . . . . . . . . . . . . . . . . . . . . 26
2.4.6 Changing the size of the Shared Class Cache . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
2.4.7 Updating classes in the Shared Class Cache . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
2.5 Heap management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
2.5.1 Categories of classes in the IBM prJVM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
2.5.2 How the JVM identifies the category of a class. . . . . . . . . . . . . . . . . . . . . . . . . . . 30
2.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


Chapter 3. Software and hardware requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
3.1 Hardware prerequisites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
3.2 z/OS operating system . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
3.3 External Security Manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
3.4 Java Language Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
3.5 Java Client Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39

Chapter 4. Setting up CICS to run Java applications . . . . . . . . . . . . . . . . . . . . . . . . . . 41


4.1 Running a simple Java application in CICS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
4.1.1 Accessing the z/OS UNIX shell. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
4.1.2 Setting up the CICS sample Java application . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
4.2 System configuration. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
4.2.1 UNIX System Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
4.2.2 Language Environment (LE) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
4.2.3 CICS Transaction Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
4.3 Managing your CICS Java environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
4.3.1 CEMT INQUIRE CLASSCACHE. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
4.3.2 CEMT INQUIRE DISPATCHER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
4.3.3 CEMT INQUIRE JVM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
4.3.4 CEMT INQUIRE JVMPOOL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
4.3.5 CEMT INQUIRE PROGRAM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
4.3.6 CEMT PERFORM CLASSCACHE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
4.3.7 CEMT SET DISPATCHER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
4.3.8 CEMT SET JVMPOOL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61

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

Chapter 5. Getting started . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65


5.1 Coding your application in Rational Application Developer. . . . . . . . . . . . . . . . . . . . . . 66
5.2 Deploying and running the program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
5.2.1 Deploying the code to CICS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
5.2.2 Setting up the transaction and program definitions. . . . . . . . . . . . . . . . . . . . . . . . 72
5.2.3 Running the program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
5.2.4 Troubleshooting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75

Chapter 6. The JCICS API. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77


6.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
6.2 A short overview of the JCICS API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
6.2.1 Program control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
6.2.2 File control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
6.2.3 Synchronization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
6.2.4 Scheduling services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
6.2.5 Unit of work . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
6.2.6 Document services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
6.2.7 Web and TCP/IP services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
6.2.8 Transient storage queues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
6.2.9 Transient data queues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
6.2.10 Terminal control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
6.2.11 Miscellaneous services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
6.2.12 Services not supported by the JCICS API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
6.3 JCICS basics. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
6.4 Input and output streams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
6.5 Exception handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
6.6 Calling other programs and passing data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89

iv Java Application Development for CICS


6.6.1 Calling other programs using LINK and XCTL . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
6.6.2 Communicating via the COMMAREA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
6.7 Remoteable resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
6.8 Using transient storage queues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
6.9 How to perform serialization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
6.10 Web, TCP/IP, and Document services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
6.11 File control. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
6.12 Interval control. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
6.13 Terminal services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110

Chapter 7. Evolving a legacy application using Java . . . . . . . . . . . . . . . . . . . . . . . . . 121


7.1 The legacy trader application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
7.2 Adding a JCICS Web interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
7.2.1 Wrapping the COMMAREA. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
7.2.2 Understanding COMMAREA request formats. . . . . . . . . . . . . . . . . . . . . . . . . . . 126
7.2.3 A test Web application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
7.2.4 Designing the HTML interface. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
7.2.5 Implementing the design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
7.2.6 Setting up TraderPL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
7.2.7 Web security . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
7.3 Migrating TRADERBL to JCICS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
7.3.1 Mapping COBOL to Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
7.3.2 Using TraderBL with VSAM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
7.3.3 Setting up TraderBL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
7.4 Moving to a DB2 back-end . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
7.4.1 Data migration. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
7.4.2 Using TraderBL with DB2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
7.4.3 Setting up TraderBL with DB2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154

Chapter 8. Problem determination and debugging . . . . . . . . . . . . . . . . . . . . . . . . . . . 157


8.1 Debugging and problem determination . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
8.1.1 First considerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
8.2 Where to look when you receive AJ07 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
8.3 Where to look for diagnostic information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
8.3.1 Javadumps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161
8.3.2 JVM stdout and stderr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
8.3.3 Logging events in the JVM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
8.3.4 JVM method tracing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168
8.3.5 JVM class loader tracing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170
8.4 Interactive debugging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
8.4.1 Execution diagnostic facility . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
8.4.2 Java Platform Debugger Architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
8.4.3 The CICS JVM plug-in mechanism . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176

Chapter 9. Performance for Java in CICS TS V2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179


9.1 Reusable JVM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180
9.1.1 The Reusable JVM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180
9.2 Shared Class Cache facility . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
9.3 Things to avoid . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183
9.3.1 Unresettable Event . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184
9.3.2 JVM stealing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184
9.3.3 Reset trace events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
9.3.4 Using application classpath . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187
9.3.5 Excessive garbage collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187

Contents v
9.4 JVM startup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188

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

Appendix A. Channels and containers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193


Creating channels and containers in JCICS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194
Putting data into a container . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194
Passing a channel to another program or task . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194
Link and xctl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194
Return transid . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194
Start transid. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195
Receiving the current channel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195
Getting data from a container. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195
Browsing the current channel. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195
A JCICS example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 196

Appendix B. Hints and tips . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197


Priority of public static void main() methods. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198
Getting transaction arguments using Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198
Never use System.exit() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199

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

Appendix D. Program listings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203


Scratchpad example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204
VsamMap example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206
JBMS (Java Basic Mapping Support) example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210
Component.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210
Container.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212
Field.java. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213
Label.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219
MenuScreen.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219
Panel.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220
PasswordText.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221
PfKeyPanel.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221
Screen.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222
Text.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225
Util.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225

Appendix E. Additional material . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227


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

Related publications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229


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

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

vi 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


Trademarks
The following terms are trademarks of the International Business Machines Corporation in the United States,
other countries, or both:
AD/Cycle® Eserver® Rational®
AFS® HiperSockets™ Redbooks™
AIX® IMS™ Redbooks (logo) ™
C/370™ Language Environment® RACF®
CICS® Multiprise® S/390®
CICSPlex® MVS™ VisualAge®
COBOL/370™ MVS/ESA™ VTAM®
DB2® OS/2® WebSphere®
DFS™ OS/390® z/Architecture™
ETE™ OS/400® z/OS®
eServer™ Parallel Sysplex® zSeries®
Eserver® PR/SM™ 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


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 redbook


This 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


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 Cocker
CICS Strategy and Project Management
IBM Certified Solution Designer—CICS enablement for e-business
IBM Hursley, UK

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

Bob Herman
IBM Global Solutions—CICS System Support, Endicott

Jim Coolbaugh
CICS/390 Early Programs, Raleigh

Julie Czubik
International Technical Support Organization, Poughkeepsie Center

Become a published author


Join 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


Obtain more information about the residency program, browse the residency index, and apply
online at:
ibm.com/redbooks/residencies.html

Comments welcome
Your comments are important to us!

We want our Redbooks™ to be as helpful as possible. Send us your comments about this or
other Redbooks in one of the following ways:
򐂰 Use the online Contact us review redbook form found at:
ibm.com/redbooks
򐂰 Send your comments in an email to:
[email protected]
򐂰 Mail your comments to:
IBM Corporation, International Technical Support Organization
Dept. HYJ Mail Station P099
2455 South Road
Poughkeepsie, NY 12601-5400

Preface xi
xii Java Application Development for CICS
Part 1

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.

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


2 Java Application Development for CICS
1

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.

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


1.1 z/OS
z/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


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
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.3


CICS 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


򐂰 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 Java
Java 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 language


The 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
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


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 Machine


At 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/OS


The 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
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 tools


The 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


򐂰 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 tools
The 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
򐂰 orbd
򐂰 servertool

1.4 CICS TS Support for Java


CICS 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


1.4.1 CICS Java applications using JCICS
You 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 JVM


CICS 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
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


2

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.

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


2.1 Overview
Java 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 CICS


In 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


2.2.1 CICS TS 1.3
CICS 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.2


These 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.3


This 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.1


CICS 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


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 modes


In 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.

Single use JVM (REUSE=NO)


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

Resettable JVM (REUSE=RESET)


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

Continuous JVM (REUSE=YES)


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

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

2.3.1 Single-use JVM


Single 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.

18 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 JVM


This 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


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


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 JVM


The 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


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.

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.

Unresettable actions
As 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()

22 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 behavior


CICS provides logging facilities to assist you in finding out whether and why an application
program has caused a JVM to become unresettable.

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.

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 modes


Table 2-1 on page 24 summarizes the different JVM modes.

Chapter 2. Java Virtual Machine support in CICS 23


Table 2-1 Comparison of JVM modes
REUSE Can program Are programs Relative Can be a Compatible
option in invocations allowed to performance master with the
profile pass state? change JVM? Shared
characteristics Class
of the JVM? Cache?

Single use NO N/A (JVM Yes Lowest (JVM No No


destroyed) initialized for
each use)

Resettable RESET No No (JVM will be Medium Yes Yes


destroyed)

Continuous YES Yes Yes High Yes Yes

2.4 JVMSets and the Shared Class Cache


As 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.

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.

2.4.1 Benefits of the Shared Class Cache


The 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.

24 Java Application Development for CICS


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.

2.4.2 Master JVM


The 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.

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

2.4.3 Worker JVM


The 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.

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.

2.4.4 Starting the Shared Class Cache


The 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.

Chapter 2. Java Virtual Machine support in CICS 25


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 Cache


To 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).

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

Figure 2-2 CEMT INQUIRE CLASSCACHE screen, short form

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

Figure 2-3 CEMT INQUIRE CLASSCACHE screen, long form

26 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:
Started
The 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.
Stopped
The 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


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:
Reset
The master JVM and worker JVMs are resettable.
Reuse
The master JVM and worker JVMs are continuous.
Unknown
The 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 Cache


When 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


2.4.7 Updating classes in the Shared Class Cache
Suppose 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.

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.

2.5 Heap management


In 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 prJVM


All 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).

Chapter 2. Java Virtual Machine support in CICS 29


򐂰 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 class


The 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


System
default c
lasspa th
Bootstrap class loader
System classes

tcla sspath
- Xboo

System default or java.ext dirs


Standard extension
Extension class loader
classes

Shareable trusted ibm.jvm.trusted.middleware.class.path Trusted middleware


Extension class loader
middleware classes (in CICS: use TMPREFIX, class loader (TMC)
CICS_DIRECTORY, JAVA_HOME,
TMSUFFIX)

ibm.jvm.shareable.application.class.path
Shareable Shareable application
application classes class loader (SAC)

java.class.path
Non-shareable Default nonshareable
application classes application class loader

Figure 2-4 Classpath determining class category

2.5.3 Heap management


As 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


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, Quick clear of transactional


mark/sweep) data

Chapter 2. Java Virtual Machine support in CICS 31


System heap Middleware heap Transient heap

Objects 򐂰 Class objects for 򐂰 Objects reachable from 򐂰 Non-shareable


shareable classes the statics of primordial application classes
classes 򐂰 Application objects
򐂰 Non-shareable 򐂰 Primordial objects
middleware classes created by application
򐂰 Middleware objects methods
򐂰 Primordial objects 򐂰 Arrays created by
created by middleware application methods
methods
򐂰 Arrays created by
middleware methods
򐂰 Interned strings and the
arrays for those strings

The system heap


The 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 heap


The 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 heap


The 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 heap


The 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

32 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 mode


In 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


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


Part 2

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.

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


36 Java Application Development for CICS
3

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

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


3.1 Hardware prerequisites
The 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 system


The 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 Environment
Language 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 Manager


In this section we discuss External Security Manager.

Integrated security functions


Security 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


򐂰 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 Support


CICS 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 Support


To 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


40 Java Application Development for CICS
4

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.

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


4.1 Running a simple Java application in CICS
In 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 shell


The 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.

Experienced UNIX user Experienced TSO user

UNIX Interface ISPF based


¾ Direct login (telnet, ssh, rlogin) ¾ ISHELL
¾ OMVS
Menu interface
Command line
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).

42 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


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


4.1.2 Setting up the CICS sample Java application
In 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 makefile


CICS 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


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.

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:$PATH
export PATH
export JAVA_HOME=/usr/lpp/java/J1.4

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.

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.

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.

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 jvm
javac -deprecation -classpath .:/usr/lpp/cicsts/cicsts23/lib/dfjcics.jar examples/HelloWorld/HelloWorld.java
javac -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 HFS


In 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.

46 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

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

Modify the JVM profile


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

Table 4-1 DFHJVMPR options


Option Description What we coded

WORK_DIR Working directory for WORK_DIR=/u/cicsts23/workdir


JVM

CICS_DIRECTORY CICS TS installation CICS_DIRECTORY=/usr/lpp/cicsts/cicsts23


path

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


path

JVMPROPS Path and name of JVMPROPS=/u/cicsts23/props/dfjjvmpr.props


JVM properties file

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


path for Java classes

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 parameters


You 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 definitions


Once CICS is back up, you can log on and install the CICS resource definitions.

Chapter 4. Setting up CICS to run Java applications 47


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 application


Enter 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.

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.

4.2 System configuration


In 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 Services


You 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

48 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


RACF OMVS segment attribute name BPXPRMxx parameter name

ASSIZEMAX MAXASSIZE

CPUTIMEMAX MAXCPUTIME

FILEPROCMAX MAXFILEPROC

PROCUSERMAX MAXPROCUSER

THREADSMAX MAXTHREADS

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.

Chapter 4. Setting up CICS to run Java applications 49


The LE runtime options for the enclave in which the JVM runs are obtained from:
1. CEEDEOPT
2. DFHJVMRO
3. 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.

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

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 Server


This section describes the tasks needed to configure CICS to run Java applications.

Security settings for the CICS region user ID


To 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.

50 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 parameters


You 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.

JVMPROFILEDIR
JVMPROFILEDIR 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


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.

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.

JVMCCPROFILE
JVMCCPROFILE 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.

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

JVMCCSIZE
JVMCCSIZE 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.

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

JVMCCSTART
JVMCCSTART 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.

52 Java Application Development for CICS


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.

MAXJVMTCBS
CICS 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.

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

Setting up JVM profiles


The 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.

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

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

Chapter 4. Setting up CICS to run Java applications 53


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.

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


Option Default Master Worker Standalone

CLASSCACHE NO Ignored YES NO

REUSE RESET RESET or Ignored REUSE or


YES 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 Resettable


only 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


Option Default Master Worker Standalone

DUMP YES OK OK OK

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 files


Each 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.

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.

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


Supplied JVM profile name Corresponding JVM systems property file

DFHJVMCC dfjjvmcc.props

DFHJVMPC dfjjvmpc.props

DFHJVMPR dfjjvmpr.props

Chapter 4. Setting up CICS to run Java applications 55


Supplied JVM profile name Corresponding JVM systems property file

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.

CICS PROGRAM definition attributes


You 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.

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

JVMCLASS
JVMCLASS 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.

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.

JVMPROFILE
JVMPROFILE 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.

56 Java Application Development for CICS


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

CONCURRENCY
JVM programs must be defined as threadsafe.

4.3 Managing your CICS Java environment


The 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 CLASSCACHE


INQUIRE 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


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 DISPATCHER


INQUIRE 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 JVM


INQUIRE 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


4.3.4 CEMT INQUIRE JVMPOOL
INQUIRE 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 PROGRAM


INQUIRE 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


Jvmprofile( DFHJVMPR )

4.3.6 CEMT PERFORM CLASSCACHE


You 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


4.3.7 CEMT SET DISPATCHER
You 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 JVMPOOL


The 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


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


Part 3

Part 3 Java programming


for CICS

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


64 Java Application Development for CICS
5

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.

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


5.1 Coding your application in Rational Application Developer
Now 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


/**
* 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


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.

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\rationa
lsdp6.0\workspace\SG24-5275
C:\Documents and Settings\TOT195\IBM\rationalsdp6.0\workspace\SG24-5275>ftp wtsc
66.itso.ibm.com
Connected 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)): cicsrs3
331 Send password please.
Password: ********
230 CICSRS3 is logged on. Working directory is "CICSRS3.".
ftp> cd /usr/lpp/cicsts/cicsts23/lib
250 HFS directory /usr/lpp/cicsts/cicsts23/lib is the current working directory
ftp> bin
200 Representation type is Image
ftp> get dfjcics.jar
200 Port request OK.
125 Sending data set /usr/lpp/cicsts/cicsts23/lib/dfjcics.jar
250 Transfer completed successfully.
ftp: 139283 bytes received in 0.02Seconds 6964.15Kbytes/sec.
ftp> quit
221 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).

68 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.

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.

5.2 Deploying and running the program


Now 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 CICS


The 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.

Chapter 5. Getting started 69


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

Exporting to a shared file system


To 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).

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.

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.

70 Java Application Development for CICS


Figure 5-3 Export to file system wizard

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.

Exporting via FTP


If 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.

Chapter 5. Getting started 71


Figure 5-4 Export to an FTP server wizard

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.

5.2.2 Setting up the transaction and program definitions


Next, 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

72 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.

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 )

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 program


Now, 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.

Chapter 5. Getting started 73


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.

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

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).

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

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.

74 Java Application Development for CICS


5.2.4 Troubleshooting
If 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. Updates
to 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.)

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

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.

Chapter 5. Getting started 75


76 Java Application Development for CICS
6

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.

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


6.1 Introduction
There 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.

CICS COBOL program


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

CICS translator

Translated COBOL program


CICS translator generates calls into
CALL “DFHEI1" USING … CICS language interface module
END-CALL

COBOL compiler

Language interface
Object code
module

Linkage editor

Load module

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.

78 Java Application Development for CICS


6.2 A short overview of the JCICS API
In 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


6.2.1 Program control
Program 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 control


File 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 Synchronization
Synchronization 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 services


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

6.2.5 Unit of work


This 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 services


Document 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


6.2.7 Web and TCP/IP services
Web 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 queues


Temporary 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 queues


Transient 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 control


Terminal 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


6.2.11 Miscellaneous services
This 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


6.2.12 Services not supported by the JCICS API
The 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 basics


JCICS 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


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.

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.

6.4 Input and output streams


Just 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 handling


Since 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.

84 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


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


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


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


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 data


In 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


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 XCTL


The 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


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 COMMAREA


To 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


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


< 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 resources


Most 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 started
try {
startRequest.setSysId("PJA6"); // System ID of remote CICS region
startRequest.issue(); // Issue request
} catch (CicsException e) {
log("Error starting remote transaction: " + e);
}

Chapter 6. The JCICS API 93


Figure 6-5 The RemoteableResource class hierarchy

6.8 Using transient storage queues


Transient 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


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


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


* 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
Writing 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 serialization


When 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


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


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.

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.

6.10 Web, TCP/IP, and Document services


CICS 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.

Chapter 6. The JCICS API 99


6.11 File control
The 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


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


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 constructors


We 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


}

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 record
Next, 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


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 record
Next, 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


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 record
To 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.

Iteration
Finally, 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


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


}

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 implementation


To 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


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


6.12 Interval control
An 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


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 services


JCICS 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


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.

Component
This 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


Container
This 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.

Panel
Right 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.

Screen
This 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.

Field
This is the abstract superclass of all basic components of a screen, that is, the actual fields
that make up the screen.

Label
Represents 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.

Text
This 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


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


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


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


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


Table 6-2 Some 3270 attributes and their possible values
Type Attribute type Values
code

0xC0 3270 Field attribute 0x20 Field is protected

Value is a combination of bits. 0x10 Field is numeric


Some combinations have
0x30 Field is autoskip (no entry)
special meanings (autoskip,
nondisplay). 0x08 Intensified
Value must be EBCDIC
encoded. 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

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.

Chapter 6. The JCICS API 117


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


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


120 Java Application Development for CICS
7

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.

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


7.1 The legacy trader application
The 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.

VSAM

Company
3270 file
TRADERPL C C TRADERPL
TRADERBL
O O
BMS M LINK M
Presentation M M Business
Presentation
Logic A A Logic
Logic
R R
E E
A A

Customer
file

Figure 7-1 Breakdown of the legacy application

Installation
The COBOL trader application requires the following resources.

Files
The 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.

Programs
Two 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.

Mapset
Trader 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.

122 Java Application Development for CICS


CICS definitions
These 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 interface


The 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


VSAM

Company
3270 file
TRADERPL C C TRADERPL
TRADERBL
O O
BMS M LINK M
Presentation M M Business
Presentation
Logic A A Logic
Logic
R R
E E
A A

Customer
file
LINK

Web
Client
TRADERPJ C
HTTP O
M
JCICS Web M
Presentation A
Logic R
E
A

Java

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 COMMAREA


In 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.

Example
As 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

124 Java Application Development for CICS


Example 7-2 The structure of the wrapper class
public class CommareaWrapper {

// Values in the COMMAREA


private final int[] COMMAREA_BUFFER = {0, 372}; // (1)
private final int[] REQUEST_TYPE = {0, 15};

// Variable to hold the binary data in the COMMAREA


private 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 values
The 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


Binary-based values
COBOL 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[].

Arrays
The 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]);
}

Note: COBOL arrays can get quite complex, but it is still possible to wrapper them using
indexing techniques similar to above.

7.2.2 Understanding COMMAREA request formats


Having 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.

126 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 application


To 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.

SimpleTraderPL
Using 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[].

Important: Program names specified for the JCICS link() command are case sensitive and
so need to be presented in uppercase.

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.

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


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 TRADERBL


commareaWrapper.setRequestType(TraderConstants.GET_COMPANY_REQ);

// Send the data request to TRADERBL


final Program program = new Program();

HttpResponse response = null;


Document document = null;

try {
// Link to TRADERBL
program.setName("TRADERBL");
program.link(commareaWrapper.getByteArray());

// Build the HTML response


response = 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 response


response.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.

Installation
The 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


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.

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.

Running SimpleTraderPL
Bring 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.

Note: The program name at the end of the URL is not case sensitive.

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.

Chapter 7. Evolving a legacy application using Java 129


7.2.4 Designing the HTML interface
After 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 display


The 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.

Logon

Select a
company

Quote, buy or
sell

Real-time
Buy Sell
quote

Figure 7-4 Navigation of the trader application

The HTML design


The 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.

130 Java Application Development for CICS


Quote, buy or sell from
company list

Real-time
Buy Sell
quote

Figure 7-5 Web interface navigation

7.2.5 Implementing the design


With 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.

Note: PDS members have a fixed width, so HTML files uploaded using FTP should be
checked to ensure that long lines are not truncated.

TraderPL
The 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 fields


For 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

Chapter 7. Evolving a legacy application using Java 131


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 data


final 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 page


if (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 instead


showList();
}
}

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


Perform buy/sell
The 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 Traderbl
fCommareaWrapper.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 TRADERBL


sendLinkRequest();

// If the link failed then a message was set by sendLinkRequest.


// If it worked then check the return value from TRADERBL
if (fMessage == null)
fMessage = TraderConstants.getMessage(fCommareaWrapper.getReturnValue());
}

Get request details


All 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.

Note: The Get_Company request to TRADERBL does not produce a return value and so
is not checked.

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.

Chapter 7. Evolving a legacy application using Java 133


Example 7-8 The showList() method
private void showList() {
// Prepare COMMAREA for request to COBOL program Traderbl
fCommareaWrapper.setRequestType(TraderConstants.GET_COMPANY_REQ);

// Send the data request to TRADERBL


sendLinkRequest();

// Return value is not checked as none are returned from a GET_COMPANY_REQ request

// Set appropriate symbol values


final 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 response


sendResponse(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 COMMAREA
fCommareaWrapper.setUserId(Task.getTask().getUSERID());

program.link(fCommareaWrapper.getByteArray());
}
catch (Exception e) { System.err.println(e); e.printStackTrace(); fMessage = "Error - "
+ e; }
}

Note: If security is disabled, the user ID defaults to CICSUSER. See “Web security” on
page 138 for enabling security in Web applications.

Display next page


The 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

134 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.

Tip: Use CEMT INQUIRE DOCTEMPLATE to ensure your DOCTEMPLATE has been
installed.

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 list
document = new Document();
document.setSymbolList(new SymbolList(symbolList)); // (1)

// Append the template


// Note this needs to have been defined in cics as a DOCTEMPLATE resource
document.appendTemplate(template);

// If we get here then the append succeeded


appendTemplateWorked = true;
}
catch (Exception e) { sendErrorResponse(); e.printStackTrace(); }

// If the append failed then send back a message using the document object
if (!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.

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.

For more information about documents and templates, see CICS Application Programming
Guide, SC34-6231.

Chapter 7. Evolving a legacy application using Java 135


7.2.6 Setting up TraderPL
Follow these instructions to install and run TraderPL.

Installation
Similar 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.

Note: DFHHTML is the DD card for template data sets in the startup JCL. In our example it
is set to 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)

136 Java Application Development for CICS


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.

Running TraderPL
Similar 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.

Chapter 7. Evolving a legacy application using Java 137


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.

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.

7.2.7 Web security


Enabling 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.

Note: For information about basic authentication and other forms of Web security, see
CICS Internet Guide, SC34-6245.

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.

138 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.

Note: For enhanced levels of Web security refer to CICS RACF Security Guide,
SC34-6249.

7.3 Migrating TRADERBL to JCICS


A 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.

Chapter 7. Evolving a legacy application using Java 139


3270
TRADERPL C C TRADERPL
TRADERBL
O O
BMS M M
Presentation M M Business
Presentation
Logic A A Logic
Logic
R R
E E
A A

Company
Web file
Client
TRADERPJ C TRADERPL
TRADERBL
TRADERBJ TRADERPL
TraderDataAccess
C
HTTP O O
M M VSAM
JCICS Web JCICS
Presentation Presentation
M M
Presentation Business
Logic Logic
A A
Logic Logic
R R
E E
A A
Customer
Java file
Java

Figure 7-9 Migrating the back-end to JCICS

7.3.1 Mapping COBOL to Java


Instead 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.

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.

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.

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.

Working storage
The 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

140 Java Application Development for CICS


Error messages
These 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 buffers
The 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.

Constants
Various 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 fields
One 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.

Miscellaneous
What 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 together
Following 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


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 access


With 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


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 section
This 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 section
In TRADERBL the MAINLINE section evaluates the request passed in the COMMAREA and
executes the relevant code section before exiting the program.

Writeq-TS
At 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.

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.

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) {

Chapter 7. Evolving a legacy application using Java 143


// Get a time stamp
final 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 comment


comment.trim();

// Original wrote to TSQ, for Java we'll use stdout


System.out.println(timeStamp + " TraderBL: " + comment);
}

Tip: Use tail -f <filename> to continually display Java stdout or stderr in a ssh or telnet
terminal.

Evaluate statement
Evaluate 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-TYPE
WHEN GET-COMPANY-REQ
PERFORM GET-COMPANY
WHEN SHARE-VALUE-REQ
PERFORM GET-SHARE-VALUE
END-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.

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.

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().

144 Java Application Development for CICS


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.

Putting it together
Following 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 reference
fTraderDataAccess = traderDataAccess;

writeComment("Entry");

// Get the commarea byte[] and put in wrapper


fCommareaWrapper.setByteArray(commAreaHolder.value);

// Evaluate the request type


final 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.

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.

Get company
The GET-COMPANY section is the first to include file access functionality. It also has a few
other commands worth mentioning.

Move
To 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

Chapter 7. Evolving a legacy application using Java 145


which wrapper the variable is in and you might need to check the working-storage section for
clarification.

Perform varying
Although 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 version


With 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 bought


The 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-WORK1
EVALUATE SHARES-OVERFLOW
WHEN 0
MOVE SHARES-NORMAL TO NO-OF-SHARES-DEC
MOVE SHARES-NORMAL TO DEC-NO-SHARES
PERFORM UPDATE-BUY-SELL-FIELDS
WHEN OTHER
MOVE INVALID-BUY TO RETURN-VALUE
MOVE TOO-MANY-MSG TO COMMENT-FIELD
PERFORM 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


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 value


This 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));

Housekeeping
It 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


7.3.2 Using TraderBL with VSAM
The 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 component


The 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 READ
FILE('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


7.3.3 Setting up TraderBL
Follow these instructions to install and run TraderPL with TraderBL as the back-end.

Installation
The 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.

Note: Before deploying your newly developed back-end on a live system, ensure it has
been thoroughly tested against sample or replica data.

Running TraderBL
Since 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: Entry
12:07:49 PM TraderBL: Entry to GET-SHARE-VALUE
12:07:49 PM TraderBL: Reading record from customer file
12:07:49 PM TraderBL: Reading record from company file
12:07:49 PM TraderBL: Building return commarea
12: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-end


With 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

Chapter 7. Evolving a legacy application using Java 149


“Migrating TRADERBL to JCICS” on page 139, combined with an understanding of DB2
JDBC, aids this in being a trivial task.

3270
TRADERPL C Company
O file
BMS M
Presentation M TraderDataAccess
Logic A
R VSAM
E
A

Customer
file

C TRADERPL
TRADERBL
TRADERBJ TRADERPL
TraderDataAccess Data
O migration
M JCICS DB2
M Presentation
Business Presentation
A Logic
Logic Logic
R
E DB2
A

Java

Web
Client
TRADERPJ C
HTTP O
M
JCICS Web M
Presentation A
Logic R
E
A

Java

Figure 7-10 Implementing a DB2 back-end

7.4.1 Data migration


The 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 tables
The data in the VSAM file COMPDATA is broken down into the columns shown in Table 7-1.

Table 7-1 The TRADER_COMPANY table


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


Column name Column type Length Nulls

price7daysago Double 8 No

sellcommission Double 8 No

buycommission Double 8 No

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


Column name Column type Length Nulls

username Character 8 No

companyname Character 20 No

sharesheld Decimal 19,0 No

The TRADER_CUSTOMER table contains the minimum fields required to perform share
transactions.

Data migration SQL


To 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 DB2


With 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 connection


A 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)

Chapter 7. Evolving a legacy application using Java 151


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 statements


SQL 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


"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 query
All 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 data


if (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


}
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 TraderDB2Access
The 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 DB2


Follow these instructions to install and run TraderPL with TraderBL using DB2 for data
access.

Installation
The 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


򐂰 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 TraderBL
Since 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


156 Java Application Development for CICS
8

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.

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


8.1 Debugging and problem determination
There 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 considerations


Before 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 using


IBM 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


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


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.

Is the JVM failing to start


Is 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 use


Which 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 abended


If 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 has
failed. (Return code was - X’0000001C’)

Chapter 8. Problem determination and debugging 159


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 AJ07


You 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 information


You 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


– 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 Javadumps
The 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.

JAVADUMP
A 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


򐂰 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


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

CEEDUMP
The 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


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).

SYSDUMP
A 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 Dump
JVMHP012: System Transaction Dump written to PLOWMAN.JVM.TDUMP.COMKZCES.D050419.T231519
JVMDG303: JVM Requesting Java core file
JVMDG304: Java core file written to
/u/plowman/cics630/workdir/JAVADUMP.20050419.231606.83886118.txt
JVMDG215: 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


8.3.2 JVM stdout and stderr
The 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.

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.

8.3.3 Logging events in the JVM


You 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}

Chapter 8. Problem determination and debugging 165


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 events


You 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.881
THREAD=DFJ$JHE2.TASK479.JHE2 (0:349a7f98)
CLASS=ResetJVMEvent
DESCRIPTION=JVM reset number 1 completed successfully
[END EVENT]
[EVENT 0x1]
TIME=12/05/2005 at 10:55:55.227
THREAD=DFJ$JHE2.TASK480.JHE2 (0:349a7f98)
CLASS=ResetJVMEvent
DESCRIPTION=JVM reset number 2 completed successfully
[END EVENT]
[EVENT 0x1]
TIME=12/05/2005 at 10:55:57.294
THREAD=DFJ$JHE2.TASK481.JHE2 (0:349a7f98)
CLASS=ResetJVMEvent
DESCRIPTION=JVM reset number 3 completed successfully
[END EVENT]
[EVENT 0x1]
TIME=12/05/2005 at 10:55:59.203
THREAD=DFJ$JHE2.TASK482.JHE2 (0:349a7f98)
CLASS=ResetJVMEvent
DESCRIPTION=JVM reset number 4 completed successfully
[END EVENT]
[EVENT 0x1]
TIME=12/05/2005 at 10:56:01.333
THREAD=DFJ$JHE2.TASK483.JHE2 (0:349a7f98)
CLASS=ResetJVMEvent
DESCRIPTION=JVM reset number 5 completed successfully
[END EVENT]

Logging unresettable actions


An 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


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.555
THREAD=URECLAS2.TASK513.CECI (0:349a7fb8)
CLASS=UnresettableEvent
DESCRIPTION=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.934
THREAD=URECLAS2.TASK495.CECI (0:349a8028)
CLASS=UnresettableEvent
DESCRIPTION=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 events


One 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


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.747
THREAD=URECLASS.TASK526.CECI (0:349a8128)
CLASS=CrossHeapReferenceEvent
DESCRIPTION=Transient or Shared heap object(0x435FBC88) being referenced in Middleware heap
at 0x3D3895A8. 0x435FBC88 is an instance of java/io/FileOutputStream
STACK=
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.881
THREAD=URECLASS.TASK526.CECI (0:349a8128)
CLASS=UnresettableEvent
DESCRIPTION=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 tracing


Method 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


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=mt
JVMDG200: Diagnostics system property ibm.dg.trc.methods=examples/HelloWorld/HelloCICSWorld.*()
JVMDG200: Diagnostics system property ibm.jvm.events.output=event.log
10: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 buffers


The 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


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 file


You 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.

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.

Formatting trace
The 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 tracing


The 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.

170 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*

Note: The fully qualified class name must be specified.

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.HelloCICSWorld
ExtClassLoader using classpath /usr/lpp/java142s/J1.4/lib/ext/dumpfmt.jar:/usr/lpp/java142s/J1.4/lib/ext/gskikm.jar:/usr/lpp/java14r
ExtClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/lib/ext/dumpfmt.jar
ExtClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/lib/ext/gskikm.jar
ExtClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/lib/ext/ibmjcefips.jar
ExtClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/lib/ext/ibmjceprovider.jar
ExtClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/lib/ext/ibmjce4758.jar
ExtClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/lib/ext/ibmjsseprovider2.jar
ExtClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/lib/ext/ibmpkcs11impl.jar
ExtClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/lib/ext/indicim.jar
ExtClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/lib/ext/jaccess.jar
ExtClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/lib/ext/ldapsec.jar
ExtClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/lib/ext/oldcertpath.jar
ExtClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/lib/ext/recordio.jar
ExtClassLoader could not find examples.HelloWorld.HelloCICSWorld

MiddlewareClassLoader attempting to find examples.HelloWorld.HelloCICSWorld


MiddlewareClassLoader using classpath /SYSTEM/cicsts/cics630/lib/dfjcicsras.jar:/SYSTEM/cicsts/cics630/lib/ras.jar:/SYSTEM/cicsts/cr
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/dfjcicsras.jar
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/ras.jar
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/dfjwrap.jar
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/dfjorb.jar
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/dfjcont.jar
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/dfjcsi.jar
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/dfjcics.jar
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/dfjcdmn.jar
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/dfjjts.jar
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/dfjadjr.jar
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/omgcos.jar
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/dfjname.jar
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/websphere.jar
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/dfjcci.jar
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/ctg/ctgclient.jar
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/ctg/ctgserver.jar
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/ctg/ccf.jar
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /SYSTEM/cicsts/cics630/lib/dfjejbdd.jar
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/standard/ejb/2_0/ejb20.jar
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/standard/jta/1_0_1/jta-specr
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/java142s/J1.4/standard/jca/connector.jar
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/db2710/db2710/jcc/classes/db2jcc.jar
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/db2710/db2710/jcc/classes/db2jcc_javax.jar
MiddlewareClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /usr/lpp/db2710/db2710/jcc/classes/db2jcc_license_r
MiddlewareClassLoader could not find examples.HelloWorld.HelloCICSWorld

AppClassLoader attempting to find examples.HelloWorld.HelloCICSWorld


AppClassLoader using classpath /u/plowman/cics630/myprogs/myCICSPrograms.jar:/u/plowman/cics630/samples/dfjcics:/u/plowman/cics630/s
AppClassLoader could not find examples/HelloWorld/HelloCICSWorld.class in /u/plowman/cics630/myprogs/myCICSPrograms.jar
AppClassLoader found examples/HelloWorld/HelloCICSWorld.class in /u/plowman/cics630/samples/dfjcics
AppClassLoader found examples.HelloWorld.HelloCICSWorld

Chapter 8. Problem determination and debugging 171


8.4 Interactive debugging
In this section we discuss interactive debugging.

8.4.1 Execution diagnostic facility


You 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.

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.

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 Architecture


The 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.

172 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 changes


To 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


CICS resource definition changes
You 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 configuration


We 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.

Note: You need to add dfjcics.jar to the Java build path for your project.

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.

174 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 application


You 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


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.

Figure 8-2 Configuring remote Java application

8.4.3 The CICS JVM plug-in mechanism


In 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.

176 Java Application Development for CICS


Figure 8-3 Debug perspective

Chapter 8. Problem determination and debugging 177


178 Java Application Development for CICS
9

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.

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


9.1 Reusable JVM
In this section we discuss reusable JVM.

CICS TCBs and the JVM


CICS 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 JVM


There 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


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 facility


In 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.

Overview
The 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.

JIT compiled code Shared Memory


JIT compiled code
System Heap ACSH

Nonsystem
Heap Nonsystem
Nonsystem
Heap
Heap

Master JVM Worker1 JVM WorkerN JVM

Figure 9-1 One view of the Shared Class Cache

Chapter 9. Performance for Java in CICS TS V2 181


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.

JVM Pool
MAXJVMTCBS=5

worker
JVM10 JVM6
DFHJVMPR DFHJVMPC Shared
User key User key class cache
Allocated Allocated
to task to task
J9 TCB J9 TCB Master
JVM
JVM9 JVM7 DFHJVMCC
USERJVM1 worker DFHJVMPC User key
CICS key worker User key
Allocated Available JM TCB
to task for reuse
JVM8
J8 TCB J9 TCB
USERJVM2
CICS key
Available
for reuse
J8 TCB

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.

182 Java Application Development for CICS


JVM Pool
MAXJVMTCBS=5

JVM10 JVM6
USERJVM3 DFHJVMPC Shared
REUSE=YES REUSE=RESET class cache
Allocated Allocated
to task to task

Master
JVM
JVM9 JVM7
DFHJVMCC
USERJVM1 DFHJVMPC REUSE=RESET
REUSE=RESET REUSE=RESET
Allocated Available
to task for reuse
JVM8
USERJVM2
REUSE=NO
Available
for reuse

Figure 9-3 REUSE and the Shared Class Cache

Benefits of using the Shared Class Cache


The 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 avoid


This 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.

Chapter 9. Performance for Java in CICS TS V2 183


– 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 stealing


If 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


JVM Stealing

Not-in-use
JVM with No At Max No Init a new
matching JVM TCB? JVM to
profile? match

Yes Yes

JVM with No Wait for an


Reuse JVM other profile available
not-in-use? JVM

Yes

Steal and
reinitialise
it

High TCB Mismatch in CICS Stats


Figure 9-4 JVM stealing

9.3.3 Reset trace events


The 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.

Transient heap
Object D
Active cross heap
reference found at
reset

Object A Object B Object C


JVM reset fails and
JVM destroyed
Middleware heap

Figure 9-5 Active cross heap reference

Figure 9-6 on page 186 shows an example of an inactive cross heap reference.

Chapter 9. Performance for Java in CICS TS V2 185


Transient heap
Object D
Inactive cross heap
reference found at
Nulled reset
reference

Object A Object B Object C


JVM reset ok but costly
Middleware heap

Figure 9-6 Inactive cross heap reference

Transient heap
Object D
Nulled
No cross heap
reference references found at
reset

Object A Object B Object C


JVM reset ok
No performance hit
Middleware heap

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.

186 Java Application Development for CICS


[EVENT 0x1]
TIME=14/03/2001 at 12:03:58.439
THREAD=TRGQIIRP.TASK29685.TRGQ (0:17129580)
CLASS=ResetTraceEvent
DESCRIPTION=0x18C24D70 is an instance of zc01/_callcobolImpl
from address 0x1809Fd80 within obj or array at 0x1809FD78.
0x1809FD78 is an instance of vendor/io/ObjectClass/cache
[END EVENT]
Figure 9-8 Example of a reset trace event message

9.3.4 Using application classpath


Class path is where we have put out application programs on the Classpath and not the
Shareable classpath.

Things to avoid
Total CPU% (of 1 engine)

100

Ave CPU per tran 80


Base 1.67ms
60
GC (heap too 2.14ms
small) 40
No JIT 2.66ms
Debug 23.5ms 20
Java tracing 3.14ms
0
Steal (1:500) 6.47ms
0 200 400 600
Class.path 3.04ms
Transactions per Second
No JIT Too much GC Steal 1:500 Debug=Yes
Base Java tracing Classpath

Figure 9-9 Classpath problems

9.3.5 Excessive garbage collection


Excessive 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.

Chapter 9. Performance for Java in CICS TS V2 187


򐂰 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 startup


JVM 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


JVM startup
2.5
CTS 2.2 GA
CTS 2.2 PTFs
2 CTS 2.3 Cont
CTS 2.3 Reset
CPU seconds

CTS 2.3 Worker


1.5

0.5

Figure 9-10 JVM startup

Chapter 9. Performance for Java in CICS TS V2 189


190 Java Application Development for CICS
Part 4

Part 4 Appendix

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


192 Java Application Development for CICS
A

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.

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


Creating channels and containers in JCICS
To 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 container


To 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 alternatively
custRec.put("00054321");

Passing a channel to another program or task


Similar to the ways COMMAREAs can be passed to programs or tasks, the facility to pass a
channel instead exists also.

Link and xctl


To 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 transid
To 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


Start transid
To 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 channel


It 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 container


Use 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 channel


A 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


}

A JCICS example
Example 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


B

Appendix B. Hints and tips


Here are some tips through the evolution of what a typical Java program in CICS might look
like.

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


Priority of public static void main() methods
CICS 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 Java


When 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


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


200 Java Application Development for CICS
C

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=ON
platform.notASCII=true
java.runtime.name=Java(TM) 2 Runtime Environment, Standard Edition
sun.boot.library.path=/usr/lpp/java/J1.4/bin
java.vm.version=1.4.2
ibm.dg.trc.resettable=on
java.vm.vendor=IBM Corporation
java.vendor.url=http://www.ibm.com/
path.separator=:
gateway.T.trace=off
java.vm.name=Classic VM
file.encoding.pkg=sun.io
sun.os.patch.level=
gateway.T.stack=on
DB2SQLJJDBCPROGRAM=GMBJDBC
gateway.T.exit=off
java.vm.specification.name=Java Virtual Machine Specification
user.dir=/u/cicsts22/workdir
java.runtime.version=1.4.2
java.fullversion=J2RE 1.4.2 IBM z/OS Persistent Reusable VM build cm142sr1a-2005
0209 (JIT enabled: jitc)
java.awt.graphicsenv=sun.awt.X11GraphicsEnvironment
gateway.T=off
java.endorsed.dirs=/usr/lpp/java/J1.4/lib/endorsed
os.arch=390
com.ibm.vm.bitmode=32
java.io.tmpdir=/tmp
line.separator=

gateway.T.entry=off
java.vm.specification.vendor=Sun Microsystems Inc.
java.awt.fonts=
gateway.T.lines=off

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


gateway.T.timing=on
os.name=z/OS
sun.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/lib
ibm.jvm.events.output=event.log
java.class.version=48.0
java.specification.name=Java Platform API Specification
ibm.jvm.unresettable.events.level=max
ibm.system.encoding=Cp1047
java.util.prefs.PreferencesFactory=java.util.prefs.FileSystemPreferencesFactory
os.version=01.06.00
user.home=/u/cicsts22
user.timezone=
java.awt.printerjob=sun.print.PSPrinterJob
java.specification.version=1.4
file.encoding=Cp1047
user.name=CICSTS
java.class.path=/usr/lpp/cicsts/cicsts23/samples/dfjcics:/SC66/mqm/java/lib/com.
ibm.mq.jar:/u/cicsts22/jars/Trader-1.jar
java.vm.specification.version=1.0
sun.arch.data.model=32
java.home=/usr/lpp/java/J1.4
java.specification.vendor=Sun Microsystems Inc.
user.language=en
java.vm.info=J2RE 1.4.2 IBM z/OS Persistent Reusable VM build cm142sr1a-20050209
(JIT enabled: jitc)
java.version=1.4.2
java.ext.dirs=/usr/lpp/java/J1.4/lib/ext
sun.boot.class.path=/usr/lpp/java/J1.4/lib/core.jar:/usr/lpp/java/J1.4/lib/graph
ics.jar:/usr/lpp/java/J1.4/lib/security.jar:/usr/lpp/java/J1.4/lib/server.jar:/u
sr/lpp/java/J1.4/lib/xml.jar:/usr/lpp/java/J1.4/lib/charsets.jar:/usr/lpp/java/J
1.4/classes:/usr/lpp/java/J1.4/lib/ibmcertpathprovider.jar:/usr/lpp/java/J1.4/li
b/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/l
ib/ibmorb.jar:/usr/lpp/java/J1.4/lib/ibmorbapi.jar:/usr/lpp/java/J1.4/lib/ibmpkc
s.jar
java.vendor=IBM Corporation
file.separator=/
java.vendor.url.bug=
java.compiler=jitc
sun.io.unicode.encoding=UnicodeBig
ibm.jvm.trusted.middleware.class.path=/usr/lpp/cicsts/cicsts23/lib/dfjcicsras.ja
r:/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.ja
r:/usr/lpp/cicsts/cicsts23/lib/dfjcdmn.jar:/usr/lpp/cicsts/cicsts23/lib/dfjjts.j
ar:/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/websph
ere.jar:/usr/lpp/cicsts/cicsts23/lib/dfjcci.jar:/usr/lpp/cicsts/cicsts23/ctg/ctg
client.jar:/usr/lpp/cicsts/cicsts23/ctg/ctgserver.jar:/usr/lpp/cicsts/cicsts23/c
tg/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


D

Appendix D. Program listings


This appendix contains the full code of the examples we developed for this book.

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


Scratchpad example
package 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


/**
* 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


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 example
package com.ibm.itso.sg245275.vsam;

import java.util.AbstractMap;
import java.util.AbstractSet;

206 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


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


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


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.java
package com.ibm.itso.sg245275.jbms;

import java.io.ByteArrayOutputStream;

210 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


* @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


* @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.java
package com.ibm.itso.sg245275.jbms;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.text.Format;

Appendix D. Program listings 213


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


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


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


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


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


* 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.java
package 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.java
package 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


/**
* 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.java
package com.ibm.itso.sg245275.jbms;

/**

220 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.java
package 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.java
package 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


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.java
package 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


/**
* 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


*/
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


* @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.java
package 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.java
package 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


, 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


E

Appendix E. Additional material


This redbook refers to additional material that can be downloaded from the Internet as
described below.

Locating the Web material


The 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 material


The additional Web material that accompanies this redbook includes the following files:
File name Description
SG245275.zip Zipped Code Samples

System requirements for downloading the Web material


The following system configuration is recommended:
Hard disk space: 3 MB minimum
Operating System: Windows/z/OS/CICS

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


How to use the Web material
Create 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


Related publications

The publications listed in this section are considered particularly suitable for a more detailed
discussion of the topics covered in this redbook.

IBM Redbooks
For information 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 publications
These 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 resources
These Web sites and URLs are also relevant as further information sources:
򐂰 IBM JVM Diagnostics Guide

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


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 Redbooks


You 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 IBM


IBM Support and downloads
ibm.com/support

IBM Global Services


ibm.com/services

230 Java Application Development for CICS


Index
CHAR-VALUE 147
Numerics CICS Dynamic Storage Areas (DSAs) 51
3270 130 CICS JVM plug-in mechanism 176
64-bit Support 5 CICS language interface module 78
CICS LINK 89
A CICS Master Trace flag being set on 183
AD/Cycle C/370 38 CICS PROGRAM definition attributes 56
AddressResource 98 CONCURRENCY 57
AJ07 abend 160 JVM 56
APAR II13519 159 JVMCLASS 56
APAR PQ79281 39 JVMPROFILE 56
Application abends that are not handled 183 LANGUAGE 57
application-class system heap 32 CICS terminal 48
ASKTIME 143 CICS Transaction Gateway server 6
Autostartst 27 CICS translator 78
CICS using HTTP 99
CICSUSER 134
B Class declaration and constructors 102
Basic Mapping Support 81 COBOL 6, 122
Binary based values 126 COMMAREA 91, 124, 133
BMS 81, 130 COMMAREA-BUFFER 124, 141
BPXI040 49 CommareaWrapper 125, 133, 141
BPXPRMxx 49 Common Client Interface (CCI) 39
BPXPRMxx parameter 49 Common Work Area 82
MAXASSIZE 49 Common Work Area (CWA) 82
MAXCPUTIME 49 COMPANY-IO-BUFFER 141
MAXFILEPROC 49 CompanyIOWrapper 141
MAXPROCUSER 49 COMPFILE 122
MAXTHREADS 49 Component 111
BUY-SELL-UPDATE 147 Container 112
Continuous JVM 180
conversion 141
C CUSTFILE 122
C/C++ 4 CustomerIOWrapper 141
Cachefree 27 CWBA 127
Cachesize 27
CALCULATE-SHARES-BOUGHT 146
calculateSharesBought() 147 D
CECI 73 Data migration SQL 151
CEDA 48 Database tables 150
CEDX 172 Datestarted 27
CEE3DMP 161 DB2 5, 139
CEEDUMP 161, 163 Debugging 158
CEEHRNUH 163 JVM abended? 159
CEEPIPI 48, 159 JVM failing to start? 159
CEMT INQUIRE CLASSCACHE 57 Debugging the application 175
CEMT INQUIRE DISPATCHER 58 DecimalFormat 147
CEMT INQUIRE JVM 58 Deploying code to CICS 69
CEMT INQUIRE JVMPOOL 59 DFH$JVM 48
CEMT INQUIRE PROGRAM 59 DFHJVMCC 52
CEMT PERFORM CLASSCACHE 60 DFHJVMCD 52
CEMT SET DISPATCHER 61 DFHJVMPC 182
CEMT SET JVMPOOL 61 DFHJVMPR 52, 182
Channels & containers 193 DFHWEB 129
Character based values 125 DFJ$JHE2 48

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


diagnostic information 160 Hot Pooling 17
DOCTEMPLATE 134, 136 HPJ 17
Document 128 HTML 4, 130
Document API 80 HTML design 130
Document services 80 HTTP input fields 131
Documents 131 HttpResponse 128
dynamic HTML 131
Dynamic VIPA (virtual IP addressing) 6
I
IBM Directory Server 5
E IBM eServer zSeries 4
EIBRESP 142 IBM Rational Software Development Platform (RAD). 38
ENQ/DEQ 97 ImageLoader 136
Enterprise JavaBeans 4 IMS(TM) 6
Entry Sequenced Data Sets (ESDS) 80 Integrated Cryptographic Service Facility (ICSF) 5
entry-sequenced data set 100 Intelligent Resource Director (IRD) 4
ESDS 100 IPCSEMNSEMS 48–49
EVALUATE 144 ISPF shell 43
exceptions
checked 85
unchecked 85 J
Excessive garbage collection 184 J2EE Connector Architecture Specification 39
EXEC CICS DOCUMENT 99 Java 140
EXEC CICS WEB 99 Java Build Path 68
Execution diagnostic facility 172 Java Client Support 39
External Security Manager 38 Java for z/OS 9
DCE Security Server 39 Java Language 7
Firewall Technologies 39 Java Language Support 39
Lightweight Directory Access Protocol 38 Java Platform Debugger Architecture 172
Network Authentication Services 39 Java Program Objects 17
Open Cryptographic Enhanced Plug-ins 38 Java SDK 5
RACF 38 Java servlets 81
Java Virtual Machine 9
Java Virtual Machines (JVMs) 12
F JAVA_DUMP_OPTS 161
formatting 141 Javadumps 160–161
Formatting trace 170 JBMS 81
FORTRAN IV 38 JCICS API 79
JCICS Web interface 123, 129
JCICS Web program 127
G JDBC 12
G5 38 JHE2 48
G6 38 JNDI 12, 19
GET 131 JVM class loader tracing 170
getByteArray() 127 JVM method tracing 168
GET-COMPANY 144–145 JVM operation modes 18
getCompany() 144, 146 Continuous mode 18
GID 50 Resettable mode 18
GUI 16 Single use mode 18
JVM profile 47
H JVM profile options 54
Heap management 29 CICS_DIRECTORY 54
The application-class system heap CLASSCACHE 54
application-class system heap 32 CLASSCACHE_MSGLOG 54
The Middleware heap 32 CLASSPATH 54
The system heap 32 DUMP 55
The transient heap 32 JAVA_HOME 54
HelloCICSWorld Java application 48 JVMPROPS 54
HFS 46 LIBPATH 54
High Performance Java 17 REUSE 54
HiperSockets 4 STDERR 54

232 Java Application Development for CICS


STDIN 54 M
STDOUT 54 main() 143
TMPREFIX, TMSUFFIX 54 MAINLINE 143
VERBOSE 54 master JVM 24
WORK_DIR 54 MAXASSIZE 48
Xinitacsh 54 MAXCPUTIME 49
Xinitsh 54 MAXFILEPROC 48
Xinitth 54 MAXJVMTCBS 53
Xmaxe 54 MAXPROCSYS 48
Xmaxf 54 MAXPROCUSER 48–49
Xmine 54 MAXPTYS 48
Xminf 54 MAXTHREADS 49
JVM profile options table 54 MAXTHREADTASKS 49
JVM Startup 188 MAXUIDS 48
JVM stdout and stderr 165 Middleware heap 32
JVM stealing 183 move 145
JVM support in CICS 16 Multiprise 3000 servers 38
CICS TS 1.3 17 MVS IEATDUMP 161
CICS TS 2.1 and 2.2 17
CICS TS 2.3 17
CICS TS 3.1 17 N
JVM system properties files 55 NameResource 98
JVMCCPROFILE 25, 52 Network Authentication Services 39
JVMCCSIZE 52 NEWTRAD 122
JVMCCSTART 52 non-shareable 25
JVMCCSTART PARAMETERS NUM-VALUE 147
JVMCCSTART=NO 26
JVMCCSTART=YES 26
JVMPROFILEDIR 47, 51
O
object-oriented (OO) 3
JVMSet 24
OCCURS X TIME 126
JVMSets and the shared class cache 24
Oldcaches 27
Benefits of the shared class cache 24
OpenLDAP 5
JVMCCSTART=AUTO,JVMCCSTARTPARAME-
TERS
JVMCCSTART=AUTO 26 P
JVMCCSTART=NO 26 Parallel Sysplex 4
JVMCCSTART=YES 26 PERFORM 144, 146
Master JVM 25 performBuy() 133
Worker JVM 25 performSell() 133
Phasingout 28
PL/I 6
K POST 131
Key Sequenced Data Sets (KSDS) 80
Program control 80
key-sequenced data set 100
PTFs 159
KSDS 100
UK00802 159
UQ90449 159
L UQ93743 159
Language Environment 49 Public Key Services in z/OS 6
CEEDEOPT 50
DFHJVMRO 50
SCEERUN 49
R
RACF 38
SCEERUN2 49
RACF ADDUSER 49
LDAP 38
RACF OMVS 49
legacy trader application 122
ASSIZEMAX 49
LIBPATH 51
CPUTIMEMAX 49
Linux for zSeries 4
FILEPROCMAX 49
Logging reset events 166
PROCUSERMAX 49
Logging unresettable actions 166
THREADSMAX 49
logoff 139
Rational Application Developer 65
LPARs 5

Index 233
RBHOME 136 TRADERPL 122
Redbooks Web site 230 TraderPL 131–132
Contact us xi TRADERPS 129
relative record data set 100 Transaction Work Area 82
Relative Record Data Sets (RRDS) 80 Transaction Work Area (TWA) 82
request formats 126 Transient data queues 81
Reset Trace Events 183 transient heap 32
RETURN 145 Transient storage queues 81
Return transid 194 Troubleshooting 75
Reusable JVM 18, 180 TSO ISHELL 43
REUSE=RESET 182 TSO OMVS 43
Reusest 28
rlogin 44
RRDS 100 U
UID 50
Unicode 4
S Unknown RefID_ijava
SDFJAUTH 51 bytecode 8
SDK tools 11 dynamically loading classes 8
sendErrorResponse() 128, 135 Unresettable Event 184
sendLinkRequest() 134 Unresettable events 183
sendResponse() 135 UPDATE-BUY-SELL 133
Service Oriented Architecture (SOA) 17 URL 129, 137
services oriented architecture (SOA) 6 userid 134
SETOMVS 49 USEROUTPUTCLASS 51
Shared Class Cache Facility 181 Using Application Classpath 184
showList() 134
SimpleTraderPL 128
SQL statements 152 V
ssh 44 VisualAge for Java 91
standard extensions 29 VS FORTRAN 38
Start transid 195 VTAM 82
strip() 133
symbol list 133 W
SymbolList 135 Web 127
symbols 131 Web and TCP/IP services 81
SYSDUMP 164 Web pages 131
Sysplex Distributor 6 Web security 138
system heap 32 WebSphere Application Server 12
WebSphere MQ message queues 81
T worker JVM 24
tail 144 Working storage 140
TCP/IP network support 6 WORKING-STORAGE 142
TCPIPS 129 wrapper 124
TCPIPSERVICE 129 writeMessage() 143
telnet 44 WRITEQ-TS 143
templates 131, 136 Writeq-TS 143
Terminal control 81 Writing trace to buffers 169
Terminal services 110
Timestarted 28 X
TMPREFIX 51 XCTL (“transfer control”) 89
TMSUFFIX 51 Xdebug=YES 173
TN3270 6 XML 4
Totaljvms 28
TRADER 123
Trader-1.jar 128 Z
TRADERBL 122, 140 z/Architecture 4
TraderConstants 127, 133 z/OS 3
TraderDataAccess 142 4
TRADERPJ 136 z/OS HTTP Server 5

234 Java Application Development for CICS


z/OS LPAR 44
z/OS Managed System Infrastructure 5
z/OS UNIX System Services for z/OS (USS) 9
z/VM 4
z800 38
z890 38
z900 38
z990 38

Index 235
236 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
Java Application Development for
CICS
Java Application Development for
CICS
Back cover ®

Java Application
Development for CICS

Setting up CICS to run This IBM Redbook is intended for clients who are implementing
the Java language support provided by CICS Transaction Server INTERNATIONAL
Java applications
for z/OS V2.3. Its prime audience is CICS and z/OS system TECHNICAL
programmers who provide support for Java application SUPPORT
CICS Java problem development, and Java application programmers who need a
gentle introduction to Java development for CICS. ORGANIZATION
determination and
debugging This book assumes a certain level of knowledge of z/OS, CICS,
UNIX System Services, and Java.
Evolving a legacy
We start by reviewing the basic concepts of the z/OS, CICS TS
application using V2.3, and Java environments, and introduce new terminology. We
BUILDING TECHNICAL
Java then discuss the software and hardware requirements for
INFORMATION BASED ON
developing and executing Java applications in CICS TS V2.3 and PRACTICAL EXPERIENCE
the customization of the application development environment,
UNIX System Services, MVS, and CICS. IBM Redbooks are developed
by the IBM International
We briefly discuss three possible application development Technical Support
roadmaps: Java application programs that use CICS services, Organization. Experts from
IIOP server applications, and CICS Enterprise Beans. IBM, Customers and Partners
from around the world create
Subsequent chapters contain an expanded explanation and timely technical information
examples of Java application programs that use CICS services, based on realistic scenarios.
and use of CICS-supplied Java class library and the Java Virtual Specific recommendations
Machine (JVM). We then present a CICS business application are provided to help you
that has presentation and business logic. implement IT solutions more
effectively in your
As a special addition, we present a package called JBMS, which environment.
makes it possible to display and interact with 3270 screens from a
CICS Java application.

Finally, we provide guidance on debugging and problem


determination. For more information:
ibm.com/redbooks

SG24-5275-02 ISBN 0738493791

You might also like