Making an existing program callable from Java

The JAVA-CALLABLE directive is provided to make an existing COBOL program callable from Java™.

You can use the JAVA-CALLABLE directive to make an existing COBOL program callable from Java if the program has a well-defined interface that consists of zero or more Java-compatible parameters and optionally a returned value that must also be Java-compatible.

You need to add the JAVA-CALLABLE directive to your existing program anywhere before the PROCEDURE DIVISION header. When the program is compiled, the compiler will generate a file called a "COBOL native method stub" program which is written to a z/OS UNIX directory. You can specify the location of the directory via the OUTPATH suboption of the compiler option JAVAIOP. For more details, see JAVAIOP.

The main purpose of the COBOL native method stub file is as follows:
  • Convert any incoming Java arguments to the appropriate format of the COBOL parameter that will receive them
  • Make a dynamic call to the existing COBOL program, which must reside in your program object library included in the STEPLIB when the program runs
  • Convert an outgoing returned value from a COBOL data format to an appropriate Java format before returning to Java

There are other stub files associated with a COBOL program. See JAVA-SHAREABLE in Enterprise COBOL for z/OS® Language Reference for more details.

A COBOL/Java interoperable application may involve many Java-callable COBOL programs. All stub files needed for the application must be built into a DLL for the application using the cjbuild utility that exists in the bin sub-directory of the COBOL install directory in the z/OS UNIX file system. The resulting DLL will be loaded into the Java Virtual Machine (JVM) at run time before a call from Java to COBOL is made or when Java is accessing the WORKING-STORAGE memory of COBOL, and will also be accessed whenever a COBOL program makes a call to a static Java method using the CALL statement. See Building non-OO applications that interoperate with Java for more details.

Example

        identification division.
        program-id. COBPROG.
        data division.
        working-storage section.
        linkage-section.
        01 arg1 pic s9(9) comp-5.
        01 arg2.
           03 pic s9(18) comp-5 occurs 10 times.
        01 retval pic x(20).
        >>JAVA-CALLABLE
        procedure division using arg1 arg2 arg3
                             returning retval
       * COBOL code follows
       :
In this example, the JAVA-CALLABLE directive makes this program automatically callable by Java.
Note:
  • If a COBOL program with the JAVA-CALLABLE directive has parameters that are not one of the Java-compatible types, an error will be generated.
  • If a general COBOL group item is specified as a parameter and is not a legal Java-compatible array type, then it will be mapped to a byte array in Java (byte[]). In this case, you need to fill the byte array with data that matches the layout of the COBOL group that will be used to map those bytes.

    For more details, see Mapping between COBOL and Java types in Enterprise COBOL for z/OS Language Reference.

The COBPROG program should be compiled as usual but with the JAVAIOP(OUTPATH(zos-unix-directory)) option specified to indicate an output directory on the z/OS UNIX file system where the generated "stub" programs for the application are to be generated.

The above program will produce at least one stub program in the specified output directory which is the so-called "native method" stub program. In this example, the name of the stub program is as follows:
COBPROG_java_native.cbl

When running the cjbuild utility to build the DLL for this application, you can specify a package name (-p option) that will indicate the Java package with which the COBOL native methods are to be associated in your Java application. The default is enterprise.COBOL.

For an application that consists of just one COBOL native method called COBPROG and the stub files generated by the compiler are located in the current directory which does not contain stub files for any other applications, and you accept the current directory for all the output paths for cjbuild (which is the default and which we do here for simplicity but is not recommended in production), then cjbuild can be invoked as follows:
cjbuild -v app1
which tells cjbuild to include all the stub files in the current directory into the DLL it builds. The string "app1" is used to construct the name of the resulting DLL. For a DLL written to a z/OS UNIX path, the DLL will be called libapp1.so. If the DLL is output to an MVS data set, the DLL will appear as a member in that data set with the name LIBAPP1. See the -d option of cjbuild utility for details.
Alternatively, if you are mixing stub files for multiple interoperable applications in the same directory you can create a file in your current z/OS UNIX directory called "programs" that contains the name COBPROG, which is the only program that is part of this current application, and then you can invoke cjbuild as follows:
cjbuild -v programs app1
As a further alternative, if you are mixing stub files for multiple interoperable applications in the same directory, you can use the `-i/--progid` option of cjbuild to indicate that COBPROG is the only COBOL program in the current application, and then you can invoke cjbuild as:
cjbuild -v -i COBPROG app1
The -i/--progid option can be specified once for each COBOL program in your application, just like the program file can contain the name of each COBOL program in your application.

Programming tip: Using a program file or specifying one or more -i\--progid options is supported so that if you want to place the stub files for all your COBOL programs in a single z/OS UNIX directory, you can specify which subset of them you care about for a particular interoperable application you are building. However, if you use one directory of stub files per interoperable application, which is one possible approach to organizing your code, then you can simply omit those options and arguments, and cjbuild will process all stub files in the artifact directory as indicated by the -c/--coboldir option, and this can simplify your build process and is recommended.

Note: If the DLL resides on the z/OS UNIX file system, you can use the java.library.path property of the JVM on the java command that starts the application to indicate the location of the DLL.
For example, to run a Java application that starts with the "main" method of class TestApp and calls a COBOL program with an associated stub program DLL located in /home/myid/libs, issue the following command:
java -Djava.library.path="/home/myid/libs" TestApp

Otherwise, if the DLL is output to a data set, ensure that data set is in your STEPLIB at run time.

The actual Java code to invoke this native method is as follows:
import enterprise.COBOL.*;

:
int arg1 = 5;
int[] arg2 = new int[10];
:
String retval = enterprise.COBOL.progs.COBPROG(arg1, arg2);
Note: If the name of your COBOL native method program is not defined using a literal, that is, the name is not case-sensitive, then you must refer to it in Java in its form of upper case, as in the above example with COBPROG. However, if the COBPROG program was compiled with the PGMNAME(LONGMIXED) option in effect, then the program name should be specified as "cobprog" and the program should be referred to in Java with the name exactly as it appears in the quotes. See the following example:
String retval = enterprise.COBOL.progs.cobprog(arg1, arg2);

Related references  
Example: COBPROD application - building and running
JAVA-CALLABLE (Enterprise COBOL for z/OS Language Reference)