When developing a Java program to link to a CICS COBOL program with a COMMAREA or to access a VSAM file, you will typically need to map the data fields from a record structure to specific Java datatypes. This article describes a batch process to automate the generation of Java helper classes from a COBOL copybook using the IBM Record Generator for Java V3.0 and then shows how to use the generated Java classes in a CICS Java application.
Prerequisites
IBM Record Generator for Java V3
IBM JZOS Toolkit API package com.ibm.jzos.fields at V2.4.8 or later
IBM Enterprise COBOL for z/OS V4.2 or later
Eclipse development environment with the CICS Explorer SDK plugin
A CICS JVM server if you want to deploy the example into CICS
Estimated time
It should take you about 1 hour to complete this tutorial.
IBM Record Generator for Java
The Record Generator is a scriptable Java-based utility that takes as input the ADATA from the COBOL compiler, and uses it to generate Java helper classes to access the fields in a COBOL record structure. The ADATA provides additional program data that can be used to extract information about the program for symbolic debugging or cross-reference tools. The Record Generator is based on a function in the IBM JZOS Toolkit that provides field converter classes for mapping byte array fields into Java data types.
Product details
IBM Record Generator for Java V3.0 is an IBM product that was generally available as of 29th Sept 2017. It superseded the IBM alphaWorks version of the JZOS Record Generator V2.4.6, which is now withdrawn. The Record Generator for Java, V3.0, provides the following new and enhanced functions:
Support for ADATA files with or without an IBM Record Descriptor Word (RDW) prefix, making it easier to transfer the ADATA files from z/OS to distributed platforms
Support for a user-supplied, Java name generator class to control the schema for generating accessor methods from field names
Support to ignore OCCURS 1 on COBOL single element arrays, so that fields are generated as an array of size 1
Ability to set the string encoding during record generation
A set of new generation options to optimize the generated code
The Record Generator for Java V3.0 is freely available to download for all users of z/OS V2.1, or later. License redistribution rights are provided for deployment to non-z/OS platforms to support distributed development and build.
Steps
The following steps will be covered in this article:
Download the Record Generator zip archive from the download site.
Extract ibm-recgen.jar and transfer this to a directory on your zFS as this will be required by the batch job to generate records from the COBOL source.
Download the EDUPGM CICS COBOL sample if you want to deploy the example from this tutorial.
2. Use the Record Generator to create the Java record wrapper class
The next step is to create the Java record wrapper class from the COBOL copybook using the IBM Record Generator for Java. This creates a helper class than can then be used in your Java application to marshal data to and from the COBOL record-based structures.
2.1. Create the COBOL build job
The first step in creating a record is to modify the compile process to
produce ADATA output. To produce the ADATA you simply need to add the
ADATA keyword to the COBOL PARM statement and then direct the output to
a pre-allocated SYSADATA dataset. This ADATA dataset will then be used
as input for the Java record generation in the next step.
Next, if required, link edit the load module for deployment into CICS.
The following JCL provides a sample COBOL V5.1 compile job with the
ADATA PARM option and SYSADATA DD, based on the sample in the CICS
translate and compile job DFHZITCL:
Now create a job step using BPXBATCH to invoke the Java
RecordClassGenerator utility class from the ibm-recgen.jar using the
ADATA as the input and naming the desired COBOL structure. In the
example below, we used the ADATA in the input PDS
USER.CICS.COBADATA from step 2.1 and generated a record
com.ibm.cicsdev.bean.JZOSCommareaWrapper.java. This wrappers the
DFHCOMMAREA structure from our EDUPGM COBOL program. The inputs to the
job are parameterized to allow this to be scripted later.
Lastly, you need to build the Java record JZOSCommareaWrapper.java
created in step 2.2. This requires compiling using the javac compiler
and then packaging as a JAR for deployment using the Java-supplied jar
utility. You can simply add the following statements to the end of the
BPXBATCH job step:
The job is now ready and can be used as part of a build system to easily
rebuild the record when any changes are made to the copybooks. The
record can be transferred to your source code management system and
then downloaded for use in an Eclipse development environment to assist
with the marshalling of data when interacting with COBOL structures in a
COMMAREA or other sequential data records such as VSAM files.
3. Develop the CICS Java program
CICS Java development is centered around the use of the CICS Explorer
SDK, which helps you develop with OSGi. In an OSGi development
environment, Target Platform definitions are used to define the plug-ins
that applications in the workspace will be built against.
3.1 Create the Eclipse project
The first step is to create an Eclipse project. You will be using an OSGi
development environment, so before you generate any code you first
need to create a new OSGi Plug-in project in Eclipse using the wizard:
File -> New -> Plug-in Development -> Plug-in Project.
As you go through the New Plug-in Project wizard, follow these steps:
On the first panel of the New Plug-in Project wizard, select the standard OSGi framework option as you do not need any extra Eclipse or Equinox extensions.
On the second panel, make sure that the Version is set to 1.0.0 without a qualifier as the OSGi JVM server does not support the use of qualifiers. Also ensure that the selected Java execution environment is supported in your JVM server, and that the option to generate an activator is not selected as this is not required.
On the third panel, uncheck the box to "Create a plug-in using a template" as you will add your own application code to the project.
3.2 Creating the Target Platform
The CICS Explorer SDK provides a set of sample Target Platforms that
provide the JCICS APIs for different CICS TS versions. The Target
Platform is set using the Eclipse menu: Windows -> Preferences ->
Plug-in Development -> Target Platform. Click Add, and then from
the supplied templates select the CICS TS release for your runtime
environment, and click Next and then Finish. You can then select
this and apply it to your workspace, which will allow you to use
the JCICS APIs in your application. For further details on the options
for defining OSGi package imports, refer to the article Configuring
OSGi package imports.
3.3 Adding OSGI package imports
In addition to JCICS, you also need to consider the Java packages used by the generated records. These records rely on classes in the the com.ibm.jzos.fields package, which is provided with the IBM SDK for Java V8 on z/OS in ibmjzos.jar available in the lib/ext directory, or by IBM Semeru Runtime Certified Edition, Version 11 from this download site.
If you just use the pre-built generated records in your application, then OSGI package imports are not required when compiling the application; however, they will be required at runtime in the OSGI JVM server as all the dependencies need to be correctly wired when the OSGI bundles are installed. To resolve this import, there are 3 options:
Download and wrapper the ibmjzos.jar as an OSGI bundle, export the required packages, add this OSGI bundle to your Eclipse workspace or target platform, and then add an Import-Package statement for com.ibm.jzos.fields to the bundle manifest.
Use a resolution:=optionalImport-Package statement in the OSGi bundle manifest. This will allow the bundle to activate if the packages can't be located. This allows the code to be compiled and exported without the JZOS packages being available in the workspace, but will still allow the JZOS package dependency to be resolved in the JVM server when the bundle is installed. This is because the CICS OSGi JVM server adds the JZOS packages to the default list exported by the OSGI system bundle.
If you are using CICS TS V5.3 or later, you can exploit the OSGi last resort boot delegation behaviour which will load classes from the JVM boot classpath if they fail to load from the bundle class loaders. This means you would not need to add an Import-Package statement unless you modify the default boot delegation behavior of the JVM server. For further details, refer to Configuring OSGi package imports.
You will use the optional import method (#2) as you don't need to use any other functions of JZOS other than the com.ibm.jzos.fields package, and it is good practice to ensure that all dependencies are explicitly declared in the bundle manifest.
Add the following Import-Package statements to the bundle manifest for JCICS and JZOS. The JCICS import should be versioned to define the OSGi semantic version referring to the supported JCICS API -- for instance, com.ibm.cics.server;version="[1.300.0,3.0.0)". However, the JZOS package com.ibm.jzos.fields can be listed without a
referenced version.
Your resulting manifest should now look something like this:
Now you are ready to create the Java application. As you will need to use OSGi, you first need to ensure that the packages required are exported from their corresponding OSGi bundles. We already discussed access to the JZOS packages in step 3.2, but the CommareaWrapper class was built as an ordinary JAR. You can either create a wrapper project for this to convert it into an OSGi bundle, or you can just add this JAR to the OSGi bundle classpath of your new application. You will use the latter method and add the JAR to the bundle classpath. This method will limit usage of the CommareaWapper to components in the OSGi bundle you are about to create, which is fine for our example.
Create a new OSGi bundle project in Eclipse using the wizard: File -> New -> Other -> Plug-in Project, as described in section 3.1. Then create a new Java package com.ibm.cicsdev.jzostest in the src folder and add a new class JZOSprog to that package. Copy in the code shown below, which makes a JCICS Program.link() call to your EDUPGM CICS COBOL program. Alternatively, you can download the sample code.
package com.ibm.cicsdev.jzostest;
import java.text.MessageFormat;
import com.ibm.cics.server.InvalidProgramIdException;
import com.ibm.cics.server.InvalidRequestException;
import com.ibm.cics.server.Program;
import com.ibm.cics.server.Task;
import com.ibm.cicsdev.bean.JZOSCommareaWrapper;
publicclassJZOSprog {
publicstaticStringproglink="EDUPGM"; // Linked to COBOL programpublicstaticvoidmain(String[] args)
{
// Get details about our current CICS taskTasktask= Task.getTask();
task.getOut().println(" - Starting JOZSprog");
// Wrapper objects for input and output commareasJZOSCommareaWrappercwIn=null;
JZOSCommareaWrappercwOut=null;
// Set the input data fieldsShortbinarydigit=1;
Stringcharstring="hello";
Shortnumericstring=1234;
Integerpackeddigit=123456789;
Integersignedpackeddigit= -100;
Stringbool="1";
cwIn = newJZOSCommareaWrapper();
cwIn.setBinaryDigit(binarydigit );
cwIn.setCharacterString(charstring );
cwIn.setNumericString(numericstring );
cwIn.setPackedDigit(packeddigit );
cwIn.setSignedPacked(signedpackeddigit );
cwIn.setBool(bool );
// Create a reference to the CICS programProgramprog=newProgram();
prog.setName(proglink);
// Create byte array for input commarea from wrapperbyte[] commarea = cwIn.getByteBuffer();
try {
// Link to target CICS program
prog.link(commarea);
//Create output record from updated commarea
cwOut = newJZOSCommareaWrapper(commarea);
// Catch specific JCICS exception
} catch (InvalidProgramIdException e) {
Stringmsg="ERROR: Invalid CICS Program {0} with msg({1})";
task.getOut().println(MessageFormat.format(msg, proglink, e.getMessage()));
// Catch any other exception and force a rollback of CICS UOW
} catch (Exception e) {
Stringmsg="ERROR: Exception on link to {0} with msg({1})";
task.getOut().println(MessageFormat.format(msg, proglink, e.getMessage()));
// Rollback the CICS Tasktry
{
task.rollback();
} catch (InvalidRequestException e1) {
// If this fails, then throw Runtime ExceptionthrownewRuntimeException(e1);
}
}
Stringmsg="Returned from {0} with rc({1}) {2}";
task.getOut().println(MessageFormat.format(msg, proglink,cwOut.getResultCode(), cwOut.getResultText()));
}
}
Show more
This sample uses the setter methods from the generated CommareaWrapper to access the individual fields in the record. Each field in the COBOL record can be written to using methods such as setBinaryDigit() and setCharacterString(), and also read via corresponding getters. The entire byte array representing the records can be passed into a call using a Java byte[] array that's returned via the getByteBuffer().
When generating Java code from COBOL records, it may be helpful if you rename the COBOL data fields in a mixed-case Java fashion so that the generated code has a naming convention that is more familiar to a Java programming style. The figure above shows an example of the renaming used in our COBOL data structure: The image on the left uses the original uppercase-based format, and the image on the right shows the mixed-case format used as input to the Record Generator utility.
The screen shot below shows the outline view of the generated CommareaWrapper class in Eclipse with all the generated setters and getters for the fields in the record.
Next, transfer the EDUPGM.jar containing the CommareaWrapper record onto the workstation. Create a new folder in the project called lib, and then drag the JAR into this folder in your Eclipse project. Then, from the OSGi bundle manifest editor add this JAR to the OSGI bundle classpath using the menu Runtime -> Classpath -> Add. This will add the following statement to the manifest:
Bundle-ClassPath:lib/EDUPGM.jar,
.
Show more
Also update the Build tab in the manifest editor to add the lib directory to the Binary Build to ensure that the EDUPGM.jar gets added to the build output.
Finally, add a CICS-MainClass: definition to the bundle manifest to register a MainClass service for your com.ibm.cicsdev.jzostest.JZOSprog class. This allows the Java class to be LINKed to using a CICS program definition. Your manifest should now look something like this:
The application is now ready to be tested, and can simply be deployed into a CICS OSGi JVM server using a CICS Bundle project as follows:
In Eclipse: Create a CICS bundle project using the menu New -> CICS Bundle Project.
In Eclipse: Add the OSGi Plugin project created in 3.1 to the CICS Bundle project.
Right-click on the CICS Bundle project you just created.
Select New -> OSGi Bundle Project Include.
Then click on the OSGI bundle from the Select an OSGI bundle box.
Type the name of the JVM Server to be used in your CICS region.
Click Finish.
In Eclipse: Deploy to zFS
Right-click on the CICS Bundle project and select Export Bundle Project to z/OS UNIX File System.
Select Export to a specific location in the file system.
Deploy to a location of your choice on z/FS by updating the Parent Directory field.
Check Clear existing contents of the bundle directory.
Click Finish.
In CICS: Create a CICS BUNDLE definition that references this zFS location and install it.
In CICS: Create a CICS PROGRAM definition for the Java application called JZOSPROG. This should name the CICS-MainClass: com.ibm.cicsdev.jzostest.JZOSprog in the JVMClass attribute. Also set the JVMServer attribute to the name of the JVMSERVER to be used.
In CICS: Optionally, create a PROGRAM definition for the COBOL EDUPGM if you are not using program autoinstall.
In CICS: Create a transaction definition that references the JZOSPROG program definition if this is to be run from a 3270 terminal.
In CICS: Install the program and transaction definitions.
When invoked, your Java class JZOSprog will link to the COBOL EDUPGM using the CommareaWrapper classes to marshall the input to the required COBOL record formats. It should return the following messages, if successful, indicating the input and output CommareaWrapper records have been successfully used to marshall the data in the COMMAREA:
Starting JZOSprog
Returned from EDUPGM with rc(0) PARAMETERS AREALL OK
Show more
Summary
This tutorial has demonstrated how to automate the building of Java helper classes from COBOL copybooks using the IBM Record Generator for Java. These helper classes greatly simplify the mapping of record-based data to Java data types within Java applications that need to access data on IBM Z systems. After completing this tutorial, you should be able to customise this process for your own COBOL copybooks or assembler DSECTs, and integrate the build within your own development pipeline.
For more details on the technologies covered in this tutorial, see the Resources links in the right-hand column.
About cookies on this siteOur websites require some cookies to function properly (required). In addition, other cookies may be used with your consent to analyze site usage, improve the user experience and for advertising.For more information, please review your cookie preferences options. By visiting our website, you agree to our processing of information as described in IBM’sprivacy statement. To provide a smooth navigation, your cookie preferences will be shared across the IBM web domains listed here.