Enterprise COBOL: Package Tutorial

Oleg Kunitsyn
6 min readJan 5, 2021

You will learn and create an application-level library in Enterprise COBOL dialect. You will structure the package, implement automatic tests on z/OS, deploy on GitHub and enable Continuous Integration workflow. Finally, you will publish the package in the COBOL package registry.

Photo by Carson Masterson on Unsplash

Preconditions

You have learned basic principles, methods and standards of COBOL. In this tutorial we’ll use IBM Enterprise COBOL for z/OS — a proprietary COBOL compiler which implements a substantial part of COBOL 85, COBOL 2002 and COBOL 2014. We’ll run COBOL code on z/OS — a proprietary 64-bit operating system for IBM mainframes, introduced in October 2000 and backward compatible with the older functionality originated since the 1960s .

  • You have NPM, a package manager for JavaScript programming language, installed.
  • You have Git, an open source distributed version control client, installed.
  • You have GitHub account for publishing of the package.
  • You may use any text editor you like, but I recommend Visual Studio Code with IBM Z Open Editor extension installed.

You need a mainframe account, since IBM does not provide redistributable execution environments like GnuCOBOL. Fortunately, you can obtain one for training purposes, free of charge. Register at IBM and follow the instructions. You will receive a registration email with USER ID, IP address and PORT. Then, login on Open Mainframe Project Slack workspace and add zih app via Apps menu. Post a message e.g. Hi and the app will ask your email address and USER ID that you have received. Post these details one by one and the bot will create your PASSWORD.

Perhaps the easiest way to interact with the mainframe is Zowe. Zowe is an open-source framework that allows teams to manage, control, script, and develop on the mainframe. Install Zowe command-line tool and create a profile by using your mainframe credentials:

$ npm i -g @zowe/cli --ignore-scripts
$ zowe profiles create zosmf ztrial --host <IP> --port <PORT> --user <USER ID> --pass <PASSWORD> --reject-unauthorized false
Profile created successfully!

Verify that your profile can communicate with z/OSMF:

$ zowe zosmf check status

If everything was made correct, you will see a list of z/OSMF components in ACTIVE state. Well done!

Package vs Library

Each programming language has standard set of functions provided by default. In COBOL we call them Intrinsic functions. Intrinsics cover basic programming needs, but we’ve used to extend this set by own functions every time writing something smarter than Hello, world!.

Gradually, custom functions form reusable COBOL libraries for inclusion into other COBOL programs and services on-demand. Thanks to Version Control Systems, contributors are able to effectively cooperate and deliver the libraries to the programmers. The only problem was an integration with external source-code that might be casually written in other COBOL dialect, coding standard or approach. And package management is a solution here.

Similar to other application-level package managers, such as Yarn for JavaScript, Maven for Java, Packagist for PHP, NuGet for C# etc., in 2020 COBOL obtained its own public package manager that standardizes the way the contributors should treat the libraries — COBOLget. This tutorial explains how to create and publish your first COBOL package the modern way.

Specifications

For financial applications we’ll implement demo-banking package which exposes single ibanok program — an IBAN validator. The program accepts an alphanumeric argument and returns an alphanumeric value 1 in case of success or 0 otherwise. The algorithm is as follows:

  1. Calculate actual IBAN length in the argument.
  2. Check IBAN structure.
  3. Move the first 4 characters to the end.
  4. Replace each character with two digits, where A = 10, B = 11, …, Z = 35.
  5. Compute the remainder by MOD97. If the remainder is 1, the checksum is valid.

Structuring

Please create new GitHub repository demo-banking and copy template of the package to your local copy of the repository. Here’s the structure:

├── .github
│ └── workflows
│ └── nodejs.yml
├── .gitignore
├── modules.json
├── modules-lock.json
├── README.md
├── src
│ └── banking.cbl
└── tests
├── tests.cbl
└── tests.jcl

The file banking.cbl is a library which contains the program. The file tests.cbl is a test program. The file tests.jcl is a JCL script which executes the tests on the mainframe. The file modules.json is a Manifest of the package which describes the library and its dependencies:

{
"name": "demo-banking-FIXME",
"description": "Demo banking package",
"modules": [
"src/banking.cbl"
],
"dialect": "entcobol",
"licenses": [
"MIT"
],
"authors": [
"FIXME"
],
"dependencies": {},
"dependencies-debug": {
"ecblunit": "*"
}
}

The properties are speaking enough and similar to other package managers. Our package does not use any dependencies, but requires ECBLUnit package at any version (by default, the latest available) for testing purposes. Property modules must list COBOL files for compiling, our library. Full schema of the Manifest you can find on https://cobolget.com/schema.json. Let’s install COBOLget command-line tool and validate the package:

$ npm install -g cobolget
$ cobolget validate
An error occurred: Error: "demo-banking-FIXME" does not match to ^[a-z0-9\-]+$

Oops! Please replace FIXME keyword with your GitHub username in README.md and in modules.json, in lower-case, making the package valid and unique. Don’t forget to replace FIXME in the command below:

$ cobolget validate
Manifest modules.json is valid.
$ cobolget list demo-banking-FIXME
No matching results.

The structure of the package is finished. We’ll test our library in the next step.

Testing

ECBLUnit tests are simple COBOL programs that allow further execution (without STOP RUN statement). The file tests.cbl has 8 ECBLUeq (equality assertions) calls that expect 1 returned by ibanok program. This assertion is a COBOL program which awaits two values for comparison — expected and actual. More details you can find on the homepage of the tool. Let’s run the test locally replacing <USER ID>by your own:

$ cobolget run build
...
Modules modules.cpy and modules.cbl updated.
$ zowe zos-files upload file-to-data-set modules/modules.cbl <USER ID>.CBL
...
Data set uploaded successfully.
$ zowe zos-files upload file-to-data-set tests/tests.cbl <USER ID>.CBL
...
Data set uploaded successfully.
$ zowe jobs submit local-file tests/tests.jcl --view-all-spool-content
...
Time: 00:00:00
There was 004 failure(s):
#005 EQ F140404040404040 1
F040404040404040 0
^^
#006 EQ F140404040404040 1
F040404040404040 0
^^
#007 EQ F140404040404040 1
F040404040404040 0
^^
#008 EQ F140404040404040 1
F040404040404040 0
^^
FAILURES!
Tests: 001, Skipped: 000
Assertions: 008, Failures: 004, Exceptions: 000

Yes, the test failed — assertions #5..#8 return 0 instead of 1. Definitely, it’s a false negative result because those IBANs have been carefully copied from Wikipedia. :) You may open tests.cbl, remove all inner spaces in the IBANs, upload and re-run the test again, but I suggest to improve ibanok instead. Spaces are generally acceptable in IBAN and must pass the validation. The best implementation will be included into main COBOLget package under your name. Nevertheless, you may commit and push the package to GitHub and proceed to the next step.

Publishing

Our package will follow Continuous Integration practices, where each modification of the source-code is getting tested on the repository. Each push or pull request to GitHub will trigger nodejs.yml workflow which automates the steps above:

  1. Install Zowe.
  2. Create Zowe profile.
  3. Install COBOLget.
  4. Build the COBOLget package by installing the dependencies.
  5. Upload the COBOLget module to the mainframe.
  6. Upload the ECBLUnit test to the mainframe.
  7. Execute the test and return an exit code back.

Please commit and push your package to GitHub and “release” it by attaching a version tag e.g. 1.2.3 to the commit. On GitHub in the Actions tab you’ll see an overall progress of the workflow. Any non-zero exit code will mark a step, as well as entire workflow, as failed.

Now you can import your package into COBOLget Registry by using index command in the console:

$ cobolget index -h
Usage: index [options] <name|url>
Import or update the package in the registryOptions:
-t, --token <token> Repository token for private package
-o, --organization <organization> Organization name for private package
-h, --help output usage information

Newborn packages we’ll index by URL of the repository. Don’t forget to replace FIXME.

$ cobolget index https://github.com/FIXME/demo-banking
Package 'demo-banking-FIXME' has been indexed in the registry.

Well done! Your first COBOL package is published on cobolget.com and ready for integration into applications and services.

Conclusion

You have created and successfully published an application-level COBOL library in COBOLget format by using z/OS, Git, Zowe, Unit-Testing and Continuous Integration practices. 60-years old COBOL fits modern software engineering.

Are you GnuCOBOL enthusiast? Read Modern COBOL: Package Tutorial and Modern COBOL: Microservice Tutorial articles.

--

--