While COBOL has its roots in mainframe computing, it has successfully transitioned to UNIX and Linux environments, offering organizations flexibility in deploying their COBOL applications. This evolution has allowed businesses to leverage the cost advantages and open ecosystems of these platforms while preserving their investment in COBOL business logic.
Several vendors provide COBOL compilers that generate native code for UNIX and Linux systems:
These compilers typically implement most of the ANSI/ISO COBOL standards (COBOL 85, COBOL 2002, COBOL 2014) with various extensions to facilitate migration from mainframe environments.
When moving COBOL applications from mainframes to UNIX/Linux, several differences become apparent:
COBOL programs for UNIX/Linux follow the same basic structure as mainframe COBOL, but typically include platform-specific adaptations for file handling and environment interaction:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374IDENTIFICATION DIVISION. PROGRAM-ID. UNIX-SAMPLE. AUTHOR. MAINFRAME-MASTER. * A simple COBOL program for UNIX/Linux environments ENVIRONMENT DIVISION. CONFIGURATION SECTION. SOURCE-COMPUTER. LINUX. OBJECT-COMPUTER. LINUX. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT CUSTOMER-FILE ASSIGN TO EXTERNAL CUSTOMER-PATH ORGANIZATION IS INDEXED ACCESS MODE IS DYNAMIC RECORD KEY IS CUST-ID FILE STATUS IS FILE-STATUS. DATA DIVISION. FILE SECTION. FD CUSTOMER-FILE. 01 CUSTOMER-RECORD. 05 CUST-ID PIC X(6). 05 CUST-NAME PIC X(30). 05 CUST-ADDRESS PIC X(50). 05 CUST-PHONE PIC X(15). WORKING-STORAGE SECTION. 01 FILE-STATUS PIC XX. 01 CUSTOMER-PATH PIC X(128). 01 ENV-VARS. 05 HOME-DIR PIC X(128). 01 UNIX-COMMAND PIC X(256). 01 CMD-RESULT PIC S9(9) COMP. PROCEDURE DIVISION. MAIN-LOGIC. DISPLAY "COBOL for UNIX/Linux Example". * Get environment variables using standard COBOL intrinsic ACCEPT HOME-DIR FROM ENVIRONMENT "HOME". DISPLAY "Home directory: " HOME-DIR. * Setting the file path using environment variables and concatenation STRING HOME-DIR DELIMITED BY SPACE "/data/customers.idx" DELIMITED BY SIZE INTO CUSTOMER-PATH END-STRING. DISPLAY "Customer file path: " CUSTOMER-PATH. * Using CALL to execute a UNIX command (implementation dependent) MOVE "ls -l $HOME/data" TO UNIX-COMMAND. CALL "SYSTEM" USING UNIX-COMMAND RETURNING CMD-RESULT. IF CMD-RESULT NOT = 0 DISPLAY "Error executing UNIX command. Status: " CMD-RESULT END-IF. OPEN I-O CUSTOMER-FILE. IF FILE-STATUS = "00" PERFORM PROCESS-CUSTOMERS CLOSE CUSTOMER-FILE ELSE DISPLAY "Error opening customer file. Status: " FILE-STATUS END-IF. STOP RUN. PROCESS-CUSTOMERS. DISPLAY "Processing customer records...". * Process customer records here DISPLAY "Processing complete.".
Note the UNIX-specific features: external file assignment that can be set at runtime, calls to system functions, and interaction with environment variables.
Modern COBOL development on UNIX/Linux can leverage:
COBOL on Windows represents a significant evolution of the language, bringing mainframe business logic to the most widely used desktop and server operating system in the world. This migration has transformed how organizations deploy and interact with their COBOL applications, often modernizing the user interface and integration capabilities while preserving critical business rules.
Windows-based COBOL development offers several advantages over traditional mainframe development:
Several commercial and open-source COBOL compilers are available for Windows:
One of the most significant advancements in Windows COBOL is the ability to create modern graphical user interfaces:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788IDENTIFICATION DIVISION. PROGRAM-ID. WINDOWS-GUI-EXAMPLE. CLASS-CONTROL. MyForm IS CLASS "MyForm" System.Windows.Forms.Form IS CLASS "System.Windows.Forms.Form" System.Windows.Forms.Button IS CLASS "System.Windows.Forms.Button" System.Windows.Forms.TextBox IS CLASS "System.Windows.Forms.TextBox" System.Windows.Forms.Label IS CLASS "System.Windows.Forms.Label". OBJECT SECTION. CLASS-OBJECT. CLASS MyForm INHERITS FROM System.Windows.Forms.Form. 01 myForm OBJECT REFERENCE. 01 calculateButton OBJECT REFERENCE. 01 amountTextBox OBJECT REFERENCE. 01 rateTextBox OBJECT REFERENCE. 01 resultLabel OBJECT REFERENCE. PROCEDURE DIVISION. MAIN-LOGIC. PERFORM INITIALIZE-FORM INVOKE System.Windows.Forms.Application::Run(myForm) STOP RUN. INITIALIZE-FORM. INVOKE MyForm NEW RETURNING myForm INVOKE myForm::set_Text("COBOL Interest Calculator") INVOKE myForm::set_Width(450) INVOKE myForm::set_Height(250) INVOKE System.Windows.Forms.Label NEW RETURNING resultLabel INVOKE resultLabel::set_Text("Result will appear here") INVOKE resultLabel::set_Width(300) INVOKE resultLabel::set_Location(NEW System.Drawing.Point(20, 150)) INVOKE myForm::Controls::Add(resultLabel) INVOKE System.Windows.Forms.TextBox NEW RETURNING amountTextBox INVOKE amountTextBox::set_Width(100) INVOKE amountTextBox::set_Location(NEW System.Drawing.Point(120, 20)) INVOKE myForm::Controls::Add(amountTextBox) INVOKE System.Windows.Forms.Label NEW RETURNING tempLabel INVOKE tempLabel::set_Text("Loan Amount:") INVOKE tempLabel::set_Width(100) INVOKE tempLabel::set_Location(NEW System.Drawing.Point(20, 23)) INVOKE myForm::Controls::Add(tempLabel) INVOKE System.Windows.Forms.TextBox NEW RETURNING rateTextBox INVOKE rateTextBox::set_Width(100) INVOKE rateTextBox::set_Location(NEW System.Drawing.Point(120, 50)) INVOKE myForm::Controls::Add(rateTextBox) INVOKE System.Windows.Forms.Label NEW RETURNING tempLabel INVOKE tempLabel::set_Text("Interest Rate:") INVOKE tempLabel::set_Width(100) INVOKE tempLabel::set_Location(NEW System.Drawing.Point(20, 53)) INVOKE myForm::Controls::Add(tempLabel) INVOKE System.Windows.Forms.Button NEW RETURNING calculateButton INVOKE calculateButton::set_Text("Calculate") INVOKE calculateButton::set_Location(NEW System.Drawing.Point(120, 90)) INVOKE myForm::Controls::Add(calculateButton) INVOKE calculateButton::add_Click(NEW System.EventHandler(CALCULATE-BUTTON-CLICK)) . CALCULATE-BUTTON-CLICK. LINKAGE SECTION. 01 sender OBJECT REFERENCE. 01 e OBJECT REFERENCE. PROCEDURE DIVISION USING BY VALUE sender e. DECLARE amount DECIMAL DECLARE rate DECIMAL DECLARE result DECIMAL INVOKE amountTextBox::get_Text RETURNING temp-string MOVE FUNCTION NUMVAL(temp-string) TO amount INVOKE rateTextBox::get_Text RETURNING temp-string MOVE FUNCTION NUMVAL(temp-string) TO rate COMPUTE result = amount * (1 + rate / 100) INVOKE resultLabel::set_Text("Future Value: $" & result) EXIT PROGRAM. END PROGRAM WINDOWS-GUI-EXAMPLE.
This example shows COBOL integration with .NET Windows Forms to create a simple interest calculator application. Note the object-oriented syntax and event handling, which are extensions to standard COBOL.
Windows COBOL applications can leverage various Windows-specific technologies:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758IDENTIFICATION DIVISION. PROGRAM-ID. REGISTRY-EXAMPLE. ENVIRONMENT DIVISION. DATA DIVISION. WORKING-STORAGE SECTION. * Variables for Windows Registry Access 01 REG-KEY-HANDLE PIC S9(9) COMP-5. 01 REG-VALUE-NAME PIC X(50). 01 REG-VALUE-TYPE PIC S9(9) COMP-5. 01 REG-DATA-BUFFER PIC X(1024). 01 REG-DATA-SIZE PIC S9(9) COMP-5. 01 REG-RESULT PIC S9(9) COMP-5. 01 HKEY-CONSTANTS. 05 HKEY-CURRENT-USER PIC S9(9) COMP-5 VALUE 2147483649. 05 REG-SZ PIC S9(9) COMP-5 VALUE 1. 05 KEY-READ PIC S9(9) COMP-5 VALUE 131097. PROCEDURE DIVISION. MAIN-LOGIC. DISPLAY "Windows Registry Access Example". * Read a value from the Windows Registry * (Note: specific registry API calls are implementation-dependent) MOVE "Software\MyCompany\MyCobolApp\Settings" TO REG-VALUE-NAME. MOVE 1024 TO REG-DATA-SIZE. CALL "RegOpenKeyEx" USING BY VALUE HKEY-CURRENT-USER BY REFERENCE REG-VALUE-NAME BY VALUE 0 BY VALUE KEY-READ BY REFERENCE REG-KEY-HANDLE RETURNING REG-RESULT. IF REG-RESULT = 0 MOVE "InstallPath" TO REG-VALUE-NAME CALL "RegQueryValueEx" USING BY VALUE REG-KEY-HANDLE BY REFERENCE REG-VALUE-NAME BY VALUE 0 BY REFERENCE REG-VALUE-TYPE BY REFERENCE REG-DATA-BUFFER BY REFERENCE REG-DATA-SIZE RETURNING REG-RESULT IF REG-RESULT = 0 DISPLAY "Install Path from Registry: " REG-DATA-BUFFER(1:REG-DATA-SIZE) ELSE DISPLAY "Error reading registry value. Error: " REG-RESULT END-IF CALL "RegCloseKey" USING BY VALUE REG-KEY-HANDLE ELSE DISPLAY "Error opening registry key. Error: " REG-RESULT END-IF. STOP RUN.
Migrating mainframe COBOL applications to Windows involves several considerations:
Web-enabling COBOL applications represents a significant modernization strategy that extends the reach of traditional COBOL programs to web browsers and mobile devices. This approach allows organizations to preserve their valuable business logic while providing modern user interfaces and integration points.
Several strategies exist for connecting COBOL applications to the web:
One of the most common approaches is exposing COBOL business logic as web services. This can be implemented in several ways:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384IDENTIFICATION DIVISION. PROGRAM-ID. CUSTOMER-SERVICE. AUTHOR. MAINFRAME-MASTER. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-CUSTOMER-RECORD. 05 WS-CUST-ID PIC X(6). 05 WS-CUST-NAME PIC X(30). 05 WS-CUST-EMAIL PIC X(50). 05 WS-CUST-PHONE PIC X(15). 05 WS-CUST-STATUS PIC X(1). 88 WS-CUST-ACTIVE VALUE "A". 88 WS-CUST-INACTIVE VALUE "I". 05 WS-CUST-BALANCE PIC S9(7)V99. 01 WS-RESPONSE. 05 WS-STATUS-CODE PIC 9(3). 05 WS-RESPONSE-MESSAGE PIC X(100). LINKAGE SECTION. 01 DFHCOMMAREA. 05 LS-REQUEST-TYPE PIC X(4). 88 LS-GET-CUSTOMER VALUE "GET ". 88 LS-ADD-CUSTOMER VALUE "ADD ". 88 LS-UPD-CUSTOMER VALUE "UPD ". 05 LS-CUSTOMER-ID PIC X(6). 05 LS-CUSTOMER-DATA PIC X(250). 05 LS-RESPONSE-DATA PIC X(500). PROCEDURE DIVISION. MAIN-LOGIC. EVALUATE TRUE WHEN LS-GET-CUSTOMER PERFORM GET-CUSTOMER-DETAILS WHEN LS-ADD-CUSTOMER PERFORM ADD-CUSTOMER WHEN LS-UPD-CUSTOMER PERFORM UPDATE-CUSTOMER WHEN OTHER MOVE 400 TO WS-STATUS-CODE MOVE "Invalid request type" TO WS-RESPONSE-MESSAGE END-EVALUATE MOVE WS-RESPONSE TO LS-RESPONSE-DATA EXEC CICS RETURN END-EXEC. GET-CUSTOMER-DETAILS. * Logic to retrieve customer from database EXEC CICS READ DATASET('CUSTFILE') INTO(WS-CUSTOMER-RECORD) RIDFLD(LS-CUSTOMER-ID) RESP(WS-RESPONSE-CODE) END-EXEC IF WS-RESPONSE-CODE = DFHRESP(NORMAL) MOVE 200 TO WS-STATUS-CODE STRING '{"customerId":"' DELIMITED BY SIZE WS-CUST-ID DELIMITED BY SIZE '","name":"' DELIMITED BY SIZE WS-CUST-NAME DELIMITED BY SIZE '","email":"' DELIMITED BY SIZE WS-CUST-EMAIL DELIMITED BY SIZE '","status":"' DELIMITED BY SIZE WS-CUST-STATUS DELIMITED BY SIZE '","balance":' DELIMITED BY SIZE WS-CUST-BALANCE DELIMITED BY SIZE '}' DELIMITED BY SIZE INTO WS-RESPONSE-MESSAGE ELSE MOVE 404 TO WS-STATUS-CODE MOVE "Customer not found" TO WS-RESPONSE-MESSAGE END-IF. ADD-CUSTOMER. * Logic to parse JSON from LS-CUSTOMER-DATA and add customer * ... UPDATE-CUSTOMER. * Logic to update existing customer * ...
This example demonstrates a CICS COBOL program structured to act as a web service. It processes requests based on a request type and returns JSON-formatted data. A web service framework (like CICS Web Services) would handle the HTTP protocol details and marshaling/unmarshaling of data.
Creating modern web interfaces for COBOL applications typically involves:
The architecture typically looks like this:
Web Browser -> Web Server -> API Gateway -> COBOL Application (HTML/JS) (Node.js/ (REST/SOAP) (Mainframe/ Java/.NET) Distributed)
Some modern COBOL environments support direct web enablement:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162IDENTIFICATION DIVISION. PROGRAM-ID. WEB-CUSTOMER-FORM. * Example using hypothetical COBOL web extensions ENVIRONMENT DIVISION. CONFIGURATION SECTION. SPECIAL-NAMES. WEB-CONTEXT IS CUSTOMER-WEB. DATA DIVISION. WORKING-STORAGE SECTION. 01 CUSTOMER-DATA. 05 CUST-ID PIC X(6). 05 CUST-NAME PIC X(30). 05 CUST-EMAIL PIC X(50). 05 CUST-PHONE PIC X(15). WEB SECTION. * This is a conceptual example of how a COBOL web * extension might define UI components 01 CUSTOMER-FORM. 05 FORM-TITLE VALUE "Customer Information". 05 ID-FIELD LABEL "Customer ID" SOURCE CUST-ID MAXLENGTH 6 READONLY. 05 NAME-FIELD LABEL "Customer Name" SOURCE CUST-NAME REQUIRED. 05 EMAIL-FIELD LABEL "Email" SOURCE CUST-EMAIL TYPE "email". 05 PHONE-FIELD LABEL "Phone Number" SOURCE CUST-PHONE. 05 SUBMIT-BUTTON LABEL "Save Customer" ACTION ON-SUBMIT. PROCEDURE DIVISION. MAIN-LOGIC. INITIALIZE CUSTOMER-DATA ACCEPT CUST-ID FROM HTTP-REQUEST-PARAM "id" IF CUST-ID NOT = SPACES PERFORM GET-CUSTOMER-DATA END-IF DISPLAY CUSTOMER-FORM STOP RUN. GET-CUSTOMER-DATA. * Logic to retrieve customer data from database * ... ON-SUBMIT. ACCEPT CUSTOMER-DATA FROM CUSTOMER-FORM * Logic to save customer data * ... RESPOND HTTP-STATUS 200 CONTENT-TYPE "application/json" BODY '{"status":"success","message":"Customer saved"}' STOP RUN.
This conceptual example demonstrates how a hypothetical web-enabled COBOL extension might define UI components directly in COBOL code. While not standard COBOL, some vendors provide similar capabilities through their own extensions.
Microservices architecture represents a modern approach to building distributed systems, where applications are composed of loosely coupled, independently deployable services. While microservices are often associated with newer languages and platforms, COBOL applications can successfully participate in and benefit from this architectural style.
Integrating COBOL into a microservices architecture typically involves:
Traditional COBOL applications often follow monolithic design patterns. Transforming them into microservices requires careful analysis and refactoring:
1IDENTIFICATION DIVISION.PROGRAM-ID. CUSTOMER-MICROSERVICE.AUTHOR. MAINFRAME-MASTER.DATA DIVISION.WORKING-STORAGE SECTION.01 WS-HTTP-STATUS PIC 9(3).01 WS-REQUEST-METHOD PIC X(10).01 WS-REQUEST-PATH PIC X(256).01 WS-REQUEST-BODY PIC X(4096).01 WS-RESPONSE-BODY PIC X(4096).01 WS-CUSTOMER-RECORD. 05 WS-CUST-ID PIC X(6). 05 WS-CUST-NAME PIC X(30). 05 WS-CUST-EMAIL PIC X(50). 05 WS-ACCOUNT-INFO. 10 WS-ACCOUNT-TYPE PIC X(1). 88 WS-ACCOUNT-STANDARD VALUE "S". 88 WS-ACCOUNT-PREMIUM VALUE "P". 10 WS-ACCOUNT-BALANCE PIC S9(7)V99. 10 WS-ACCOUNT-OPEN-DATE PIC X(10). 01 WS-DB-STATUS PIC X(2).01 WS-SERVICE-CONFIG. 05 WS-SERVICE-PORT PIC 9(5) VALUE 8080. 05 WS-DB-CONNECTION PIC X(100). 05 WS-LOG-LEVEL PIC X(10) VALUE "INFO".PROCEDURE DIVISION.MAIN-LOGIC. PERFORM INITIALIZE-SERVICE PERFORM UNTIL FOREVER PERFORM WAIT-FOR-REQUEST PERFORM PROCESS-REQUEST PERFORM SEND-RESPONSE END-PERFORM STOP RUN.INITIALIZE-SERVICE. DISPLAY "Starting Customer Microservice on port " WS-SERVICE-PORT PERFORM LOAD-CONFIGURATION PERFORM INITIALIZE-DB-CONNECTION PERFORM REGISTER-WITH-SERVICE-REGISTRY.PROCESS-REQUEST. EVALUATE WS-REQUEST-METHOD ALSO WS-REQUEST-PATH WHEN "GET" ALSO "/api/customers" PERFORM GET-ALL-CUSTOMERS WHEN "GET" ALSO MATCHING("/api/customers/*") PERFORM GET-CUSTOMER-BY-ID WHEN "POST" ALSO "/api/customers" PERFORM CREATE-CUSTOMER WHEN "PUT" ALSO MATCHING("/api/customers/*") PERFORM UPDATE-CUSTOMER WHEN "DELETE" ALSO MATCHING("/api/customers/*") PERFORM DELETE-CUSTOMER WHEN OTHER MOVE 404 TO WS-HTTP-STATUS MOVE '{"error":"Resource not found"}' TO WS-RESPONSE-BODY END-EVALUATE.GET-ALL-CUSTOMERS. * Retrieves all customers with pagination * Query implementation would go here * ... MOVE 200 TO WS-HTTP-STATUS.GET-CUSTOMER-BY-ID. * Extract ID from path * Lookup customer in database * Return JSON representation * ... MOVE 200 TO WS-HTTP-STATUS.CREATE-CUSTOMER. * Parse customer data from request body (JSON) * Validate fields * Insert into database * ... MOVE 201 TO WS-HTTP-STATUS.* Additional procedures for other endpoints* ...REGISTER-WITH-SERVICE-REGISTRY. * Logic to register this service with service discovery system * For example, connecting to Eureka, Consul, or etcd * ...
This simplified example shows how a COBOL program could be structured as a microservice with RESTful endpoints. In practice, this would be implemented using platform-specific extensions or frameworks to handle the HTTP communication and interact with the service mesh.
Several patterns are particularly relevant when integrating COBOL into a microservices architecture:
Applying the Strangler Pattern to COBOL applications:
Phase 1: Original Monolithic COBOL Application┌───────────────────────────────────────────────┐│ ││ COBOL Monolith ││ - Customer Management ││ - Account Processing ││ - Reporting ││ - Transaction Handling ││ │└───────────────────────────────────────────────┘Phase 2: API Gateway + First Microservice┌─────────────────┐ ┌───────────────────────┐│ │ │ ││ API Gateway │─────│ COBOL Monolith ││ │ │ (Legacy Components) │└─────┬───────────┘ │ │ │ └───────────────────────┘ │ │ ┌───────────────────────┐ │ │ │ └─────────────────│ Customer Service │ │ (New Microservice) │ │ │ └───────────────────────┘Phase 3: Multiple Microservices┌─────────────────┐ │ │ │ API Gateway │ │ │ └─────┬───────────┘ │ ├─────────────────┐ │ │ │ ▼ │ ┌───────────────────────┐ │ │ │ │ │ Customer Service │ │ │ (COBOL or New Lang) │ │ │ │ │ └───────────────────────┘ │ │ ┌───────────────────────┐ │ │ │ ├─────────────────│ Account Service │ │ │ (COBOL) │ │ │ │ │ └───────────────────────┘ │ │ ┌───────────────────────┐ │ │ │ └─────────────────│ Transaction Service │ │ (New Language) │ │ │ └───────────────────────┘
Containerizing COBOL services allows them to be deployed and managed using modern DevOps practices:
1# Example Dockerfile for a COBOL microserviceFROM microfocus/enterprise-developer:latest# Set environment variablesENV COBDIR=/opt/microfocus/EnterpriseDeveloperENV TERM=xtermENV PATH=$COBDIR/bin:$PATHENV COBPATH=/app/copybooks# Create application directoryWORKDIR /app# Copy source code, copybooks, and configurationCOPY src/ ./src/COPY copybooks/ ./copybooks/COPY config/ ./config/# Compile the COBOL programRUN cobol -x src/customer-service.cbl -o bin/customer-service# Expose the service portEXPOSE 8080# Run the service when container startsCMD ["bin/customer-service"]
This Dockerfile example shows how a COBOL microservice could be containerized using the Micro Focus Enterprise Developer product. The container includes the COBOL runtime, compiled application, and necessary configuration.
For orchestration, a Kubernetes manifest could be used to deploy and manage the service:
1apiVersion: apps/v1kind: Deploymentmetadata: name: customer-service labels: app: customer-service spec: replicas: 3 selector: matchLabels: app: customer-service template: metadata: labels: app: customer-service spec: containers: - name: customer-service image: mycompany/customer-service:1.0.0 ports: - containerPort: 8080 env: - name: DB_CONNECTION_STRING valueFrom: secretKeyRef: name: customer-service-secrets key: db-connection - name: LOG_LEVEL value: "INFO" resources: limits: memory: "512Mi" cpu: "500m" requests: memory: "256Mi" cpu: "250m" readinessProbe: httpGet: path: /health port: 8080 initialDelaySeconds: 5 periodSeconds: 10---apiVersion: v1kind: Servicemetadata: name: customer-servicespec: selector: app: customer-service ports: - port: 80 targetPort: 8080 type: ClusterIP
REST (Representational State Transfer) has become the predominant architectural style for modern APIs. Integrating COBOL applications with REST APIs enables them to participate in contemporary digital ecosystems, allowing for greater interoperability and extended functionality. This section explores how COBOL programs can both consume and provide REST services.
COBOL programs can call external REST APIs, though implementation details vary based on the environment:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899IDENTIFICATION DIVISION. PROGRAM-ID. REST-API-CLIENT. AUTHOR. MAINFRAME-MASTER. ENVIRONMENT DIVISION. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-HTTP-REQUEST. 05 WS-REQUEST-URL PIC X(255). 05 WS-REQUEST-METHOD PIC X(10). 05 WS-REQUEST-HEADERS. 10 WS-CONTENT-TYPE PIC X(50). 10 WS-AUTHORIZATION PIC X(100). 05 WS-REQUEST-BODY PIC X(1000). 01 WS-HTTP-RESPONSE. 05 WS-RESPONSE-CODE PIC 9(3). 05 WS-RESPONSE-BODY PIC X(10000). 05 WS-RESPONSE-LENGTH PIC 9(8) COMP. 05 WS-ERROR-MESSAGE PIC X(100). 01 WS-WEATHER-DATA. 05 WS-TEMPERATURE PIC S9(3)V9. 05 WS-CONDITION PIC X(30). 05 WS-HUMIDITY PIC 9(3). 05 WS-WIND-SPEED PIC 9(3)V9. 01 WS-JSON-PARSER USAGE IS POINTER. 01 WS-HTTP-CLIENT USAGE IS POINTER. 01 WS-RESULT PIC 9(9) COMP. PROCEDURE DIVISION. MAIN-LOGIC. DISPLAY "COBOL REST API Client Example" * Initialize HTTP client library CALL "HTTP_INITIALIZE" RETURNING WS-HTTP-CLIENT * Set up the request MOVE "https://api.weather.example.com/forecast?city=NewYork" TO WS-REQUEST-URL MOVE "GET" TO WS-REQUEST-METHOD MOVE "application/json" TO WS-CONTENT-TYPE MOVE "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." TO WS-AUTHORIZATION * Make the API call CALL "HTTP_SEND_REQUEST" USING BY VALUE WS-HTTP-CLIENT BY REFERENCE WS-HTTP-REQUEST BY REFERENCE WS-HTTP-RESPONSE RETURNING WS-RESULT * Check response IF WS-RESULT NOT = 0 DISPLAY "Error calling API: " WS-ERROR-MESSAGE STOP RUN END-IF DISPLAY "Response code: " WS-RESPONSE-CODE IF WS-RESPONSE-CODE = 200 * Parse JSON response CALL "JSON_PARSER_INIT" RETURNING WS-JSON-PARSER CALL "JSON_PARSE" USING BY VALUE WS-JSON-PARSER BY REFERENCE WS-RESPONSE-BODY RETURNING WS-RESULT IF WS-RESULT = 0 * Extract data from JSON CALL "JSON_GET_NUMBER" USING BY VALUE WS-JSON-PARSER BY CONTENT "temperature" BY REFERENCE WS-TEMPERATURE CALL "JSON_GET_STRING" USING BY VALUE WS-JSON-PARSER BY CONTENT "condition" BY REFERENCE WS-CONDITION * Display the weather information DISPLAY "Current weather in New York:" DISPLAY "Temperature: " WS-TEMPERATURE " °C" DISPLAY "Condition: " WS-CONDITION ELSE DISPLAY "Error parsing JSON response" END-IF * Clean up CALL "JSON_PARSER_FREE" USING BY VALUE WS-JSON-PARSER ELSE DISPLAY "API call failed with status: " WS-RESPONSE-CODE END-IF CALL "HTTP_CLEANUP" USING BY VALUE WS-HTTP-CLIENT STOP RUN.
This example demonstrates a COBOL program that calls a hypothetical weather API. It uses generic HTTP client and JSON parser functions that would be provided by environment-specific libraries. In reality, the exact implementation would vary based on the COBOL compiler and platform.
To expose COBOL functionality as REST APIs, several approaches can be used:
Architecture for exposing COBOL as REST:
┌───────────────┐ HTTP/REST ┌────────────────┐ Service Call ┌─────────────────┐ │ REST Clients │◄─────────────►│ API Gateway/ │◄──────────────►│ COBOL Program │ │ (Web/Mobile) │ │ Middleware │ │ (Business Logic)│ └───────────────┘ └────────────────┘ └─────────────────┘ │ │ │ │ ▼ ▼ ┌────────────────┐ ┌─────────────────┐ │ API Definition │ │ Database Access │ │ (OpenAPI/YAML) │ │ (DB2, VSAM, etc)│ └────────────────┘ └─────────────────┘
Example OpenAPI (Swagger) definition for a COBOL-backed API:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687openapi: 3.0.0 info: title: Customer Management API description: REST API for customer data backed by COBOL business logic version: 1.0.0 paths: /customers: get: summary: Get all customers parameters: - name: page in: query schema: type: integer - name: limit in: query schema: type: integer responses: '200': description: Successfully retrieved customers content: application/json: schema: type: array items: $ref: '#/components/schemas/Customer' post: summary: Create a customer requestBody: content: application/json: schema: $ref: '#/components/schemas/NewCustomer' responses: '201': description: Customer created successfully /customers/{id}: get: summary: Get customer by ID parameters: - name: id in: path required: true schema: type: string responses: '200': description: Customer found content: application/json: schema: $ref: '#/components/schemas/Customer' '404': description: Customer not found components: schemas: Customer: type: object properties: id: type: string name: type: string email: type: string status: type: string enum: [active, inactive] balance: type: number NewCustomer: type: object required: - name - email properties: name: type: string email: type: string status: type: string default: active
JSON has become the standard data format for REST APIs. Modern COBOL compilers offer various mechanisms for JSON processing:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465IDENTIFICATION DIVISION. PROGRAM-ID. JSON-HANDLING-SAMPLE. AUTHOR. MAINFRAME-MASTER. DATA DIVISION. WORKING-STORAGE SECTION. * Customer data structure 01 CUSTOMER-DATA. 05 CUSTOMER-ID PIC X(6). 05 CUSTOMER-NAME PIC X(30). 05 CUSTOMER-EMAIL PIC X(50). 05 CUSTOMER-STATUS PIC X(1). 88 CUSTOMER-ACTIVE VALUE "A". 88 CUSTOMER-INACTIVE VALUE "I". 05 CUSTOMER-BALANCE PIC S9(7)V99. * JSON document 01 JSON-DOC PIC X(1000). 01 JSON-LENGTH PIC 9(4) COMP. * Work fields 01 WS-RESULT PIC S9(9) COMP. PROCEDURE DIVISION. MAIN-LOGIC. * Example 1: Generate JSON from COBOL data structure MOVE "CUS123" TO CUSTOMER-ID MOVE "John Doe" TO CUSTOMER-NAME MOVE "john.doe@example.com" TO CUSTOMER-EMAIL MOVE "A" TO CUSTOMER-STATUS MOVE 1250.75 TO CUSTOMER-BALANCE * Using IBM Enterprise COBOL JSON GENERATE DISPLAY "Generating JSON from COBOL data..." JSON GENERATE JSON-DOC FROM CUSTOMER-DATA COUNT IN JSON-LENGTH DISPLAY JSON-DOC(1:JSON-LENGTH) * Example 2: Parse JSON into COBOL data structure DISPLAY "Parsing JSON to COBOL data..." MOVE '{ "customerId": "CUS456", "customerName": "Jane Smith", "customerEmail": "jane.smith@example.com", "customerStatus": "I", "customerBalance": -125.50 }' TO JSON-DOC INITIALIZE CUSTOMER-DATA * Using IBM Enterprise COBOL JSON PARSE JSON PARSE JSON-DOC INTO CUSTOMER-DATA DISPLAY "Parsed customer data:" DISPLAY "ID: " CUSTOMER-ID DISPLAY "Name: " CUSTOMER-NAME DISPLAY "Email: " CUSTOMER-EMAIL DISPLAY "Status: " CUSTOMER-STATUS DISPLAY "Balance: " CUSTOMER-BALANCE STOP RUN.
This example demonstrates the JSON PARSE and JSON GENERATE statements available in IBM Enterprise COBOL. These built-in features significantly simplify working with JSON in COBOL applications.
When integrating COBOL with REST APIs, several security considerations are essential:
1. Which COBOL compiler vendor is well-known for providing solutions for UNIX/Linux and Windows?
2. What technology commonly allowed COBOL programs to be exposed as web services in earlier web enablement efforts?
3. When integrating COBOL with REST APIs, what data format is most commonly used for message payloads?
4. Which of these is a key challenge when deploying COBOL applications in a microservices architecture?
5. What is a common approach to allow a COBOL program on a mainframe to call an external REST API?