MainframeMaster

COBOL Tutorial

COBOL and XML/JSON

Progress0 of 0 lessons

Modern COBOL applications need to integrate with web services, APIs, and modern data formats. XML and JSON processing capabilities in COBOL enable seamless data exchange between legacy COBOL systems and contemporary applications, making modernization and integration projects more feasible.

XML PARSE Statement

The XML PARSE statement, introduced in COBOL 2002, provides a powerful way to process XML documents. It uses an event-driven parsing model that allows COBOL programs to handle XML data efficiently and systematically.

Basic XML PARSE Syntax

cobol
1
2
3
4
XML PARSE xml-document PROCESSING PROCEDURE processing-procedure [ON EXCEPTION imperative-statement] [END-XML]

Complete XML Parsing Example

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
IDENTIFICATION DIVISION. PROGRAM-ID. XML-PARSER. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-XML-DOCUMENT PIC X(4096). 01 WS-XML-EVENT PIC X(20). 01 WS-XML-TEXT PIC X(256). 01 WS-XML-NAMESPACE PIC X(100). 01 WS-XML-NAME PIC X(100). 01 WS-XML-ATTRIBUTE PIC X(100). 01 WS-XML-VALUE PIC X(256). 01 WS-CUSTOMER-DATA. 05 CUST-ID PIC 9(10). 05 CUST-NAME PIC X(50). 05 CUST-EMAIL PIC X(100). 05 CUST-PHONE PIC X(15). 05 CUST-ADDRESS. 10 ADDR-STREET PIC X(50). 10 ADDR-CITY PIC X(30). 10 ADDR-STATE PIC X(2). 10 ADDR-ZIP PIC X(10). 01 WS-CURRENT-ELEMENT PIC X(20). 01 WS-PARSING-STATE PIC X(20). PROCEDURE DIVISION. MAIN-PROCESS. * Sample XML document STRING "" "" "John Smith" "john.smith@example.com" "555-123-4567" "
" "123 Main St" "Anytown" "NY" "12345" "
" "
" DELIMITED BY SIZE INTO WS-XML-DOCUMENT. * Parse the XML document XML PARSE WS-XML-DOCUMENT PROCESSING PROCEDURE XML-HANDLER ON EXCEPTION DISPLAY "XML Parsing Error" END-XML. * Display parsed data DISPLAY "Customer ID: " CUST-ID. DISPLAY "Name: " CUST-NAME. DISPLAY "Email: " CUST-EMAIL. DISPLAY "Phone: " CUST-PHONE. DISPLAY "Address: " ADDR-STREET ", " ADDR-CITY ", " ADDR-STATE " " ADDR-ZIP. STOP RUN. XML-HANDLER. * Get XML event type EVALUATE XML-EVENT WHEN "START-OF-DOCUMENT" DISPLAY "Starting XML parsing..." WHEN "START-OF-ELEMENT" MOVE XML-NAME TO WS-CURRENT-ELEMENT EVALUATE WS-CURRENT-ELEMENT WHEN "customer" PERFORM PROCESS-CUSTOMER-ATTRIBUTES WHEN "name" MOVE "PARSING-NAME" TO WS-PARSING-STATE WHEN "email" MOVE "PARSING-EMAIL" TO WS-PARSING-STATE WHEN "phone" MOVE "PARSING-PHONE" TO WS-PARSING-STATE WHEN "street" MOVE "PARSING-STREET" TO WS-PARSING-STATE WHEN "city" MOVE "PARSING-CITY" TO WS-PARSING-STATE WHEN "state" MOVE "PARSING-STATE" TO WS-PARSING-STATE WHEN "zip" MOVE "PARSING-ZIP" TO WS-PARSING-STATE END-EVALUATE WHEN "CONTENT-CHARACTERS" EVALUATE WS-PARSING-STATE WHEN "PARSING-NAME" MOVE XML-TEXT TO CUST-NAME WHEN "PARSING-EMAIL" MOVE XML-TEXT TO CUST-EMAIL WHEN "PARSING-PHONE" MOVE XML-TEXT TO CUST-PHONE WHEN "PARSING-STREET" MOVE XML-TEXT TO ADDR-STREET WHEN "PARSING-CITY" MOVE XML-TEXT TO ADDR-CITY WHEN "PARSING-STATE" MOVE XML-TEXT TO ADDR-STATE WHEN "PARSING-ZIP" MOVE XML-TEXT TO ADDR-ZIP END-EVALUATE WHEN "END-OF-ELEMENT" MOVE SPACES TO WS-PARSING-STATE WHEN "END-OF-DOCUMENT" DISPLAY "XML parsing completed" WHEN "ATTRIBUTE-NAME" MOVE XML-NAME TO WS-XML-ATTRIBUTE WHEN "ATTRIBUTE-CHARACTERS" IF WS-XML-ATTRIBUTE = "id" MOVE XML-TEXT TO CUST-ID END-IF END-EVALUATE. PROCESS-CUSTOMER-ATTRIBUTES. * Handle customer element attributes CONTINUE.

Advanced XML Parsing Techniques

Namespace Handling

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
IDENTIFICATION DIVISION. PROGRAM-ID. XML-NAMESPACE-PARSER. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-XML-DOCUMENT PIC X(4096). 01 WS-NAMESPACE-PREFIX PIC X(20). 01 WS-NAMESPACE-URI PIC X(256). PROCEDURE DIVISION. MAIN-PROCESS. * XML with namespaces STRING "" "" "" "" "12345" "John Smith" "" "" "" DELIMITED BY SIZE INTO WS-XML-DOCUMENT. XML PARSE WS-XML-DOCUMENT PROCESSING PROCEDURE XML-NAMESPACE-HANDLER END-XML. STOP RUN. XML-NAMESPACE-HANDLER. EVALUATE XML-EVENT WHEN "NAMESPACE-DECLARATION" MOVE XML-NAME TO WS-NAMESPACE-PREFIX MOVE XML-TEXT TO WS-NAMESPACE-URI DISPLAY "Namespace: " WS-NAMESPACE-PREFIX " = " WS-NAMESPACE-URI WHEN "START-OF-ELEMENT" IF XML-NAMESPACE NOT = SPACES DISPLAY "Element: " XML-NAMESPACE ":" XML-NAME ELSE DISPLAY "Element: " XML-NAME END-IF WHEN "CONTENT-CHARACTERS" DISPLAY "Content: " XML-TEXT END-EVALUATE.

Error Handling in XML Parsing

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
IDENTIFICATION DIVISION. PROGRAM-ID. XML-ERROR-HANDLER. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-XML-DOCUMENT PIC X(4096). 01 WS-XML-ERROR-CODE PIC 9(4). 01 WS-XML-ERROR-MSG PIC X(256). 01 WS-PARSING-ERRORS PIC 9(3) VALUE 0. PROCEDURE DIVISION. MAIN-PROCESS. * Malformed XML for testing STRING "" "" "John Smith" "john@example.com" *> Missing closing tag "555-1234" "" DELIMITED BY SIZE INTO WS-XML-DOCUMENT. XML PARSE WS-XML-DOCUMENT PROCESSING PROCEDURE XML-ERROR-HANDLER ON EXCEPTION DISPLAY "Critical XML parsing error occurred" DISPLAY "Error count: " WS-PARSING-ERRORS END-XML. STOP RUN. XML-ERROR-HANDLER. EVALUATE XML-EVENT WHEN "EXCEPTION" ADD 1 TO WS-PARSING-ERRORS DISPLAY "XML Error #" WS-PARSING-ERRORS DISPLAY "XML Error Code: " XML-CODE DISPLAY "XML Error Text: " XML-TEXT WHEN "START-OF-DOCUMENT" MOVE 0 TO WS-PARSING-ERRORS DISPLAY "Beginning XML validation..." WHEN "END-OF-DOCUMENT" IF WS-PARSING-ERRORS = 0 DISPLAY "XML document is valid" ELSE DISPLAY "XML document has " WS-PARSING-ERRORS " errors" END-IF WHEN OTHER * Normal processing continues CONTINUE END-EVALUATE.

XML Schema Validation

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
IDENTIFICATION DIVISION. PROGRAM-ID. XML-SCHEMA-VALIDATOR. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-XML-DOCUMENT PIC X(4096). 01 WS-SCHEMA-LOCATION PIC X(256). 01 WS-VALIDATION-ERRORS PIC 9(3) VALUE 0. PROCEDURE DIVISION. MAIN-PROCESS. MOVE "customer.xsd" TO WS-SCHEMA-LOCATION. * XML document with schema reference STRING "" "" "12345" "John Smith" "john@example.com" "" DELIMITED BY SIZE INTO WS-XML-DOCUMENT. * Parse with schema validation XML PARSE WS-XML-DOCUMENT VALIDATING AGAINST SCHEMA WS-SCHEMA-LOCATION PROCESSING PROCEDURE XML-VALIDATION-HANDLER ON EXCEPTION DISPLAY "Schema validation failed" END-XML. IF WS-VALIDATION-ERRORS = 0 DISPLAY "Document is schema-valid" ELSE DISPLAY "Document has " WS-VALIDATION-ERRORS " validation errors" END-IF. STOP RUN. XML-VALIDATION-HANDLER. EVALUATE XML-EVENT WHEN "VALIDATION-ERROR" ADD 1 TO WS-VALIDATION-ERRORS DISPLAY "Validation Error: " XML-TEXT WHEN "START-OF-ELEMENT" DISPLAY "Processing element: " XML-NAME END-EVALUATE.

XML GENERATE Statement

The XML GENERATE statement allows COBOL programs to create well-formed XML documents from COBOL data structures. This is essential for outputting data to web services, APIs, and modern integration scenarios.

Basic XML Generation

Simple XML Generation

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
IDENTIFICATION DIVISION. PROGRAM-ID. XML-GENERATOR. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-CUSTOMER-DATA. 05 CUST-ID PIC 9(10) VALUE 12345. 05 CUST-NAME PIC X(30) VALUE "John Smith". 05 CUST-EMAIL PIC X(50) VALUE "john.smith@example.com". 05 CUST-PHONE PIC X(15) VALUE "555-123-4567". 05 CUST-STATUS PIC X(10) VALUE "ACTIVE". 01 WS-XML-OUTPUT PIC X(4096). PROCEDURE DIVISION. MAIN-PROCESS. * Generate XML from COBOL data structure XML GENERATE WS-XML-OUTPUT FROM WS-CUSTOMER-DATA WITH ENCODING "UTF-8" WITH XML-DECLARATION END-XML. DISPLAY "Generated XML:". DISPLAY WS-XML-OUTPUT. STOP RUN.

Advanced XML Generation with Attributes

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
IDENTIFICATION DIVISION. PROGRAM-ID. XML-GENERATOR-ADVANCED. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-CUSTOMER-RECORD. 05 CUST-ID PIC 9(10) VALUE 12345. 05 CUST-INFO. 10 CUST-NAME PIC X(30) VALUE "John Smith". 10 CUST-EMAIL PIC X(50) VALUE "john@example.com". 10 CUST-TYPE PIC X(10) VALUE "PREMIUM". 05 CUST-ADDRESS. 10 ADDR-STREET PIC X(40) VALUE "123 Main Street". 10 ADDR-CITY PIC X(25) VALUE "Anytown". 10 ADDR-STATE PIC X(2) VALUE "NY". 10 ADDR-ZIP PIC X(10) VALUE "12345-6789". 05 CUST-ORDERS OCCURS 3 TIMES. 10 ORDER-ID PIC 9(8). 10 ORDER-DATE PIC X(10). 10 ORDER-AMOUNT PIC 9(7)V99. 01 WS-XML-OUTPUT PIC X(8192). 01 WS-XML-DOCUMENT PIC X(8192). PROCEDURE DIVISION. MAIN-PROCESS. * Initialize sample order data MOVE 1001 TO ORDER-ID(1). MOVE "2024-01-15" TO ORDER-DATE(1). MOVE 150.50 TO ORDER-AMOUNT(1). MOVE 1002 TO ORDER-ID(2). MOVE "2024-02-20" TO ORDER-DATE(2). MOVE 275.75 TO ORDER-AMOUNT(2). MOVE 1003 TO ORDER-ID(3). MOVE "2024-03-10" TO ORDER-DATE(3). MOVE 89.99 TO ORDER-AMOUNT(3). * Generate XML with custom formatting XML GENERATE WS-XML-OUTPUT FROM WS-CUSTOMER-RECORD WITH ENCODING "UTF-8" WITH XML-DECLARATION SUPPRESS ZERO SUPPRESS SPACE NAME "Customer" TYPE "record" NAMESPACE-PREFIX "cust" NAMESPACE "http://example.com/customer" END-XML. * Format XML for readability PERFORM FORMAT-XML-OUTPUT. DISPLAY "Formatted XML Output:". DISPLAY WS-XML-DOCUMENT. STOP RUN. FORMAT-XML-OUTPUT. * Simple XML formatting (in production, use XML formatter) STRING "" DELIMITED SIZE X"0A" *> Line feed "" DELIMITED SIZE X"0A" " " CUST-ID "" DELIMITED SIZE X"0A" " " DELIMITED SIZE X"0A" " " FUNCTION TRIM(CUST-NAME) "" DELIMITED SIZE X"0A" " " FUNCTION TRIM(CUST-EMAIL) "" DELIMITED SIZE X"0A" " " FUNCTION TRIM(CUST-TYPE) "" DELIMITED SIZE X"0A" " " DELIMITED SIZE X"0A" "" DELIMITED SIZE INTO WS-XML-DOCUMENT.

XML Template Generation

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
IDENTIFICATION DIVISION. PROGRAM-ID. XML-TEMPLATE-GENERATOR. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-XML-TEMPLATE PIC X(2048). 01 WS-GENERATED-XML PIC X(4096). 01 WS-CUSTOMER-DATA. 05 CUST-ID PIC 9(10). 05 CUST-NAME PIC X(50). 05 CUST-BALANCE PIC 9(8)V99. 05 CUST-LAST-LOGIN PIC X(19). PROCEDURE DIVISION. MAIN-PROCESS. * Initialize customer data MOVE 12345 TO CUST-ID. MOVE "John Smith" TO CUST-NAME. MOVE 1500.50 TO CUST-BALANCE. MOVE "2024-01-15T10:30:00" TO CUST-LAST-LOGIN. * Create XML template STRING "" "" "" "" "" "{{CUST-NAME}}" "{{CUST-BALANCE}}" "{{CUST-LAST-LOGIN}}" "" "" "" "" DELIMITED BY SIZE INTO WS-XML-TEMPLATE. * Replace template variables PERFORM SUBSTITUTE-XML-VALUES. DISPLAY "Generated SOAP Response:". DISPLAY WS-GENERATED-XML. STOP RUN. SUBSTITUTE-XML-VALUES. * Replace template placeholders with actual values MOVE WS-XML-TEMPLATE TO WS-GENERATED-XML. INSPECT WS-GENERATED-XML REPLACING ALL "{{CUST-ID}}" BY CUST-ID. INSPECT WS-GENERATED-XML REPLACING ALL "{{CUST-NAME}}" BY FUNCTION TRIM(CUST-NAME). INSPECT WS-GENERATED-XML REPLACING ALL "{{CUST-BALANCE}}" BY CUST-BALANCE. INSPECT WS-GENERATED-XML REPLACING ALL "{{CUST-LAST-LOGIN}}" BY CUST-LAST-LOGIN.

Working with JSON Data

While COBOL doesn't have native JSON support like XML, modern COBOL environments provide libraries and techniques for JSON processing. JSON is crucial for REST APIs and modern web service integration.

JSON Parsing Techniques

Simple JSON Parser

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
IDENTIFICATION DIVISION. PROGRAM-ID. JSON-PARSER. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-JSON-INPUT PIC X(4096). 01 WS-JSON-POSITION PIC 9(4) VALUE 1. 01 WS-JSON-LENGTH PIC 9(4). 01 WS-CURRENT-CHAR PIC X. 01 WS-PARSE-STATE PIC X(20). 01 WS-FIELD-NAME PIC X(50). 01 WS-FIELD-VALUE PIC X(100). 01 WS-CUSTOMER-DATA. 05 CUST-ID PIC 9(10). 05 CUST-NAME PIC X(50). 05 CUST-EMAIL PIC X(100). 05 CUST-ACTIVE PIC X VALUE "N". PROCEDURE DIVISION. MAIN-PROCESS. * Sample JSON input STRING "{" '"id": 12345,' '"name": "John Smith",' '"email": "john.smith@example.com",' '"active": true' "}" DELIMITED BY SIZE INTO WS-JSON-INPUT. MOVE LENGTH OF FUNCTION TRIM(WS-JSON-INPUT) TO WS-JSON-LENGTH. * Parse JSON PERFORM PARSE-JSON. * Display parsed data DISPLAY "Parsed Customer Data:". DISPLAY "ID: " CUST-ID. DISPLAY "Name: " CUST-NAME. DISPLAY "Email: " CUST-EMAIL. DISPLAY "Active: " CUST-ACTIVE. STOP RUN. PARSE-JSON. PERFORM VARYING WS-JSON-POSITION FROM 1 BY 1 UNTIL WS-JSON-POSITION > WS-JSON-LENGTH MOVE WS-JSON-INPUT(WS-JSON-POSITION:1) TO WS-CURRENT-CHAR EVALUATE WS-CURRENT-CHAR WHEN "{" MOVE "OBJECT-START" TO WS-PARSE-STATE WHEN "}" MOVE "OBJECT-END" TO WS-PARSE-STATE WHEN '"' PERFORM PARSE-STRING WHEN ":" MOVE "VALUE-SEPARATOR" TO WS-PARSE-STATE WHEN "," PERFORM PROCESS-FIELD-VALUE MOVE SPACES TO WS-FIELD-NAME WS-FIELD-VALUE WHEN OTHER IF WS-PARSE-STATE = "VALUE-SEPARATOR" PERFORM PARSE-VALUE END-IF END-EVALUATE END-PERFORM. * Process last field IF WS-FIELD-NAME NOT = SPACES PERFORM PROCESS-FIELD-VALUE END-IF. PARSE-STRING. MOVE SPACES TO WS-FIELD-NAME. ADD 1 TO WS-JSON-POSITION. PERFORM VARYING WS-JSON-POSITION FROM WS-JSON-POSITION BY 1 UNTIL WS-JSON-POSITION > WS-JSON-LENGTH OR WS-JSON-INPUT(WS-JSON-POSITION:1) = '"' STRING WS-FIELD-NAME DELIMITED BY SPACE WS-JSON-INPUT(WS-JSON-POSITION:1) DELIMITED BY SIZE INTO WS-FIELD-NAME END-PERFORM. PARSE-VALUE. MOVE SPACES TO WS-FIELD-VALUE. * Skip whitespace PERFORM UNTIL WS-JSON-INPUT(WS-JSON-POSITION:1) NOT = SPACE AND WS-JSON-INPUT(WS-JSON-POSITION:1) NOT = X"09" ADD 1 TO WS-JSON-POSITION END-PERFORM. * Parse value based on first character EVALUATE WS-JSON-INPUT(WS-JSON-POSITION:1) WHEN '"' PERFORM PARSE-STRING-VALUE WHEN "t" MOVE "true" TO WS-FIELD-VALUE ADD 3 TO WS-JSON-POSITION WHEN "f" MOVE "false" TO WS-FIELD-VALUE ADD 4 TO WS-JSON-POSITION WHEN OTHER PERFORM PARSE-NUMBER-VALUE END-EVALUATE. PARSE-STRING-VALUE. ADD 1 TO WS-JSON-POSITION. PERFORM VARYING WS-JSON-POSITION FROM WS-JSON-POSITION BY 1 UNTIL WS-JSON-POSITION > WS-JSON-LENGTH OR WS-JSON-INPUT(WS-JSON-POSITION:1) = '"' STRING WS-FIELD-VALUE DELIMITED BY SPACE WS-JSON-INPUT(WS-JSON-POSITION:1) DELIMITED BY SIZE INTO WS-FIELD-VALUE END-PERFORM. PARSE-NUMBER-VALUE. PERFORM VARYING WS-JSON-POSITION FROM WS-JSON-POSITION BY 1 UNTIL WS-JSON-POSITION > WS-JSON-LENGTH OR WS-JSON-INPUT(WS-JSON-POSITION:1) = "," OR WS-JSON-INPUT(WS-JSON-POSITION:1) = "}" STRING WS-FIELD-VALUE DELIMITED BY SPACE WS-JSON-INPUT(WS-JSON-POSITION:1) DELIMITED BY SIZE INTO WS-FIELD-VALUE END-PERFORM. SUBTRACT 1 FROM WS-JSON-POSITION. PROCESS-FIELD-VALUE. EVALUATE WS-FIELD-NAME WHEN "id" MOVE WS-FIELD-VALUE TO CUST-ID WHEN "name" MOVE WS-FIELD-VALUE TO CUST-NAME WHEN "email" MOVE WS-FIELD-VALUE TO CUST-EMAIL WHEN "active" IF WS-FIELD-VALUE = "true" MOVE "Y" TO CUST-ACTIVE ELSE MOVE "N" TO CUST-ACTIVE END-IF END-EVALUATE.

JSON Generation

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
IDENTIFICATION DIVISION. PROGRAM-ID. JSON-GENERATOR. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-CUSTOMER-DATA. 05 CUST-ID PIC 9(10) VALUE 12345. 05 CUST-NAME PIC X(50) VALUE "John Smith". 05 CUST-EMAIL PIC X(100) VALUE "john.smith@example.com". 05 CUST-ACTIVE PIC X VALUE "Y". 05 CUST-BALANCE PIC 9(8)V99 VALUE 1500.50. 05 CUST-ORDERS OCCURS 2 TIMES. 10 ORDER-ID PIC 9(8). 10 ORDER-TOTAL PIC 9(6)V99. 01 WS-JSON-OUTPUT PIC X(4096). 01 WS-TEMP-AMOUNT PIC X(12). 01 WS-ACTIVE-FLAG PIC X(5). 01 WS-I PIC 9(2). PROCEDURE DIVISION. MAIN-PROCESS. * Initialize order data MOVE 1001 TO ORDER-ID(1). MOVE 150.50 TO ORDER-TOTAL(1). MOVE 1002 TO ORDER-ID(2). MOVE 275.25 TO ORDER-TOTAL(2). * Generate JSON PERFORM BUILD-JSON-RESPONSE. DISPLAY "Generated JSON:". DISPLAY WS-JSON-OUTPUT. STOP RUN. BUILD-JSON-RESPONSE. * Convert boolean IF CUST-ACTIVE = "Y" MOVE "true" TO WS-ACTIVE-FLAG ELSE MOVE "false" TO WS-ACTIVE-FLAG END-IF. * Build main JSON structure STRING "{" '"id":' CUST-ID "," '"name":"' FUNCTION TRIM(CUST-NAME) '",' '"email":"' FUNCTION TRIM(CUST-EMAIL) '",' '"active":' WS-ACTIVE-FLAG "," '"balance":' CUST-BALANCE "," '"orders":[' DELIMITED BY SIZE INTO WS-JSON-OUTPUT. * Add orders array PERFORM VARYING WS-I FROM 1 BY 1 UNTIL WS-I > 2 IF WS-I > 1 STRING WS-JSON-OUTPUT DELIMITED BY SPACE "," DELIMITED BY SIZE INTO WS-JSON-OUTPUT END-IF STRING WS-JSON-OUTPUT DELIMITED BY SPACE "{" '"orderId":' ORDER-ID(WS-I) "," '"total":' ORDER-TOTAL(WS-I) "}" DELIMITED BY SIZE INTO WS-JSON-OUTPUT END-PERFORM. * Close JSON structure STRING WS-JSON-OUTPUT DELIMITED BY SPACE "]}" DELIMITED BY SIZE INTO WS-JSON-OUTPUT.

Complex JSON Handling

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
IDENTIFICATION DIVISION. PROGRAM-ID. JSON-COMPLEX-HANDLER. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-JSON-REQUEST PIC X(8192). 01 WS-JSON-RESPONSE PIC X(8192). 01 WS-REQUEST-DATA. 05 REQ-METHOD PIC X(20). 05 REQ-ENDPOINT PIC X(100). 05 REQ-CUSTOMER-ID PIC 9(10). 05 REQ-FILTERS. 10 FILTER-DATE-FROM PIC X(10). 10 FILTER-DATE-TO PIC X(10). 10 FILTER-STATUS PIC X(20). 01 WS-RESPONSE-DATA. 05 RESP-STATUS PIC X(20) VALUE "success". 05 RESP-MESSAGE PIC X(100). 05 RESP-DATA. 10 RESP-CUSTOMERS OCCURS 5 TIMES. 15 RESP-CUST-ID PIC 9(10). 15 RESP-CUST-NAME PIC X(50). 15 RESP-CUST-TOTAL PIC 9(8)V99. 05 RESP-PAGINATION. 10 RESP-PAGE PIC 9(4) VALUE 1. 10 RESP-PAGE-SIZE PIC 9(4) VALUE 10. 10 RESP-TOTAL PIC 9(6) VALUE 0. PROCEDURE DIVISION. MAIN-PROCESS. * Sample complex JSON request STRING "{" '"method":"GET",' '"endpoint":"/api/customers",' '"customerId":12345,' '"filters":{' '"dateFrom":"2024-01-01",' '"dateTo":"2024-12-31",' '"status":"active"' "}," '"pagination":{' '"page":1,' '"pageSize":10' "}}" DELIMITED BY SIZE INTO WS-JSON-REQUEST. * Process request PERFORM PARSE-COMPLEX-JSON. PERFORM PROCESS-CUSTOMER-REQUEST. PERFORM BUILD-COMPLEX-JSON-RESPONSE. DISPLAY "Complex JSON Response:". DISPLAY WS-JSON-RESPONSE. STOP RUN. PARSE-COMPLEX-JSON. * Simplified parsing - in production, use JSON library MOVE "GET" TO REQ-METHOD. MOVE "/api/customers" TO REQ-ENDPOINT. MOVE 12345 TO REQ-CUSTOMER-ID. MOVE "2024-01-01" TO FILTER-DATE-FROM. MOVE "2024-12-31" TO FILTER-DATE-TO. MOVE "active" TO FILTER-STATUS. PROCESS-CUSTOMER-REQUEST. * Simulate data retrieval MOVE "Data retrieved successfully" TO RESP-MESSAGE. MOVE 12345 TO RESP-CUST-ID(1). MOVE "John Smith" TO RESP-CUST-NAME(1). MOVE 1500.50 TO RESP-CUST-TOTAL(1). MOVE 1 TO RESP-TOTAL. BUILD-COMPLEX-JSON-RESPONSE. STRING "{" '"status":"' FUNCTION TRIM(RESP-STATUS) '",' '"message":"' FUNCTION TRIM(RESP-MESSAGE) '",' '"data":{' '"customers":[' "{" '"id":' RESP-CUST-ID(1) "," '"name":"' FUNCTION TRIM(RESP-CUST-NAME(1)) '",' '"total":' RESP-CUST-TOTAL(1) "}" "]" "}," '"pagination":{' '"page":' RESP-PAGE "," '"pageSize":' RESP-PAGE-SIZE "," '"total":' RESP-TOTAL "}}" DELIMITED BY SIZE INTO WS-JSON-RESPONSE.

Data Conversion Strategies

Converting between COBOL data formats and XML/JSON requires careful handling of data types, encoding, and formatting differences. Proper conversion strategies ensure data integrity and compatibility.

COBOL to XML/JSON Conversion

Data Type Mapping

COBOL TypeXML RepresentationJSON RepresentationConversion Notes
PIC 9(5)<value>12345</value>"value": 12345Numeric, no quotes needed in JSON
PIC X(20)<text>Hello</text>"text": "Hello"String, trim trailing spaces
PIC 9(5)V99<amount>123.45</amount>"amount": 123.45Decimal, insert decimal point
PIC S9(5) COMP<value>-12345</value>"value": -12345Signed integer
88-level<active>true</active>"active": trueBoolean conversion

Universal Data Converter

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
IDENTIFICATION DIVISION. PROGRAM-ID. DATA-CONVERTER. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-CONVERSION-FUNCTIONS. 05 WS-OUTPUT-FORMAT PIC X(4) VALUE "JSON". *> JSON or XML 05 WS-DATE-FORMAT PIC X(10) VALUE "ISO". *> ISO or US 05 WS-DECIMAL-PLACES PIC 9(2) VALUE 2. 05 WS-TRIM-SPACES PIC X VALUE "Y". 01 WS-SOURCE-DATA. 05 SRC-CUSTOMER-ID PIC 9(10) VALUE 12345. 05 SRC-CUSTOMER-NAME PIC X(30) VALUE "John Smith". 05 SRC-ACCOUNT-BALANCE PIC 9(8)V99 VALUE 1500.50. 05 SRC-LAST-UPDATED PIC 9(8) VALUE 20240115. 05 SRC-ACTIVE-FLAG PIC X VALUE "Y". 01 WS-CONVERTED-OUTPUT PIC X(4096). PROCEDURE DIVISION. MAIN-PROCESS. EVALUATE WS-OUTPUT-FORMAT WHEN "JSON" PERFORM CONVERT-TO-JSON WHEN "XML" PERFORM CONVERT-TO-XML WHEN OTHER DISPLAY "Unsupported output format" END-EVALUATE. DISPLAY "Converted Output:". DISPLAY WS-CONVERTED-OUTPUT. STOP RUN. CONVERT-TO-JSON. STRING "{" '"customerId":' SRC-CUSTOMER-ID "," '"customerName":"' FUNCTION TRIM(SRC-CUSTOMER-NAME) '",' '"accountBalance":' SRC-ACCOUNT-BALANCE "," '"lastUpdated":"' FUNCTION CONVERT-DATE(SRC-LAST-UPDATED) '",' '"active":' FUNCTION CONVERT-BOOLEAN(SRC-ACTIVE-FLAG) "}" DELIMITED BY SIZE INTO WS-CONVERTED-OUTPUT. CONVERT-TO-XML. STRING "" "" "" SRC-CUSTOMER-ID "" "" FUNCTION TRIM(SRC-CUSTOMER-NAME) "" "" SRC-ACCOUNT-BALANCE "" "" FUNCTION CONVERT-DATE(SRC-LAST-UPDATED) "" "" FUNCTION CONVERT-BOOLEAN(SRC-ACTIVE-FLAG) "" "" DELIMITED BY SIZE INTO WS-CONVERTED-OUTPUT. FUNCTION CONVERT-DATE(INPUT-DATE). * Convert YYYYMMDD to ISO format YYYY-MM-DD PROCEDURE DIVISION USING INPUT-DATE RETURNING RESULT-DATE. STRING INPUT-DATE(1:4) "-" INPUT-DATE(5:2) "-" INPUT-DATE(7:2) DELIMITED BY SIZE INTO RESULT-DATE. FUNCTION CONVERT-BOOLEAN(INPUT-FLAG). * Convert Y/N to true/false PROCEDURE DIVISION USING INPUT-FLAG RETURNING RESULT-BOOLEAN. IF INPUT-FLAG = "Y" OR INPUT-FLAG = "y" MOVE "true" TO RESULT-BOOLEAN ELSE MOVE "false" TO RESULT-BOOLEAN END-IF.

Character Encoding Handling

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
IDENTIFICATION DIVISION. PROGRAM-ID. ENCODING-CONVERTER. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-INPUT-DATA PIC X(1024). 01 WS-OUTPUT-DATA PIC X(1024). 01 WS-CHAR-POSITION PIC 9(4). 01 WS-CURRENT-CHAR PIC X. 01 WS-ENCODED-CHAR PIC X(6). PROCEDURE DIVISION. MAIN-PROCESS. MOVE "Special chars: <>&"'" TO WS-INPUT-DATA. PERFORM ENCODE-XML-CHARACTERS. DISPLAY "Original: " WS-INPUT-DATA. DISPLAY "Encoded: " WS-OUTPUT-DATA. STOP RUN. ENCODE-XML-CHARACTERS. MOVE SPACES TO WS-OUTPUT-DATA. PERFORM VARYING WS-CHAR-POSITION FROM 1 BY 1 UNTIL WS-CHAR-POSITION > LENGTH OF FUNCTION TRIM(WS-INPUT-DATA) MOVE WS-INPUT-DATA(WS-CHAR-POSITION:1) TO WS-CURRENT-CHAR EVALUATE WS-CURRENT-CHAR WHEN "<" MOVE "<" TO WS-ENCODED-CHAR PERFORM APPEND-ENCODED-CHAR WHEN ">" MOVE ">" TO WS-ENCODED-CHAR PERFORM APPEND-ENCODED-CHAR WHEN "&" MOVE "&" TO WS-ENCODED-CHAR PERFORM APPEND-ENCODED-CHAR WHEN '"' MOVE """ TO WS-ENCODED-CHAR PERFORM APPEND-ENCODED-CHAR WHEN "'" MOVE "'" TO WS-ENCODED-CHAR PERFORM APPEND-ENCODED-CHAR WHEN OTHER STRING WS-OUTPUT-DATA DELIMITED BY SPACE WS-CURRENT-CHAR DELIMITED BY SIZE INTO WS-OUTPUT-DATA END-EVALUATE END-PERFORM. APPEND-ENCODED-CHAR. STRING WS-OUTPUT-DATA DELIMITED BY SPACE WS-ENCODED-CHAR DELIMITED BY SPACE INTO WS-OUTPUT-DATA.

Integration with Web Services

COBOL applications can effectively integrate with modern web services through various approaches, enabling legacy systems to participate in contemporary architectures.

SOAP Web Services

SOAP Client Implementation

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
IDENTIFICATION DIVISION. PROGRAM-ID. SOAP-CLIENT. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-SOAP-REQUEST PIC X(4096). 01 WS-SOAP-RESPONSE PIC X(4096). 01 WS-HTTP-HEADERS PIC X(512). 01 WS-SERVICE-URL PIC X(256). 01 WS-SOAP-ACTION PIC X(100). 01 WS-PARSE-STATE PIC X(20). 01 WS-REQUEST-DATA. 05 REQ-CUSTOMER-ID PIC 9(10) VALUE 12345. 05 REQ-OPERATION PIC X(20) VALUE "GetCustomer". 01 WS-RESPONSE-DATA. 05 RESP-CUSTOMER-ID PIC 9(10). 05 RESP-NAME PIC X(50). 05 RESP-EMAIL PIC X(100). 05 RESP-STATUS PIC X(20). PROCEDURE DIVISION. MAIN-PROCESS. MOVE "http://example.com/CustomerService" TO WS-SERVICE-URL. MOVE "GetCustomer" TO WS-SOAP-ACTION. PERFORM BUILD-SOAP-REQUEST. PERFORM SEND-SOAP-REQUEST. PERFORM PARSE-SOAP-RESPONSE. DISPLAY "SOAP Response Data:". DISPLAY "Customer ID: " RESP-CUSTOMER-ID. DISPLAY "Name: " RESP-NAME. DISPLAY "Email: " RESP-EMAIL. DISPLAY "Status: " RESP-STATUS. STOP RUN. BUILD-SOAP-REQUEST. STRING "" "" "" "" "" "" REQ-CUSTOMER-ID "" "" "" "" DELIMITED BY SIZE INTO WS-SOAP-REQUEST. SEND-SOAP-REQUEST. * Build HTTP headers STRING "Content-Type: text/xml; charset=utf-8" X"0A" "SOAPAction: " WS-SOAP-ACTION X"0A" "Content-Length: " LENGTH OF FUNCTION TRIM(WS-SOAP-REQUEST) DELIMITED BY SIZE INTO WS-HTTP-HEADERS. * Make HTTP POST request CALL "HTTP-POST" USING WS-SERVICE-URL WS-HTTP-HEADERS WS-SOAP-REQUEST WS-SOAP-RESPONSE. PARSE-SOAP-RESPONSE. * Parse SOAP response XML XML PARSE WS-SOAP-RESPONSE PROCESSING PROCEDURE SOAP-RESPONSE-HANDLER END-XML. SOAP-RESPONSE-HANDLER. EVALUATE XML-EVENT WHEN "START-OF-ELEMENT" EVALUATE XML-NAME WHEN "CustomerId" MOVE "PARSING-ID" TO WS-PARSE-STATE WHEN "Name" MOVE "PARSING-NAME" TO WS-PARSE-STATE WHEN "Email" MOVE "PARSING-EMAIL" TO WS-PARSE-STATE WHEN "Status" MOVE "PARSING-STATUS" TO WS-PARSE-STATE END-EVALUATE WHEN "CONTENT-CHARACTERS" EVALUATE WS-PARSE-STATE WHEN "PARSING-ID" MOVE XML-TEXT TO RESP-CUSTOMER-ID WHEN "PARSING-NAME" MOVE XML-TEXT TO RESP-NAME WHEN "PARSING-EMAIL" MOVE XML-TEXT TO RESP-EMAIL WHEN "PARSING-STATUS" MOVE XML-TEXT TO RESP-STATUS END-EVALUATE END-EVALUATE.

SOAP Service Implementation

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
IDENTIFICATION DIVISION. PROGRAM-ID. SOAP-SERVICE. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-SOAP-REQUEST PIC X(4096). 01 WS-SOAP-RESPONSE PIC X(4096). 01 WS-HTTP-STATUS PIC 9(3) VALUE 200. 01 WS-PARSE-STATE PIC X(20). 01 WS-REQUEST-DATA. 05 REQ-CUSTOMER-ID PIC 9(10). 05 REQ-OPERATION PIC X(20). 01 WS-CUSTOMER-RECORD. 05 CUST-ID PIC 9(10). 05 CUST-NAME PIC X(50). 05 CUST-EMAIL PIC X(100). 05 CUST-STATUS PIC X(20). PROCEDURE DIVISION. MAIN-PROCESS. * Read SOAP request from STDIN ACCEPT WS-SOAP-REQUEST. * Parse SOAP request PERFORM PARSE-SOAP-REQUEST. * Process business logic PERFORM PROCESS-CUSTOMER-REQUEST. * Build SOAP response PERFORM BUILD-SOAP-RESPONSE. * Send HTTP response DISPLAY "Content-Type: text/xml; charset=utf-8". DISPLAY "Status: " WS-HTTP-STATUS. DISPLAY " ". DISPLAY WS-SOAP-RESPONSE. STOP RUN. PARSE-SOAP-REQUEST. * Parse incoming SOAP XML XML PARSE WS-SOAP-REQUEST PROCESSING PROCEDURE SOAP-REQUEST-HANDLER END-XML. SOAP-REQUEST-HANDLER. EVALUATE XML-EVENT WHEN "START-OF-ELEMENT" EVALUATE XML-NAME WHEN "GetCustomerRequest" MOVE "GetCustomer" TO REQ-OPERATION WHEN "CustomerId" MOVE "PARSING-CUSTOMER-ID" TO WS-PARSE-STATE END-EVALUATE WHEN "CONTENT-CHARACTERS" IF WS-PARSE-STATE = "PARSING-CUSTOMER-ID" MOVE XML-TEXT TO REQ-CUSTOMER-ID END-IF END-EVALUATE. PROCESS-CUSTOMER-REQUEST. * Simulate database lookup EVALUATE REQ-CUSTOMER-ID WHEN 12345 MOVE 12345 TO CUST-ID MOVE "John Smith" TO CUST-NAME MOVE "john.smith@example.com" TO CUST-EMAIL MOVE "ACTIVE" TO CUST-STATUS WHEN OTHER MOVE REQ-CUSTOMER-ID TO CUST-ID MOVE "Customer Not Found" TO CUST-NAME MOVE SPACES TO CUST-EMAIL MOVE "NOT_FOUND" TO CUST-STATUS MOVE 404 TO WS-HTTP-STATUS END-EVALUATE. BUILD-SOAP-RESPONSE. STRING "" "" "" "" "" "" CUST-ID "" "" FUNCTION TRIM(CUST-NAME) "" "" FUNCTION TRIM(CUST-EMAIL) "" "" FUNCTION TRIM(CUST-STATUS) "" "" "" "" "" DELIMITED BY SIZE INTO WS-SOAP-RESPONSE.

RESTful Web Services

REST API Consumer

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
IDENTIFICATION DIVISION. PROGRAM-ID. REST-CLIENT. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-REST-URL PIC X(256). 01 WS-HTTP-METHOD PIC X(10). 01 WS-REQUEST-BODY PIC X(4096). 01 WS-RESPONSE-BODY PIC X(4096). 01 WS-HTTP-STATUS PIC 9(3). 01 WS-CONTENT-TYPE PIC X(50) VALUE "application/json". 01 WS-CUSTOMER-DATA. 05 CUST-ID PIC 9(10). 05 CUST-NAME PIC X(50). 05 CUST-EMAIL PIC X(100). PROCEDURE DIVISION. MAIN-PROCESS. * GET request example MOVE "GET" TO WS-HTTP-METHOD. MOVE "https://api.example.com/customers/12345" TO WS-REST-URL. PERFORM MAKE-HTTP-REQUEST. PERFORM PARSE-JSON-RESPONSE. * POST request example MOVE "POST" TO WS-HTTP-METHOD. MOVE "https://api.example.com/customers" TO WS-REST-URL. PERFORM BUILD-JSON-REQUEST. PERFORM MAKE-HTTP-REQUEST. DISPLAY "REST API operations completed". STOP RUN. MAKE-HTTP-REQUEST. CALL "HTTP-REQUEST" USING WS-HTTP-METHOD WS-REST-URL WS-CONTENT-TYPE WS-REQUEST-BODY WS-RESPONSE-BODY WS-HTTP-STATUS. DISPLAY "HTTP Status: " WS-HTTP-STATUS. IF WS-HTTP-STATUS >= 200 AND WS-HTTP-STATUS < 300 DISPLAY "Request successful" ELSE DISPLAY "Request failed: " WS-RESPONSE-BODY END-IF. BUILD-JSON-REQUEST. MOVE 12346 TO CUST-ID. MOVE "Jane Doe" TO CUST-NAME. MOVE "jane.doe@example.com" TO CUST-EMAIL. STRING "{" '"id":' CUST-ID "," '"name":"' FUNCTION TRIM(CUST-NAME) '",' '"email":"' FUNCTION TRIM(CUST-EMAIL) '"' "}" DELIMITED BY SIZE INTO WS-REQUEST-BODY. PARSE-JSON-RESPONSE. * Simple JSON parsing for demonstration * In production, use proper JSON parsing library DISPLAY "Response: " WS-RESPONSE-BODY.

Microservice Integration

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
IDENTIFICATION DIVISION. PROGRAM-ID. MICROSERVICE-INTEGRATION. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-SERVICE-REGISTRY. 05 CUSTOMER-SERVICE-URL PIC X(100) VALUE "http://customer-svc:8080". 05 ACCOUNT-SERVICE-URL PIC X(100) VALUE "http://account-svc:8080". 05 NOTIFICATION-SVC-URL PIC X(100) VALUE "http://notify-svc:8080". 01 WS-REQUEST-ID PIC X(36). 01 WS-CORRELATION-ID PIC X(36). 01 WS-CIRCUIT-BREAKER PIC X VALUE "CLOSED". 01 WS-REST-URL PIC X(256). 01 WS-REQUEST-BODY PIC X(4096). 01 WS-RESPONSE-BODY PIC X(4096). 01 WS-HTTP-STATUS PIC 9(3). PROCEDURE DIVISION. MAIN-PROCESS. * Generate request correlation ID CALL "GENERATE-UUID" RETURNING WS-CORRELATION-ID. * Call customer microservice PERFORM CALL-CUSTOMER-SERVICE. * Call account microservice PERFORM CALL-ACCOUNT-SERVICE. * Send notification PERFORM CALL-NOTIFICATION-SERVICE. STOP RUN. CALL-CUSTOMER-SERVICE. IF WS-CIRCUIT-BREAKER = "CLOSED" CALL "HTTP-GET" USING CUSTOMER-SERVICE-URL WS-CORRELATION-ID WS-RESPONSE-BODY WS-HTTP-STATUS IF WS-HTTP-STATUS NOT = 200 PERFORM HANDLE-SERVICE-FAILURE END-IF ELSE PERFORM FALLBACK-CUSTOMER-DATA END-IF. CALL-ACCOUNT-SERVICE. STRING ACCOUNT-SERVICE-URL "/accounts/12345" DELIMITED BY SIZE INTO WS-REST-URL. CALL "HTTP-GET" USING WS-REST-URL WS-CORRELATION-ID WS-RESPONSE-BODY WS-HTTP-STATUS. CALL-NOTIFICATION-SERVICE. STRING "{" '"type":"customer_update",' '"customerId":12345,' '"correlationId":"' WS-CORRELATION-ID '",' '"timestamp":"' FUNCTION CURRENT-DATE '"' "}" DELIMITED BY SIZE INTO WS-REQUEST-BODY. CALL "HTTP-POST" USING NOTIFICATION-SVC-URL "application/json" WS-REQUEST-BODY WS-RESPONSE-BODY WS-HTTP-STATUS. HANDLE-SERVICE-FAILURE. * Implement circuit breaker pattern EVALUATE WS-HTTP-STATUS WHEN 500 THRU 599 MOVE "OPEN" TO WS-CIRCUIT-BREAKER DISPLAY "Circuit breaker opened due to server error" WHEN 429 DISPLAY "Rate limit exceeded, retrying..." CALL "SLEEP" USING 1000 *> Wait 1 second WHEN OTHER DISPLAY "Service call failed with status: " WS-HTTP-STATUS END-EVALUATE. FALLBACK-CUSTOMER-DATA. * Implement fallback logic when service is unavailable.

Enterprise Integration Patterns

Integration Benefits

  • Preserve existing business logic investments
  • Enable gradual modernization
  • Support hybrid architectures
  • Maintain data consistency
  • Reduce integration complexity

Best Practices

  • Use standard protocols (HTTP, HTTPS)
  • Implement proper error handling
  • Add retry and timeout mechanisms
  • Monitor service health and performance
  • Secure API endpoints appropriately

Key Takeaways

  • XML PARSE and GENERATE statements provide powerful tools for XML processing in modern COBOL
  • JSON handling requires custom parsing and generation routines but enables REST API integration
  • Proper data type conversion ensures compatibility between COBOL and modern data formats
  • Character encoding and escaping are crucial for data integrity in XML/JSON processing
  • COBOL can effectively participate in SOAP and REST web service architectures
  • Microservice integration patterns enable COBOL applications to work in modern distributed systems