0
votes

I need to run a Java class program on z/OS mainframe as a JCL job step. Has anyone done this? I have already tried running java programs under AIX on the mainframe. But I need to run the same program in a JCL jobstream. I understand that I can pass the return code back to JCL steps with System.exit(rc). But how does one execute, setup CLASSPATH, input parameters and files, and write files to z/OS?

2
Is JZOS available? - cschneid

2 Answers

4
votes

You can certainly do this with BPXBATCH to run a shell script that sets up whatever variables you need and then invokes Java. For simple and static things, you can pass BPXBATCH a list of environment variables via a special DDNAME in JCL. If you need more complex processing, you'd probably write a short shell script to set whatever you need, and that could include copying parameters from JCL-defined files to local UNIX Services files that you can pass to your Java app.

If your script to invoke Java is fairly thin, you might prefer BPXBATSL - it does a local spawn and will save you some resources. You can read about them here.

Be careful about things like output files - using something like "SYSOUT=*" doesn't work too well when you're running UNIX apps that might fork other processes...better to redirect output to a local UNIX file as in this example from the IBM doc mentioned above: BPXBATCH SH /u/usr/joe/shellscriptA > /tmp/a.out. If you need this output printed (or whatever), you can always have a subsequent step that uses OGET - see here.

If you do a lot of this and you want every last bit of performance you can get, you can always write yourself a small C program that handles all of these steps for you. You'd set whatever environment variables and so on that you need, then spawn the Java process and wait for it to end. If you want to be sophisticated, you can even write directly to SYSOUT by setting up a few pipes and passing them to Java as STDOUT/STDERR.

1
votes

Here is an example that will run a very simple Java program (myapp) that resides in /u/tstradm/myapp and writes the output to /u/tstradm/myapp.

//TSTRADMB  JOB  MSGCLASS=X,MSGLEVEL=(1,1),NOTIFY=&SYSUID,REGION=0M
//EXPORT EXPORT SYMLIST=*
// SET APPROOT='/u/tstradm/myapp'
//RUNJAVA EXEC PGM=BPXBATSL,REGION=0M,TIME=NOLIMIT,
// PARM='SH java -cp &APPROOT myapp'
//STDOUT DD PATH='&APPROOT/myapp.out',
//  PATHOPTS=(OWRONLY,OCREAT,OTRUNC),
//  PATHMODE=SIRWXU
//STDERR DD PATH='&APPROOT/myapp.err',
//  PATHOPTS=(OWRONLY,OCREAT,OTRUNC),
//  PATHMODE=SIRWXU

Note that I have used a JCL symbol called APPROOT for the root directory where the classes live and then used it for the substitution when setting up my classpath on the java invocation.

I wouldn't do too much complicated stuff in JCL - it's an annoying language with constraints on how long things can be, but it'll let you run a program in the shell and redirect output to the HFS.