IC5Notice: We have upgraded developerWorks Community to the latest version of IBM Connections. For more information, read our upgrade FAQ.
Topic
  • No replies
infocat
infocat
8 Posts

Pinned topic Calling Java from COBOL

‏2013-05-22T19:09:54Z |

I'm just learning how to use COBOL to interact with Java.  A couple of questions/comments:

Why?  :-)  By that I mean, what issues are you resolving by having COBOL call Java, or having Java call COBOL?

With that out of the way, am I the only one who finds COBOL calling Java to be, well, excessively verbose?  (Even more than COBOL is already pretty verbose!)  I have attached a "very simple" COBOL program that calls two Java methods.  Essentially, it's doing what the following Java program does:

import java.io.PrintStream;

class CobJava {
  public static void main(String argv[]) {
    Object obj;
    Class1 cobj;
    PrintStream Sysout = HelloJ.getSystemOut();
    String jString1 = System.getProperty("java.version");
    Sysout.println(jString1);
    System.out.println("Java version: " + jString1);
    return;
  }
}

Am I making the COBOL harder than it need be? 

Also, I had to create a little Java helper method, HelloJ.getSystemOut(), so that I could use the System.out.println() method.  Could I have done something directly in COBOL to facilitate this?  Here's the code of my helper method:

  public static PrintStream getSystemOut() {               
    return System.out;                                     
  }                                                        
 

Here is the COBOL program:      

process pgmname(longmixed) nodynam dll thread
       Identification division.
       Program-id. "Cobol_Calls_Java_Test" is recursive.

       Environment Division.
       Configuration section.
       Repository.
           Class System                is "java.lang.System"
           Class System_out            is "java.lang.System.out"
           Class JavaObject            is "java.lang.Object"
           Class JavaException         is "java.lang.Exception"
           Class PrintStream           is "java.io.PrintStream"
           Class jstring               is "jstring"
           Class JavaHelper            is "HelloJ"
           Class Class1                is 'Class1'                
           .

       Data division.
       Working-storage section.
       77  null_ptr                    usage is pointer
                                       value is null.
       77  obj                         object reference JavaObject.
       77  ex                          object reference JavaException.
       77  Sysout                      object reference PrintStream.
       77  cobj                        object reference Class1.
       77  Java_Version_Property_ID    picture is n(12)
                                       usage is national
                                       value N'java.version'.
       77  Java_Vendor_Property_ID     pic n(11) value N'java.vendor'.
       77  jString0                    usage is object reference jstring.
       77  jString1                    object reference jstring.
       77  UTF-16_StrLen               pic s9(9) comp-5.
       77  UTF-16_StrAddr              pointer.

       Linkage section.
       01  UTF-16_String               group-usage national.
           05  pic n occurs 0 to 9999 depending on UTF-16_StrLen.

       Copy jni suppress.

       Procedure division.
       Mainline section.
       Init-Java.
           Set address of JNIenv to JNIEnvPtr
           Set address of JNINativeInterface to JNIenv
           Invoke JavaHelper 'getSystemOut' returning Sysout
           Perform CheckException
           .

       Get_Version.
           Compute UTF-16_StrLen =
                   function length(Java_Version_Property_ID)
           Call NewString of JNINativeInterface
                using reference JNIEnv
                                Java_Version_Property_ID
                      value UTF-16_StrLen
                returning jString0
           Invoke System 'getProperty'
                  using value jString0 returning jString1
           Perform CheckException
      *
           Invoke Sysout 'println' using value jString1
           Perform CheckException
      *
           Call GetStringLength of JNINativeInterface
                using JNIEnv value jString1 returning UTF-16_StrLen
           Call GetStringChars of JNINativeInterface
                using reference JNIEnv
                      value jString1
                            null_ptr
                returning UTF-16_StrAddr
           Set address of UTF-16_String to UTF-16_StrAddr
           Display 'Java version: '
                   function display-of(UTF-16_String)
           Call ReleaseStringChars
                using value JNIEnvPtr, jString1, UTF-16_StrAddr
           .

       Exit-Program.
           Goback.

       CheckException.
           Call ExceptionOccurred using
                value JNIEnvPtr
                returning ex
           If ex not = null
               Call ExceptionClear using JNIEnv
               Display "Caught an unexpected exception"
               Invoke ex "printStackTrace"
               Stop run
           End-if
           .

       End Program "Cobol_Calls_Java_Test".
 

I should mention that I used, intentionally, some optional COBOL keywords that I might otherwise normally omit.  Simply because they (the BY REFERENCE phrase of CALL, specifically), more explicitly indicate what is being done.  In that case I am using CALL BY REFERENCE of a COBOL (national) string, rather than passing it's address explicitly by value, which would be even more code!!

Attachments

Updated on 2013-05-22T19:12:57Z at 2013-05-22T19:12:57Z by infocat
  • infocat
    infocat
    8 Posts

    Re: Calling Java from COBOL

    ‏2013-05-22T19:24:57Z  

    I did just think of one small simplification:

    Call NewString using value JNIEnvPtr                          
                               address of Java_Version_Property_ID
                               length of Java_Version_Property_ID
         returning jString0                           

    Also tried this, but it is disallowed:

    Call GetStringChars of JNINativeInterface using JNIEnv
         value jString1 null_ptr                          
         returning address of UTF-16_String             

    But got this error:

    IGYPS2000-S Expected a data-name, but found "ADDRESS".  The "CALL" statement was discarded.

  • BillWoodger
    BillWoodger
    126 Posts

    Re: Calling Java from COBOL

    ‏2013-05-24T13:31:53Z  

    Have you looked at using INVOKE?

  • BillWoodger
    BillWoodger
    126 Posts

    Re: Calling Java from COBOL

    ‏2013-05-24T13:39:19Z  
    • infocat
    • ‏2013-05-22T19:24:57Z

    I did just think of one small simplification:

    Call NewString using value JNIEnvPtr                          
                               address of Java_Version_Property_ID
                               length of Java_Version_Property_ID
         returning jString0                           

    Also tried this, but it is disallowed:

    Call GetStringChars of JNINativeInterface using JNIEnv
         value jString1 null_ptr                          
         returning address of UTF-16_String             

    But got this error:

    IGYPS2000-S Expected a data-name, but found "ADDRESS".  The "CALL" statement was discarded.

    According to the Lanaguage Reference for CALL: "RETURNING data item, which can be any data item defined in the data division."

    That's "can be" as in "cannot be anything else". "ADDRESS OF" is not defined in the DATA DIVISION, it is a SPECIAL-REGISTER, which the compiler defines.

    You could of course return a POINTER, put then there's all that typing to make a SET, and define the POINTER.

    Really, despite allegations of "verbosity", if you get a good grip on your editor, you'll find you lessen the amount of typing, and if you learn to type using all your fingers, it'll not see like such a dull, boring, task. Maybe :-)

  • infocat
    infocat
    8 Posts

    Re: Calling Java from COBOL

    ‏2013-05-24T17:08:15Z  

    My original post did have the RETURNING phrase use a pointer.  I was hoping to avoid this extra variable and line of code.  Its not so much the typing (I am a very good typer), I just find it overly verbose to look at.

    As for using Invoke to call JNI services, have you ever tried this?  JNI services are not written in Java, and therefore cannot be "invoked".

    Have you (or anyone) written extensively COBOL programs that invoke Java methods?  I'd be curious to see a real world example.

  • BillWoodger
    BillWoodger
    126 Posts

    Re: Calling Java from COBOL

    ‏2013-05-24T22:43:58Z  
    • infocat
    • ‏2013-05-24T17:08:15Z

    My original post did have the RETURNING phrase use a pointer.  I was hoping to avoid this extra variable and line of code.  Its not so much the typing (I am a very good typer), I just find it overly verbose to look at.

    As for using Invoke to call JNI services, have you ever tried this?  JNI services are not written in Java, and therefore cannot be "invoked".

    Have you (or anyone) written extensively COBOL programs that invoke Java methods?  I'd be curious to see a real world example.

    Sorry, no, not I.

    I changed your program. It now only does two things. Not verbose. If you need to look at the two things it does,  OK, but mostly you (or who picks up the program next) won't need to.

     

           process pgmname(longmixed) nodynam dll thread
           Identification division.
           Program-id. "Cobol_Calls_Java_Test" is recursive.
     
           Environment Division.
           Configuration section.
           Repository.
               Class System                is "java.lang.System"
               Class System_out            is "java.lang.System.out"
               Class JavaObject            is "java.lang.Object"
               Class JavaException         is "java.lang.Exception"
               Class PrintStream           is "java.io.PrintStream"
               Class jstring               is "jstring"
               Class JavaHelper            is "HelloJ"
               Class Class1                is 'Class1'                 
               .
     
           Data division.
           Working-storage section.
           77  null_ptr                    usage is pointer
                                           value is null.
           77  obj                         object reference JavaObject.
           77  ex                          object reference JavaException.
           77  Sysout                      object reference PrintStream.
           77  cobj                        object reference Class1.
           77  Java_Version_Property_ID    picture is n(12)  
                                           usage is national
                                           value N'java.version'.
           77  Java_Vendor_Property_ID     pic n(11) value N'java.vendor'.
           77  jString0                    usage is object reference jstring.
           77  jString1                    object reference jstring.
           77  UTF-16_StrLen               pic s9(9) comp-5.
           77  UTF-16_StrAddr              pointer.
     
           Linkage section.
           01  UTF-16_String               group-usage national.
               05  pic n occurs 0 to 9999 depending on UTF-16_StrLen.
     
           Copy jni suppress.
     
           Procedure division.
               PERFORM                     Init-Java
               PERFORM                     Get_Version
               Goback.
     
           Init-Java.
               Set address of JNIenv       to JNIEnvPtr
               Set address of JNINativeInterface
                                           to JNIenv
               Invoke JavaHelper           'getSystemOut'
                                           returning Sysout
               Perform                     CheckException
               .
           Get_Version.
               Compute UTF-16_StrLen       = function length
                                             ( Java_Version_Property_ID )
               Call NewString of JNINativeInterface  
                                           using
                                             reference
                                                JNIEnv
                                                Java_Version_Property_ID  
                                             value  
                                                UTF-16_StrLen
                                           returning
                                              jString0
               Invoke System 'getProperty'  
                                           using
                                             value
                                               jString0
                                           returning
                                             jString1
               Perform                     CheckException
     
               Invoke Sysout 'println'     
                                           using
                                             value
                                               jString1
               Perform                     CheckException
     
               Call GetStringLength of JNINativeInterface  
                                           using JNIEnv
                                             value
                                               jString1
                                           returning
                                              UTF-16_StrLen
     
               Call GetStringChars of JNINativeInterface
                                           using
                                             reference
                                               JNIEnv
                                             value
                                               jString1  
                                               null_ptr
                                           returning
                                             UTF-16_StrAddr
               Set address of UTF-16_String
                                             to UTF-16_StrAddr
               Display 'Java version: '
                       function display-of(UTF-16_String)
               Call ReleaseStringChars
                                             using
                                               value
                                                 JNIEnvPtr
                                                 jString1
                                                 UTF-16_StrAddr
               .
     
           CheckException.
               Call ExceptionOccurred
                                             using
                                               value
                                                 JNIEnvPtr
                                             returning
                                               ex
               If ex not = null
                   Call ExceptionClear       using JNIEnv
                   Display "Caught an unexpected exception"
                   Invoke ex "printStackTrace"
                   Stop run
               End-if
               .
     
           End Program "Cobol_Calls_Java_Test".

  • infocat
    infocat
    8 Posts

    Re: Calling Java from COBOL

    ‏2013-05-28T22:24:11Z  

    Sorry, no, not I.

    I changed your program. It now only does two things. Not verbose. If you need to look at the two things it does,  OK, but mostly you (or who picks up the program next) won't need to.

     

           process pgmname(longmixed) nodynam dll thread
           Identification division.
           Program-id. "Cobol_Calls_Java_Test" is recursive.
     
           Environment Division.
           Configuration section.
           Repository.
               Class System                is "java.lang.System"
               Class System_out            is "java.lang.System.out"
               Class JavaObject            is "java.lang.Object"
               Class JavaException         is "java.lang.Exception"
               Class PrintStream           is "java.io.PrintStream"
               Class jstring               is "jstring"
               Class JavaHelper            is "HelloJ"
               Class Class1                is 'Class1'                 
               .
     
           Data division.
           Working-storage section.
           77  null_ptr                    usage is pointer
                                           value is null.
           77  obj                         object reference JavaObject.
           77  ex                          object reference JavaException.
           77  Sysout                      object reference PrintStream.
           77  cobj                        object reference Class1.
           77  Java_Version_Property_ID    picture is n(12)  
                                           usage is national
                                           value N'java.version'.
           77  Java_Vendor_Property_ID     pic n(11) value N'java.vendor'.
           77  jString0                    usage is object reference jstring.
           77  jString1                    object reference jstring.
           77  UTF-16_StrLen               pic s9(9) comp-5.
           77  UTF-16_StrAddr              pointer.
     
           Linkage section.
           01  UTF-16_String               group-usage national.
               05  pic n occurs 0 to 9999 depending on UTF-16_StrLen.
     
           Copy jni suppress.
     
           Procedure division.
               PERFORM                     Init-Java
               PERFORM                     Get_Version
               Goback.
     
           Init-Java.
               Set address of JNIenv       to JNIEnvPtr
               Set address of JNINativeInterface
                                           to JNIenv
               Invoke JavaHelper           'getSystemOut'
                                           returning Sysout
               Perform                     CheckException
               .
           Get_Version.
               Compute UTF-16_StrLen       = function length
                                             ( Java_Version_Property_ID )
               Call NewString of JNINativeInterface  
                                           using
                                             reference
                                                JNIEnv
                                                Java_Version_Property_ID  
                                             value  
                                                UTF-16_StrLen
                                           returning
                                              jString0
               Invoke System 'getProperty'  
                                           using
                                             value
                                               jString0
                                           returning
                                             jString1
               Perform                     CheckException
     
               Invoke Sysout 'println'     
                                           using
                                             value
                                               jString1
               Perform                     CheckException
     
               Call GetStringLength of JNINativeInterface  
                                           using JNIEnv
                                             value
                                               jString1
                                           returning
                                              UTF-16_StrLen
     
               Call GetStringChars of JNINativeInterface
                                           using
                                             reference
                                               JNIEnv
                                             value
                                               jString1  
                                               null_ptr
                                           returning
                                             UTF-16_StrAddr
               Set address of UTF-16_String
                                             to UTF-16_StrAddr
               Display 'Java version: '
                       function display-of(UTF-16_String)
               Call ReleaseStringChars
                                             using
                                               value
                                                 JNIEnvPtr
                                                 jString1
                                                 UTF-16_StrAddr
               .
     
           CheckException.
               Call ExceptionOccurred
                                             using
                                               value
                                                 JNIEnvPtr
                                             returning
                                               ex
               If ex not = null
                   Call ExceptionClear       using JNIEnv
                   Display "Caught an unexpected exception"
                   Invoke ex "printStackTrace"
                   Stop run
               End-if
               .
     
           End Program "Cobol_Calls_Java_Test".

    It seems like my original "issue" was not clear.  I understand how to use COBOL, and how to use performing of paragraphs to segregate processes in to manageable pieces.  My point is that I have to, no matter where it is in the code, use five or so distinct statements to do what in Java is only a single statement.  I understand that it has to be done.  I just think its more of a "plumbing" issue.

    In any case, and for whatever its worth, I've written two new versions of the program.  Of course I cut out some of the "functionality" altogether, so it's more of comparing apples to a smaller type of apple.  :-)  Anyway, they make calls to some "helper" routines that I wrote (and are also included here).  Take it for what its worth.

    I'd still be curious to know what "real world" uses are being applied to this COBOL/Java interface.

           process pgmname(longmixed) nodynam dll thread
           identification division.
           program-id. "Cobol_Calls_Java_Test" recursive.

           environment division.
           configuration section.
           repository.
               class System                is "java.lang.System"
               class jstring               is "jstring".

           data division.
           local-storage section.
           77  JavaPropertyName            object reference jstring.
           77  JavaPropertyValue           object reference jstring.
           linkage section.
           01  cob-varchar.
               05  cob-str-len             pic s9(9) comp-5.
               05  cob-string.
                   10  pic x occurs 1 to 256 depending on cob-str-len.

           procedure division.
           mainline section.
               perform init-cob-varchar
               perform get-java-version
               goback.

           init-cob-varchar.
          *  cob-varchar will point to the varchar representation
          *  of the Java string passed most recently to 'FromJavaString'
               call 'FromJavaString' using address of cob-varchar
               .

           get-java-version.
               call 'ToJavaString' using content z'java.version'
                                         JavaPropertyName
               invoke System 'getProperty' using value JavaPropertyName
                      returning JavaPropertyValue
               call 'CheckJavaException'
               call 'FromJavaString' using JavaPropertyValue
               display 'Java version: ' cob-string
               .

           end program "Cobol_Calls_Java_Test".

     

           process pgmname(longmixed) nodynam dll
           identification division.
           program-id. "Cobol_Calls_Java_Test".

           data division.
           linkage section.
           01  cob-varchar.
               05  cob-str-len             pic s9(9) comp-5.
               05  cob-string.
                   10  pic x occurs 1 to 256 depending on cob-str-len.

           procedure division.
           mainline section.
               perform init-cob-varchar
               perform get-java-version
               goback.

           init-cob-varchar.
          *  cob-varchar will point to the varchar representation
          *  of the Java string passed most recently to 'FromJavaString'
               call 'FromJavaString' using address of cob-varchar
               .

           get-java-version.
               call 'GetJavaProperty' using content z'java.version'
               display 'Java version: ' cob-string
               .

           end program "Cobol_Calls_Java_Test".

     

           process pgmname(longmixed) nodynam dll exportall thread
           id division.
           program-id. 'CheckJavaException' is recursive.

           environment division.
           configuration section.
           repository.
               class JavaException is "java.lang.Exception".

           data division.
           local-storage section.
           77  ex                          object reference JavaException.
           linkage section.
           copy jni suppress.

           procedure division.
               set address of JNIenv to JNIEnvPtr
               set address of JNINativeInterface to JNIenv
               call ExceptionOccurred using value JNIEnvPtr
                                      returning ex
               if ex not = null
                   call ExceptionClear using by value JNIEnvPtr
                   display "Caught an unexpected exception"
                   invoke ex "printStackTrace"
                   stop run
               end-if
               exit program.

           end program 'CheckJavaException'.     

     

           id division.
           program-id. 'ToJavaString' is recursive.

           environment division.
           configuration section.
           repository.
               class jstring is "jstring".

           data division.
           local-storage section.
           77  call-result                 pic s9(9) comp-5.
           linkage section.
           77  cobol_zstring               pic x(255) usage is display.
           77  javaString                  object reference jstring.
           procedure division using cobol_zstring
                                    javaString.
               call 'NewStringPlatform' using value JNIEnvPtr
                                              reference cobol_zstring
                                                        javaString
                                              value 0
                    returning call-result
               if call-result > zero
                   call 'FBABEND'
               end-if
               exit program.

           end program 'ToJavaString'.

     

           id division.
           program-id. 'FromJavaString' is recursive.

           environment division.
           configuration section.
           repository.
               class jstring is "jstring".

           data division.
           working-storage section.
           77  addr-of-caller-varchar      pointer value null.
           77  heap-id                     pic s9(9) comp-5 value zero.
           local-storage section.
           77  call-result                 pic s9(9) comp-5.
           77  cob-varchar-len             pic s9(9) comp-5.
           linkage section.
           77  parm1                       pic x.
           77  javaString                  object reference jstring.
           77  cob-varchar-addr            pointer.
           01  cob-varchar.
               05  cob-str-len             pic s9(9) comp-5.
               05  cob-string              pic x.

           procedure division using parm1.
               if addr-of-caller-varchar = null
          *      first time through we simply save the address of
          *      the parm (which in turn is the address of the
          *      caller's bll)
                   set addr-of-caller-varchar to address of parm1
               else
                   set address of javaString to address of parm1
                   perform mainline
               end-if
               exit program.

           mainline.
          *  get the length of the Java string
               perform get-string-length
          *  we want storage for length of string PLUS length of
          *  the length field itself
               add length of cob-str-len to cob-varchar-len
          *  point to the address of the caller varchar bll
               set address of cob-varchar-addr to addr-of-caller-varchar
          *  get storage and point the caller varchar to it
               perform allocate-storage-for-varchar
          *  set our view of the caller varchar
               set address of cob-varchar to cob-varchar-addr
          *  populate the str-len field within the caller varchar
               subtract length of cob-str-len from cob-varchar-len
                        giving cob-str-len
          *  place the string into the newly allocated string area
               perform get-string
          *  adjust the caller string length to ignore the trailing null
               subtract 1 from cob-str-len
               .

           get-string-length.
               call 'GetStringPlatformLength'
                    using value JNIEnvPtr
                                javaString
                          reference cob-varchar-len
                          value 0
                    returning call-result
               if call-result > zero
                   call 'FBABEND'
               end-if
               .

           allocate-storage-for-varchar.
               if cob-varchar-addr = null
                   call 'CEEGTST' using heap-id
                                        cob-varchar-len
                                        cob-varchar-addr
                                        omitted
               else
                   call 'CEECZST' using cob-varchar-addr
                                        cob-varchar-len
                                        omitted
               end-if
               .

           get-string.
               call 'GetStringPlatform' using value JNIEnvPtr
                                                    javaString
                                              reference cob-string
                                              value cob-str-len
                                              value 0
               .

           end program 'FromJavaString'.     

     

           id division.
           program-id. 'GetJavaProperty' recursive.

           environment division.
           configuration section.
           repository.
               class System                is "java.lang.System"
               class jstring               is "jstring".

           data division.
           local-storage section.
           77  JavaPropertyName            object reference jstring.
           77  JavaPropertyValue           object reference jstring.
           linkage section.
           77  property-name-zstring       pic x(80).

           procedure division using property-name-zstring.
               call 'ToJavaString' using property-name-zstring
                                         JavaPropertyName
               invoke System 'getProperty' using value JavaPropertyName
                      returning JavaPropertyValue
               call 'CheckJavaException'
               call 'FromJavaString' using JavaPropertyValue
               exit program.

           end program 'GetJavaProperty'.

    Updated on 2013-05-28T22:25:09Z at 2013-05-28T22:25:09Z by infocat