Example: invoking Java from a batch COBOL program
You can invoke Java™ from a batch COBOL program by using the Java Batch Launcher and Toolkit for z/OS® (JZOS). The following example contains JCL and source for a COBOL program that invokes a Java program in a batch job step. Numbers in parentheses refer to notes that follow the example.
In this environment, it is often desirable to direct the
standard Java
System.out
and System.err
files
to z/OS data sets or spool
files. You can do this by calling the redirectStandardStreams
method
in the com.ibm.jzos.ZUtil
class after starting the Java virtual machine (JVM). For
details about the ZUtil
class, see ZUtil in the z/OS security and legacy services API Reference.In
this example COBOL program, the main()
method from
the com.ibm.jzos.sample.HelloWorld
class is invoked,
but you can change this to invoke other Java class
methods.
//COB2JAV JOB (),'Dovetail',
// MSGCLASS=H,REGION=128M,
// NOTIFY=&SYSUID
//*
//* Tested on z/OS V2R2 with Ent Cobol V5R1 and Java V7.0
// SET COBPRFX='SYSPROG.MNT.COBOL51' (1)
// SET LIBPRFX='CEE'
// SET SYSLIB1='G1JAVA1.PRIVATE.JZOS.DEVEL.JCL' Has JNI cpybook (2)
//* See also CLASSPATH below
//*
//COMPILE EXEC PGM=IGYCRCTL,
// PARM='SIZE(5000K)'
//SYSLIB DD DISP=SHR,DSN=&SYSLIB1 (JNI) CPY
//SYSLIN DD DSNAME=&&OBJECT(TSTHELLO),UNIT=3390,DISP=(NEW,PASS),
// SPACE=(CYL,(1,1,1)),DCB=(LRECL=80,RECFM=FB)
//SYSPRINT DD SYSOUT=*
//STEPLIB DD DSN=&COBPRFX..SIGYCOMP,DISP=SHR
// DD DSN=&LIBPRFX..SCEERUN,DISP=SHR
// DD DSN=&LIBPRFX..SCEERUN2,DISP=SHR
//SYSUT1 DD UNIT=VIO,SPACE=(CYL,(1,1))
//SYSUT2 DD UNIT=VIO,SPACE=(CYL,(1,1))
//SYSUT3 DD UNIT=VIO,SPACE=(CYL,(1,1))
//SYSUT4 DD UNIT=VIO,SPACE=(CYL,(1,1))
//SYSUT5 DD UNIT=VIO,SPACE=(CYL,(1,1))
//SYSUT6 DD UNIT=VIO,SPACE=(CYL,(1,1))
//SYSUT7 DD UNIT=VIO,SPACE=(CYL,(1,1))
//SYSUT8 DD UNIT=SYSALLDA,SPACE=(CYL,(1,1))
//SYSUT9 DD UNIT=SYSALLDA,SPACE=(CYL,(1,1))
//SYSUT10 DD UNIT=SYSALLDA,SPACE=(CYL,(1,1))
//SYSUT11 DD UNIT=SYSALLDA,SPACE=(CYL,(1,1))
//SYSUT12 DD UNIT=SYSALLDA,SPACE=(CYL,(1,1))
//SYSUT13 DD UNIT=SYSALLDA,SPACE=(CYL,(1,1))
//SYSUT14 DD UNIT=SYSALLDA,SPACE=(CYL,(1,1))
//SYSUT15 DD UNIT=SYSALLDA,SPACE=(CYL,(1,1))
//SYSMDECK DD UNIT=SYSALLDA,SPACE=(CYL,(1,1))
//SYSIN DD *
cbl dll,thread
Identification division.
Program-id. "TSTHELLO" recursive.
Environment division.
Configuration section.
Repository.
Class ZUtil is "com.ibm.jzos.ZUtil" (3)
Class HelloWorld is "com.ibm.jzos.sample.HelloWorld" (4)
Class JavaException is "java.lang.Exception"
Class JavaObject is "java.lang.Object"
Class JavaString is "java.lang.String"
Class JavaClass is "java.lang.Class"
Class stringArray is "jobjectArray:java.lang.String".
Data Division.
Working-storage section.
01 args object reference stringArray.
01 argsLen pic s9(9) binary value 0.
01 jstring1 object reference JavaString.
01 stringClass object reference JavaClass.
01 ex object reference JavaException.
01 stringBuf pic X(256) usage display.
Linkage section.
COPY "JNI" SUPPRESS.
Procedure division.
Display "COBOL program TSTHELLO entered"
Set address of JNIEnv to JNIEnvPtr
Set address of JNINativeInterface to JNIENV
*
* This static JZOS method will redirect Java stdout/stderr
* to DD:STDOUT and DD:STDERR, which may be spool files or data sets
*
Invoke ZUtil "redirectStandardStreams" (3)
Perform ErrorCheck
Display "Returned from ZUtil.redirectStandardStreams"
*
* We invoke com.ibm.jzos.sample.HelloWorld,
* but this could be any arbitrary Java code
*
Perform BuildEmptyArgsArray.
Invoke HelloWorld "main" (4)
using by value args
Perform ErrorCheck
Display "Returned from HelloWorld.main"
Goback.
ErrorCheck.
Call ExceptionOccurred
using by value JNIEnvPtr
returning ex
If ex not = null then
Call ExceptionClear using by value JNIEnvPtr
Display "Caught a Java exception"
Invoke ex "printStackTrace"
Stop run
End-if.
BuildEmptyArgsArray.
* Create a new empty string
Call NewString
using by value JNIEnvPtr
address of stringBuf
0
returning jstring1
If jstring1 not = null then
Display "NewString returned OK"
Else
Display "NewString returned null!"
Stop run
End-if
* Get a reference to the String class object
Call GetObjectClass
using by value JNIEnvPtr jstring1
returning stringClass
If stringClass not = null then
Display "GetObjectClass returned OK"
Else
Display "GetObjectClass returned null!"
Stop run
End-if
* Create a zero-length String[] array
move 0 to argsLen
Call NewObjectArray
using by value JNIEnvPtr
argsLen stringClass jstring1
returning args
If args not = null then
Display "NewObjectArray returned OK"
Else
Display "NewObjectArray returned null!"
Stop run
End-if.
End program "TSTHELLO".
/*
//LKED EXEC PGM=IEWL,COND=(4,LT,COMPILE),
// 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=&&GOSET(TSTHELLO),DISP=(MOD,PASS),UNIT=3390,
// SPACE=(CYL,(1,1,1)),DSNTYPE=LIBRARY
//SYSDEFSD DD DUMMY
//OBJMOD DD DSN=&&OBJECT,DISP=(OLD,DELETE)
//SYSLIN DD *
INCLUDE OBJMOD(TSTHELLO)
INCLUDE '/usr/lpp/java/J7.0/bin/j9vm/libjvm.x' (5)
INCLUDE '/usr/lpp/cobol/V5R1/lib/igzcjava.x' (5)
//*
//* Note: we expect RC=32 since we should Stop run for exception
//*
//GO EXEC PGM=TSTHELLO,COND=(4,LT,LKED)
//CEEOPTS DD *
* Be careful when editing: quoted ENVARS wrap at col 72
ENVAR( (6)
"PATH=bin:/usr/lpp/java/J7.0/bin",
"LIBPATH=lib:/usr/lib:/usr/lpp/java/J7.0/bin:/usr/lpp/java/J7.0/lib/s390
:/usr/lpp/java/J7.0/lib/s390/j9vm",
"CLASSPATH=/home/g1java1/jzostest/jzos_test.jar")
POSIX(ON) XPLINK(ON)
*
* Add this ENVAR to send stdout/stderr to DD:SYSOUT
* "COBJVMINITOPTIONS=-Djzos.merge.sysout=true", (7)
* Debugging options:
* "COBJVMINITOPTIONS=-Xdump:ceedump -Xcheck:jni:trace -Xjit:verbose")
//STEPLIB DD DSN=*.LKED.SYSLMOD,DISP=(OLD,PASS)
// DD DSN=&LIBPRFX..SCEERUN2,DISP=SHR
// DD DSN=&LIBPRFX..SCEERUN,DISP=SHR
//SYSOUT DD SYSOUT=*
//CEEDUMP DD SYSOUT=*
//SYSUDUMP DD DUMMY
//*
//* ZUtil.redirectStandardStreams will point to these for sdtout/stderr
//* Unless you add the -Djzos.merge.sysout=true option above.
//* Using that option, both Java stdout/stderr with go to DD:SYSOUT
//STDOUT DD SYSOUT=*
//STDERR DD SYSOUT=*
//*
//* JAVAOUT/JAVAERR should not be used unless redirectStandardStreams fails
//* so you may choose to point these to DUMMY
//JAVAOUT DD PATH='/tmp/cob2jav.javaout', (8)
// PATHOPTS=(OWRONLY,OCREAT,OTRUNC),
// PATHMODE=(SIRUSR,SIWUSR,SIRGRP)
//JAVAERR DD PATH='/tmp/cob2jav.javaerr', (8)
// PATHOPTS=(OWRONLY,OCREAT,OTRUNC),
// PATHMODE=(SIRUSR,SIWUSR,SIRGRP)
- (1)
- Set the JCL symbols to match your environment.
- (2)
- You must first copy the
JNI.cpy
file from your COBOL installation directory (typically /usr/lpp/cobol/include) as member JNI in this source PDS. - (3)
- The
ZUtil
redirectStandardStreams
method will redirect JavaSystem.out
andSystem.err
toDD:STDOUT
andDD:STDERR
respectively. - (4)
- The
com.ibm.jzos.sample.HelloWorld
class prints “Hello World! (stdout)” toSystem.out
and “Hello World! (stderr)” toSystem.err
. You can download thecom.ibm.jzos.sample.HelloWorld
class with the JZOS samples. - (5)
- Set the
INCLUDE
s to point to the locations where your Java and COBOL are installed. - (6)
- Set the Language Environment®
ENVAR
s to point to your Java home directories. Note that individual environment variable settings wrap at column 72. - (7)
- You can add the COBJVMINITOPTIONS environment
variable as shown to set Java system
properties for the JVM. The
jzos.merge.sysout=true
property can be used to merge bothSystem.out
andSystem.err
to go toDD:SYSOUT
. - (8)
- The
JAVAOUT DD
andJAVAERR DD
statements are not used ifZUtil.redirectStandardStreams()
works properly, so you can point these toDD DUMMY
.
About JZOS
Java Batch Launcher and Toolkit for z/OS (JZOS) is a set of tools that helps you develop z/OS Java applications that run in a traditional batch environment, and that access z/OS system services. For details, see the JZOS Installation and User's Guide.