Register  Login
OO Cobol Examples » Interoperabilty » Cobol JNI - Java Native Interface
 

 

"History can be a good teacher if you pay attention"

 

What OO Cobol does not have

If you are developing applications with OO Cobol you may sometimes be frustrated with the lack of a comprehensive class library such as the one provided with the Java compiler. When OO Cobol was first discussed many years ago a class library was an obvious necessity, but Cobol groups could not agree with even on basic functionality. As a result, no standard class library exists for Cobol today. In fact, it is a common situation to spend days developing in OO Cobol the kind of stuff that is already created in Java, but unreachable due differences in language architecture. We cannot change the past, but the future was never so bright!


J/Adapter

J/Adapter is a technology of NetCobol for Windows that creates JNI (Java Native Interface) classes. Usually JNI applications are written in C, but J/Adapter creates pure OO Cobol classes instead. It allows you to use virtually any Java class as if it was an OO Cobol class. Just declare the class and call its methods!


But what is JNI anyways?

According to Wikipedia: "The Java Native Interface (JNI) is a programming framework that allows Java code running in a Java Virtual Machine (JVM) to call and to be called[1] by native applications (programs specific to a hardware and operating system platform) and libraries written in other languages, such as C, C and assembly."..and OO Cobol, of course!

To illustrate the power of that approach we are going to show how to create a PowerCobol application that drives a Java class via JNI to retrieve stock symbol quotes via Web Services. 


The big picture


As we can see in the diagram above, PowerCobol (or just NetCobol) apps invoke an OO Cobol method from a OO Cobol class. That class is actually generated by J/Adapter based on selected methods of Java class. The Cobol JNI class should not be modified since any changes would be lost if you regenerate it using J/Adapter. 


Generating the Cobol JNI classes 

The main Java class of our project is called StockQuoteClient:

public class StockQuoteClient {

       public StockQuoteClient() {

       }

       public String getQuote(String symbol) {

            java.lang.String result = "";

            try { // Call Web Service Operation

              net.webservicex.StockQuote service = new net.webservicex.StockQuote();

              net.webservicex.StockQuoteSoap port = service.getStockQuoteSoap();

              result = port.getQuote(symbol);

            } catch (Exception ex) {

              result = "FAIL:" ex.getMessage();

            }

           return result;

          }

}

The class contains 2 methods (the class constructor, and a getQuote method). The constructor has no parameters, but getQuote receives and return a java.lang.String type. We need to generate JNI proxy classes for these two types (StockQuoteClient and java.lang.String) using J/Adapter utility, JAVA2COB.EXE.

java2cob -classpath . -d jni -r StockQuoteClient -gc "StockQuoteClient()" -gm "getQuote(java.lang.String)"

Parameters:

-classpath .   Indicates where java2cob should look for .class files
-d jni  Folder where Cobol JNI classes should be created
-r StockQuoteClient  Java type name (your Java class). -r forces java2cob to reduce the number of Cobol JNI classes generated. Without that option java2cob would create Cobol JNI classes for whatever classes referenced  by your Java class (and may not necessary from Power perspective). Using -r you need to declare what constructors/method/properties should be mapped into Cobol JNI classes.
-gc "StockQuoteClient()"  Class constructor method
-gm "getQuote(java.lang.String) Method that calls the Web Service

To fully understand java2cob, please refer to its manual.

This is the content of JNI directory after run java2cob

java-lang-CharSequence.cob
StockQuoteClient.cob
java-io-Serializable.cob
java-lang-Object.cob
java-lang-String.cob
java-lang-Comparable.cob
java2cob.mgt

The next step is to create a NetCobol project (.prj) to create a DLL that will be used by PowerCobol. That's is pretty simple:

1. Start Cobol Project Manager
2. Open a project giving a proper name (e.g. COBOL-JNI). Confirm that you want to create it.
3. Right click on the folder icon and add a new file named StockQuoteClient.dll
4. Right click on the DLL icon and add 2 folders: Library files and Cobol Source Files
5. Add C:\PROGRAM FILES\FUJITSU NETCOBOL FOR WINDOWS\F3BIJART.LIB file under Library files
6. Add all .cob files generated by java2cob utility under Cobol Source Files folder
7. Right click on the Cobol Source Files icon and select Edit>Repository File Search>All on top menu
8. From the top menu select Tools>Class database>Create and confirm class database creation
9. Build the project using Project>Build option on top menu

Your Cobol Project Manager should look like this:

Now it is time to create the PowerCobol application. You may not have noticed, but we already have created all needed JNI classes!

This is our PowerCobol application look-and-feel:

 

Add the following LIBs to your PowerCobol project:

F3BIJART.LIB
StockQuoteClient.LIB

 


The XmlReader.LIB is a helper class that deals with XML using MS-XML. You will find that application within the Zip file at the end of this page.

Add the Cobol JNI and J/Adapter references in the repository of the Window and any other required class references that you need:

    class ClassXmlDocument      as "*COM"
    class ClassXmlReader        as "XmlReader"

     class FJ-JAVA-CONTROL
     class J-String              as "java-lang-String"
     class StockQuoteClient      as "StockQuoteClient"
        

The J/Adapter requires the JVM to be initialized. Put this code in the main Window Opened event:

       invoke FJ-JAVA-CONTROL "JVM-INIT"
     invoke StockQuoteClient "Create-StockQuoteClient-01" returning stockQuote
     
We are using the method  "Create-StockQuoteClient-01" of StockQuoteClient class to get an instance of our JNI class StockQuoteClient. That method is equivalent to Java syntax: new StockQuoteClient(); The method naming is defined automatically by java2cob. I recommend that you use the Cobol Project Manager Class Browser to find what methods are available for each generated class.

Put the following code in the Closed event of main Window to release the JVM resources:

     INVOKE FJ-JAVA-CONTROL "JVM-TERMINATE".   �

Following our application logic, there is common procedure that is called when an item in the application menu is clicked. That common procedure is called "CallJava" and this is its code:

 ENVIRONMENT     DIVISION.
 DATA            DIVISION.
 WORKING-STORAGE SECTION.
 01 xmlConfig     usage object reference ClassXmlReader.
 01 InnerText     pic x(255) value spaces.
 01 jString       usage object reference J-STRING.
 01 quoteString   usage object reference J-STRING.
 01 cobolString   pic x(8192) value spaces.
 01 quoteValue    pic x(1024)  value spaces.

 PROCEDURE       DIVISION.
     move   "Invoking Java WebService..."  to   "Caption" OF CmMessage
   
     invoke MainForm "ThruEvents" 
   
     *> Creating java String type
     invoke J-STRING "NEW-STRING-X" using symbol returning jString

     *> Getting symbol quotes thru Java Web Service
     invoke stockQuote "getQuote" using jString returning quoteString
   
     *> Moving Java String to a Cobol string type variable
     invoke quoteString "GET-STRING-X" returning cobolString
   
     move   "Java WebService Idle"  to  "Caption" OF CmMessage

     *> If we got a valid result then process the XML
     if cobolString(1:4) not = "FAIL"
        invoke ClassXmlReader "NEW" returning xmlConfig
   
        invoke xmlConfig "LoadXML" using cobolString
   
        move   xmlConfig::"GetKey"("//Symbol")              to  quoteValue
        move   quoteValue                                   to  "Caption" of CmSymbol
        move   xmlConfig::"GetKey"("//Last")                to  quoteValue
        move   quoteValue                                   to  "Caption" of CmLast
        move   xmlConfig::"GetKey"("//Date")                to  quoteValue
        move   quoteValue                                   to  "Caption" of CmDate
        move   xmlConfig::"GetKey"("//Time")                to  quoteValue
        move   quoteValue                                   to  "Caption" of CmTime
        move   xmlConfig::"GetKey"("//Change")              to  quoteValue
        move   quoteValue                                   to  "Caption" of CmChange
        move   xmlConfig::"GetKey"("//Open")                to  quoteValue
        move   quoteValue                                   to  "Caption" of CmHigh
        move   xmlConfig::"GetKey"("//High")                to  quoteValue
        move   quoteValue                                   to  "Caption" of CmOpen
        move   xmlConfig::"GetKey"("//Low")                 to  quoteValue
        move   quoteValue                                   to  "Caption" of CmLow
        move   xmlConfig::"GetKey"("//Volume")              to  quoteValue
        move   quoteValue                                   to  "Caption" of CmVolume
        move   xmlConfig::"GetKey"("//MktCap")              to  quoteValue
        move   quoteValue                                   to  "Caption" of CmMktCap
        move   xmlConfig::"GetKey"("//PreviousClose")       to  quoteValue
        move   quoteValue                                   to  "Caption" of CmPreviousClose
        move   xmlConfig::"GetKey"("//PercentageChange")    to  quoteValue
        move   quoteValue                                   to  "Caption" of CmPercentageChange
        move   xmlConfig::"GetKey"("//AnnRange")            to  quoteValue
        move   quoteValue                                   to  "Caption" of CmAnnRange
        move   xmlConfig::"GetKey"("//Earns")               to  quoteValue
        move   quoteValue                                   to  "Caption" of CmEarns
        move   xmlConfig::"GetKey"("//P-E")                 to  quoteValue
        move   quoteValue                                   to  "Caption" of CmPE
        move   xmlConfig::"GetKey"("//Name")                to  quoteValue
        move   quoteValue                                   to  "Caption" of CmName
     end-if
   
The lines in bold shows all required logic to call the Java class thru JNI. It is pretty straighforward and simple! The rest of the code deals with the web service result and show that information in the Window.

This is the aspect of out application while running:

    


Final thoughts

J/Adapter is a powerful way to integrated NetCobol and Java. The OO Cobol used here is essencial to achieve a new level of abstraction by isolating JNI complexity from business logic. Use OO Cobol without moderation!

 

Download the Zip file

Links

 
 
 
 
Creative Commons License The text of this site is licensed under a Creative Commons License.

 

 

Comments

 Name  
 Email
 Comment  
CAPTCHA image
Enter the code shown above

eeueueueueueueueueueueueueueueu rjrjrj

dgfdgdgdg  29/Jun/2011 05:29:AM

hdfhdhdhdhdh

dgfdgdgdg  29/Jun/2011 05:29:AM
Terms Of Use | Privacy Statement | Copyright 2009-2010 by RedRailsDynnamite DotNetNuke Skins & Modules