IBM Support

JZOS APIs

General Page

Who

Java developers

To do What

Can easily write and deploy Java applications that make use of services that are unique to z/OS.

Why is it important

We are providing a set of helper classes called the JZOS toolkit. This API toolkit helps Java developers make use of unique mainframe services right inside their Java applications. services like: accessing traditional mainframe data sets, submitting jobs, communicating with the system console, interop with COBOL or Assembler transaction data.
This guide will go through some examples and highlight some of the steps that are needed to deploy Java applications on the mainframe.

Real-life scenario – User Story

As a Java developer for an insurance company, I am tasked with creating a batch processing application that read, write, and maintain a list of claims using z/OS mainframe system and storage.

Introduction

What is JZOS? What is it used for? And what do you need to get going?
The tutorial assumes that you have:
  • Eclipse or equivalent IDE installed on your workstation.
  • IBM SDK for z/OS Java Technology Edition installed on a z/OS system.
    • Both JZOS Toolkit and JZOS Batch Launcher are included in the IBM SDK for z/OS Java Technology Edition.

Java applications on z/OS may run in the following execution environments:

  • Traditional mainframe batch environment
  • UNIX System Services (USS), an environment similar to Unix

By the end of this tutorial, as a Java developer, you will be able to deploy your Java application from both execution environments.

Let’s start out with a fictional user story based on real business scenario. As a Java developer for an insurance company, I am tasked with creating a batch processing application that maintains unresolved claims for the company. Claim data are stored in a database that runs in a z/OS mainframe environment.

There are two parts to our batch processing application.

  1. The first part is a mainframe batch job running a Java application that reads incoming claims data from a database and checks if the claim is payable to the insured. This batch job dumps the name of the insured, his or her address, and the claim amount into a flat file on the mainframe if the claim is payable.
  2. The second part of our batch processing application is a Java program that reads the flat file containing payee information and print checks to all the payees.

For this specific tutorial, we will focus on the second part of our batch processing application. Since it’s a very simple Java program, we should get this up and running in minutes.

Set Up

Setting up IBM SDK for Java Technology Edition in your Eclipse IDE

  • Your Eclipse IDE should support Java development. Make sure you are running Eclipse IDE for Java Developers. If your Eclipse installation does not support Java development, you will need to download Eclipse Java development tools (JDT). You can learn more about JDT at http://www.eclipse.org/jdt/.

  • In order for Eclipse to automatically detect Java compile warnings and errors and provide content assist and other convenient features, you should have a copy of IBM SDK Java Technology Edition registered in your Eclipse environment. To obtain a copy of the latest release of the IBM Developer Kits for the Java Platform Standard Edition, go to http://www.ibm.com/developerworks/java/jdk/index.html and download the version appropriate for your operating system.

  • As mentioned earlier, the IBM Explorer for z/OS V3.0 Eclipse plugin is strongly recommended for interacting with z/OS from within your Eclipse IDE. Use the following Eclipse p2 update site to install this plugin:
    http://public.dhe.ibm.com/ibmdl/export/pub/software/htp/zos/tools/aqua/

  • If you’re just writing plain Java application in your Eclipse IDE environment, then you’re all set. But if you’re developing Java applications that make use of z/OS unique features using the JZOS Toolkit, you will need a copy of ibmjzos.jar. Without this jar file, Eclipse will not be able to resolve any JZOS related APIs in your Java application. This jar file is located in the /lib/ext directory of the z/OS version of the IBM SDK Java Technology Edition. Use your favorite FTP client to download a copy of this jar from z/OS into your local Eclipse development environment. Most z/OS systems install Java in /usr/lpp/java. If you do not have Java installed on z/OS, please see the “Deploy” section on how to setup your own copy of IBM Java SDK on z/OS.

Creating a Java Project

  1. Open the Package Explorer view.

    Right-click anywhere within the view, and select New -> Java Project.

    image 10904

  2. Let’s call our project “Insurance”, use the default project location, and use Java 8.0 as our execution environment, and click

    image 10905

  3. Here is what our Insurance project look like in Package Explorer.

    image 10906

Write the application

This simple z/OS Java application uses the JZOS toolkit to open and read a z/OS data set and print its contents to standard output.

Create a Java source file named ReadPayeeData.java under the src directory of our Insurance project and copy and paste the following sample code into the Java source file.

import com.ibm.jzos.ZFile;
import com.ibm.jzos.ZUtil; 

/**
 * Sample program that reads z/OS data set containing insurance
 * payee data and prints directly to standard output.
 *
 * @see com.ibm.jzos.ZFile
 */

public class ReadPayeeData {
    public static void main(String[] args) throws Exception {       
        // Grab the name of the z/OS data set to read
        // insurance payee data from. This information is supplied
        // as an argument to this Java application.
        //
        String datasetName;
        if (args.length == 1) {
            datasetName = args[0];
        } else {
            System.out.println(
                    "Please provide the data set name "
                    + "containing payee payout information");
            return;
        }
       
        // Construct a JZOS ZFile object.
        // This will open the specified z/OS data set
        // for read in binary mode, reading one record
        // at a time, and reading in sequential mode to
        // increase I/O performance.
        //
        ZFile zFile = new ZFile(

                "//'" + datasetName + "'", "rb,type=record,noseek");
     
        // The following block of code reads from the
        // z/OS data set one record at a time, printing
        // the data read to standard output.
        //
        try {
            int nRead;
            byte[] record = new byte[zFile.getLrecl()];
            while((nRead = zFile.read(record)) >= 0) {
                String recordString = new String(
                        record,
                        0,
                        nRead,
                        ZUtil.getDefaultPlatformEncoding());
                System.out.println(recordString);
            }
        } finally {
            zFile.close();
        }
    }
}
  • This is what our project should look like:

image 10907

Notice the red (x) overlaid on top of our Java source file. This means that Eclipse wasn’t able to compile our Java source due to compilation errors.

·       Open the Problems view in our Eclipse IDE and we should see these compile errors:

image 10908

What these errors tell us is that Eclipse can’t resolve the JZOS toolkit classes that we are calling in our sample application. We need to tell Eclipse about the JZOS toolkit.

  • To tell Eclipse to include the JZOS toolkit in our project, first copy the ibmjzos.jar file that we downloaded in the Setup section into

image 10909

Then open up the project properties window by right-clicking on our Insurance project and click on Properties from the context menu. On the Properties for Insurance window, click on Java Build Path on the left side and the Libraries tab on the right.

image 10910

Click on Add JARs… and navigate to our ibmjzos.jar under the lib directory of our Insurance project, and click OK:

image 10911

  • We should see the following in our Java Build Path:

image 10912

Click OK and we should see the following in our Package Explorer view:

image 10913

The red (x) overlay is now gone. There are no compile errors or warning, and our Insurance project has compiled successfully.

  • We should see the following in our Java Build Path:

Deploy

Two ways to run our z/OS Java application on z/OS

Once we deploy our z/OS Java application to z/OS, there are two ways we can run this Java application. The first method is very familiar to existing Java programmers on Windows or Linux, and that is to run it via the command line interface in UNIX System Services (USS). USS is a Unix component of z/OS, and behaves very similar to regular Unix environments. The second method is familiar to existing z/OS programmers, which is to run it in z/OS batch.

Deploy z/OS Java application to z/OS using IBM Explorer for z/OS

IBM Explorer for z/OS allows us to export our Java project to z/OS USS file system.

  1. In the Package Explorer view, right click on our Insurance project, and click on Export… in the context menu. This will bring up the Export window. Under the General category, select z/OS UNIX File System.

    image 10914

    This will copy our Insurance project, which is currently stored locally in our Eclipse environment, to the z/OS USS file system. Click Next.

  2. Select our Insurance project as the resource to export. Select either an existing z/OS connection or create a new z/OS Remote System Connection. In the graphic below, we already have an existing z/OS connection.

    Please Note: In order to connect to a z/OS server from within Eclipse using IBM Explorer for z/OS, the server side host component of IBM Explorer for z/OS Server must be installed on the z/OS server. See https://developer.ibm.com/mainframe/products/downloads for details.

    image 10915

    Select the Destination Directory, and click Finish:

    image 10916

Compiling our z/OS Java program on z/OS

We’re going to open up a remote z/OS USS shell in order to compile our z/OS Java program.

  1. Open up the Remote Systems view and browse to the remote z/OS system where we exported our Insurance Java project. Right-click on the Insurance directory, and choose Launch Shell from the context menu:

    image 10917

    This will open up a remote z/OS USS shell environment within Eclipse.

  2. Within the Remote Shell view, issue the following command to compile our z/OS Java application:

    javac -d bin src/ReadPayeeData.java
    

    image 10918

  3. The compiled ReadPayeeData.class file should be in the bin directory under the Insurance project.

Running our z/OS Java application under the z/OS USS environment

Running a Java application under z/OS USS is like running Java in a Windows or Linux environment. First, we set our classpath point to the directory containing the Java class file we want to run, then we invoke the java command to run our program.

  1. In the Remote Systems view, browse to our Insurance project and open up a remote shell (by right clicking on the Insurance directory and click on Launch Shell from the context menu).

  2. Update the classpath so that it points to the bin directory under the Insurance project.

    image 10919

  3. Run our z/OS Java program. We need to provide our Java program with the name of the z/OS data set to read from, and in this case, we want to read a data set called JAVAFT1.HIGHRISK.DATA.PAYEE.

    image 10920

    Here is the output.

    image 10921

    We’ve done all this inside our Eclipse IDE by using the Remote Shell view. If you prefer a bit more flexibility, you can SSH into your z/OS system’s USS shell environment using a free tool such as PuTTY.

Running our z/OS Java application under the traditional z/OS batch environment

Those z/OS programmers that have accustomed to running their COBOL or assembler applications under the z/OS batch environment should feel right at home running Java under this same environment. For those of us who are new to z/OS, this process can be a bit more challenging.

In order to run Java applications under z/OS batch, we need a launcher that can launch a Java application from batch, and this is where the JZOS batch launcher comes into play. We will be using the JZOS batch launcher to launch our z/OS Java application.

Setting up the JZOS batch launcher

The JZOS batch launcher is included as part of the IBM SDK Java Technology Edition for z/OS. But before we can use it, we need to move the JZOS batch launcher from the Java install directory in the USS environment into a z/OS data set, specifically, a PDSE (partitioned data set extended, aka LIBRARY) data set.

  1. Let us create a z/OS PDSE data set. This the data set where we will copy our JZOS batch launcher into.
    Open the Remote Systems view in Eclipse. Browse to our connected z/OS system, and right click on MVS Files, choose New -> Allocate Partitioned Data Set…

    image 10922

  2. A new Allocate Partitioned Data Set window will pop up. Select your existing z/OS connection and choose a data set name for your data set. In our case, we decided on the name JAVAFT1.HIGHRISK.JZOS.LOADLIB. Click Next.

    image 10923

    We’re going to specify our data set allocation parameters manually, so select Specify characteristics (advanced allocation), and click Next.

    image 10924

  3. We’re allocating the data set with the following characteristics as shown in the screen capture below. Click Finish when complete.

    image 10925

    At this point, our z/OS PDSE data set should be allocated. Open the Remote Systems view and it will be listed under the Retrieved Data Sets category in MVS Files.

    image 10926

  4. Let us go ahead and copy the JZOS batch launcher into the allocated PDSE data set.

    We can find our JZOS batch launcher in the mvstools directory under our Java install path. Since we’re running Java 8.0 64-bit, our Java home directory is J8.0_64, and the JZOS batch launcher is a file called JVMLDM86. The LDM part of the name stands for load module, and 86 stands for Java 8.0 64-bit.

    image 10927

  5. Open up a Remote Shell from the mvstools directory, and issue the following command to copy the JZOS batch launcher into the z/OS PDSE data set that we just allocated:

    cp -X JVMLDM86 "//'JAVAFT1.HIGHRISK.JZOS.LOADLIB(JVMLDM86)'"
    

    image 10928

    To verify that the JZOS batch launcher was copied successfully, open the Remote Systems view and look for the JAVAFT1.HIGHRISK.JZOS.LOADLIB data set under the MVS Files section of your existing z/OS connection. Refresh the data set by right-clicking and selecting Refresh and you should see the JZOS batch launcher load module:

    image 10929

Setting up z/OS batch scripts (aka JCL) that will start the JZOS batch launcher

Now that we have our JZOS batch launcher setup, we need to create some z/OS scripts that will kick off the JZOS batch launcher. These scripts are called JCL, also known as the Job Control Language. In this example, we’re going to use two JCLs, one JCL specifically for invoking the JZOS batch launcher and the other JCL for defining application specific environment.

  1. The z/OS version of the IBM SDK Java Technology Edition includes samples of the z/OS batch scripts used to start the JZOS batch launcher. These samples can be found under the mvstools/samples/jcl directory of your z/OS Java installation.

    image 10930

    The file JVMPRC86 contains what is known as a PROC, which runs the JZOS batch launcher.

    The file JVMJCL86 defines application specific configurations and environment, and executes the PROC defined in JVMPRC86.

    In our case, these JCL samples are for Java 8.0 64-bit, since their name ends in 86.

  2. We want to copy these two JCL samples and place them in z/OS data sets. Create a new z/OS data set by opening the Remote Systems view and right click on your connected remote system’s MVS Files, and choose New -> Allocate Partitioned Data Set…

    Were going to call our new data set JAVAFT1.HIGHRISK.JZOS.JCL

    image 10931

    Click Next.

    Again, we’re going to specify our data set characteristics using advanced allocation.

    image 10932

    Click Next again.

  3. Allocate the data set with the following characteristics as shown in the screen capture below.

    image 10934

    Click Finish when complete.

  4. We should now see the following under the Retrieved Data Sets section in the Remote Systems view.

    image 10935

  5. Copy the two JCL samples under our z/OS Java installation path by highlighting them, right-clicking, and selecting Copy.

    image 10936

  6. Right-click on the JAVAFT1.HIGHRISK.JZOS.JCL data set and choose Paste.

    image 10937

    This will make copies of the two JCLs and place them under the JAVAFT1.HIGHRISK.JZOS.JCL data set.
    Refresh this data set and confirm that the two sample JCLs have been copied over successfully.

    image 10938

Configuring z/OS batch scripts (aka JCL)

Since the two sample JCLs that we copied over are just samples, we need to customize them for our particular environment and application.

  1. Let’s start by configuring JVMPRC86, the JCL that starts the JZOS batch launcher. The only change we need to make to this JCL is to tell it the location of our JZOS batch launcher. We do this by un-commenting the LIBRARY parameter (on line 17) of the PROC and the STEPLIB DD statement (on line 24).

    image 10939

    Update the LIBRARY parameter value to point to the PDSE data set containing our JZOS batch launcher, JAVAFT1.HIGHRISK.JZOS.LOADLIB.

  2. Configure JVMJCL86 by updating the value of the JAVACLS argument (on line 19) to the name of the Java class that we want to run. In this case, ReadPayeeData.

    image 10940

    Update JAVA_HOME (on line 26) with our z/OS Java installation path, /home/javaft1/javaonz/java/J8.0_64, ans update APP_HOME (on line 37) with the location of our Java class file, which is located in /home/javaft1/javaonz/Insurance/bin.

    image 10941

  3. We need to provide a z/OS data set name as an argument to our Java program. This is the data set that our Java program will open and read data from, which is JAVAFT1.HIGHRISK.DATA.PAYEE, in our example.

  4. Finally, we’ll need to add a job card to the very beginning of this JCL. A job card tells the system that this JCL is a job that can be submitted for execution.

    image 10942

    The name of our job is JZOSJOB.

    On line 2, the PROCLIB statement tells the system the location of JVMPRC86, which we rely on to start the JZOS batch launcher. For this example, the location is JAVAFT1.HIGHRISK.JZOS.JCL.

Submitting our job and running our Java application under z/OS batch

Once we have the JZOS batch launcher setup and our JCLs setup and configured, running our Java application under z/OS batch is as simple as clicking a few buttons.

  1. Open the Remote Systems view, under the MVS Files category, look for our JVMJCL86 JCL in our data set JAVAFT1.HIGHRISK.JZOS.JCL. Right-click on JVMJCL86, and choose Submit in the context menu. This will submit our job which will run our z/OS Java application using the JZOS batch launcher.

    image 10943

    A window will pop up confirming the job submission:

    image 10944

    If you click on Notify, a notification will display on the bottom of your Eclipse IDE when the job completes execution:

    image 10945

    Notice the completion code of 0000. That means our Java application ran successfully!

  2. Too see the output of our Java program, navigate to the JES category of the Remote Systems view, expand My Jobs, and search for our job, which is JZOSJOB:JOB00218.

    image 10946

    The STDOUT report should contain the standard output of our Java application.
    If we open it, that’s exactly what we’ll find:

    image 10947

See also: JZOS Installation (chap 2, pg3, chap 3, pg 5)

Next Steps

After you complete writing your application:

  • Show Deploy from z/OS Explorer
  • Don’t want to deploy? Want to develop/test on your local machine… Then look into RD&T (not covered in this tutorial)
  • Compile the program remotely
  • Run it from USS directly, or
  • Submit the program as a batch job using the JZOS Batch Launcher

Debug

When an issue occurs with your z/OS Java application, you can debug your application with various tools provided to you by the z/OS Java Virtual Machine (JVM).
For more information about these tools, please see the section titled “Overview of the available diagnostic tools” in the z/OS User Guide for IBM SDK, Java Technology Edition. Here is a link to the IBM SDK 8.0.0 version of this guide.

After some investigation, if you believe that the issue involves the JZOS toolkit or the JZOS batch launcher, you may turn on additional debug tracing/logging in the JZOS components.

JZOS provides logging mechanisms with the following levels of granularity:

  • E: Only error level messages are emitted
    W: Adds warning level messages
    N: Adds notice level messages (the default logging setting)
    I: Adds informational messages
    D: Adds debugging level messages
    T: Adds trace level messages

Although this logging capability is available in both JZOS toolkit and JZOS batch launcher, their logging levels are independent from each other. This means that you can configure one level of logging granularity for the JZOS toolkit and a different level for the JZOS batch launcher.

Configure JZOS toolkit native library logging

To configure the logging level for the JZOS toolkit, use the optional jzos.logging system property when starting the JVM. This property controls logging in the JZOS toolkit native library.

When starting Java under the USS environment, add -Djzos.logging=[level] after the java command to set the logging level of the JZOS toolkit, where level is one of E, W, N, I, D, T.

When starting Java under the traditional z/OS batch environment, use the IBM_JAVA_OPTIONS environment variable to set the logging level for the JZOS toolkit. To demonstrate, let’s build upon our insurance payee example from the prior session. We used a JCL called JVMJCL86 to run our Java application in z/OS batch. Open that JCL and add the following export command to our STDENV configuration script:

IJO=”$IJO -Djzos.logging=T”

This will set the JZOS toolkit logging level to T, which is the most detailed trace option available.

After this change, our STDENV configuration script should look like the following:


//STDENV DD *

# This is a shell script which configures

# any environment variables for the Java JVM.

# Variables must be exported to be seen by the launcher.

 

. /etc/profile

export JAVA_HOME=/home/javaft1/javaonz/java/J8.0_64

 

export PATH=/bin:"${JAVA_HOME}"/bin

 

LIBPATH=/lib:/usr/lib:"${JAVA_HOME}"/bin

LIBPATH="$LIBPATH":"${JAVA_HOME}"/lib/s390x

LIBPATH="$LIBPATH":"${JAVA_HOME}"/lib/s390x/j9vm

LIBPATH="$LIBPATH":"${JAVA_HOME}"/bin/classic

export LIBPATH="$LIBPATH":

 

# Customize your CLASSPATH here

APP_HOME=/home/javaft1/javaonz/Insurance/bin

CLASSPATH=$APP_HOME:"${JAVA_HOME}"/lib:"${JAVA_HOME}"/lib/ext

 

# Add Application required jars to end of CLASSPATH

for i in "${APP_HOME}"/*.jar; do

    CLASSPATH="$CLASSPATH":"$i"

    done

export CLASSPATH="$CLASSPATH":

 

# Set JZOS specific options

# Use this variable to specify encoding for DD STDOUT and STDERR

#export JZOS_OUTPUT_ENCODING=Cp1047

# Use this variable to prevent JZOS from handling MVS operator commands

#export JZOS_ENABLE_MVS_COMMANDS=false

# Use this variable to supply additional arguments to main

#export JZOS_MAIN_ARGS=""

 

# Configure JVM options

IJO="-Xms16m -Xmx128m"

IJO="$IJO -Djzos.logging=T"

# Uncomment the following to aid in debugging "Class Not Found" problems

#IJO="$IJO -verbose:class"

# Uncomment the following if you want to run with Ascii file encoding..

#IJO="$IJO -Dfile.encoding=ISO8859-1"

export IBM_JAVA_OPTIONS="$IJO "

 

If we re-run our Java application, the SYSOUT output DD should now contain details of each data set operation being performed by the JZOS native code on the JAVAFT1.HIGHRISK.DATA.PAYEE data set.

image 10948

Configure JZOS batch launcher logging

If there is an issue preventing your Java application from being launched by the JZOS batch launcher, it will be helpful to get a detailed log of the launcher. To configure the logging level for the JZOS batch launcher, use the LOGLVL='[level]’ parameter when executing the JVMPRC86 PROC (remember the number 86 in JVMPRC86 stands for Java 8.0 64-bit. The filename will be different if you’re using a different version of Java) from within your JCL, where level is one of +E, +W, +N, +I, +D, +T.

Open your JVMJCL86 JCL and add the following parameter to the JVMPRC86 PROC call:

// LOGLVL=’+T’

This will set the JZOS batch launcher logging level to T, which is the most detailed trace option available.

After this change, our JVMPRC86 PROC call should look like the following:

//JAVA EXEC PROC=JVMPRC86,

// JAVACLS='ReadPayeeData',

// ARGS='JAVAFT1.HIGHRISK.DATA.PAYEE',

// LOGLVL='+T'

If we re-run our Java application, the SYSOUT output DD should now contain detail log of the JZOS batch launcher.

image 10949

Refer to JZOS Installation (chap 3 pg8 and pg 10) for more information.

Next steps

Get familiar with the naming conventions of traditional z/OS data sets

The JZOS toolkit makes it easy for developers to write Java applications that access traditional z/OS data sets. The I/O APIs provided by JZOS have a similar feel to I/O APIs for dealing with file on Windows or Linux, but z/OS data sets have a different file name syntax. For example, Windows file paths usually start with a drive letter or a backslash “\” character, Linux with a single slash “/”, but to refer to a z/OS data set in JZOS, a double slash is needed, such as “//SYS1.SEQ”. In addition, depending on the type of data set being referenced, additional rules apply. For example, if referencing a member of a partitioned data set, we need to wrap the part after the double slash with single quotes, as in “//’SYS1.JZOS(JOB)'”. Furthermore, if you are referencing a DD name, the proper file name prefix to use should be “//DD:”.

Please note that many of the JZOS I/O APIs only work with z/OS data sets and does not support POSIX pathnames, and this includes HFS and zFS files. The only exception is the com.ibm.jzos.FileFactory class, which is a factory type class that can build file streams for either z/OS data sets or regular files. Under most circumstances, if you require regular POSIX style file I/O, use the APIs available in the java.io package.

For more information on the proper file name syntax to use with JZOS I/O APIs, refer to the Javadoc comments for class com.ibm.jzos.ZFile in the JZOS API documentation.

Keep the JZOS batch launcher load module and the JZOS toolkit in sync

One of the common mistakes associated with using the JZOS Batch Launcher is using one version of the JZOS batch launcher load module for launching a JVM that includes a different version of the JZOS toolkit. Although most times, there won’t be any issues and your Java program will run fine, on the rare occasion that if something does go wrong because of a mismatch of JZOS batch launcher and JZOS toolkit versions, this type of error can be a pain to debug.

Every z/OS version of IBM SDK Java Technology Edition includes a JZOS batch launcher load module under the mvstools sub-directory, make it a good habit of updating your JZOS batch launcher load modules whenever you use a different version of Java.

To explore more functions offered by the JZOS toolkit, download JZOS Sample Programs and use them as templates for a quick start.

To learn more how to apply JZOS in more advanced environments, follow the examples in the JZOS Cookbook.

[{"Type":"MASTER","Line of Business":{"code":"LOB61","label":"IBM Technology Lifecycle Services"},"Business Unit":{"code":"BU016","label":"Multiple Vendor Support"},"Product":{"code":"SGMV104","label":"IBM Support for Java (Oracle)"},"ARM Category":[{"code":"a8m3p000000h9a7AAA","label":"Application Platforms->Application Framework"}],"Platform":[{"code":"PF025","label":"Platform Independent"}],"Version":"All Versions"}]

Document Information

Modified date:
13 July 2021

UID

ibm16321745