On 30.06.2023 09:44, Rony G. Flatscher wrote:
On 28.06.2023 17:26, Tom Ross wrote:
Please check out the examples in the COBOL Programming Guide, in
Part 6. Developing object-oriented programs
GO here:https://www.ibm.com/support/pages/node/611415
Select which release you are interested in and then
click "Product Documentation"
thank you, Tom. Could get to <https://www.ibm.com/support/pages/node/611415#64> and from there to
the programming guide at <https://publibfp.dhe.ibm.com/epubs/pdf/igy6pg40.pdf>.
It seems that OO COBOL allows interacting with Java via JNI (Java native interface) only. 6.4 adds
the ability to invoke static Java methods without OO COBOL.
Not having any of the necessary infrastructure (mainframe ;) , OO COBOL and Java) there is nothing
I could do. So maybe just hinting of what would become possible if anyone with the OO COBOL-Java
skills would come with showing how to code the following Java program in OO COBOL.
Such an example would serve as a nutshell example that would demonstrate how to invoke scripts
from OO COBOL in any scripting language for which an implementation of javax.script.Engine exists
including supplying arguments (stored in a Java array of type java.lang.Object) and fetching the
result.
To make this as flexible (and thereby as usable) as possible, the following Java program will take
the name of a file containing a script as a single argument, and then will load with the help of
the Java scripting framework the appropriate scripting engine to execute the script, and supply as
an argument the name of a Java system property which the script should return to the caller.
Here the Java code that should be transcribed to COBOL:
import javax.script.*;
import java.io.File;
import java.io.FileReader;
class Test
{
public static void main (String args[])
{
if (args.length==0)
{
System.err.println("file name missing...");
System.exit(-1);
}
String fileName = args[0]; // get filename
String extension =
fileName.substring(fileName.lastIndexOf(".")+1);
ScriptEngineManager sem = new ScriptEngineManager();
ScriptEngine se = sem.getEngineByExtension(extension);
Object result = null;
try
{
ScriptContext sc = se.getContext();
// add filename
sc.setAttribute(se.FILENAME, fileName , sc.ENGINE_SCOPE);
// add some arbitrary arguments
Object scriptArgs[] = new Object [] { "first", "", "trois", null,
"cinque" };
sc.setAttribute(se.ARGV , scriptArgs, sc.ENGINE_SCOPE);
// create a FileReader from File
FileReader f = new FileReader(new File(fileName));
result=se.eval(f); // read and execute script
}
catch (Throwable t)
{
System.err.println("Oops, some exception occurred: "+t);
}
System.out.println("script's result: "+result);
System.exit(0);
}
}
Here a Rexx file (can be any Rexx script):
parse source s
say "source :" s
parse version v
say "version:" v
say "there are" arg() "arguments supplied:"
do i=1 to arg()
say " #" i":" arg(i)
end
return 43
The Java program "Test", once compiled can then be used to run any script (not only Rexx) from a
script file where the file extension determines which scripting language should get loaded to run
the script in the file. Here an example of running the Java program supplying the name of a file
containing a Rexx script:
G:\tmp\bsf4oorexx\cobol>java Test rexxscript.rex
REXXout>source : WindowsNT SUBROUTINE rexxscript_ori.rex
REXXout>version: REXX-ooRexx_5.1.0(MT)_64-bit 6.05 6 Jun 2023
REXXout>there are 6 arguments supplied:
REXXout> # 1: first
REXXout> # 2:
REXXout> # 3: trois
REXXout> # 4: The NIL object
REXXout> # 5: cinque
REXXout> # 6: a Slot.Argument
script's result: 43
---
The script code can also be supplied directly as a String to the script engine's eval() method
"res=eval(String scriptCode)", such that you could load the script code from a database in case
you have it stored as such. The possibilities are endless.
As you can see, one can submit any value/object as an argument to the script and fetch any result
of the script.
---
It would be interesting to see the above Java code transcribed to COBOL, so anyone with the
necessary skills please give a helping hand for the community! :)
The result would be enabling COBOL programmers to invoke any kind of scripts in any kind of
languages from COBOL exploiting the Java scripting framework.
Such scripts could e.g. dive deep into Java and serve the COBOL programs probably in an easier
manner from then on. E.g., the following ooRexx script returns a sorted list of all the Java
system properties of the currently running JVM in a string array:
clzSystem = bsf.loadClass("java.lang.System")
properties = clzSystem~getProperties -- get the System properties
arrSortedKeys = properties~makeArray~sort -- let ooRexx sort the array
-- create Java array of appropriate size
strArray = bsf.createJavaArray("java.lang.String", arrSortedKeys~items)
do counter c key over arrSortedKeys
strArray[c]=key":" properties~getProperty(key)
end
return strArray
::requires BSF.CLS -- load the bidirectional ooRexx-Java bridge
As you can see everything becomes possible, only the sky is then the limit for COBOL programmers
who become able to invoke such scripts. :)
Again, any COBOL programmers who would take on this little task?
---rony
Maybe one more idea: as 6.4 allows for using static Java methods one could come up with a Java class
having static methods for running scripts from files and from strings. This way it is much easier
for the COBOL programmer to invoke scripts.
Such a Java class could look like this:
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
class ScriptingFramework4COBOL
{
public static void main (String args[]) throws ScriptException,
FileNotFoundException
{
System.out.println( "runScriptFromFile("+args[0]+",null): "+
runScriptFromFile(args[0],null));
System.out.println("...");
String scriptCode = "parse source s; say .dateTime~new':' s";
System.out.println("runScriptFromString(\"rexx\","+scriptCode+"),null): "+
runScriptFromString("rexx",scriptCode,null) );
System.exit(0);
}
public static Object runScriptFromFile (String fileName, Object []
scriptArgs) throws
ScriptException, FileNotFoundException
{
if (fileName == null)
{
throw new ScriptException ("fileName must not be null");
}
String extension =
fileName.substring(fileName.lastIndexOf(".")+1);
ScriptEngineManager sem = new ScriptEngineManager();
ScriptEngine se = sem.getEngineByExtension(extension);
if (se == null)
{
throw new ScriptException ("cannot load script engine for extension:
"+extension);
}
Object result = null;
ScriptContext sc = se.getContext();
// add filename
sc.setAttribute(se.FILENAME, fileName , sc.ENGINE_SCOPE);
// script arguments to add?
if (scriptArgs != null)
{
sc.setAttribute(se.ARGV , scriptArgs, sc.ENGINE_SCOPE);
}
// create a FileReader from File
FileReader f = new FileReader(new File(fileName));
result=se.eval(f); // read and execute script
return result;
}
public static Object runScriptFromString (String scriptEngineName,
String scriptCode,
Object [] scriptArgs) throws ScriptException, FileNotFoundException
{
if (scriptEngineName == null)
{
throw new ScriptException ("scriptEngineName must not be null");
}
if (scriptCode == null)
{
throw new ScriptException ("scriptCode must not be null");
}
ScriptEngineManager sem = new ScriptEngineManager();
ScriptEngine se = sem.getEngineByName(scriptEngineName);
if (se == null)
{
throw new ScriptException ("cannot load script engine with name:
"+scriptEngineName);
}
Object result = null;
ScriptContext sc = se.getContext();
// add filename
sc.setAttribute(se.FILENAME, "via_runScriptFromString" ,
sc.ENGINE_SCOPE);
// script arguments to add?
if (scriptArgs != null)
{
sc.setAttribute(se.ARGV , scriptArgs, sc.ENGINE_SCOPE);
}
// create a FileReader from File
result=se.eval(scriptCode); // read and execute script
return result;
}
}
It defines two static Java methods with the following signatures:
public static Object runScriptFromFile (String fileName, Object []
scriptArgs)
public static Object runScriptFromString (String scriptEngineName, String
scriptCode, Object []
scriptArgs)
If no arguments are needed one can supply null instead or an empty Java Object
array.
The Java main method in the above program demonstrates calling both static
methods.
---
Would be very interested how a COBOL program looks like that invokes both static methods
runScriptFromFile() and runScriptFromString().
---rony
----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to [email protected] with the message: INFO IBM-MAIN