COBOL/Java Interoperability
With COBOL-IT, calling COBOL from Java requires an intermediate C program, which in the sample below, we refer to as a JNI glue program. You can use JNI to call COBOL IT DLL's in Windows or shared libraries that contain COBOL code routines in UNIX.
In effect, the way from Java to COBOL-IT is through C, as suggested in this diagram:
Java < > “C” < > COBOL
The following example includes a Java program, a JNI glue program (written in C) and a COBOL program, which receives the data passed from the original Java program, and processes it. This is only a working sample. Please refer to the Java JNI documentation for full detail about calling C code from Java.
Note
Take care to match memory models (32-bit or 64-bit) between your Java and COBOL installations. Mixing 32-bit (Java or Cobol) with 64-bit (Java or Cobol) is not allowed.
Prerequisites
The COBOL/Java interoperability samples require that the Java Development Kit (JDK) be installed on the host system. Visit the Oracle website for information on how to download and install the Java Development Kit.
This sample also requires that a C compiler, and COBOL-IT COBOL compiler be installed on the host system. Linux/Unix systems will typically have a C compiler installed. For Windows systems that do not have a C compiler installed, visit the Microsoft website for information on how to download and install a Visual Studio C++ compiler.
Calling COBOL from Java
Many businesses looking at Application Modernization will naturally look to Java for building graphical front ends, and enabling them to connect internet portals, mobile devices and application servers to their core application technology. With COBOL/Java Interoperability, solution engineers are able to propose solutions that include websites, connecting to application servers such as WebLogic, WebSphere, or JBoss, connecting in turn to legacy COBOL applications, which connect in turn to industry-leading database engines such as Oracle, DB2, Microsoft SQL Server, MySQL, and PostgreSQL.
While it is clear that Java is a powerful enabler in these cases, it is equally clear that it is not designed to serve as a replacement for the legacy COBOL applications. As a result, we see COBOL/Java Interoperability developing as an important topic in the area of Application Modernization.
In a Java/COBOL solution, the COBOL legacy applications continue to run the business- and are deployed as programs that are CALL’ed from Java through a C calling interface known as the JNI.
The Java Program
This is a Java program that will take an argument as input, and pass that information to the JNI
glue program, written in C. In our example, the JNI glue program is progjavainterface.so
(Linux/Unix), or progjavainterface.dll
(Windows).
JavaProg.java
public class JavaProg
{
public native String prog(int i, String s);
static {
System.loadLibrary("progjavainterface");
}
public static void main(String[] args) {
String s = "From Java";
JavaProg cobol= new JavaProg();
for (int i=0; i<args.length; i++) {
s = cobol.prog(i, args[i]);
System.out.println("JAVA: Returned : " + s);
}
}
}
Verify that Java Development Kit (JDK) is installed on your machine, and that the bin directory
of the JDK installation is in your PATH
. Then, you can compile the java program as follows:
>javac JavaProg.java
The JNI Glue Program
progjavainterface.c
To be able to call this COBOL program from our Java code we need a JNI glue program written in C.
#include "jni.h"
#include "libcob.h"
void
cob_string_to_C(COB_RTD, char *s, int size){
int i;
for ( i = (int) size - 1; i >= 0; i-- ) {
if ( s[i] != CHAR_SP && s[i] != 0 ) {
break;
}
}
s[i + 1] = '\0';
}
JNIEXPORT jstring JNICALL Java_JavaProg_prog(JNIEnv *env, jobject
obj, jint javaint, jstring javaString)
{
jstring jstr;
const int nativeint = javaint;
const char *nativeString = (*env)->GetStringUTFChars(env,
javaString, 0);
/*Get COBOL-IT runtime data*/
cit_runtime_t * rtd;
/*The COBOL program interface */
int (*cobolprog)(int *, char*, char*);
/* Buffer to avoid memory protection in cobol this must be the
same size +1 as string declared in LINKAGE*/
char cobolstring[32];
char resstring[41];
strncpy (cobolstring, nativeString, 31);
memset (resstring, ' ' , 40);
/*call the cobol program*/
rtd = cob_get_rtd();
cob_init(rtd, 0, NULL);
cobolprog = cob_resolve(rtd, "prog");
if(cobolprog) {
cobolprog(&nativeint, cobolstring, resstring);
}
cob_string_to_C(rtd, resstring, 41);
jstr = (*env)->NewStringUTF(env, resstring);
(*env)->ReleaseStringUTFChars(env, javaString, nativeString);
return jstr;
}
Compile the JNI glue program written in C and create a shared object:
In Linux/Unix:
cobc -b progjavainterface.c -o libprogjavainterface.so
Be careful to name the output lib<yourname> ;
this is required by the Unix loader.
In Windows:
cobc -I "C:\Program Files\Java\jdk1.6.0_22\include" -I "C:\Program Files\Java\jdk1.6.0_22\include\win32" -b progjavainterface.c
The COBOL-IT program
In our sample, the JNI glue program, written in C, has been hard-coded to call the COBOL program prog
, which will load the shared object prog.so
(Linux/Unix) or prog.dll
(Windows).
prog.cbl
IDENTIFICATION DIVISION.
PROGRAM-ID. prog.
ENVIRONMENT DIVISION.
DATA DIVISION.
LINKAGE SECTION.
01 VALINT USAGE UNSIGNED-INT.
01 VALSTR PIC X(30) USAGE DISPLAY.
01 RETS.
03 RETSTR1 PIC 9(9) USAGE DISPLAY.
03 RETSTR2 PIC X(30) USAGE DISPLAY.
03 FILLER PIC X(1) VALUE ZERO.
*
PROCEDURE DIVISION USING VALINT VALSTR RETS.
DISPLAY "COBOL: " VALINT " IS '" VALSTR "'".
MOVE VALINT to RETSTR1.
MOVE VALSTR to RETSTR2.
GOBACK.
Compile prog.cbl
cobc -m -fthread-safe prog.c bl
Take care to use the -fthread-safe
compiler flag with all of your COBOL programs, even those not directly called by Java.
Note that we use USAGE UNSIGNED-INT
for the numeric input value in the LINKAGE
section. This type matches with the native C int type.
Please refer to the COBOL-IT Reference manual for more detail about USAGE
memory mapping.
Run the java program
In Linux/Unix:
run.sh
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
java JavaProg "12345" "Calling COBOL from Java" "c"
In Windows:
java -classpath . JavaProg "12345" "Calling COBOL from Java" "c"
In summary
You can combine the compile and run commands above into scripts (Linux/Unix) or batch files (Windows) as follows:
Linux/Unix:
buildnrun.sh
javac JavaProg.java
cobc -b progjavainterface.c -o libprogjavainterface.so
cobc -m -fthread-safe prog.cbl
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
java JavaProg "12345" "Calling COBOL from Java" "c"
Windows 32:
build.bat
set JAVA_HOME=c:\program files\java\jdk1.6.0_22\bin
set PATH=%JAVA_HOME%;%PATH%
javac JavaProg.java
cobc -I "C:\Program Files (x86)\Java\jdk1.6.0_20\include" -I
"C:\Program Files (x86)\Java\jdk1.6.0_20\include\win32" -b
progjavainterface.c
cobc -m -fthread-safe prog.cob
java -classpath . JavaProg "12345" "Calling COBOL from Java" "c"
Windows 64:
buildx64.bat
set JAVA_HOME=c:\program files\java\jdk1.6.0_22\bin
set PATH=%JAVA_HOME%;%PATH%
javac JavaProg.java
cobc -I "C:\Program Files\Java\jdk1.6.0_22\include" -I
"C:\Program Files\Java\jdk1.6.0_22\include\win32" -b
progjavainterface.c
cobc -m -fthread-safe prog.cob
java -classpath . JavaProg "12345" "Calling COBOL from Java" "c"
Running JavaProg returns the following output:
COBOL: 0000000000 IS '12345 '
JAVA: Returned : 00000000012345
COBOL: 0000000001 IS 'Calling COBOL from Java '
JAVA: Returned : 000000001Calling COBOL from Java
COBOL: 0000000002 IS 'c '
JAVA: Returned : 000000002c
Calling Java from COBOL
With COBOL-IT, calling Java from COBOL requires an intermediate C program, which in the sample below, we refer to as a JNI glue program. In effect, the way from COBOL-IT to Java is through C, as suggested in this diagram:
COBOL-IT < > “C” < > Java
The following example includes a COBOL-IT program, a JNI glue program (written in C) and a Java program, which receives the data passed from the original Java program, and processes it. This is only a working sample. Please refer to the COBOL IT documentation for full detail about Calling C from COBOL IT.
Note
Take care to match memory models (32-bit or 64-bit) between your Java and COBOL installations. Mixing 32-bit (Java or Cobol) with 64-bit (Java or Cobol) is not allowed.
The COBOL-IT Program
prog.cbl
IDENTIFICATION DIVISION.
PROGRAM-ID. prog.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 STRDATA.
02 STR PIC X(20) VALUE "COBOL STRING".
02 FILLER PIC X VALUE LOW-VALUE.
PROCEDURE DIVISION.
CALL "CALLJAVA" using STRDATA.
STOP RUN.
Compile prog.cbl
cobc -x prog.cbl
The JNI Glue Program
CALLJAVA.c
#include <stdio.h>
#include <jni.h>
#include <string.h>
#include "libcob.h"
#define PATH_SEPARATOR ':' /* define it to be ';' on windows */
#define USER_CLASSPATH "." /* where Prog.class is */
JNIEnv* create_vm(JavaVM ** jvm) {
JNIEnv *env;
JavaVMInitArgs vm_args;
JavaVMOption options;
int ret;
options.optionString = "-Djava.class.path=."; //Path to
the java source code
vm_args.version = JNI_VERSION_1_6; //JDK version.
This indicates version 1.6
vm_args.nOptions = 1;
vm_args.options = &options;
vm_args.ignoreUnrecognized = 0;
ret = JNI_CreateJavaVM(jvm, (void**)&env, &vm_args);
if (ret < 0)
printf("\nUnable to Launch JVM\n");
return env;
}
COB_CALL_TARGET int CALLJAVA(char* str)
{
JNIEnv *env;
JavaVM * jvm;
jclass clsH=NULL;
jmethodID midCalling = NULL;
jstring StringArg;
/* create Jave VM ... This should be done only once */
env = create_vm(&jvm);
if (env == NULL)
return 1;
// Find the Java Class
clsH = (*env)->FindClass(env, "jmodule");
//Obtaining Method IDs
if (clsH != NULL) {
midCalling = (*env)->GetStaticMethodID(env,
clsH,"TestCall","(Ljava/lang/String;)V");
} else {
printf("\nUnable to find the requested class\n");
}
if (midCalling!=NULL) {
StringArg = (*env)->NewStringUTF(env, str);
//Calling another static method and passing string
type parameter
(*env)->CallStaticVoidMethod(env,
clsH,midCalling,StringArg);
}
/* close Java VM*/
(*jvm)->DestroyJavaVM(jvm);
}
Compile the JNI glue program written in C and create a shared object
In Linux/Unix:
cobc -m -I $JAVA_HOME/include -I $JAVA_HOME/include/linux
CALLJAVA.c -R $JAVA_HOME/jre/lib/amd64/server -L
$JAVA_HOME/jre/lib/amd64/server -ljvm
In Windows:
SET JAVA_HOME=C:\Program Files (x86)\Java\jdk1.6.0_20
PATH=%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin\server;%PATH%
SET LIB=%LIB%;%JAVA_HOME%\lib
SET
INCLUDE=%INCLUDE%;%JAVA_HOME%\include;%JAVA_HOME%\include\win32
cobc -m CALLJAVA.c -l jvm.lib
The Java Program
jmodule.java
public class jmodule
{
public static void main(String args[])
{
System.out.println("Hello World!");
System.out.println("This is the main function in
jmodule class");
}
public static void TestCall(String szArg)
{
System.out.println("Print from Java");
System.out.println(szArg);
}
}
Verify that Java Development Kit (JDK) is installed on your machine, and that the bin directory of the JDK installation is in your PATH
.
Compile the java program
>javac jmodule.java
Run the COBOL Program
In Linux/Unix:
./prog
In Windows:
SET JAVA_HOME=C:\Program Files\Java\jdk1.6.0_22
SET LIB=%LIB%;%JAVA_HOME%\lib
./prog
In summary
You can combine the compile and run commands above into scripts (Linux/Unix) or batch files (Windows) as follows:
Linux/Unix:
cobc -x prog.cob
cobc -m -I $JAVA_HOME/include -I $JAVA_HOME/include/linux
CALLJAVA.c -R $JAVA_HOME/jre/lib/amd64/server -L
$JAVA_HOME/jre/lib/amd64/server -ljvm
javac jmodule.java
./prog
Windows 32:
SET JAVA_HOME=C:\Program Files (x86)\Java\jdk1.6.0_22
SET PATH=%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin\server;%PATH%
SET LIB=%LIB%;%JAVA_HOME%\lib
SET
INCLUDE=%INCLUDE%;%JAVA_HOME%\include;%JAVA_HOME%\include\win32
cobc -x prog.cob
cobc -m CALLJAVA.c -l jvm.lib
javac jmodule.java
prog
Windows 64:
SET JAVA_HOME=C:\Program Files\Java\jdk1.6.0_22
SET PATH=%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin\server;%PATH%
SET LIB=%LIB%;%JAVA_HOME%\lib
SET
INCLUDE=%INCLUDE%;%JAVA_HOME%\include;%JAVA_HOME%\include\win32
cobc -x prog.cob
cobc -m CALLJAVA.c -l jvm.lib
javac jmodule.java
prog
Running Prog returns the following output:
Print from Java
COBOL STRING