spring-bootibm-mqebcdicpacked-decimaljrecord

Read packed decimal and convert to numeric in spring boot


All,

I am using a Spring boot application to store data in DB. I am getting this data from IBM MQ through Kafka topic. I am getting messages in EBCDIC format, so used cobol copybook, JRecord, cb2xml jars to convert to readable format and store in DB.

Now i am getting another file also in the same manner, but after conversion the data looks like this:

10020REFUNDONE
10021REFUNDTWO ·"   ÷/
10022REFUNDTHREE   oú^  " 
10023REFUNDFOUR              ¨jÄ ò≈

Here is how i am converting to readable format from ebcdic:

AbstractLineReader reader = null;
StringBuffer finalBuffer = new StringBuffer();
        try {
            String copybook = "/ds_header.cbl";
            reader = CustomCobolProvider.getInstance().getLineReader(copybook, Convert.FMT_MAINFRAME, new BufferedInputStream(new ByteArrayInputStream(salesData)));
AbstractLine line;
        while ((line = reader.read()) != null) {
            if (null != line.getFieldValue(REC_TYPE)){
                finalBuffer.append(line.getFullLine());
            }
        }
            }
        

and this is my getLineReader method:

public AbstractLineReader getLineReader(String copybook, int numericType, InputStream fileStream) throws Exception {

        String font = "";
        if (numericType == 1) {
            font = "cp037";
        }

        InputStream stream = CustomCobolProvider.class.getResourceAsStream(copybook);

        if(stream == null ) throw new RuntimeException("Can't Load the Copybook Metadata file from Resource....");
        LayoutDetail copyBook = ((ExternalRecord)this.copybookInt.loadCopyBook(stream, copybook, CopybookLoader.SPLIT_REDEFINE, 0, font, CommonBits.getDefaultCobolTextFormat(), Convert.FMT_MAINFRAME, 0, (AbsSSLogger)null).setFileStructure(Constants.IO_FIXED_LENGTH)).asLayoutDetail();
        AbstractLineReader ret = LineIOProvider.getInstance().getLineReader(copyBook, (LineProvider)null);
        ret.open(fileStream, copyBook);
        return ret;
    }

I am stuck here with the numeric conversion, i got to know it is coming in packed decimal. I have nil knowledge on cobol and mainframe, referred few sites and got to know how to convert from ebcdic to readable format. Please help!


Solution

  • The problem is getFullLine() method does not do any field translation; you need to access individual fields. You can use the line.getFieldIterator(0) to get a field iterator for the line.

    Also unless you are using an ancient version of JRecord, you are better off using the JRecordInterface1 class.

    Some thing like the following should work:

        StringBuffer finalBuffer = new StringBuffer();
    
        try {
            ICobolIOBuilder iob = JRecordInterface1.COBOL .newIOBuilder(copybookName)
                                   .setFont("cp037") 
                                   .setFileOrganization(Constants.IO_FIXED_LENGTH)
                                       ;  
    
    
            AbstractLineReader reader = iob.newReader(dataFile);
            while ((line = reader.read()) != null) {
                String sep = "";
                for (AbstractFieldValue fv : line.getFieldIterator(0)) {
                    finalBuffer.append(sep).append(fv);
                    sep = "\t";
                }
                finalBuffer.append("\n");
            }
    
            reader.close();
        } catch (Exception e) {
           // what ever ....
        }
    

    Other points

    With MQ data source you do not need to create line-readers. You can create lines directly from a byte array:

            ICobolIOBuilder iob = JRecordInterface1.COBOL .newIOBuilder(copybookName)
                                   .setFont("cp037") 
                                   .setFileOrganization(Constants.IO_FIXED_LENGTH)
                                       ;  
    
            AbstractLine line = iob.newLine(byteArrayFromMq);
            for (AbstractFieldValue fv : line.getFieldIterator(0)) {
                // what ever
            }