Start of change

Sample JCL for building and running the COBPROD application

This section contains sample JCL for building and running the COBPROD application. Previous sections describe the COBPROD demo application and how to build and run it using z/OS® UNIX shell scripts and makefiles. Some users, however, may prefer to build and run non-OO COBOL/Java™ interoperable applications using JCL. The provided JCL is specifically for the COBPROD demo application but should be easily adaptable to any non-OO COBOL/Java interoperable application.

Much of the JCL is typical of any JCL to build and link COBOL applications. The main difference is that the build process contains a step for building the DLL for the interoperable application using the cjbuild tool. While cjbuild is a native z/OS UNIX program, the sample shows how it can be easily run from JCL using the BPXBATCH utility.

Things to consider before using the sample JCL to build and run the COBPROD application.
  1. The JCL itself contains comprehensive comments at the beginning describing the changes that need to be made to the JCL to make it run successfully in your environment.
  2. Follow the instructions in the JCL carefully, and ensure to meet the following important conditions:
    • All instances of userid in z/OS UNIX paths in the JCL are replaced by the user id of the account from which the JCL will be run (the user id on z/OS UNIX is typically just the lowercase version of your z/OS user id).
    • The various JCL path variables defined at the top of the JCL file (for example, WORKDIR, ZFSCBDIR, OUTDIR) are set appropriately for your environment.
    • A z/OS UNIX work directory location on your system is identified that can be used for the build job, where various listings and other artifact files produced by cjbuild will be created. The work directory and all its subdirectories will be created automatically by the sample JCL. There is no need to create them yourself first. You only need to define the work directory location via the WORKDIR JCL variable.
    • The LNGPRFX and LIBPRFX JCL variables are set appropriately to indicate your compiler and runtime levels respectively.
  3. Before the JCL is run for the first time, you must ensure that the two COBOL user source files in the COBPROD application are copied to a data set with name USERID.COBOL.COBOL where USERID is the user id of the account from which the JCL will be run. If a differently named data set is desired, the JCL must be modified accordingly. The two user source files are:
    • cobprod.cbl
    • addlist.cbl
    and they exist in the COBPROD application demo directory:
    demo/cobol_java_interop_sample
    which is located in the COBOL install directory in the z/OS UNIX file system, which typically has a path such as /usr/lpp/cobol/igyv6r4. Copying these files to the data set can be done using the following z/OS UNIX commands, assuming you run the commands from the cobol_java_interop_sample directory:
    
    cp cobprod.cbl “//’USERID.COBOL.COBOL(COBPROD)’”
    cp addlist.cbl “//’USERID.COBOL.COBOL(ADDLIST)’”
    
    Note: In a production build environment, it is most likely that your user COBOL source files are already located in a data set. This extra copying is only needed for building these demo files which happen to reside in the COBOL install directory in the z/OS UNIX file system.
  4. The provided JCL makes use of the BPXBATCH utility to run z/OS UNIX commands from JCL. BPXBPATCH causes a z/OS UNIX shell to be started, which in turn causes the .profile file in your z/OS UNIX home directory to be “sourced” (that is, loaded into your environment and run). It is common in some z/OS UNIX environments for other non-default UNIX shells to be started at the end of the .profile file using the command:
    exec <alternative-shell-program>
    Note: If a non-default shell is not executed from your .profile, you may safely ignore the rest of this point.
    A non-default shell is simply a shell program that is not the default shell set for your system, which is usually the sh UNIX command. This could cause a problem with BPXPATCH. A reliable way to prevent such a problem is to ensure that your custom shell program is only run if you are running an interactive shell session. This can be achieved by guarding the exec command in your .profile file as follows:
    
    if [[ $- == *i* ]]; then
      exec <alternative-shell-program>
    fi
    
    If this method does not work for some reason, the sample JCL sets a shell variable called NO_CUSTOM_SHELL that can be used by the user in their .profile to prevent the custom shell from running. The shell code would look like the following:
    
    if [[ -z $NO_CUSTOM_SHELL ]]; then
      exec <alternative-shell-program>
    fi
    
  5. It is important to set the JAVA_HOME environment variable in the .profile file in the z/OS UNIX home directory of the user that is running the JCL. The line to add to the .profile file to ensure the 31-bit COBPROD application in the sample JCL runs successfully is:
    export JAVA_HOME=/usr/lpp/java/IBM/J8.0
    Note: Failure to do this could result in STEP 2 of the JCL failing to launch the cjbuild utility, which is a Java program.

Output from a successful run of the application

When the application runs successfully from the JCL, the job log should contain the following output:

<<Java: CobProd.main: entered>>

Java: Access COBOL product info from COBPROD
Java: prod table size = 5
Java: Product name = chair                Price = $29.99
Java: Product name = table                Price = $45.98
Java: Product name = bed                  Price = $149.45
Java: Product name = blanket              Price = $19.99
Java: Product name = sofa                 Price = $239.99

Java: call COBOL addlist to add prices

<<COBOL: addlist: entered>>
Java (called from COBOL): printResult: total price is: $225.42
<<COBOL: addlist: exited>>

<<Java: CobProd.main: exited>>

COBPROD JCL sample file

This sample JCL is available in member IGYCJDMJ of the Enterprise COBOL compiler's SIGYSAMP data set. It is also available as z/OS UNIX file cobprod.jcl in subdirectory demo/cobol_java_interop_sample of the COBOL install directory in the z/OS UNIX file system.

//USERID2 JOB 'JAVA/COBOL interop',
// MSGLEVEL=(1,1),MSGCLASS=S,CLASS=C,NOTIFY=&SYSUID,
// REGION=0M
//********************************************************************/
//*                IBM Enterprise COBOL for z/OS                     */
//********************************************************************/
//********************************************************************/
//*                                                                   *
//*      LICENSED MATERIALS -- PROPERTY OF IBM.                       *
//*                                                                   *
//*      5655-EC6                                                     *
//*      COPYRIGHT IBM CORP. 2023, 2024                               *
//*                                                                   *
//*      US GOVERNMENT USERS RESTRICTED RIGHTS - USE, DUPLICATION OR  *
//*      DISCLOSURE RESTRICTED BY GSA ADP SCHEDULE CONTRACT WITH IBM  *
//*      CORP.                                                        *
//*                                                                   *
//********************************************************************/
//*********************************************************************
//*
//*  Sample JCL for building and running the COBPROD application
//*  demonstrating non-OO COBOL/Java interoperability.
//*
//*********************************************************************
//*
//*  Prerequisites:
//*
//*  1) COBPROD demo source files cobprod.cbl and addlist.cbl from
//*     the ZFS COBOL install directory
//*
//*       demo/cobol_java_interop_sample
//*
//*     must be copied to a PDS or PDSE data set with name
//*     userid.COBOL.COBOL.
//*
//*     Alternatively, the JCL could be modified to read the
//*     source files directly from the zFS install directory
//*     in steps COBOL1 and COBOL2 below.
//*
//*  2) A PDSE data set named userid.COBOL.OBJECT must exist
//*     to receive object program files generated by the COBOL
//*     compiler.
//*
//*  3) A PDSE data set userid.COBOL.LOAD must exist to receive
//*     program object files. These program objects come from
//*     linking object files from user programs and also from
//*     linking the object files associated with stub programs
//*     into a DLL.
//*
//*     A PDS data set (FB 80) called userid.COBOL.EXP must also
//*     exist prior to running this JCL.  This data set will
//*     receive the side deck for the DLL produced by cjbuild
//*     and is used during subsequent link steps.
//*
//*  4) You must ensure the following JCL variables are set below,
//*     which control various build parameters. This includes the
//*     z/OS UNIX directory into which stub files will be generated
//*     by the compiler and the z/OS UNIX work directory to be
//*     used by the cjbuild utility. The cjbuild utility uses this
//*     directory to build the DLL needed for the interoperable
//*     application.
//*
//*     For this sample, we assume the z/OS UNIX directory
//*     structure to be used for building the application is as
//*     follows:
//*
//*     /home/userid/jtoc/cobprod
//*       - main work directory
//*     /home/userid/jtoc/cobprod/out
//*       - stub file output directory (compiler places stub
//*         files here)
//*     /home/userid/jtoc/cobprod/class
//*       - directory where cjbuild places any generated .class
//*         files
//*
//*     The following variables must be set:
//*
//*     JAVAHOME
//*     ZFSCBDIR
//*     OUTDIR
//*     INTMODE
//*     WORKDIR
//*     CLASSOUT
//*     JVSRCOUT
//*     PKGNAME
//*     DLLNAME
//* 
//*     See below for detailed descriptions of how to set these
//*     variables. Example values are provided.
//*
//*     NOTE: z/OS UNIX directories for stub files and the work
//*           directory for cjbuild do not have to exist.  The
//*           JCL below create the directories if they do not
//*           exist prior to running this job (see STEP 0).
//*
//*********************************************************************
// EXPORT SYMLIST=*
//*********************************************************************
//* Set compiler and run time library levels below
//*******************************************************************
//         SET LIBPRFX='CEE'
//         SET LNGPRFX='COBOL.COMPILER'
//*******************************************************************
//* JAVAHOME: Set this to your Java home directory. This will be used
//*           to set the JAVA_HOME environment variable needed by
//*           Java operations
//*******************************************************************
//         SET JAVAHOME='/usr/lpp/java/J11.0_64'
//*******************************************************************
//* ZFSCBDIR: This should point to the location of your COBOL zFS
//*          install directory (e.g., /usr/lpp/cobol/igyv6r4)
//*
//*          The bin directory of this directory is where the cob2
//*          and cjbuild utilities reside.  They will be needed
//*          when building the interoperable application
//*******************************************************************
//         SET ZFSCBDIR='/home/userid/cobol/igyv6r4'
//*******************************************************************
//* OUTDIR: Set this to the z/OS UNIX directory that will receive
//*         the stub files and other artifact files generated by
//*         the COBOL compiler compiling programs that contain
//*         the JAVA-CALLABLE and JAVA-SHAREABLE directives or
//*         programs that make calls to Java using a CALL statement
//*         of the form:
//*
//*             CALL 'Java.class-name.static-method-name' ...
//*
//*         The cjbuild uility (see STEP 2) will get the files from
//*         this directory (see --coboldir option) so the directory
//*         specified for OUTDIR should be used both in the OUTPATH
//*         suboption of JAVAIOP when compiling the user COBOL
//*         program as well as the --coboldir option of cjbuild.
//*******************************************************************
//         SET OUTDIR='/home/userid/jtoc/cobprod/out'
//*******************************************************************
//* INTMODE: Set this to the interoperability mode to be used
//*          by your application (needed by the cjbuild utility)
//*
//*          PURE31 - AMODE 31 COBOL, AMODE 31 Java
//*          PURE64 - AMODE 64 COBOL, AMODE 64 Java
//*          MIX_31_64 - AMODE 31 COBOL, AMODE 64 Java
//*
//*          NOTE: if you specify MIX_31_64, you must add the
//*                JAVA64 suboption to the JAVAIOP option of
//*                all related user COBOL programs.
//*******************************************************************
//         SET INTMODE='MIX_31_64'
//*******************************************************************
//* WORKDIR: Set this to the z/OS UNIX directory to be used as a work
//*          directory for building the interoperable application.
//*          cjbuild will be run from this directory and basic
//*          artifact files it generates (object files, listing,
//*          etc.) go to this directory automatically.
//*******************************************************************
//         SET WORKDIR='/home/userid/jtoc/cobprod'
//*******************************************************************
//* CLASSOUT: Set this to the directory you want any .class files
//*           generated by cjbuild to go.  These are the .class
//*           files for Java accessor classes for JAVA-SHAREABLE
//*           items, and also .class files for any Java files
//*           generated by cjbuild, such as cobol.java, progs.java,
//*           and strg.java.
//*******************************************************************
//         SET CLASSOUT='/home/userid/jtoc/cobprod/class'
//*******************************************************************
//* JVSRCOUT: Set this to the directory you want any .java files
//*           generated by cjbuild to go (cobol.java, progs.java,
//*           strg.java).
//*******************************************************************
//         SET JVSRCOUT='/home/userid/jtoc/cobprod'
//*******************************************************************
//* PKGNAME:  Set this to the name of the Java package that you
//*           want the 'progs' and 'strg' class to be a part of.
//*           The default is enterprise.COBOL.  This affects how
//*           COBOL programs are invoked from Java.  e.g., if the
//*           package name is enterprise.COBOL., then you would
//*           invoke a COBOL program called PROG1 as follows:
//*
//*           enterprise.COBOL.progs.PROG1();
//*******************************************************************
//         SET PKGNAME='enterprise.COBOL'
//*******************************************************************
//* DLLNAME: The name of the DLL that cjbuild creates and which
//*          is needed at runtime when interoperable activities
//*          occur in the application.
//*
//*          If the DLL is targeted for a data set (which is
//*          the usual way, see --dlloutdir option of cjbuild)
//*          then the DLL will be stored as a member of the
//*          specified data set, and is called LIB<DLLNAME>.
//*
//*          If the DLL is targeted to the z/OS UNIX file system,
//*          it will be called lib<dllname>.so.
//*******************************************************************
//         SET DLLNAME=APP1
//*******************************************************************
//PROCLIB JCLLIB ORDER=(&LNGPRFX..SIGYPROC)
//*******************************************************************
//*******************************************************************
//* STEP 0: Ensure required z/OS UNIX directories exist
//*******************************************************************
//*******************************************************************
//CRDIRS   EXEC PGM=BPXBATCH
//STDPARM  DD *,SYMBOLS=EXECSYS
SH mkdir -p &OUTDIR;
mkdir -p &WORKDIR;
mkdir -p &CLASSOUT;
mkdir -p &JVSRCOUT
/*
//STDOUT   DD SYSOUT=*
//STDERR   DD SYSOUT=*
//STDENV   DD *
NO_CUSTOM_SHELL=1
/*
//*******************************************************************
//*******************************************************************
//* STEP 1: Compile user COBOL programs, specifying JAVAIOP option
//*******************************************************************
//*******************************************************************
// SET INFILE='COBPROD'
//*******************************************************************
// IF (CRDIRS.RUN AND (CRDIRS.RC EQ 0)) THEN
//COBOL1   EXEC IGYWC,
//  LNGPRFX=&LNGPRFX,
//  LIBPRFX=&LIBPRFX,
//  PARM.COBOL='OPTFILE'
//SYSLIB   DD DSN=&SYSUID..COBOL.COBOL,DISP=SHR
//SYSIN    DD DSN=&SYSUID..COBOL.COBOL(&INFILE),DISP=SHR
//SYSLIN   DD DSN=&SYSUID..COBOL.OBJECT(&INFILE),DISP=SHR
//SYSPRINT DD SYSOUT=*
//SYSOPTF  DD *,SYMBOLS=EXECSYS
 JAVAIOP(OUTPATH('&OUTDIR'),JAVA64)
/*
//SYSOUT   DD SYSOUT=*
// ENDIF
//*******************************************************************
// SET INFILE='ADDLIST'
//*******************************************************************
// IF (COBOL1.COBOL.RUN AND (COBOL1.COBOL.RC EQ 0)) THEN
//COBOL2   EXEC IGYWC,
//  LNGPRFX=&LNGPRFX,
//  LIBPRFX=&LIBPRFX,
//  PARM.COBOL='OPTFILE'
//SYSLIB   DD DSN=&SYSUID..COBOL.COBOL,DISP=SHR
//SYSIN    DD DSN=&SYSUID..COBOL.COBOL(&INFILE),DISP=SHR
//SYSLIN   DD DSN=&SYSUID..COBOL.OBJECT(&INFILE),DISP=SHR
//SYSPRINT DD SYSOUT=*
//SYSOPTF  DD *,SYMBOLS=EXECSYS
 JAVAIOP(OUTPATH('&OUTDIR'),JAVA64)
/*
//SYSOUT   DD SYSOUT=*
// ENDIF
//*******************************************************************
//* STEP 2: Build stub file DLL using cjbuild
//*******************************************************************
// IF (COBOL2.COBOL.RUN AND (COBOL2.COBOL.RC EQ 0)) THEN
//CJBUILD EXEC PGM=BPXBATCH
//STDPARM  DD *,SYMBOLS=EXECSYS
SH export JAVA_HOME=&JAVAHOME;
PATH=.:/bin:/usr/bin:/usr/local/bin:&ZFSCBDIR/bin;
cd &WORKDIR;

&ZFSCBDIR/bin/cjbuild
 -v
 --coboldir &OUTDIR
 --dlloutdir "//'&SYSUID..COBOL.LOAD'"
 --mode &INTMODE
 --pkgname &PKGNAME
 --javaclassdir &CLASSOUT
 --javasrcdir &JVSRCOUT
 &DLLNAME
/*
//STEPLIB DD  DSN=&LNGPRFX..SIGYCOMP,DISP=SHR
//        DD  DSN=&LIBPRFX..SCEERUN,DISP=SHR
//        DD  DSN=&LIBPRFX..SCEERUN2,DISP=SHR
//STDOUT  DD SYSOUT=*
//STDERR  DD SYSOUT=*
//STDENV  DD *,SYMBOLS=EXECSYS
NO_CUSTOM_SHELL=1
_C89_LSYSLIB=&LIBPRFX..SCEELKED
/*
// ENDIF
//*******************************************************************
//*******************************************************************
//* STEP 3: Link user programs.  User programs may call out to
//*         programs in the DLL produced by cjbuild in STEP 2
//*         thus should be linked with the side deck produced in
//*         that step
//*******************************************************************
//*******************************************************************
// SET INFILE='COBPROD'
//*******************************************************************
// IF (CJBUILD.RUN AND (CJBUILD.RC EQ 0)) THEN
//LKED1 EXEC PGM=IEWL,
// PARM='RENT,LIST,LET,DYNAM(DLL),CASE(MIXED)'
//SYSLIB DD DSN=&LIBPRFX..SCEELKED,DISP=SHR
//       DD DSN=&LIBPRFX..SCEELKEX,DISP=SHR
//SYSPRINT DD SYSOUT=*
//SYSTERM DD SYSOUT=*
//SYSLMOD DD DSN=&SYSUID..COBOL.LOAD(&INFILE),DISP=SHR
//SYSDEFSD DD DUMMY
//OBJMOD DD DSN=&SYSUID..COBOL.OBJECT(&INFILE),DISP=SHR
//SIDEDK DD DSN=&SYSUID..COBOL.EXP(LIB&DLLNAME),DISP=SHR
//SYSLIN DD *
 INCLUDE OBJMOD
 INCLUDE SIDEDK
/*
// ENDIF
//*******************************************************************
// SET INFILE='ADDLIST'
//*******************************************************************
// IF (LKED1.RUN AND (LKED1.RC EQ 0)) THEN
//LKED2 EXEC PGM=IEWL,
// PARM='RENT,LIST,LET,DYNAM(DLL),CASE(MIXED)'
//SYSLIB DD DSN=&LIBPRFX..SCEELKED,DISP=SHR
//       DD DSN=&LIBPRFX..SCEELKEX,DISP=SHR
//SYSPRINT DD SYSOUT=*
//SYSTERM DD SYSOUT=*
//SYSLMOD DD DSN=&SYSUID..COBOL.LOAD(&INFILE),DISP=SHR
//SYSDEFSD DD DUMMY
//OBJMOD DD DSN=&SYSUID..COBOL.OBJECT(&INFILE),DISP=SHR
//SIDEDK DD DSN=&SYSUID..COBOL.EXP(LIB&DLLNAME),DISP=SHR
//SYSLIN DD *
 INCLUDE OBJMOD
 INCLUDE SIDEDK
/*
// ENDIF
//*******************************************************************
//*******************************************************************
//* STEP 4: Builds Java application
//*******************************************************************
//*******************************************************************
// IF (LKED2.RUN AND (LKED2.RC EQ 0)) THEN
//BLDJAVA EXEC PGM=BPXBATSL
//STDPARM DD *,SYMBOLS=EXECSYS
PGM &JAVAHOME/bin/javac
 -d &CLASSOUT
 &ZFSCBDIR/demo/cobol_java_interop_sample/CobProd.java
/*
//STDOUT  DD SYSOUT=*
//STDERR  DD SYSOUT=*
//STDENV  DD *,SYMBOLS=EXECSYS
JAVA_HOME=&JAVAHOME
CLASSPATH=.:&CLASSOUT
PATH=.:/bin:/usr/bin:/usr/local/bin:&ZFSCBDIR/bin
/*
// ENDIF
//*******************************************************************
//*******************************************************************
//* STEP 5: Run COBOL/Java interoperable application
//*******************************************************************
//*******************************************************************
// IF (BLDJAVA.RUN AND (BLDJAVA.RC EQ 0)) THEN
//GO      EXEC PGM=BPXBATSL
//STDPARM DD *,SYMBOLS=EXECSYS
PGM &JAVAHOME/bin/java CobProd
/*
//STEPLIB DD DSN=&SYSUID..COBOL.LOAD,DISP=SHR
//        DD DSN=&LNGPRFX..SIGYCOMP,DISP=SHR
//        DD DSN=&LIBPRFX..SCEERUN,DISP=SHR
//        DD DSN=&LIBPRFX..SCEERUN2,DISP=SHR
//STDOUT  DD SYSOUT=*
//STDERR  DD SYSOUT=*
//STDENV  DD *,SYMBOLS=EXECSYS
JAVA_HOME=&JAVAHOME
PATH=.:/bin:/usr/bin:/usr/local/bin:&ZFSCBDIR/bin
_C89_LSYSLIB=&LIBPRFX..SCEELKED
CLASSPATH=.:&CLASSOUT
_CEE_RUNOPTS=POSIX(ON)
IBM_JAVA_OPTIONS=-XX:+Enable3164Interoperability
/*
// ENDIF

End of change