"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