Java Application Development For CICS
Java Application Development For CICS
Chris Rayns
Scott Clee
Ulrich Gehlert
Vasilis Karras
Debra Payne
Bill Plowman
ibm.com/redbooks
International Technical Support Organization
August 2005
SG24-5275-02
Note: Before using this information and the product it supports, read the information in “Notices” on
page vii.
© 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
Contents v
9.4 JVM startup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231
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.
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.
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.
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.
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.
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.
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
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.
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.
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.
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.
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.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.
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.
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
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.
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.
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.
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.
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
Chapter 1. Introduction 11
orbd
servertool
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
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.
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.
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.
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.
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.
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).
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.
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.
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.
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.
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.
*/
/**
* 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());
}
}
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.
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.
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.
To summarize, the resettable JVM provides the benefits of reuse while offering the greatest
protection between program invocations.
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()
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.)
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.
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.
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.
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.
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.
I CLASSCACHE
STATUS: RESULTS - OVERTYPE TO MODIFY
Cla Ena Sta Pro(DFHJVMCC) Dat(04/05/05) Tim(11:55:15)
Tot(0001) Old(0000) Pha(0000) Reu Caches(24M )
SYSID=PJA7 APPLID=SCSCPJA7
RESPONSE: NORMAL TIME: 11.55.39 DATE: 04.05.05
PF 1 HELP 3 END 5 VAR 7 SBH 8 SFH 9 MSG 10 SB 11 SF
I CLASSCACHE
RESULT - OVERTYPE TO MODIFY
Classcache
Autostartst( Enabled )
Status(Started)
Profile(DFHJVMCC)
Datestarted(04/05/05)
Timestarted(11:55:15)
Totaljvms(0001)
Oldcaches(0000)
Phasingout(0000)
Reusest(Reuse)
Cachesize(24M )
Cachefree(18389160 )
SYSID=PJA7 APPLID=SCSCPJA7
TIME: 11.56.16 DATE: 04.05.05
PF 1 HELP 2 HEX 3 END 5 VAR 7 SBH 8 SFH 10 SB 11 SF
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.
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.
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.
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.
tcla sspath
- Xboo
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
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.
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.
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 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.
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 {
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.
Use the documentation provided with each product for guidance on their installation.
z/OS runs on the latest IBM mainframe servers—the z990, z900, z890, z800, G6, G5, and
Multiprise® 3000 servers.
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)
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.
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.
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.
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.
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.
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).
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.
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.
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.
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
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).
$ [SC66] /u/cicsrs1:
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).
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.
You have now created two Java classes, HelloWorld and HelloCICSWorld. They are stored in
the $CICS_HOME/samples/dfjcics/examples/HelloWorld directory.
You also create a new working directory for the JVM. The CICS JVM uses this directory when
creating the stdin, stdout, and stderr files for the JVM. The working directory is specified in the
JVM profile.
Tip: The cp commands in Example 4-4 specify a period (.) as the target directory. In UNIX,
this denotes the current directory.
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.
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.
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.
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.
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)
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.
The options in Example 4-6 cannot be over-ridden and are set by the CICS JVM launcher
program.
You can override all other runtime options for the JVM by assembling and linking a module
called DFHJVMRO. The source code for a sample DFHJVMRO is provided in SDFHSAMP. A
DFHJVMRO load module is not shipped.
If you assemble and link a new version of DFHJVMRO while CICS is running, you must use
the command CEMT SET PROG(DFHJVMRO) NEW to load the new version of the program.
If DFHJVMRO cannot be loaded by the JVM launcher program, CICS builds the default
runtime options programmatically. Example 4-7 shows the default runtime options.
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.
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
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.
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.
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.
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.
WORK_DIR /tmp OK OK OK
Xmaxe 0 OK OK OK
Xmaxf 0.6 OK OK OK
Xmine 1 MB OK OK OK
Xminf 0.3 OK OK OK
STDERR dfhjvmerr OK OK Ok
STDIN dfhjvmin OK OK OK
STDOUT dfhjvmout OK OK OK
VERBOSE NO OK OK OK
DUMP YES OK OK OK
Java Applications in CICS, SC34-6238, contains more detailed information about the
CICS-supplied JVM profiles.
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.
DFHJVMCC dfjjvmcc.props
DFHJVMPC dfjjvmpc.props
DFHJVMPR dfjjvmpr.props
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.
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.
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.
CONCURRENCY
JVM programs must be defined as threadsafe.
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.
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
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.
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.
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.
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.
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).
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.
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.
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.
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.
import java.io.PrintWriter;
import com.ibm.cics.server.*;
/**
* 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)
}
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.
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.
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).
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.
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.
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.
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.
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.
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.
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.
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.
After a moment, the program should print its output to the terminal (Example 5-3).
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.
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).
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.
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.
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.
Figure 6-1 shows the program preparation process for CICS applications by example of a
COBOL program.
CICS translator
COBOL compiler
Language interface
Object code
module
Linkage editor
Load module
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.
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.
In the following sections, we briefly describe several functional areas of the API.
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.
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();
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.
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.
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.
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.
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.
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 {
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
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.
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.
As usual, error reporting and handling in JCICS is integrated into the standard Java exception
handling mechanism.
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.
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.
import java.io.PrintWriter;
import com.ibm.cics.server.*;
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).
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.
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).
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.
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.
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.
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.
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).
public LinkDemo() {
okk850 = new Program();
okk850.setName("OKK850");
}
...
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.
import com.ibm.cics.server.CommAreaHolder;
To test the program, we can write another little program (Example 6-8), which invokes it using
Program.link().
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).
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.
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
Example 6-11 shows a skeleton version of our Scratchpad class, just having a reference to
the TS queue to use, and three constructors.
/**
*
* Demonstrates how to use TS queues as a scratchpad.
*
* @author Ulrich Gehlert
*/
public class Scratchpad {
Next, we implement methods for writing data into, and getting data from, the scratchpad
(Examples Example 6-12 and Example 6-13, respectively).
/**
* 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)
}
/**
* 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);
}
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
You can enqueue by string or by address. The JCICS classes provide an AddressResource
class and a NameResource class (see Figure 6-6).
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.
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.
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.
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.
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.
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)
/**
* 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);
}
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.
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.
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).
Adding a record
To implement Map.put(), we try to write a record to the data set (Example 6-18).
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.
public VsamIterator() {
try {
fb = ksds.startBrowse(new byte[keylength]); // (1)
} catch (CicsException e) {
throw new RuntimeException(e);
}
}
import java.util.Iterator;
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);
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.
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.
import java.util.BitSet;
import com.ibm.cics.server.*;
You can test the sample using CEMT, as we show in Example 6-23.
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.
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.
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.
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).
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;
term.clear();
while (!end) {
// 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);
// 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);
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.
To generate the data stream, we recursively iterate over all components (Example 6-26).
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.
0xF1 Blink
0xF4 Underscore
0xF1 Blue
...
0xFF White
Now we are ready to show how the data stream for a single field is generated (Example 6-27).
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)
}
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)
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.
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
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.
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.
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
Following this approach, you will implement a Web interface to the trader application using
the JCICS Web API.
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).
/*
* 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) { ... }
}
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.
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.
Note: COBOL arrays can get quite complex, but it is still possible to wrapper them using
indexing techniques similar to above.
If you set these values in the CommareaWrapper and link to TRADERBL the data returned
will be exactly the same as that for TRADERPL.
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.
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.
try {
// Link to TRADERBL
program.setName("TRADERBL");
program.link(commareaWrapper.getByteArray());
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>");
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.
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.
Logon
Select a
company
Quote, buy or
sell
Real-time
Buy Sell
quote
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.
Real-time
Buy Sell
quote
Note: PDS members have a fixed width, so HTML files uploaded using FTP should be
checked to ensure that long lines are not truncated.
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.
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
public TraderPL() {
try {
action = request.getFormField("action");
fCompanyName = request.getFormField("companyname");
fNumShares = request.getFormField("numshares"); // Used when buying/selling shares
}
catch (InvalidRequestException e) {}
Note: By default, HTTP parameters are case sensitive. To bypass this your Java program
can use the String.toLowerCase() function for string comparisons.
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.
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.
// Return value is not checked as none are returned from a GET_COMPANY_REQ request
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.
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.
try {
// Create a new document and set the symbol list
document = new Document();
document.setSymbolList(new SymbolList(symbolList)); // (1)
// 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) {}
}
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.
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)
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)
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.
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.
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.
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.
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.
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
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
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 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.
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.
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.
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.
comment =
comment.replaceFirst("#RRRRRRRRRRRRRR", fCommareaWrapper.getRequestType());
comment =
comment.replaceFirst("#UUUUUUUUUUUUUU",
fCommareaWrapper.getUserId().substring(0, 15));
comment =
comment.replaceFirst("#R", fCommareaWrapper.getReturnValue());
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.
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().
Putting it together
Following the directions discussed so far, the MAINLINE code in TraderBL becomes the code
shown in Example 7-17.
writeComment("Entry");
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");
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
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.
fTraderDataAccess.getCompanyNames(fCommareaWrapper);
}
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
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.
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.
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.
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.
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.
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.
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
Database tables
The data in the VSAM file COMPDATA is broken down into the columns shown in Table 7-1.
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
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.
username Character 8 No
companyname Character 20 No
The TRADER_CUSTOMER table contains the minimum fields required to perform share
transactions.
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);
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;
}
try {
fConnection.close();
fConnection = null;
}
catch (Exception e) {
result = DFHRESP_UNKNOWN;
System.err.print("Exception: " + e);
e.printStackTrace();
}
return result;
}
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.
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.
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)
closeConnection();
return result;
}
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.
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.
The new CICS resources that need to be defined alongside the existing definitions in the
TRADER group are:
DB2ENTRY(TRADER)
PLAN(DSNJDBC)
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.
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.
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.
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/
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.
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.
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.
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
Each line of the JAVADUMP starts with a tag. This tag can be used to parse the JAVADUMP.
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.
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).
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.
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
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.
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.
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
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.
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}
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.
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.
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.
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 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.
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.
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.
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[,...]]
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.
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.
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.
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.
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.
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.
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: 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.
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.
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.
You could also change the profile name temporarily using the expanded CEMT INQ
PROGRAM display.
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.
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.
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.
These plug-ins are not described further in this book. Refer to Java Applications in CICS,
SC34-6238, for more information.
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.
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
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.
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.
Nonsystem
Heap Nonsystem
Nonsystem
Heap
Heap
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
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.
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
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.
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.
Not-in-use
JVM with No At Max No Init a new
matching JVM TCB? JVM to
profile? match
Yes Yes
Yes
Steal and
reinitialise
it
Transient heap
Object D
Active cross heap
reference found at
reset
Figure 9-6 on page 186 shows an example of an inactive cross heap reference.
Transient heap
Object D
Nulled
No cross heap
reference references found at
reset
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.
Things to avoid
Total CPU% (of 1 engine)
100
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.
0.5
Part 4 Appendix
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.
// Or alternatively
custRec.put("00054321");
Return transid
To set the next channel on a program-return call, use the setNextChannel() method of the
TerminalPrincipalFacility class.
if (custData != null) {
Container custRec = custData.getContainer("Customer_Record");
}
else {
System.out.println("There is no Current Channel");
}
While (iterator.hasNext()) {
Container custData = iterator.next();
// Process the container...
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();
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).
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.
if (args != null) {
final java.util.StringTokenizer tokenizer =
new java.util.StringTokenizer(args, " "); // (1)
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.
gateway.T.entry=off
java.vm.specification.vendor=Sun Microsystems Inc.
java.awt.fonts=
gateway.T.lines=off
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 {
/**
* 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;
}
/**
* 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 {
/**
* 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;
/**
* 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 {
public VsamIterator() {
try {
fb = ksds.startBrowse(new byte[keylength]);
} catch (CicsException e) {
throw new RuntimeException(e);
}
}
public SimpleEntry(Map.Entry e) {
this.key = e.getKey();
this.value = e.getValue();
}
/**
* 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);
}
import java.io.ByteArrayOutputStream;
/**
* 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;
}
/**
/**
* 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.
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;
/**
* 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;
}
/**
* 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
*/
/**
* 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.
*
*/
/**
* 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.
*/
/**
* @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;
}
/**
/**
* 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 {
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;
Label titleLabel;
Label promptLabel;
Text promptText;
List choiceLabels = new ArrayList();
List itemLabels = new ArrayList();
Panel selectionPanel;
Panel.java
package com.ibm.itso.sg245275.jbms;
/**
/**
* 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 {
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");
/**
* Constructor using the default row position (24).
*
* @param parent This panel's parent (a Screen).
*/
public PfKeyPanel(Screen parent) {
this(parent, 23);
}
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 {
public Screen() {
super(null, 0, 0);
}
/**
* 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;
}
/**
* @return Returns the 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();
}
/**
/**
* 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 {
Util.java
package com.ibm.itso.sg245275.jbms;
/**
* Contains utility methods.
*
* @author Ulrich Gehlert
*/
class Util {
Select the Additional materials and open the directory that corresponds with the redbook
form number, SG245275.
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
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
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.