Access z/OS batch jobs from Java

Java provides access to z/OS batch jobs from anywhere

You probably know that you can use File Transfer Protocol (FTP) to transfer files, but the z/OS FTP server is a little different. Not only can it provide standard access to z/OS UNIX® System Services files, the server can also provide the following:

z/OS datasets

Job Entry Subsystem (JES) spool datasets

SQL result sets

You can access these types of information from any FTP session. With the help of a Java FTP client, you can put the information to good use. Naturally, this article makes use of the access to the JES spool.

The FTP server provides access to a number of JES functions, including the following:

Submitting a job

Displaying the status of jobs

Receiving the spool output of a job (Job Control Language [JCL] messages and SYSOUT)

Deleting a job

Submitting a job and automatically receiving output

This article addresses the second and third functions in more detail: displaying job status and receiving spool output.

Basics

Before starting, ensure the following:

Your z/OS machine has the FTP server running

You have a suitably authorized user ID

In addition, you can use any of several configuration parameters to control the behaviour of the JES interface, including the most important configuration parameter JESINTERFACELEVEL . Table 1 shows a summary of configuration parameters.

Table 1. JES interface configuration parameters

Parameter Description JESINTERFACELEVEL Specifies the level of function the JES interface provides. Set to 2 for the most function. JESENTRYLIMIT Limits how many jobs will be returned. The default is 200. JESOWNER Limits jobs retrieved to jobs with this owner. If blank, defaults to the current user. JESJOBNAME Limits jobs retrieved to jobs with this job name. If blank, defaults to the current user concatenated with an *. Use * to retrieve all jobs. JESSTATUS Limits jobs retrieved to jobs with this status. If blank, defaults to all states. Valid states are OUTPUT, ACTIVE, and INPUT.

You can use the STAT command to verify the settings of the FTP server. Listing 1 shows an example.

Listing 1. Using the STAT command

ftp> quote stat 211-Server FTP talking to host 192.168.152.1, port 1858 211-User: ISIELW Working directory: ISIELW. 211-The control connection has transferred 117 bytes 211-There is no current data connection. 211-The next data connection will be actively opened 211-to host 192.168.152.1, port 1858, 211-using Mode Stream, Structure File, type ASCII, byte-size 8 211-Automatic recall of migrated data sets. 211-Automatic mount of direct access volumes. 211-Auto tape mount is allowed. 211-Inactivity timer is set to 300 211-Timer FTPKEEPALIVE is set to 0 211-VCOUNT is 59 211-ASA control characters in ASA files opened for text processing 211-will be transferred as ASA control characters. 211-Trailing blanks are removed from a fixed format 211-data set when it is retrieved. 211-Data set mode. (Do not treat each qualifier as a directory.) 211-ISPFSTATS is set to FALSE 211-Primary allocation 1 track. Secondary allocation 1 track. 211-Partitioned data sets will be created with 27 directory blocks. 211-FileType SEQ (Sequential - default). 211-Number of access method buffers is 5 211-RDWs from variable format data sets are discarded. 211-Records on input tape are unspecified format 211-SITE DB2 subsystem name is DB2 211-Data not wrapped into next record. 211-Tape write is not allowed to use BSAM I/O 211-Truncated records will not be treated as an error ... 211-JESLRECL is 80 211-JESRECFM is Fixed 211-JESINTERFACELEVEL is 2 211-Encoding is set to SBCS 211-Port of Entry resource class for IPv4 clients is: TERMINAL 211-Record format VB, Lrecl: 256, Blocksize: 6233 211 *** end of status *** ftp>

Simple FTP session

When you finish configuration, start an ordinary FTP session with the server. After you establish a session, use the SITE FILETYPE subcommand to indicate that you want to obtain JES information rather than normal HFS files.

Listing 2 shows an interactive FTP session from a Windows® client.

Listing 2. Using the SITE command

C:\>ftp 192.168.152.2 Connected to 192.168.152.2. 220-FTPD1 IBM FTP CS V1R5 at p390.qld.isi.com.au, 04:26:27 on 2006-09-06. 220 Connection will close if idle for more than 5 minutes. User (192.168.152.2:(none)): isielw 331 Send password please. Password: 230 ISIELW is logged on. Working directory is "ISIELW.". ftp> quote SITE FILETYPE=JES 200 SITE command was accepted ftp>

After you change the filetype to JES, several FTP commands operate differently, as described in Table 2.

Table 2. JES interface command differences

Command Description dir Lists jobs on the SYSOUT queue get Returns one or more SYSOUT files put Submits a job to JES delete Removes SYSOUT files

The operation of two of these commands is described below.

Command: dir

JES jobs on the SYSOUT queue are treated as single-level directories. The dir command works in one of two ways:

The dir command with no arguments returns a list of all jobs that match the current setting of the JESJOBNAME parameter.

command with no arguments returns a list of all jobs that match the current setting of the parameter. The dir command with an argument of a Jobid returns a list of all SYSOUT files that make up that job.

Listing 3 shows an example using the dir command.

Listing 3. Using the dir command

ftp> dir 200 Port request OK. 125 List started OK for JESJOBNAME=ISIELW*, JESSTATUS=ALL and JESOWNER=ISIELW JOBNAME JOBID OWNER STATUS CLASS ISIELW TSU00629 ISIELW OUTPUT TSU ABEND=522 3 spool files ISIELW TSU00609 ISIELW OUTPUT TSU ABEND=522 3 spool files ISIELW TSU00294 ISIELW OUTPUT TSU ABEND=522 3 spool files ISIELW TSU00250 ISIELW OUTPUT TSU ABEND=522 3 spool files ISIELW TSU00218 ISIELW OUTPUT TSU ABEND=522 3 spool files ISIELW TSU00199 ISIELW OUTPUT TSU ABEND=622 3 spool files ISIELW TSU00171 ISIELW OUTPUT TSU ABEND=522 3 spool files 250 List completed successfully. ftp: 524 bytes received in 0.06Seconds 8.45Kbytes/sec. ftp> dir TSU00629 200 Port request OK. 125 List started OK for JESJOBNAME=ISIELW*, JESSTATUS=ALL and JESOWNER=ISIELW JOBNAME JOBID OWNER STATUS CLASS ISIELW TSU00629 ISIELW OUTPUT TSU ABEND=522 -------- ID STEPNAME PROCSTEP C DDNAME BYTE-COUNT 001 JES2 K JESMSGLG 962 002 JES2 K JESJCL 13983 003 JES2 K JESYSMSG 17176 3 spool files 250 List completed successfully. ftp: 340 bytes received in 0.03Seconds 10.63Kbytes/sec. ftp>

Note the following about this example:

The jobs match the criteria as specified in the status line 125.

Job TSU00629 has 3 files, and this is what is reported when using the second command.

Command: get

The get command retrieves the contents of a specified JES job from the SYSOUT queue. The command works in one of two ways:

Using an argument of jobid.n, the command retrieves the contents of file n from the job jobid .

from the job . Using an argument of jobid.x, the command retrieves the contents of all files that make up job jobid. In this case, the files are concatenated with a special separator of !! END OF JES SPOOL FILE !! .

Listing 4 shows an example using the get command.

Listing 4. Using the get command

ftp> get TSU00629.x 200 Port request OK. 125 Sending all spool files for requested Jobid 250 Transfer completed successfully. ftp: 37422 bytes received in 1.19Seconds 31.53Kbytes/sec. ftp> get TSU00629.1 200 Port request OK. 125 Sending data set ISIELW.ISIELW.TSU00629.D0000002.JESMSGLG 250 Transfer completed successfully. ftp: 1402 bytes received in 0.16Seconds 8.93Kbytes/sec. ftp>

Java environment for sample code

The examples in this article were developed and run using the Eclipse environment. Follow these steps to use the sample source code:

Create a new Eclipse project, or use an existing one. Download the source code JAR file, and unzip it to a temporary location. See Download. Import the source code into the Project. Download the Commons Net Library. See Related topics. Adjust the Project build path to include the Commons Net JAR file.

Java access

So far, I have given examples of FTP command line access to the JES spool files. This is fine for simple work, but you can exploit the power of accessing the JES using FTP using a programmatic approach, such as Java.

You can use Java at two levels to access the JES using FTP:

Using Java to gain basic access to FTP services. To do this, use the Jakarta Commons Net package. See Related topics to find a link to download the Jakarta Commons Net package.

Exploiting the z/OS enhanced FTP server. To do this, enhance the Commons Net configuration to adapt to the z/OS FTP server.

The two levels are described below in more detail.

Using the Commons Net library

Using the Commons Net library is easy, and it provides a means to access a number of communication protocols, including FTP. When using the library for FTP access, use the main class FTPClient . Refer to the Javadoc for useful getting-started notes about this class.

Listing 5 provides an example to illustrate how easy the library is to use.

Listing 5. Using the Commons Net library

package evan.org; import org.apache.commons.net.ftp.*; import java.io.IOException; /** * This class provides a simple example of how to access * JES files using an FTP server from Java code. * <p>The user ID and password must be valid for the server * accessed. */ public class FtpExampleOne { public FtpExampleOne() { } public static void main(String[] args) { FTPClient ftp = null; String sUserid = "ISIELW"; String sPassword = "PASSWD"; String sHost = "192.168.152.2"; String sJobPrefix = "ISIELW*"; String replyText; ftp = new FTPClient(); FTPFile[] result = null; try { // Connect to the server ftp.connect(sHost); replyText = ftp.getReplyString(); System.out.println(replyText); // Log into the server ftp.login(sUserid, sPassword); replyText = ftp.getReplyString(); System.out.println(replyText); // Tell the server to use the JES interface ftp.site("filetype=jes"); replyText = ftp.getReplyString(); System.out.println(replyText); // Get a list of jobs String[] names = ftp.listNames("*"); for (int i = 0; i < names.length; i++) { System.out.println("file " + i + " is " + names[i]); } } catch (Exception e) { e.printStackTrace(); } finally { try { ftp.quit(); } catch (IOException e) { e.printStackTrace(); } } } }

Listing 6 shows the output from the program shown in Listing 5.

Listing 6. Results of Commons Net library example application

220-FTPD1 IBM FTP CS V1R5 at p390.qld.isi.com.au, 00:29:00 on 2006-09-07. 220 Connection will close if idle for more than 5 minutes. 230 ISIELW is logged on. Working directory is "ISIELW.". 200 SITE command was accepted file 0 is TSU00629 file 1 is TSU00609 file 2 is TSU00294 file 3 is TSU00250 file 4 is TSU00218 file 5 is TSU00199 file 6 is TSU00171

The example code fragment in Listing 7 shows how to retrieve the contents of a SYSOUT file.

Listing 7. Retrieving a SYSOUT file

// Retrieve part of a JES job String sRemoteFilename = "TSU00629.2"; InputStream is = ftp.retrieveFileStream(sRemoteFilename); BufferedReader br = new BufferedReader(new InputStreamReader((is))); boolean bContinue = true; while (bContinue) { String sLine = br.readLine(); if (sLine != null) { System.out.println("line ... " + sLine); } else { bContinue = false; is.close(); br.close(); } } ftp.completePendingCommand();

Listing 8 shows the output from a program that uses the Listing 7 code.

Listing 8. Viewing the results of the SYSOUT file retrieval

220-FTPD1 IBM FTP CS V1R5 at p390.qld.isi.com.au, 00:40:52 on 2006-09-07. 220 Connection will close if idle for more than 5 minutes. 230 ISIELW is logged on. Working directory is "ISIELW.". 200 SITE command was accepted 1 //ISIELW JOB 'ACCT#',REGION=8192K TSU00629 2 //ISPFPROC EXEC ISPFPROC XX******************************************************************** 00010000 XX* 00020000 XX* ISPF FULL-FUNCTION LOGON PROC 00030000 XX* 00040000 XX********************************************************************* 00050000 3 XXISPFPROC EXEC PGM=IKJEFT01,REGION=0M,DYNAMNBR=175, 00060000 XX PARM='%ISPFCL' 00070000 XX*TEPLIB DD DISP=SHR,DSN=ISIMPO.VSS611.VANLOAD 00080000

Extending use of the Commons Net library

The examples above provide a simple approach to obtaining JES output. But, how can you get more fine-grained control over what you access and retrieve? The Javadoc for the FTPClient describes a listFiles method. This method provides a degree of encapsulation of the files concept, because it returns an array of FTPFile objects rather than simple String objects. Listing 9 shows the use of the listFiles method.

Listing 9. Using listFiles

FTPFile[] result = ftp.listFiles("*"); for (int i=0; i < result.length; i++) { System.out.println("file " + i + " is " + result[i].getName()); }

As the output in Listing 10 shows, the results are not acceptable. The retrieved filenames do not correspond with the filenames the FTP server is meant to report. Seemingly, even though the Commons Net library can detect the host type automatically, this does not extend to the z/OS FTP extensions.

Listing 10. Using listFiles results

220-FTPD1 IBM FTP CS V1R5 at p390.qld.isi.com.au, 02:03:36 on 2006-09-07. 220 Connection will close if idle for more than 5 minutes. 230 ISIELW is logged on. Working directory is "ISIELW.". 200 SITE command was accepted file 0 is CLASS file 1 is files file 2 is files file 3 is files file 4 is files file 5 is files file 6 is files file 7 is files file 8 is TSU

The good news is you can use the Commons Net library to configure the FTPClient to parse different types of file listings. All you need to do is to produce a parser that can understand the output from the dir command and create instances of an FTPFile class. But first, get the most flexibility by extending the FTPFile class. This enables you to store the special attributes available to describe the JES files. Listing 11 illustrates the outline of such a class.

Listing 11. Extending the FTPFile class

package evan.org; import org.apache.commons.net.ftp.FTPFile; /** * The JesJob class extends the FTPFile class. This * allows for <code>JES</code> specific information to * be maintained, in addition to the standard <code>FTPFile</code> * information. * <p>This allows information for the spool files such as: * <ul> * <li>job name</li> * <li>job id</li> * <li>job owner</li> * <li>job status</li> * <li>job class</li> * <li>job return code</li> * </ul> */public class JesJob extends FTPFile { private static final long serialVersionUID = 1L; private String sJobName; private String sOwner; private String sStatus; private String sJobClass; private String sReturnCode; private String sNumFiles; public JesJob() { super(); sJobName = ""; sOwner = ""; sStatus = ""; sJobClass = ""; sReturnCode = ""; sNumFiles = ""; } public String getJobName() { return sJobName; } public void setJobName(String jobname) { sJobName = jobname; } ... }

You can configure the FTPClient to use a particular parser by supplying an instance of the FTPClientConfig class, as shown in Listing 12. This object is created with the name of a class that implements the FTPFileEntryParse interface.

Listing 12. Configuring the FTPClient

ftp = new FTPClient(); FTPClientConfig conf = new FTPClientConfig("evan.org.SimpleJesFileParser"); ftp.configure(conf);

Listing 13 shows a basic implementation of evan.org.SimpleJesFileParser .

Listing 13. Implementing the parser

package evan.org; import java.io.BufferedReader; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.net.ftp.FTPFile; import org.apache.commons.net.ftp.FTPFileEntryParser; public class SimpleJesFileParser implements FTPFileEntryParser { /** Parses a single line of text, and returns an FTPFile. * <p>Typically, the text would be something like this: * <pre> * ISIELW TSU00807 ISIELW OUTPUT TSU ABEND=522 3 spool files * jobname jobid owner status type result * </pre> * * @see org.apache.commons.net.ftp.FTPFileEntryParser#parseFTPEntry(java.lang.String) */ public FTPFile parseFTPEntry(String arg0) { JesJob f = new JesJob(); String sOwner = ""; String sStatus = ""; String sType = ""; String sReturnCode = ""; // Use regular expressions to break into words ... // remembering that: // - the first backslash is the Java String escape mechanism // so that \\S is really just \S in regexp terms. // - \S means any non-whitespace character // - \S+ means a bunch of them // - (\S+) means a bunch of them - as a group // - \s+ means some whitespace Pattern p = Pattern.compile("(\\S+)\\s+(\\S+)\\s+(.*)"); Matcher matcher = p.matcher(arg0); if (matcher.find()) { String sJobname = matcher.group(1); String sJobid = matcher.group(2); String sRemainder = matcher.group(3); if (!sRemainder.equals("")) { Pattern p2 = Pattern .compile("(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+(.*)"); Matcher matcher2 = p2.matcher(sRemainder); if (matcher2.find()) { sOwner = matcher2.group(1); sStatus = matcher2.group(2); sType = matcher2.group(3); String remainder = matcher2.group(4); if (remainder.startsWith("RC=")) { sReturnCode = remainder.substring(3, 8); } if (remainder.startsWith("ABEND=")) { sReturnCode = "S" + remainder.substring(6, 10); } if (remainder.startsWith("(JCL error)")) { sReturnCode = "JCL error"; } } } f.setName(sJobid); f.setJobName(sJobname); f.setOwner(sOwner); f.setStatus(sStatus); f.setJobClass(sType); f.setReturnCode(sReturnCode); f.setType(FTPFile.DIRECTORY_TYPE); } return f; } /** Filter a list that contains the strings from a list of * file entries. * This is an opportunity to remove any superfluous lines; * that is, strings that do not describe a real file. A common * example is headings. * * @see org.apache.commons.net.ftp.FTPFileEntryParser#preParse(java.util.List) */ public List preParse(List arg0) { Iterator it = arg0.iterator(); while (it.hasNext()) { Object o = it.next(); if (o instanceof String) { String s = (String) o; String sSub = s.substring(9, 14); if (sSub.equals("JOBID")) { it.remove(); } } } return arg0; } public String readNextEntry(BufferedReader arg0) throws IOException { String s = arg0.readLine(); return s; } }

Note the following about the code shown in Figure 13:

The main responsibility of the parser is to take a line of text and produce an FTPFile instance. In this case, you actually return an instance of JesJob , because you want to provide the extra JES information.

instance. In this case, you actually return an instance of , because you want to provide the extra JES information. The parsing performed in this code uses a mixture of regular expressions and string comparisons. This is a simple, functional implementation, though you could use better performing code to do the same thing.

Use the preParse method to filter out extra lines of information from the directory listing. In the example, the heading line is detected and removed.

Finally, you can invoke the listFiles method, as shown in Listing 14. Note that the returned result is cast to the JesJob type.

Listing 14. Using the custom parser

ftp = new FTPClient(); FTPClientConfig conf = new FTPClientConfig("evan.org.SimpleJesFileParser"); ftp.configure(conf); try { String replyText; // Connect to the server ftp.connect(sHost); replyText = ftp.getReplyString(); System.out.println(replyText); // Login to the server ftp.login(sUserid, sPassword); replyText = ftp.getReplyString(); System.out.println(replyText); // Tell server that the file will have JCL records ftp.site("filetype=jes"); replyText = ftp.getReplyString(); System.out.println(replyText); ftp.site("jesowner=*"); ftp.site("jesjobname=" + sJobPrefix); FTPFile[] result = ftp.listFiles("*"); for (int i = 0; i < result.length; i++) { JesJob job = (JesJob) result[i]; System.out.println("file " + i + " is " + job.getName() + " jobname is " + job.getJobName() + " class is " + job.getJobClass() + " status is " + job.getStatus() + " rc is " + job.getReturnCode()); } } catch (Exception e) { e.printStackTrace(); }

Listing 15 shows sample output from the Listing 14 code fragment.

Listing 15. Output from the custom parser

220-FTPD1 IBM FTP CS V1R5 at p390.qld.isi.com.au, 04:30:52 on 2006-09-07. 220 Connection will close if idle for more than 5 minutes. 230 ISIELW is logged on. Working directory is "ISIELW.". 200 SITE command was accepted file 0 is TSU00629 jobname is ISIELW class is TSU status is OUTPUT rc is S522 file 1 is TSU00609 jobname is ISIELW class is TSU status is OUTPUT rc is S522 file 2 is TSU00294 jobname is ISIELW class is TSU status is OUTPUT rc is S522 file 3 is TSU00250 jobname is ISIELW class is TSU status is OUTPUT rc is S522 file 4 is TSU00218 jobname is ISIELW class is TSU status is OUTPUT rc is S522 file 5 is TSU00199 jobname is ISIELW class is TSU status is OUTPUT rc is S522 file 6 is TSU00171 jobname is ISIELW class is TSU status is OUTPUT rc is S522 file 7 is TSU00656 jobname is ISIELW class is TSU status is ACTIVE rc is

Conclusion

This article showed you how to use Java to access z/OS JES Sysout files. In addition, extending the Commons Net Library allows the specific JES file attributes to be encapsulated in Java objects.

Downloadable resources

Related topics