Blog: Accelerating migration of COBOL applications to Java

According to Forbes contributing writer Tom Taulli’s article COBOL Language: Call It A Comeback?, the recent demands on government agencies with old COBOL applications to deal with COVID-19 coupled with the lack of developers has added additional stress to people who have lost their jobs and can’t get their unemployment benefits. Let’s face reality, today’s developers have zero training in COBOL. At DB Best, we’ve developed a COBOL to Java conversion tool along with a test automation framework and CI/CD pipeline we covered in a prior blog post to future-proof our client’s SaaS application.

In this blog post, we’ll go over the process we used to perform the COBOL to Java migration.

Factors to consider for selecting a target language

In this blog post, we cover COBOL to Java migration because our client already made the decision to standardize development using the Java platform. However, with other modern programming languages like C#, Python, Rust, Swift, Go, etc., development shops can choose the language that best matches their expertise and culture.

Java as the perfect environment for COBOL batch job apps

Our customer had over 50 complex batch job applications written in Oracle Pro*COBOL applications running against their original Oracle database. Previously, the DB Best team had migrated this Oracle database to Amazon Aurora PostgreSQL. Their development team already had experience writing Java applications but there was no one with the company any longer who could support innovation using COBOL.

So, the decision to migrate their Oracle Pro*COBOL applications to Java was obvious.

Let’s dive into the migration process we used.

Application conversion as part of the DB Best migration process

Over the last decade, DB Best has created and refined a multi-step program for helping our customers migrate their database assets. Our DB Best 12-step database migration plan allows us to easily develop a migration project plan. Take advantage of our unprecedented database conversion service expertise to understand the level of effort of each step, as shown below.
12 step Migration Methodology
The combination of application conversion and functional testing makes up 54% of the effort for modernizing database applications. So, anything we can do to reduce time makes it possible for our customers to innovate with reduced cycle times.

Accelerating the conversion with an automated application migration tool

Our in-house application migration tool uses ANTLR4 (ANother Tool for Language Recognition) to handle the first conversion phase. Using our modifications to the COBOL and JAVA grammar lexicon, we were able to automate approximately 85% of the conversion process. The translation included the structures, methods, and data types. As a result, after the first step of conversion, our team received an operable Java code that looked like COBOL. Although the code works properly, we don’t consider it production quality code.

The following diagram shows the processes uses by our application migration tool for the first conversion phase.

COBOL to Java conversion architecture diagram

The ANTLR parser uses a COBOL grammar file to create an Abstract Syntax Tree (AST) of the original code.

The ANTLR parser then traverses the AST to create an Abstract Semantic Graph (ASG) using the ASG tree mapper.

Our developers enhanced the translation of code using a language-specific printer manager module. In this case, the Java printer manager traverses the ASG elements tree using a Java grammar file represented in the diagram as Java code context to create the resulting Java source code.

Let’s look at a simple example of how our three-stage migration process works.

Stage 0 — Create a migration project from the existing COBOL codebase

We need to gather our COBOL code and organize it into a project structure for the migration effort. The structure aligns with how we ultimately want the source code control optimized for CI/CD pipelines.

Let’s take the following sample of COBOL to see how this works.

PERFORM PRAM01-FIND-PARM THRU PRAM01-FIND-PARM-EXIT
 UNTIL WS-FOUND-PARM-FLAG NOT = SPACES.
PRAM01-FIND-PARM.
 IF  DQY-DEBUG-FLAG > 0
  STRING 'Section: PRAM01-FIND-PARM ' DELIMITED BY SIZE,
   WS-PARM-VARIABLE          DELIMITED BY SPACE
  INTO WS-GENERIC-MESSAGE
   PERFORM PROC1 THRU PROC1-EXIT.
  IF PARAMETER-NAME(WS-RANGE-100) = SPACES
   MOVE WS-PARM-VARIABLE TO PARAMETER-NAME(WS-RANGE-100)
   PERFORM MSG01-PROMPT-USER-FOR-VALUE THRU MSG01-PROMPT-EXIT
   MOVE 'Y' TO WS-FOUND-PARM-FLAG
  ELSE
   IF PARAMETER-NAME(WS-RANGE-100) = WS-PARM-VARIABLE
    MOVE 'Y' TO WS-FOUND-PARM-FLAG
   ELSE
    ADD 1 TO WS-RANGE-100.
   IF WS-RANGE-100 > 100
    MOVE 'Y' TO WS-FOUND-PARM-FLAG.
PRAM01-FIND-PARM-EXIT.
EXIT.

Stage 1 — Initial conversion using our COBOL to JAVA application migration tool

Using our COBOL to Java migration tool, the code runs and produces the same results. The code has all the commands and structures, yet it looks like procedural COBOL versus object-oriented Java code. This makes the resulting Java code harder to use for test automation.

Here is what the generated “dirty” code looks like.

while(!(wsFoundParmFlag != null)) {
  param01FindParm();//THRU param01FindParmExit
}  
private void param01FindParm() {
 if (dqyDebugFlag > 0) {
  wsGenericMessage = "Section: PARAM01-FIND-PARM " + wsParmVariable.substring(0, wsParmVariable.indexOf(" ") == -1 ? wsParmVariable.length() : wsParmVariable.indexOf(" "));
  proc1();//THRU proc1Exit
 }
 if (parameterName[wsRange100 - 1] == null) {
  parameterName[wsRange100 - 1] = wsParmVariable;
  msg01PromptUserForValue();//THRU msg01PromptExit
  wsFoundParmFlag = "Y";
 } else {
  if (parameterName[wsRange100 - 1] != null && parameterName[wsRange100 - 1].equals(wsParmVariable)) {
   wsFoundParmFlag = "Y";
  } else {
   wsRange100 = wsRange100 + (1);
  }
 }
 if (wsRange100 > 100) {
  wsFoundParmFlag = "Y";
 }
  param01FindParmExit();
}

Stage 2 — Convert to robust Java code

In the second stage, we refactored our dirty Java code. At this point, our goal was to make it clear and easy to read for the Java developers. Here an example of the final Java code.

public FindParamResData findParam(String[] parameterName, String wsParmVariable, int wsParmLen, String parmIsDate) throws BatchProcessorException, IOException {
 WriterService writerService = WriterService.getInstance();
  int wsRange100;
  for (wsRange100 = 0; wsRange100 < parameterName.length; wsRange100++) {
   if (DebugConfig.getInstance().getDqyDebugFlag() > 0) {
    writerService.printLine(CommonConstants.SECTION_PARAM01 + wsParmVariable);
   }
   if (parameterName[wsRange100] == null) {
   //FROM COBOL. MSG01-PROMPT-USER-FOR-VALUE
   UserForValueModel userForValueModel = msg01PromptUserForValue(wsParmVariable, wsParmLen, parmIsDate,
    parameterName[wsRange100]);
   return new FindParamResData(userForValueModel, ++wsRange100);
   } else {
    if (parameterName[wsRange100].equals(wsParmVariable)) {
     return new FindParamResData(null, ++wsRange100);
    }
   }
  }
  return new FindParamResData(null, ++wsRange100);
}

Then our developers optimized the architecture and created the optimal Java solution. This required discovering and recreating the legacy business logic using documentation and the knowledge of our client.

Our client no existing test automation for the batch COBOL code. Therefore, our team delivered both unit tests and integration testing to future proof their product. Please check out our blog post to learn more about how we implemented testing for the new code.

Migrating from OCI to JDBC for PostgreSQL

The original Oracle Pro*COBOL code utilized the Oracle Call Interface (OCI) to interact with the Oracle database. Because we migrated their Oracle database to PostgreSQL, our team faced the challenge of connecting the application with a database. Usually, best practice is to use the ODBC interface instead of OCI in database migration projects. For example, we used this approach to modernize an advanced engineering application from Oracle to SQL Server.

For this Java solution, we had to change OCI to the PostgreSQL JDBC driver. This driver requires accurate regulation of all input and output parameters. Thus, our developers had to manage the requests for manually clarifying the parameters.

Once we had the pattern in place, it was easy to apply the changes across the solution. Adding this additional capability is on our product roadmap for the COBOL to Java Migration tool.

Take advantage of our established migration process

A successful migration is about a stated process. Our best practices allow for migrating any legacy system to any target you require. We have no need to assemble two teams proficient with source and target languages.  For instance, for this project, we invited one COBOL specialist to give us the benefit of an expert’s opinions. To accomplish this migration project, we engaged 8 of our Java developers.

As a result of this migration project, our team delivered a future proof solution based on the Java language. In addition to that, we created an ecosystem of tools for DevOps. Also, the new system is fully covered with automatic tests.

DB Best has the experience to fulfill any challenging migration project. This is because we rely on a trusted approach and knowledge of software architecture. No matter what the source and target environments are, our developers can automate your project. In other words, our team does not need expert knowledge in COBOL to write new applications on Java. Contact us to learn more and get an assessment of your unique project.

Share this...
Share on Facebook
Facebook
Tweet about this on Twitter
Twitter
Share on LinkedIn
Linkedin