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.
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>
|
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.
JES jobs on the SYSOUT queue are treated as single-level directories. The dir command works in one of two ways:
- The
dircommand with no arguments returns a list of all jobs that match the current setting of theJESJOBNAMEparameter. - The
dircommand with an argument of aJobidreturns 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.
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.
- 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 Resources.
- Adjust the Project build path to include the Commons Net JAR file.
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 Resources 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 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
FTPFileinstance. In this case, you actually return an instance ofJesJob, 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
preParsemethod 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 |
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.
| Description | Name | Size | Download method |
|---|---|---|---|
| Sample Java source code | es-jesjava.jar | 6KB | HTTP |
Information about download methods
Learn
-
Submit batch jobs from Java on z/OS: Read the developerWorks article by Nagesh Subrahmanyam that details the basics of using the z/OS FTP server.
-
Communications Server for z/OS V1R2 TCP/IP Implementation Guide Volume 2: UNIX Applications, SG24-5228: Refer to this IBM Redbook™ for details on how to use the z/OS FTP server.
-
developerWorks technical events and webcasts: Stay current with developerWorks technical events and webcasts.
Get products and technologies
-
Jakarta Commons Net package: Download the package.
-
IBM trial software: Build your next development project with software for download directly from developerWorks.
Discuss
-
IBM Systems forums and developerWorks blogs: Exchange information with other developers.

Evan Williams is a consultant based in Brisbane, Australia. His 20 years of computing experience is based in the mainframe area -- especially DB2 on the mainframe. However, lately he has embraced all things new, such as Java and XML. Evan is particularly interested in the integration of these newer technologies with the mainframe world.




