Topic
6 replies Latest Post - ‏2013-05-28T22:24:11Z by infocat
infocat
infocat
8 Posts
ACCEPTED ANSWER

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
    ACCEPTED ANSWER

    Re: Calling Java from COBOL

    ‏2013-05-22T19:24:57Z  in response to infocat

    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
      116 Posts
      ACCEPTED ANSWER

      Re: Calling Java from COBOL

      ‏2013-05-24T13:39:19Z  in response to infocat

      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 :-)

  • BillWoodger
    BillWoodger
    116 Posts
    ACCEPTED ANSWER

    Re: Calling Java from COBOL

    ‏2013-05-24T13:31:53Z  in response to infocat

    Have you looked at using INVOKE?

  • infocat
    infocat
    8 Posts
    ACCEPTED ANSWER

    Re: Calling Java from COBOL

    ‏2013-05-24T17:08:15Z  in response to infocat

    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
      116 Posts
      ACCEPTED ANSWER

      Re: Calling Java from COBOL

      ‏2013-05-24T22:43:58Z  in response to infocat

      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
        ACCEPTED ANSWER

        Re: Calling Java from COBOL

        ‏2013-05-28T22:24:11Z  in response to BillWoodger

        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