The non-OO COBOL/Java interoperability framework was introduced in Enterprise COBOL 6.4. This framework provided the cjbuild utility to assist users with building the DLL of "stub" programs that act as the glue code between the COBOL and Java programs in the application. To improve the utility’s efficiency and usability, several improvements are delivered in the Enterprise COBOL 6.4 June 2024 PTF, including the ability to specify COBOL programs and Java methods directly on the cjbuild command line, removal of the previous requirement for users to create a “methods” file (now called a “program file”), simplifying the content requirements for these program files, providing a “clean” script for COBOL/Java interoperability artifacts, and providing an option to compile all .class files into a .jar file for the application.
Curious about how these improvements enhance efficiency and usability? Let's dive in!
How did cjbuild work in the past?
The cjbuild utility was first introduced with the release of Enterprise COBOL 6.4 in 2022. This utility originally required the creation and maintenance of a "methods file” that contained the names of all COBOL programs in an interoperable application that utilize Java interoperability features, as well as the names of every Java method called by these programs.
The "methods file" approach provided users with the ability to maintain a centralized directory that stored the Java interoperability artifact files for all COBOL programs in their organization, including for multiple, different interoperable applications. The purpose of the methods file was to select a subset of stub files in this central repository directory that would be included in the DLL for a particular application, with the relevant stub files being identified by their associated COBOL program name or Java method name. The cjbuild utility would then build a DLL for the specified application that would be located at runtime via STEPLIB or LIBPATH.
However, there are several restrictions and limitations to this approach. For example:
-
Managing multiple "methods files," especially when dealing with multiple interoperable applications, leads to additional complexity in file management.
-
Manually maintaining a list of all programs in an application and Java methods they call is cumbersome and error-prone, especially as the application evolves.
-
Even when it makes sense to maintain a methods file (i.e., when you are placing the stub files for more than one application in a central directory), placing the names of COBOL programs and Java methods in a file, instead of directly specifying them on the command line, makes the operation less intuitive and different from common compilation tools. Additionally, having to specify the name of each Java method called from COBOL increases maintenance unnecessarily.
Improved cjbuild utility for COBOL/Java interoperability
Starting with Enterprise COBOL 6.4 with the June 2024 PTF (APAR PH61700 installed), the cjbuild utility is greatly improved to address the growing sentiment for a simplified and streamlined user experience.
The improved cjbuild utility contains the following features/benefits:
-
A modification to the cjbuild syntax where the "methods" file argument is no longer a mandatory argument. The only mandatory argument is the <dll-base-name> argument, which allows the user to name the DLL produced by the utility.
-
when a “methods file” (now called a “program file”) argument is not provided, cjbuild will simply process all files in the specified COBOL artifact directory (-c/--coboldir option) and include all stub files found in the DLL it builds
-
NOTE: As long as you have all only the stub files you want to be included in the application DLL in your input directory, this method works out well, and is simple (no methods file needed). cjbuild will figure out everything for you. This approach is recommended.
-
A new cjbuild option -i/--progid is provided to allow users to specify the name of COBOL a program on the cjbuild command line instead of in a methods file. This new option would only be used by users who prefer to continue to provide cjbuild with an explicit list of programs whose stub files should be included in the application DLL, but who would prefer to provide the information on the cjbuild command line instead of in a separate file.
-
A new option -r/--jar <jar-file> is provided to allow the user to specify the location of a .jar file that will be generated from all .class files produced from compiling any Java files generated by the COBOL compiler and by cjbuild. These .class files will be needed by Java at the application’s run time.
-
cjbuild will generate a script for the user to run later that can be used to clean up COBOL/Java interoperability-related artifact files it generated in the z/OS UNIX work directory where it runs.
Here’s the new cjbuild syntax with related "help" descriptions for new or modified arguments/options:
$ cjbuild
Running cjbuild COBOL/Java build tool
=====================================
Usage: cjbuild [-hv]
[-c/--coboldir <cobol-dir>]
[-d/--dlloutdir <dll-out-dir>]
[-i/--progid <program-id>] ...
[-j/--javaclassdir <java-class-dir>]
[-k/--cleanscript <cleanup-script-name>]
[-m/--mode PURE31|PURE64|MIX_31_64]
[-p/--pkgname <package-name>]
[-r/--jar <jar-dir>]
[-s/--javasrcdir <java-src-dir>]
[<program-file>] <lib-base-name>
where:
<program-file>
NOTE: This argument was called <methods-file> in previous
versions of cjbuild and was a mandatory argument.
It is now optional.
Optional input file containing a list of COBOL programs
in the interoperable application whose stub files in the
COBOL artifact directory (indicated by the -c/--coboldir
option) are to be processed by cjbuild. When <program-file>
is not specified, and -i is also not specified, ALL stub files
in the directory are processed.
The programs listed should be those programs in the
application that have have interoperability features,
such as the >>JAVA-CALLABLE directive, the
>>JAVA-SHAREABLE directive, or CALL statements of the form:
CALL 'Java.<java-class-name>.<java-static-method-name>'
Programs compiled with the >>JAVA-CALLABLE directive
will be grouped into a class called 'progs' in the
specified package (see -p), and data items that fall under
the scope of a >>JAVA-SHAREABLE directive in any of the listed
COBOL programs will be grouped into a class called 'strg' in
the specified package.
For example, the contents of the program file for an
application consisting of two Java-callable COBOL programs
COBPROG1 and COBPROG2, one of which makes a call to
a static Java method 'Java.com.acme.MyClass.myMethod'
would look as follows:
COBPROG1
COBPROG2
<lib-base-name>
Used to create the name of the DLL that contains the
stub code needed at run time by the interoperable
application (both Java and COBOL may need this DLL).
This name is also used as the base name for the .jar
file created when when the -r/--jar option is not
specified.
e.g., If <lib-base-name> is app1, then the DLL will
be called libapp1.so if the argument to the -d
option is a z/OS UNIX directory, or LIBAPP1 if
the argument to the -d option is an MVS PDS data set.
The .jar file created when -r/--jar is not specified
is libapp1.jar.
Options:
========
-c/--coboldir <cobol-dir>
Path to COBOL artifact directory. This directory contains
files generated by the compiler when compiling COBOL
programs that contain the >>JAVA-CALLABLE and/or
>>JAVA-SHAREABLE directives.
The <cobold-dir> is usually the same directory used in the
JAVAIOP(OUTPATH) compiler option when building COBOL
programs involved in the interoperable application.
Default: current directory
-d/--dlloutdir <dll-out-dir>
Path where DLL of stub code is to be placed. For a PDS,
use path of form:
//<DATASET-NAME>
e.g., //COBOL.LOAD or //'USER.COBOL.LOAD'
Default: current directory
-h/--help
Display verbose help.
-i/--progid <program-id>
Indicates the name of a COBOL program whose stub files
in the directory indicated by the -c/--coboldir option
are to be processed by cjbuild.
The option can be specified multiple times, once for each
program to be included in cjbuild's processing.
This option is similar to the <program-file> argument, which
serves the same purpose, but -i allows you to provide the
same information to cjbuild on the command line instead of in
an input file.
<program-id> corresponds to the name of the COBOL
program as specified in the program-id clause of the
program. If the name is specified without quotes in the
COBOL program, then the name should be specified with all
upper case letters in the -i option. If the name is
specified as a literal in the COBOL program, then the case
of characters specified in the -i option should match
exactly with the program-id clause in the COBOL program.
Default: none
-j/--javaclassdir <java-class-dir>
Path to location of output .class files for generated Java code.
This path should be in your CLASSPATH environment variable.
If the -r/--jar option is specified, this option is recommended
to be left to its default value, which is the current
directory.
Default: current directory
-k/--cleanscript <cleanup-script-name>
Customize the cleanup script name. The shell script is
responsible for deleting all temporary files created by
cjbuild. The user specific filename must end with '.sh'.
Option '--all-artifacts' can be specified when invoking
the cleanup script to remove all Java interop artifacts,
including those generated by Enterprise COBOL compiler
Default: 'cjbuild_clean.sh'
-m/--mode PURE31|PURE64|MIX_31_64
Java/Cobol Interoperability mode.
Specify PURE31 for 31-bit COBOL / 31-bit Java application
Specify PURE64 for 64-bit COBOL / 64-bit Java application.
Specify MIX_31_64 for 31-bit COBOL / 64-bit Java application.
NOTE: You must build AMODE 31 COBOL programs with the
JAVAIOP(JAVA64) option for MIX_31_64 mode
applications.
Default: PURE31
-p/--pkgname <package-name>
Name of package with which COBOL native methods
will be associated. Each application should have its
own package name.
e.g., com.acme.COBOL.myapp1
Three classes will be created as part of this package:
com.acme.COBOL.myapp1.cobol
com.acme.COBOL.myapp1.progs
com.acme.COBOL.myapp1.strg
Default: enterprise.COBOL
-r/--jar <jar-file>
Create a Java .jar file from any .class files generated from
compiling Java source files produced by the COBOL compiler
and cjbuild. The .jar file will have the name indicated
by the <jar-file> argument.
The .jar file should be in your Java CLASSPATH at runtime.
Default: a .jar file with name 'lib<lib-base-name>.jar' is
created in the current directory.
-s/--javasrcdir <java-src-dir>
Path to location of output Java source files. It is
generally safe to simply accept the default for this
option.
Default: current directory
-v/--verbose
Verbose output. Shows compile/link commands executed.
For more details, see the following topics:
It is worth emphasizing that cjbuild will now simply process all files in the specified COBOL artifact directory (-c/--coboldir) if no methods file is provided. And if you choose to continue to provide a methods file, it is no longer required to individually list each Java method called from COBOL programs in the file -- only the names of the COBOL programs that contain the calls to Java, as well as the names of COBOL programs that contain the JAVA-CALLABLE and/or JAVA-SHAREABLE directive. Additionally, a new cjbuild option -i/--progid is provided to allow users to specify the name of a COBOL program on the cjbuild command line instead of in a methods file, if they still want to explicitly provide the names of COBOL programs to cjbuild. Note that the -i/--progid option can be specified as many times as necessary in a single cjbuild invocation.
cjbuild command usage and parameter descriptions
Here is the cjbuild command line syntax:
cjbuild [-hv]
[-c/--coboldir <cobol-dir>]
[-d/--dlloutdir <dll-out-dir>]
[-i/--progid <program-id>] ...
[-j/--javaclassdir <java-class-dir>]
[-k/--cleanscript <cleanup-script-name>]
[-m/--mode PURE31|PURE64|MIX_31_64]
[-p/--pkgname <package-name>]
[-r/--jar <jar-dir>]
[-s/--javasrcdir <java-src-dir>]
[<program-file>] <dll-base-name>
<program-file> is the optional input file containing a list of COBOL programs in the interoperable application whose stub files in the COBOL artifact directory (indicated by the -c/--coboldir option) are to be processed by cjbuild. This file was formerly called the “methods file”. When <program-file> is not specified, and -i is also not specified, all stub files in the directory are processed. The programs listed should be those programs in the application that have interoperability features, such as the >>JAVA-CALLABLE directive, the >>JAVA-SHAREABLE directive, or CALL statements of the form:
CALL 'Java.<java-class-name>.<java-static-method-name>'
Programs compiled with the >>JAVA-CALLABLE directive will be grouped into a class called 'progs' in the specified package (see -p), and data items that fall under the scope of a >>JAVA-SHAREABLE directive in any of the listed COBOL programs will be grouped into a class called 'strg' in the specified package. For example, the contents of the program file for an application consisting of two Java-callable COBOL programs COBPROG1 and COBPROG2, one of which makes a call to a static Java method 'Java.com.acme.MyClass.myMethod', would look as follows:
COBPROG1
COBPROG2
NOTE: Notice that it is no longer necessary to include the name of the Java method called in the file any longer.
<dll-base-name> is used to create the name of the DLL that contains the stub code needed at run time by the interoperable application (both Java and COBOL may need this DLL). This name is also used as the base name for the .jar file created when the -r/--jar option is not specified and the .jar file name defaults. For example, if <dll-base-name> is app1, then the DLL will be called libapp1.so if the argument to the -d/--dlloutdir option is a z/OS UNIX directory, or LIBAPP1 if the argument to the -d/--dlloutdir option is an MVS PDS data set. The .jar file created when the --jar <jar-file> option is not specified is libapp1.jar and is located in the directory from which cjbuild is running.
A Comparison with Previous Usage: Example
myprog.cbl:
cbl pgmname(longmixed)
identification division.
program-id. 'myprog'.
data division.
working-storage section.
01 num1 pic s9(9)v9(2) comp-3 value -12.36.
>> java-shareable on
01 num2 pic s9(9)v9(2) comp-3 value 20.12.
>> java-shareable off
procedure division.
MainProgram.
display '<<Entering COBOL program: myprog>>'
call 'Java.myjavaapps.TestApp.add' using num1
on exception
display 'Error calling myjavaapps.TestApp.add'
end-call
call 'Java.myjavaapps.TestApp.sub' using num1
on exception
display 'Error calling myjavaapps.TestApp.sub'
end-call
call 'Java.myjavaapps.TestApp.mul' using num1
on exception
display 'Error calling myjavaapps.TestApp.mul'
end-call
display '<<Exiting COBOL program: myprog>>'
goback.
end program 'myprog'.
TestApp.java
package myjavaapps;
import java.math.*;
import enterprise.COBOL.*;
public class TestApp
{
public static void add(BigDecimal num1) throws Exception
{
BigDecimal num2 = enterprise.COBOL.strg.myprog.NUM2.get();
System.out.println("TestApp.add: num1 + num2 = " + num1.add(num2));
}
public static void sub(BigDecimal num1) throws Exception
{
BigDecimal num2 = enterprise.COBOL.strg.myprog.NUM2.get();
System.out.println("TestApp.sub: num1 - num2 = " + num1.subtract(num2));
}
public static void mul(BigDecimal num1) throws Exception
{
BigDecimal num2 = enterprise.COBOL.strg.myprog.NUM2.get();
System.out.println("TestApp.mul: num1 * num2 = " + num1.multiply(num2));
}
}
Imagine an interoperable application that consists of:
Before: Previous cjbuild Usage
To build this application, the cjbuild command would require specifying each Java method:
methods:
Java.myjavaapps.TestApp.add
Java.myjavaapps.TestApp.sub
Java.myjavaapps.TestApp.mul
myprog
cjbuild command:
cjbuild -v -m MIX_31_64 methods myapp
After: Enhanced cjbuild Usage
The enhanced cjbuild utility simplifies this process, reducing the need to specify individual methods:
cjbuild -v -m MIX_31_64 myapp
Optional Enhancements:
[Optional] If you still want to specify a subset of programs in the input directory (-c/--coboldir) whose stub files should be included in the application DLL, use -i:
cjbuild -v -m MIX_31_64 -i 'myprog' myapp
[Optional] If you wish to rename the jar file from default name “libmyapp.jar” to “libapp.jar”, use -r:
cjbuild -v -m MIX_31_64 -r 'libapp.jar' myapp
Clean Script
After each invocation of cjbuild, a clean-up script (cjbuild_clean.sh) is automatically generated. You can use this script to remove generated artifacts as follows:
./cjbuild_clean.sh
./cjbuild_clean.sh --all-artifacts
Ready to explore the enhanced cjbuild utility? Try it now! Also, keep an eye out for future blog posts on COBOL/Java interoperability.
Further information
For more information about the new COBOL/Java interoperability framework and cjbuild enhancements, read the following blogs and topics: