Tag Archives: COBOL - Page 2

Method Chaining

Creating objects with a complex constructor can be a bit of a pain in any language. One technique I have used is method chaining. It is not applicable to every type of class but it can be useful.

Method chain can help simply the use class and allows more complex object initialisation without having to worry about the order of the parameters and be done inline.

Consider the use of an “Account” class that takes Name, Address, Telephone and Country. All of which are strings, the constructor with four strings would not be a great constructor.

So you could have a simple constructor and four properties/methods.. however so set up the object would mean you have spread the setup over multiple lines.

Using method chain you can overcome this and even space in the “value” area of the object in your storage area.

set x to new type Account::Name("xx")::Address("yy") ::Telephone("yy")
     ::Country("zz")::World("Earth")

The trick of the pattern is to provide methods that always return this/self, so we can change the invokes together… For example:

This technique could even be used to build up a series of items required, for example, the preparation and execution of a sql statement comes to mind… in a similar fashion to Linq.

So… lets look at an example:

$set ilusing"System.Collections.Generic"
program-id. Program1 as "MethodChaining1.Program1".
data division.
working-storage section.
01 accounts type List[type Account] value new type List[type Account].      
01 jAccount type Account value
   new type Account::Name("Mr Johnson")::Address("Somewhere, some place")
    ::Telephone("+44 1234 4321").
01 sAccount type Account value
   new type Account::Name("Mr Smith")::Address("Nowhere place")
     ::Telephone("+44 1234 4321")::Country("Wales").                
01 lAccount type Account.
procedure division.
 invoke accounts::Add(jAccount)
 invoke accounts::Add(sAccount)
 
 perform varying lAccount through accounts
  display lAccount
 end-perform

 goback.
end program.

WIth the class being:

class-id Account.

working-storage section.
01 wName       string property as "Name".
01 wAddres     string property as "Address".
01 wCountry    string property as "Country".
01 wTelephone  string property as "Telephone".
01 wEmail      string property as "Email".

method-id New.
local-storage section.
procedure division.
  set wCountry to type System.Globalization.RegionInfo::CurrentRegion::DisplayName
end method.

method-id Name public.
procedure division using uName as string
 returning ret as type Account.
  set self::Name to uName
  set ret to self
end method.

method-id Address public.
procedure division using uAddress as string
 returning ret as type Account.
  set self::Address to uAddress
  set ret to self
end method.

method-id Telephone public.
procedure division using uTelephone as string
 returning ret as type Account.
  set self::Address to uTelephone
  set ret to self
end method.

method-id Email public.
procedure division using uEmail as string
 returning ret as type Account.
  set self::Address to uEmail
  set ret to self
end method.

method-id Country public.
procedure division using uCountry as string
 returning ret as type Account.
  set self::Country to uCountry
  set ret to self
end method.

method-id ToString public override.
procedure division returning ret as string.
set ret to String::Format("Name:{0}, Address:{1}, Telephone:{2}, Email:{3}, Country:{4}",
     self::Name, self::Address, self::Telephone,
     self::Email, self::Country)
end method.
end class.

Which when run with Visual COBOL gives:

Name:Mr Johnson, Address:+44 1234 4321, Telephone:, Email:, Country:United Kingdom
Name:Mr Smith, Address:+44 1234 4321, Telephone:, Email:, Country:Wales

Visual COBOL @ Microsoft Teched

The last couple of weeks have been very busy and it has unfortunately affected the amount of blog entries I have done but the good news I have plenty of new material..

So, what’s my excuse.. Well we have been counting down the internal builds of Visual COBOL and we are pretty much ready to ship which is a relief since we are going to launching it at the Microsoft’s Visual Studio launch parties in Las Vegas and TechEd in Bangalore April 12-14.

Personally for me I am quite excited because I will be going to Teched in Bangalore to help show off Visual COBOL.

If would like a look at some of the Visual Studio 2010 integration Micro Focus has is about to release, pop along to http://vs2010.microfocus.com/ and see for yourself. Better still, have a visit to teched :-)

I will finish the silly little blog with a link to a demo of Visual COBOL. Just because I’m proud of it…

ref: http://www.microsoftteched.in/
and http://www.microsoft.com/visualstudio/en-gb/products/2010/default.mspx

Reflection and COBOL

For the last couple of months I have working on Visual Studio 2010 and this include Microsoft CLR v4 and I was recently asked how to write a test that determines at runtime which CLR is being used and what assemblies it uses. I replies would use reflection. So I dropped my friend a mega simple demo… and here it is.

       $set ilusing"System.Reflection"

        01 myAssembly type "Assembly".
        01 usedAssemblyName type "AssemblyName".

        set myAssembly to type "Assembly"::"GetExecutingAssembly"

        display "My exe is " myAssembly::"FullName"
        display "and is using CLR " myAssembly::"ImageRuntimeVersion"
        display "and is loaded from " myAssembly::"Location"
        display "the initial method of this program was "
          myAssembly::"EntryPoint"::"Name"

        display "This assembly references -> "
        perform varying usedAssemblyName
             through myAssembly::"GetReferencedAssemblies"
              display "-> " usedAssemblyName
        end-perform

And the output of the program is:

My exe is clrver, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
and is using CLR v2.0.50727
and is loaded from d:\clrver.exe
the initial method of this program was _MF_ENTRYThis assembly references ->
-> mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-> MicroFocus.COBOL.Runtime, Version=3.6.0.0, Culture=neutral,
PublicKeyToken=0412c5e0b2aaa8f0

Scripting Languages and COBOL

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.

Interoperability between languages is very important to COBOL environments just as much as other languages. Some platforms such as Microsoft’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.

Environments such as Sun’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.

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.

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.

With Java 6.0 and JSR 223 support for Java based scripting languages were provided via the package javax.script.

Java has a wealth of scripting languages from awk to xlst. My favourites being jpython, jruby and javascript.

The java.net website has a comprehensive list of scripting languages -
https://scripting.dev.java.net/.

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.

For example:

  • Create a ScriptEngineManager object.
  • Retrieve a ScriptEngine object from the manager.
  • Evaluate a script using the ScriptEngine object.
  • In COBOL this is quite simply:

          *> ooctrl(+p) required for COM and Java classes
          *> ooctrl(-f) used to preserve case of method names for Java
          $set ooctrl(+p) ooctrl(-f)

           class-control.
               cls-Script-EngineManager is
                   class "$JAVA$javax.script.ScriptEngineManager"
               cls-Script-Engine is
                   class "$JAVA$javax.script.ScriptEngine"
               cls-object is
                   class "$JAVA$java.lang.Object"
               cls-System is
                   class "$JAVA$java.lang.System"    
               cls-PrintStream is
                   class "$JAVA$java.io.PrintStream"
              .

           working-storage section.
           01 ws-obj-sem     object reference cls-Script-EngineManager.
           01 ws-javascript  object reference cls-Script-Engine.
           01 ws-obj         object reference cls-object.

           01 ws-pout        object reference cls-PrintStream.
           procedure division.
             invoke cls-Script-EngineManager "new"
                 returning ws-obj-sem
             end-invoke

             invoke ws-obj-sem "getEngineByName" using
                 "JavaScript" returning ws-javascript
             end-invoke

             invoke ws-javascript "eval" using
                 z"print('Hello, world!')"
                 returning ws-obj
             end-invoke

             if ws-obj not equal null
              invoke cls-System "getout" returning ws-pout
              invoke ws-pout "println"   using ws-obj
              invoke ws-pout "finalize"  returning ws-pout
              invoke ws-obj "finalize"   returning ws-obj
             end-if

          $if NO-FINALIZE not defined
             invoke ws-obj-sem "finalize"    returning ws-obj-sem
             invoke ws-javascript "finalize" returning ws-javascript
          $end
            stop run.

    The actual Javascript being execute is contained in the invoke statement, which is simply:

    print('Hello, world!')

    To use the above example, we first need to compile the code and run it.. which is done as follows:

    C:\jscripting\HelloWorld>cobol cbljscript.cbl int();
    Micro Focus Net Express V5
    Version 6.0.00059  Copyright (C) 1984-2009 Micro Focus (IP) Limited.
    URN AXCGG/AA0/00000
    * Checking complete with no errors - starting code generation
    * Generating cbljscript
    * Data:         848     Code:        1992     Literals:         904

    C:\jscripting\HelloWorld>runm cbljscript
    Micro Focus Net Express V6.0.00059                          
    RUN TIME ENVIRONMENT Copyright (C) 1984-2009 Micro Focus (IP) Limited.        
    URN AXCGG/AA0/00000                                                            
    Hello, world!

    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 ‘put’ and ‘get’ methods that allows us to simply put a name parameter and get the resulting updated or new parameter.

    So consider the example, where we need to setup a parameter called ‘message’ for the script and then read a parameter called ‘replyMessage’ after the script has been executed. The javascript to do this is:

    /* Do some insanity checking! */
    if (typeof(message) == 'undefined')
    {
        message = "ERROR - 'message' has not been setup"
    }

    println(message)

    replyMessage = "Hello from javascript"

    To setup the message parameter, we just need todo.

           *> Put a variable in engine, so the javascript
           *> can use it.
              invoke ws-javascript "put" using
                 z"message"
                 z"Hello World from COBOL!"
              end-invoke

    The after the script has executed, we just need to use the ‘get’ method..

           *> get a variable in engine
              invoke ws-javascript "get" using
                 z"replyMessage"
                 returning ws-message
              end-invoke
     
           *> now display the replyMessage if it is available
              if ws-message not equal null
                invoke ws-pout "println"   using ws-message
              else
                display "Javascript did not set a replyMessage var"

    The completed COBOL example below, uses a side file for the javascript too, the code is as follows:

          *> ooctrl(+p) required for COM and Java classes
          *> ooctrl(-f) used to preserve case of method names for Java
          $set ooctrl(+p) ooctrl(-f)

           class-control.
               cls-Script-EngineManager is
                   class "$JAVA$javax.script.ScriptEngineManager"
               cls-Script-Engine is
                   class "$JAVA$javax.script.ScriptEngine"
               cls-object is
                   class "$JAVA$java.lang.Object"
               cls-System is
                   class "$JAVA$java.lang.System"    
               cls-PrintStream is
                   class "$JAVA$java.io.PrintStream"
               cls-FileReader is
                   class "$JAVA$java.io.FileReader"
              .

           working-storage section.
           01 ws-file        object reference cls-FileReader.
           01 ws-obj-sem     object reference cls-Script-EngineManager.
           01 ws-javascript  object reference cls-Script-Engine.
           01 ws-obj         object reference cls-object.
           01 ws-message     object reference cls-object.

           01 ws-pout        object reference cls-PrintStream.
           procedure division.
          *> setup ws-pout to be System.out object
             invoke cls-System "getout" returning ws-pout

          *> Setup a FileReader object for the external helloworld.js file
             invoke cls-FileReader "new" using
                  z"helloworld.js"
                  returning ws-file
             end-invoke

          *> Create a new script manager
             invoke cls-Script-EngineManager "new"
                 returning ws-obj-sem
             end-invoke

          *> Find the javascript engine
             invoke ws-obj-sem "getEngineByName" using
                 "JavaScript" returning ws-javascript
             end-invoke

          *> Put a variable in engine, so the javascript
          *> can use it.
             invoke ws-javascript "put" using
                z"message"
                z"Hello World from COBOL!"
             end-invoke

          *> do some javascript stuff!
             invoke ws-javascript "eval" using
                ws-file
                returning ws-obj-sem
             end-invoke

          *> get a variable in engine
             invoke ws-javascript "get" using
                z"replyMessage"
                returning ws-message
             end-invoke

          *> now display the replyMessage if it is available
             if ws-message not equal null
               invoke ws-pout "println"   using ws-message
             else
               display "Javascript did not set a replyMessage var"
             end-if
       
           
          *> cleanup code, not strickly needed for the example but
          *> its good practice, to do it.
          $if NO-FINALIZE not defined
             if ws-message not equal null
                invoke ws-message "finalize" returning ws-message
             end-if
             if ws-pout not equal null
                invoke ws-pout "finalize"    returning ws-pout
             end-if
             invoke ws-obj-sem "finalize"    returning ws-obj-sem
             invoke ws-javascript "finalize" returning ws-javascript
          $end

             stop run.
    C:\jscripting\HelloWorld3>cobol cbljscript.cbl int();
    Micro Focus Net Express V5
    Version 6.0.00059  Copyright (C) 1984-2009 Micro Focus (IP) Limited.
    URN AXCGG/AA0/00000
    * Checking complete with no errors - starting code generation
    * Generating cbljscript
    * Data:         888     Code:        2528     Literals:        1296

    C:\jscripting\HelloWorld3>runm cbljscript
    Micro Focus Net Express V6.0.00059                          
    RUN TIME ENVIRONMENT Copyright (C) 1984-2009 Micro Focus (IP) Limited.        
    URN AXCGG/AA0/00000                                                            
    Hello World from COBOL!
    Hello from javascript

    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:

    function testMessage(msg)
    {
        print("testMessage : " + msg);
    }

    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.

    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.

    Then from the COBOL side, we can just use the invokeFunction above.</p>

    <p>For example:</p>
    <code lang="cobol" width="800" lines="-1" nowrap="0">
           *> invoke a function with one parameter
              invoke cls-utils "invokeFunction" using
                 ws-javascript
                 z"testMessage"
                 z"Hello to function testMessage from COBOL"

    Which gives us the following output when executed.

    C:\jscripting\InvokeFunction>runm cbljscript
    Micro Focus Net Express V6.0.00059
    RUN TIME ENVIRONMENT Copyright (C) 1984-2009 Micro Focus (IP) Limited.
    URN AXCGG/AA0/00000

    testMessage : Hello to function testMessage from COBOL

    The completed example is as follows:

          *> ooctrl(+p) required for COM and Java classes
          *> ooctrl(-f) used to preserve case of method names for Java
          $set ooctrl(+p) ooctrl(-f)

           class-control.
               cls-Script-EngineManager is
                   class "$JAVA$javax.script.ScriptEngineManager"
               cls-Script-Engine is
                   class "$JAVA$javax.script.ScriptEngine"
               cls-object is
                   class "$JAVA$java.lang.Object"
               cls-System is
                   class "$JAVA$java.lang.System"    
               cls-PrintStream is
                   class "$JAVA$java.io.PrintStream"
               cls-FileReader is
                   class "$JAVA$java.io.FileReader"
               cls-Utils is
                   class "$JAVA$utils"
              .

           working-storage section.
           01 ws-file        object reference cls-FileReader.
           01 ws-obj-sem     object reference cls-Script-EngineManager.
           01 ws-javascript  object reference cls-Script-Engine.
           01 ws-message     object reference cls-object.

           01 ws-pout        object reference cls-PrintStream.
           procedure division.
          *> setup ws-pout to be System.out object
             invoke cls-System "getout" returning ws-pout

          *> Setup a FileReader object for the external helloworld.js file
             invoke cls-FileReader "new" using
                  z"helloworld.js"
                  returning ws-file
             end-invoke

          *> Create a new script manager
             invoke cls-Script-EngineManager "new"
                 returning ws-obj-sem
             end-invoke

          *> Find the javascript engine
             invoke ws-obj-sem "getEngineByName" using
                 "JavaScript" returning ws-javascript
             end-invoke

          *> do some javascript function
             invoke ws-javascript "eval" using
                ws-file
                returning ws-obj-sem
             end-invoke

          *> invoke a function with one parameter
             invoke cls-utils "invokeFunction" using
                ws-javascript
                z"testMessage"
                z"Hello to function testMessage from COBOL"
                returning ws-message
             end-invoke

          *> cleanup code, not strickly needed for the example but
          *> its good practice, to do it.
          $if NO-FINALIZE not defined
             if ws-file not equal null
                invoke ws-file "finalize" returning ws-file
             end-if
             if ws-message not equal null
                invoke ws-message "finalize" returning ws-message
              end-if
             if ws-pout not equal null
                invoke ws-pout "finalize"    returning ws-pout
             end-if
             if ws-obj-sem not equal null
                invoke ws-obj-sem "finalize"    returning ws-obj-sem
             end-if
             if ws-javascript not equal null
                invoke ws-javascript "finalize" returning ws-javascript
             end-if
          $end

             stop run.

    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…?

    12 Tips for using Micro Focus COBOL

    12 Tips for using Micro Focus COBOL

    As it is close to Christmas and I wanted to do something with 12 in the title, I’ve thrown together some useful if not un-ordered list of 12 things tips using Micro Focus COBOL.

    Remember I am just a developer and just want to help fellow developers out :-) so…

    Merry Christmas!

    and here is my list…

    1. Use DLLs/Shared objects rather than .int code
    2. DLLs/Shared objects can be preloaded using:
      01 my-ptr procedure-pointer.
      set my-ptr to entry "sodllname"

      Note; sodllname does not have the extension… let the runtime choose it for you!

    3. Use a good development environment such as Visual Studio or on Unix use Eclipse offering if you have a workstation, otherwise I personally use vim/gvim if terminal access is the only choce.
    4. Remember you have a great choice of platforms from Windows to Linux to a load Unix platforms, so choice is king. (did I say that…)
    5. Try using managed code (.Net) if you want to create WPF/WinForms or use WCF
    6. Interopability is great, so if you see a Java Class, .Net Class, COM object, ‘C’ function or a Web Service… use it! You can even mix unmanaged and managed applications..
    7. Avoid using the following if performance is key, as this really does help our code generator:
      alter
      perform thru
      next sentence
      segments
      go to section-name
      go to paragraph outside the current section
    8. Try to end your routine with a “stop run [returning..]” or “exit program [returning..]” or “goback [returning..]” as this gives our code generators a defined end to the routine, which really does help our code analysis/generator
    9. Use comp-5, integers for speed in calculations or native .Net types in managed
    10. Use comp-x for portability (file formats etc..)
    11. Make your application more robust, use tracing in production systems, either our own CTF tracing or your own or third party… it will save your life one day! Use runtime routines to catch error and log them (CBL_ERROR_PROC), ensure your programs shutdown cleanly always use CBL_EXIT_PROC.
    12. Use the generator directive nocheck if you are happy your code is solid and want to a little more performance. ie: it turns off runtime bounds checking

    Further reading:

  • Coding for speed, size and portability
  • Eclipse/COBOL on Unix
  • Newsletter about CTF
  • For CTF_ APIs see CBL_CTF_ see library routines
  • Yes.. its a bit of a mixed list.. but hey it may be of help!