{"id":462,"date":"2010-01-19T11:39:04","date_gmt":"2010-01-19T10:39:04","guid":{"rendered":"http:\/\/www.gennard.net\/blog\/?p=462"},"modified":"2010-01-19T11:39:04","modified_gmt":"2010-01-19T10:39:04","slug":"scripting-languages-and-cobol","status":"publish","type":"post","link":"http:\/\/www.gennard.net\/blog\/2010\/01\/scripting-languages-and-cobol\/","title":{"rendered":"Scripting Languages and COBOL"},"content":{"rendered":"<p>The use of scripting languages with other languages has increased over the last couple of years, from a simple case of interoperability, reuse of scripting code to allowing your code to customised via the user of external scripts.   All of which are real world examples I have seen customers use.<\/p>\n<p>Interoperability between languages is very important to COBOL environments just as much as other languages.   Some platforms such as Microsoft&#8217;s .Net with their CLR makes life much easier by allowing all languages to share a common infrastructure ie: the instruction set and the VM (MSIL and CLR) along with a base class library to get you started.<\/p>\n<p>Environments such as Sun&#8217;s VM (JVM) provide two different approaches to interoperability with Java, the first is via JNI\/JNA and the second is producing bytecode that runs as is on the VM.<\/p>\n<p>Although the Micro Focus COBOL compiler does not support JVM bytecode or Java source generation it does have support for invoking classes\/methods via the OO invoke verb.<\/p>\n<p>This mechanism is very simple to use, you just need to let our object COBOL runtime know the class is a Java class, which can be done by placing $JAVA$ before the name of the class and ensuring the class itself can be found by the JVM itself usually by adding an extra directories or .jar files to the CLASSPATH environment variable.<\/p>\n<p>With Java 6.0 and JSR 223 support for Java based scripting languages were provided via the package javax.script.<\/p>\n<p>Java has a wealth of scripting languages from awk to xlst.  My favourites being <a href=\"http:\/\/jython.sourceforge.net\/\">jpython<\/a>, <a href=\"http:\/\/jruby.sourceforge.net\/\">jruby<\/a> and <a href=\"http:\/\/www.mozilla.org\/rhino\">javascript<\/a>.<\/p>\n<p>The java.net website has a comprehensive list of scripting languages &#8211;<br \/>\n<a href=\"https:\/\/scripting.dev.java.net\/\">https:\/\/scripting.dev.java.net\/<\/a>.<\/p>\n<p>To use the scripting packages, you first need to create a ScriptEngineManager, then use this to create a specific ScriptEngine object for your chosen scripting language and use it.<\/p>\n<p>For example:<\/p>\n<li>Create a ScriptEngineManager object.<\/li>\n<li>Retrieve a ScriptEngine object from the manager.<\/li>\n<li>Evaluate a script using the ScriptEngine object.<\/li>\n<p>In COBOL this is quite simply: <\/p>\n<p><code lang=\"cobol\" width=\"800\" lines=\"-1\" nowrap=\"0\"><br \/>\n      *> ooctrl(+p) required for COM and Java classes<br \/>\n      *> ooctrl(-f) used to preserve case of method names for Java<br \/>\n      $set ooctrl(+p) ooctrl(-f)<\/p>\n<p>       class-control.<br \/>\n           cls-Script-EngineManager is<br \/>\n               class \"$JAVA$javax.script.ScriptEngineManager\"<br \/>\n           cls-Script-Engine is<br \/>\n               class \"$JAVA$javax.script.ScriptEngine\"<br \/>\n           cls-object is<br \/>\n               class \"$JAVA$java.lang.Object\"<br \/>\n           cls-System is<br \/>\n               class \"$JAVA$java.lang.System\"<br \/>\n           cls-PrintStream is<br \/>\n               class \"$JAVA$java.io.PrintStream\"<br \/>\n          .<\/p>\n<p>       working-storage section.<br \/>\n       01 ws-obj-sem     object reference cls-Script-EngineManager.<br \/>\n       01 ws-javascript  object reference cls-Script-Engine.<br \/>\n       01 ws-obj         object reference cls-object.<\/p>\n<p>       01 ws-pout        object reference cls-PrintStream.<br \/>\n       procedure division.<br \/>\n         invoke cls-Script-EngineManager \"new\"<br \/>\n             returning ws-obj-sem<br \/>\n         end-invoke<\/p>\n<p>         invoke ws-obj-sem \"getEngineByName\" using<br \/>\n             \"JavaScript\" returning ws-javascript<br \/>\n         end-invoke<\/p>\n<p>         invoke ws-javascript \"eval\" using<br \/>\n             z\"print('Hello, world!')\"<br \/>\n             returning ws-obj<br \/>\n         end-invoke<\/p>\n<p>         if ws-obj not equal null<br \/>\n          invoke cls-System \"getout\" returning ws-pout<br \/>\n          invoke ws-pout \"println\"   using ws-obj<br \/>\n          invoke ws-pout \"finalize\"  returning ws-pout<br \/>\n          invoke ws-obj \"finalize\"   returning ws-obj<br \/>\n         end-if<\/p>\n<p>      $if NO-FINALIZE not defined<br \/>\n         invoke ws-obj-sem \"finalize\"    returning ws-obj-sem<br \/>\n         invoke ws-javascript \"finalize\" returning ws-javascript<br \/>\n      $end<br \/>\n        stop run.<\/p>\n<p><\/code><\/p>\n<p>The actual Javascript being execute is contained in the invoke statement, which is simply:<\/p>\n<p><code lang=\"javascript\" width=\"800\" lines=\"-1\" nowrap=\"0\"><br \/>\nprint('Hello, world!')<br \/>\n<\/code><\/p>\n<p>To use the above example, we first need to compile the code and run it.. which is done as follows:<\/p>\n<p><code lang=\"text\"  width=\"800\" lines=\"-1\" nowrap=\"0\"><br \/>\nC:jscriptingHelloWorld>cobol cbljscript.cbl int();<br \/>\nMicro Focus Net Express V5<br \/>\nVersion 6.0.00059  Copyright (C) 1984-2009 Micro Focus (IP) Limited.<br \/>\nURN AXCGG\/AA0\/00000<br \/>\n* Checking complete with no errors - starting code generation<br \/>\n* Generating cbljscript<br \/>\n* Data:         848     Code:        1992     Literals:         904<\/p>\n<p>C:jscriptingHelloWorld>runm cbljscript<br \/>\nMicro Focus Net Express V6.0.00059<br \/>\nRUN TIME ENVIRONMENT Copyright (C) 1984-2009 Micro Focus (IP) Limited.<br \/>\nURN AXCGG\/AA0\/00000<br \/>\nHello, world!<br \/>\n<\/code><\/p>\n<p>This is just the start, the next thing piece that is required with interoperability to another language is the ability to pass parameters to in and out of the script.  Luckily for us the clever chaps on the jsr group have provided &#8216;put&#8217; and &#8216;get&#8217; methods that allows us to simply put a name parameter and get the resulting updated or new parameter.<\/p>\n<p>So consider the example, where we need to setup a parameter called &#8216;message&#8217; for the script and then read a parameter called &#8216;replyMessage&#8217; after the script has been executed.   The javascript to do this is: <\/p>\n<p><code lang=\"javascript\" width=\"800\" lines=\"-1\" nowrap=\"0\"><br \/>\n\/* Do some insanity checking! *\/<br \/>\nif (typeof(message) == 'undefined')<br \/>\n{<br \/>\n\tmessage = \"ERROR - 'message' has not been setup\"<br \/>\n}<\/p>\n<p>println(message)<\/p>\n<p>replyMessage = \"Hello from javascript\"<br \/>\n<\/code><\/p>\n<p>To setup the message parameter, we just need todo.<\/p>\n<p><code lang=\"cobol\" width=\"800\" lines=\"-1\" nowrap=\"0\"><br \/>\n       *> Put a variable in engine, so the javascript<br \/>\n       *> can use it.<br \/>\n          invoke ws-javascript \"put\" using<br \/>\n             z\"message\"<br \/>\n             z\"Hello World from COBOL!\"<br \/>\n          end-invoke<\/p>\n<p><\/code><\/p>\n<p>The after the script has executed, we just need to use the &#8216;get&#8217; method..<\/p>\n<p><code lang=\"cobol\" width=\"800\" lines=\"-1\" nowrap=\"0\"><br \/>\n       *> get a variable in engine<br \/>\n          invoke ws-javascript \"get\" using<br \/>\n             z\"replyMessage\"<br \/>\n             returning ws-message<br \/>\n          end-invoke<\/p>\n<p>       *> now display the replyMessage if it is available<br \/>\n          if ws-message not equal null<br \/>\n            invoke ws-pout \"println\"   using ws-message<br \/>\n          else<br \/>\n            display \"Javascript did not set a replyMessage var\"<br \/>\n<\/code><\/p>\n<p>The completed COBOL example below, uses a side file for the javascript too, the code is as follows:<\/p>\n<p><code lang=\"cobol\" width=\"800\" lines=\"-1\" nowrap=\"0\"><br \/>\n      *> ooctrl(+p) required for COM and Java classes<br \/>\n      *> ooctrl(-f) used to preserve case of method names for Java<br \/>\n      $set ooctrl(+p) ooctrl(-f)<\/p>\n<p>       class-control.<br \/>\n           cls-Script-EngineManager is<br \/>\n               class \"$JAVA$javax.script.ScriptEngineManager\"<br \/>\n           cls-Script-Engine is<br \/>\n               class \"$JAVA$javax.script.ScriptEngine\"<br \/>\n           cls-object is<br \/>\n               class \"$JAVA$java.lang.Object\"<br \/>\n           cls-System is<br \/>\n               class \"$JAVA$java.lang.System\"<br \/>\n           cls-PrintStream is<br \/>\n               class \"$JAVA$java.io.PrintStream\"<br \/>\n           cls-FileReader is<br \/>\n               class \"$JAVA$java.io.FileReader\"<br \/>\n          .<\/p>\n<p>       working-storage section.<br \/>\n       01 ws-file        object reference cls-FileReader.<br \/>\n       01 ws-obj-sem     object reference cls-Script-EngineManager.<br \/>\n       01 ws-javascript  object reference cls-Script-Engine.<br \/>\n       01 ws-obj         object reference cls-object.<br \/>\n       01 ws-message     object reference cls-object.<\/p>\n<p>       01 ws-pout        object reference cls-PrintStream.<br \/>\n       procedure division.<br \/>\n      *> setup ws-pout to be System.out object<br \/>\n         invoke cls-System \"getout\" returning ws-pout<\/p>\n<p>      *> Setup a FileReader object for the external helloworld.js file<br \/>\n         invoke cls-FileReader \"new\" using<br \/>\n              z\"helloworld.js\"<br \/>\n              returning ws-file<br \/>\n         end-invoke<\/p>\n<p>      *> Create a new script manager<br \/>\n         invoke cls-Script-EngineManager \"new\"<br \/>\n             returning ws-obj-sem<br \/>\n         end-invoke<\/p>\n<p>      *> Find the javascript engine<br \/>\n         invoke ws-obj-sem \"getEngineByName\" using<br \/>\n             \"JavaScript\" returning ws-javascript<br \/>\n         end-invoke<\/p>\n<p>      *> Put a variable in engine, so the javascript<br \/>\n      *> can use it.<br \/>\n         invoke ws-javascript \"put\" using<br \/>\n            z\"message\"<br \/>\n            z\"Hello World from COBOL!\"<br \/>\n         end-invoke<\/p>\n<p>      *> do some javascript stuff!<br \/>\n         invoke ws-javascript \"eval\" using<br \/>\n            ws-file<br \/>\n            returning ws-obj-sem<br \/>\n         end-invoke<\/p>\n<p>      *> get a variable in engine<br \/>\n         invoke ws-javascript \"get\" using<br \/>\n            z\"replyMessage\"<br \/>\n            returning ws-message<br \/>\n         end-invoke<\/p>\n<p>      *> now display the replyMessage if it is available<br \/>\n         if ws-message not equal null<br \/>\n           invoke ws-pout \"println\"   using ws-message<br \/>\n         else<br \/>\n           display \"Javascript did not set a replyMessage var\"<br \/>\n         end-if<\/p>\n<p>      *> cleanup code, not strickly needed for the example but<br \/>\n      *> its good practice, to do it.<br \/>\n      $if NO-FINALIZE not defined<br \/>\n         if ws-message not equal null<br \/>\n            invoke ws-message \"finalize\" returning ws-message<br \/>\n         end-if<br \/>\n         if ws-pout not equal null<br \/>\n            invoke ws-pout \"finalize\"    returning ws-pout<br \/>\n         end-if<br \/>\n         invoke ws-obj-sem \"finalize\"    returning ws-obj-sem<br \/>\n         invoke ws-javascript \"finalize\" returning ws-javascript<br \/>\n      $end<\/p>\n<p>         stop run.<br \/>\n<\/code><\/p>\n<p><code lang=\"text\" width=\"800\" lines=\"-1\" nowrap=\"0\"><br \/>\nC:jscriptingHelloWorld3>cobol cbljscript.cbl int();<br \/>\nMicro Focus Net Express V5<br \/>\nVersion 6.0.00059  Copyright (C) 1984-2009 Micro Focus (IP) Limited.<br \/>\nURN AXCGG\/AA0\/00000<br \/>\n* Checking complete with no errors - starting code generation<br \/>\n* Generating cbljscript<br \/>\n* Data:         888     Code:        2528     Literals:        1296<\/p>\n<p>C:jscriptingHelloWorld3>runm cbljscript<br \/>\nMicro Focus Net Express V6.0.00059<br \/>\nRUN TIME ENVIRONMENT Copyright (C) 1984-2009 Micro Focus (IP) Limited.<br \/>\nURN AXCGG\/AA0\/00000<br \/>\nHello World from COBOL!<br \/>\nHello from javascript<br \/>\n<\/code><\/p>\n<p>As you can see from the code above, setting up parameter is pretty easy todo but sometimes we just want to execute a function in the scripting language such as:<\/p>\n<p><code lang=\"javascript\" width=\"800\" lines=\"-1\" nowrap=\"0\"><br \/>\nfunction testMessage(msg)<br \/>\n{<br \/>\n\tprint(\"testMessage : \" + msg);<br \/>\n}<br \/>\n<\/code><\/p>\n<p>The ScriptEngine object that we have created to use the scripting engine may implement an optional interface called javax.script.Invocable, if the scripting engine we are using does provide this interface then a method called invokeFunction(..) can be used.<\/p>\n<p>In order to reduce the size of the COBOL code, I have coded a simple utils class in java as a simple proxy layer, the code is pretty simple but does make it easier for the COBOL to use the invokeFunction() method.<\/p>\n<p> <code lang=\"javascript\" width=\"800\" lines=\"-1\" nowrap=\"0\"<\nimport javax.script.*;\n\npublic class utils {\n\tpublic static Invocable getInvocable(ScriptEngine obj) {\n\t\treturn (Invocable)obj;\n\t}\n\n\tpublic static Object invokeFunction(ScriptEngine obj, String function, Object p1) throws ScriptException, NoSuchMethodException {\n\t\tInvocable iObj = getInvocable(obj);\n\t\treturn iObj.invokeFunction(function, p1);\n\t}\n}\n\n\n\n<p>Then from the COBOL side, we can just use the invokeFunction above.<\/p>\n<p>For example:<\/p>\n<p><code lang=\"cobol\" width=\"800\" lines=\"-1\" nowrap=\"0\"><br \/>\n       *> invoke a function with one parameter<br \/>\n          invoke cls-utils \"invokeFunction\" using<br \/>\n             ws-javascript<br \/>\n             z\"testMessage\"<br \/>\n             z\"Hello to function testMessage from COBOL\"<br \/>\n<\/code><\/p>\n<p>Which gives us the following output when executed.<\/p>\n<p><code lang=\"text\" width=\"800\" lines=\"-1\" nowrap=\"0\"><br \/>\nC:jscriptingInvokeFunction>runm cbljscript<br \/>\nMicro Focus Net Express V6.0.00059<br \/>\nRUN TIME ENVIRONMENT Copyright (C) 1984-2009 Micro Focus (IP) Limited.<br \/>\nURN AXCGG\/AA0\/00000<\/p>\n<p>testMessage : Hello to function testMessage from COBOL<br \/>\n<\/code><\/p>\n<p>The completed example is as follows:<\/p>\n<p><code lang=\"cobol\" width=\"800\" lines=\"-1\" nowrap=\"0\"><br \/>\n      *> ooctrl(+p) required for COM and Java classes<br \/>\n      *> ooctrl(-f) used to preserve case of method names for Java<br \/>\n      $set ooctrl(+p) ooctrl(-f)<\/p>\n<p>       class-control.<br \/>\n           cls-Script-EngineManager is<br \/>\n               class \"$JAVA$javax.script.ScriptEngineManager\"<br \/>\n           cls-Script-Engine is<br \/>\n               class \"$JAVA$javax.script.ScriptEngine\"<br \/>\n           cls-object is<br \/>\n               class \"$JAVA$java.lang.Object\"<br \/>\n           cls-System is<br \/>\n               class \"$JAVA$java.lang.System\"<br \/>\n           cls-PrintStream is<br \/>\n               class \"$JAVA$java.io.PrintStream\"<br \/>\n           cls-FileReader is<br \/>\n               class \"$JAVA$java.io.FileReader\"<br \/>\n           cls-Utils is<br \/>\n               class \"$JAVA$utils\"<br \/>\n          .<\/p>\n<p>       working-storage section.<br \/>\n       01 ws-file        object reference cls-FileReader.<br \/>\n       01 ws-obj-sem     object reference cls-Script-EngineManager.<br \/>\n       01 ws-javascript  object reference cls-Script-Engine.<br \/>\n       01 ws-message     object reference cls-object.<\/p>\n<p>       01 ws-pout        object reference cls-PrintStream.<br \/>\n       procedure division.<br \/>\n      *> setup ws-pout to be System.out object<br \/>\n         invoke cls-System \"getout\" returning ws-pout<\/p>\n<p>      *> Setup a FileReader object for the external helloworld.js file<br \/>\n         invoke cls-FileReader \"new\" using<br \/>\n              z\"helloworld.js\"<br \/>\n              returning ws-file<br \/>\n         end-invoke<\/p>\n<p>      *> Create a new script manager<br \/>\n         invoke cls-Script-EngineManager \"new\"<br \/>\n             returning ws-obj-sem<br \/>\n         end-invoke<\/p>\n<p>      *> Find the javascript engine<br \/>\n         invoke ws-obj-sem \"getEngineByName\" using<br \/>\n             \"JavaScript\" returning ws-javascript<br \/>\n         end-invoke<\/p>\n<p>      *> do some javascript function<br \/>\n         invoke ws-javascript \"eval\" using<br \/>\n            ws-file<br \/>\n            returning ws-obj-sem<br \/>\n         end-invoke<\/p>\n<p>      *> invoke a function with one parameter<br \/>\n         invoke cls-utils \"invokeFunction\" using<br \/>\n            ws-javascript<br \/>\n            z\"testMessage\"<br \/>\n            z\"Hello to function testMessage from COBOL\"<br \/>\n            returning ws-message<br \/>\n         end-invoke<\/p>\n<p>      *> cleanup code, not strickly needed for the example but<br \/>\n      *> its good practice, to do it.<br \/>\n      $if NO-FINALIZE not defined<br \/>\n         if ws-file not equal null<br \/>\n            invoke ws-file \"finalize\" returning ws-file<br \/>\n         end-if<br \/>\n         if ws-message not equal null<br \/>\n            invoke ws-message \"finalize\" returning ws-message<br \/>\n          end-if<br \/>\n         if ws-pout not equal null<br \/>\n            invoke ws-pout \"finalize\"    returning ws-pout<br \/>\n         end-if<br \/>\n         if ws-obj-sem not equal null<br \/>\n            invoke ws-obj-sem \"finalize\"    returning ws-obj-sem<br \/>\n         end-if<br \/>\n         if ws-javascript not equal null<br \/>\n            invoke ws-javascript \"finalize\" returning ws-javascript<br \/>\n         end-if<br \/>\n      $end<\/p>\n<p>         stop run.<br \/>\n<\/code><\/p>\n<p>Conclusions: Using a Java based scripting language from COBOL is quite easy, so feel free to use it.   Now which scripting language should I use...?<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The use of scripting languages with other languages has increased over the last couple of years, from a simple case of interoperability, reuse of scripting code to allowing your code to customised via the user of external scripts. All of &hellip; <a href=\"http:\/\/www.gennard.net\/blog\/2010\/01\/scripting-languages-and-cobol\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5,48,17,28,32],"tags":[209,118,119,120,131,144,164,165,225,166],"_links":{"self":[{"href":"http:\/\/www.gennard.net\/blog\/wp-json\/wp\/v2\/posts\/462"}],"collection":[{"href":"http:\/\/www.gennard.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.gennard.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.gennard.net\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/www.gennard.net\/blog\/wp-json\/wp\/v2\/comments?post=462"}],"version-history":[{"count":0,"href":"http:\/\/www.gennard.net\/blog\/wp-json\/wp\/v2\/posts\/462\/revisions"}],"wp:attachment":[{"href":"http:\/\/www.gennard.net\/blog\/wp-json\/wp\/v2\/media?parent=462"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.gennard.net\/blog\/wp-json\/wp\/v2\/categories?post=462"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.gennard.net\/blog\/wp-json\/wp\/v2\/tags?post=462"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}