COBOL

COBOL

COBOL

COBOL is responsible for the efficient, reliable, secure, and unseen day-to-day operations of the world's economy.

 View Only

Enhanced cjbuild utility: Streamlining COBOL/Java interoperability

By Jerry Sun posted Mon September 30, 2024 04:58 PM

  

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:

  • A COBOL program with a java-shareable data item (myprog.cbl).

  • Three Java methods callable from COBOL:

    • Java.myjavaapps.TestApp.add

    • Java.myjavaapps.TestApp.sub

    • Java.myjavaapps.TestApp.mul

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:

  • To clean only cjbuild-generated artifacts:

./cjbuild_clean.sh
  • To clean all COBOL/Java interoperability artifacts (including compiler-generated stub files):

./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:

0 comments
24 views

Permalink