cloudframe | Resource
Cobol to java mainframe engineering batch processing legacy code patterns modernization best practices

Some more "tricks of the trade" by our top tier engineers.

CloudFrame's senior engineers share advanced techniques for handling edge cases in COBOL-to-Java transformation, drawn from real-world enterprise transformation projects. These practical insights help modernization teams...

By Venkat Pillay Dec 02, 2025 ARTICLES

A Problem Worth Writing About 

Every modernization engagement brings its own set of surprises, but once in a while you encounter an issue that is both technically intriguing and representative of the realities of working across distributed and mainframe environments.  

Which is all to say, I have found myself reflecting on a particularly interesting problem we solved over the past couple of weeks. We were assisting a prospect evaluating CloudFrame for converting part of a larger CICS transaction into a standalone Java API. The converted service ran perfectly on Linux. Predictable, fast, and structurally identical to the legacy business logic. The next phase was to deploy the same API on z/OS UNIX System Services. Normally such deployments sit behind Liberty and get invoked via CICS, but in this case the client wanted to have the Java API directly on z/OS without involving Liberty at all. 

We bundled the application, deployed it on z/OS, and expected a straightforward run. And then, as it often happens in modernization projects, the “straightforward” part evaporated.

The Symptom: Valid JSON, Invalid Behavior 

The API endpoint was reachable and functional. Linux clients could POST JSON payloads without any issues. The same payload, sent from a Java client running on z/OS, however, consistently failed with exceptions coming from Jackson's deserialization logic. 

And this time the error wasn’t even reaching our controller. There was no controller log, no validation error, and no application-level exception. The request was being rejected long before it touched our code. 

The actual error looked like this: 

Article content

This was the first major hint. The JSON itself was perfectly valid. The structure was correct. The payload worked everywhere else. Yet Jackson was seeing the very first byte as 'B', which made no sense unless the raw encoding itself was wrong. 

Something was fundamentally different about the bytes arriving from a z/OS-originated request. We started suspecting codepage, but weren't sure where it is 

Investigating the Request Stream 

The first step was to inspect the raw bytes arriving at the server before Spring or Jackson touched them. 

Requests originating from Linux or Windows contained the expected UTF-8 encoded ASCII characters: 

Article content

Requests originating from z/OS told an entirely different story: 

Article content

It was at this moment that the root cause became immediately clear: 

Article content

The payload was not UTF-8. It was EBCDIC. 

A Java application running on z/OS uses the system’s default charset unless explicitly overridden. So when the z/OS client executed: 

outputStream.write(jsonString.getBytes()); 

it produced EBCDIC bytes, not UTF-8 bytes. 

To Jackson, and to every JSON parser in the world, this looked like corrupted, illegal input. 

Understanding the Point of Failure

Jackson expects UTF-8 JSON.  z/OS was sending EBCDIC JSON. 

The sequence looked like this: 

Article content

There was nothing wrong with the data.  There was nothing wrong with the controller. There was nothing wrong with Jackson. The issue was simply that the first byte of the JSON “{” in EBCDIC does not map to “{” in UTF-8. 

Designing a Platform-Aware Fix 

We needed a solution that: 


  1. Detects whether inbound JSON is UTF-8 or EBCDIC 
  2. Converts EBCDIC → UTF-8 before Jackson sees it 
  3. Ensures outbound responses are encoded appropriately 
  4. Works in a multithreaded environment 
  5. Requires zero changes from customers 


The last point is extremely important in modernization scenarios. The goal is not just “make it work,” but make it work without asking customers to change how they operate. To meet all these requirements, we implemented a Spring ControllerAdvice interceptor.  

The Architecture: Auto-Detect → Convert → Track 

Here is the overall flow we implemented: 

Article content

The inbound encoding decision is stored in a ThreadLocal<Boolean>, ensuring correct behavior even under heavy concurrency. 

The Core Implementation 

Article content
Article content

Key aspects: 


  • ASCII-dominance detection is reliable for JSON 
  • Outbound uses ObjectMapper.writeValueAsBytes to avoid toString() pitfalls 
  • ThreadLocal ensures per-request isolation 


Why This Approach Works 

The real strength of the solution is not the conversion itself. It is the auto-detection and context propagation. Encoding mismatches are one of the most common hidden traps when integrating distributed and mainframe-native workloads. A solution that “just converts” is not enough. It has to convert only when necessary and behave transparently when not. 

By making the interceptor fully automatic, with no required changes from callers, we delivered a solution that is: 


  • robust 
  • platform-aware 
  • easy for customers 
  • safe for mixed environments 


 This is precisely the level of engineering maturity required for real-world modernization. 

Closing Thoughts 

This issue is a reminder that modernization is rarely just a matter of translating COBOL into Java. It is an exercise in understanding decades of platform expectations, encoding defaults, and runtime assumptions. Something as simple as a JSON payload becomes an engineering challenge when one side speaks UTF-8 and the other speaks EBCDIC. 

At CloudFrame, these are the kinds of challenges we enjoy solving. They deepen our understanding of the mainframe ecosystem and reinforce why thoughtful, platform-aware design is critical in building modernization solutions that truly work for enterprises. 

A good way to end the month, with one more problem solved, and one more lesson gained. If you’d like the full implementation or want to go deeper into this topic, reach out to us in the comments. We'd love to hear from you!

Share Article

Spread this insight across your network.

X LinkedIn Facebook
Author

Venkat Pillay

Founder and CEO

Venkat is a true technology visionary, serial entrepreneur, strategist, deep generalist, and architect. With over 25 years of experience and a passion for innovation, his expertise ranges from Legacy to emerging technology and company building.

Continue Reading

Related Posts

Ready to modernize?

Start your journey from legacy mainframe to modern cloud-native applications today.

Agentic AI

Agentic AI is CloudFrame's orchestrated intelligence layer that combines deterministic, probabilistic, and generative models to assist, guide, and learn across the entire modernization journey—from discovery to transformation and optimization. It is context aware, adaptive and capable of independent operation.