This article is intended to demonstrate one way of refactoring a COBOL paragraph when it is in the middle of a program flow.
The examples presented here are intentionally simplified in order to show techniques rather than all the complexity that may be involved with different data types, additional dependencies, etc.
The goal of this article is to guide you on how to replace the 'GET-RECORD' paragraph with your own Java code that is called from the ACCTONE.cbl module, passing variables between the programs and modifying it.
This article assumes you have a working Eclipse and Heirloom environment, appropriate licenses, and have completed the Heirloom online training to ensure you are familiar with the Heirloom SDK.
It also assumes you have a working postgres database with the account demo records and an automatically generated view in it. If you do not, you can use our example read only database specified in the config files and sample code attached to this article.
Steps to create an example project
1. Right-click in the Project Explorer to create a new COBOL project in Eclipse:
2. Name the project 'ACCTONE':
3. The 'Default Project' project type is fine, so just click 'Finish':
4. Right click the project and choose 'Properties' from the context menu:
5. Select 'COBOL Compiler Settings' on the left and choose 'Parsing' in the Category drop-down on the right:
6. Change the 'Dead Code Analysis' option to 'Comment generated Code' and click 'Apply and Close' and then 'Yes' to allow a full build to happen:
7. Copy the COPYBOOKS (ACCTREC.cpy and R-ACCTREC.cpy) attached to this article into the copylib folder. You may either drag and drop the COPYBOOK files from your download folder into the copylib folder in Eclipse, or copy it from your download folder, right-click the copylib folder in Eclipse and paste it from the context menu:
8. Copy the resource (postgresql-9.4.1209.jar) attached to this article into the resources folder. Copy it from your download folder, right-click the resources folder in Eclipse and paste it from the context menu:
9. Right click the postgresql-9.4.1209.jar and choose 'Build Path->Add to build path' in the context menu:
10. Copy the resource (cblconfig) attached to this article into the resources folder. Copy it from your download folder, right-click the resources folder in Eclipse and paste it from the context menu. cblconfig is used to tell the Heirloom Framework it should expect to find the ACCTFIL file as a VDB table named 'acctfil'. if your table is a different name, edit the file and rename the table:
11. Copy the resource (deploy_settings) attached to this article into the resources folder. Copy it from your download folder, right-click the resources folder in Eclipse and paste it from the context menu:
12. Double click the deploy_settings file to open it in the editor, modify the URL,user, and password for the connection to your database, then save the file using the 'File->Save' menu option:
13. Copy the COBOL program (ACCTONE.cbl) attached to this article into the cobol_source folder. You may either drag and drop the COBOL file from your download folder into the cobol_source folder in Eclipse, or copy it from your download folder, right-click the cobol_source folder in Eclipse and paste it from the context menu.
Ensure you have 'Build Automatically' turned on for your project as this will create Java code in the intermediate_java_code folder. If it was not turned on, turn it on in the Project menu:
14. Double click the ACCTONE.cbl program to open it in the editor, then right click anywhere in the code and choose 'Run As->COBOL Application' from the context menu:
15. The application expects a record number as input so enter the record number 10023 in the console window and press enter:
16. The results from the program should look like this (your values may be different):
17. You will note by studying the code that the input value is used in GET-RECORD to read the record from the database. The Main paragraph calls GET-RECORD to retrieve the data and then displays it. Once the program executes successfully you are ready to replace the GET-RECORD paragraph with your own code.
Replacing the GET-RECORD paragraph with new code
18. Right click the java_source folder, and choose 'New->Class' from the context menu:
19. Enter the class name 'getRecord':
20. Click the 'Add..' button next to the Interfaces dialog and choose the ICallTarget interface:
21. Click Ok on the Interfaces selection:
22. Click Finish on the New Java Class dialog to create and open your new java class file:
23. The ICallTarget interface allows existing COBOL code to call this class using the CALL USING syntax. Replace this code with the code in orig_getRecord.java attached to this article:
24. Replace the SQL connection string on line 24 with the correct database information for your system, line 27 with the correct view name for your table, and then save the file using the 'File->Save' menu.
25. Click the ACCTONE program to edit the program. We will now remove the call to GET-RECORD and replace it with a call to this new program. Comment out the PERFORM GET-RECORD call:
26. Add the following line of code below it:
CALL "getRecord" using WS-PARM R-PAY1-BALANCE R-LIMITDO.
27. Save ACCTONE.cbl using the 'File->Save' menu and allow it to recompile automatically:
28. You'll notice the compiler automatically recognizes the GET-RECORD code is no longer used and flags it as such in the code editor window.
29. Right click anywhere in the code and choose 'Run As->COBOL Application' from the context menu:
30. The application expects a record number as input so enter the record number 10023 in the console window and press enter:
31. The results from the program should look like this (your values may be different):
Examination of new code
If you study ACCTONE.cbl you'll see we've made a simple change to remove the PERFORM GET-RECORD statement and instead CALL our new class, passing the input parameter and the two outputs we are interested in.
Open up getRecord.java - the rest of this article discusses the techniques used in there.
The call method is what will be invoked when this code is called using the COBOL expression "CALL 'getRecord' USING..." It receives two arguements, both arrays.
The first is a list of booleans indicating if the parameters are passed by reference or by value, the second array is the parameters themselves.
We can use the IDataType cast to extract them standard java objects as seen below where we get a string representing the account number (acctdo)
The bulk of the code is concerned with constructing and calling an SQL query against the view representing the data and should be recognizable to any Java developer, as such we will not discuss it here except to say that the views automatically created by the Heirloom data transformation provide a default, easy way to access previously locked up data via normal SQL methods. They can be adapted for your use and new ones created following the same patterns.
Finally this code copies the results of its search back to the parameters passed to it by the COBOL code.
The parameters need to be cast again so the underlying COBOL structures are formatted correctly (Strings being changed back into PIC 9(5)V99's for example).
More information on the IDataType and the ICallTarget interface can be found here:
This article demonstrates one way of rewriting an existing paragraph while ensuring calling code can still access it.
The code can be called by existing COBOL modules and as long as it follows the ICallTarget interface and can be written in whatever style a development team favors.
As such, it demonstrates the flexibility and agility of the Heirloom Framework in allowing targeted, progressive rewriting of existing application logic while maintaining compatibility with existing workflows.
Other methods include refactoring the original Java code produced by the compiler or rewriting the module to no longer use COBOL-like data types. Those examples are outside the scope of this article but provide their own advantages and disadvantages. The choice of them and this example will depend on the usage and requirements of each module being targeted for a rewrite.