Table of Contents
Legacy Cobol batches involve frequently dealing with EBCDIC files, using copybooks. Modernizing such batches typically requires to be able to read and write those files, given the copybooks. Two classes have been developped to support EBCDIC Read/Write :
Summer.Batch.Extra.Ebcdic.EbcdicFileReader
: to read from an ebcdic file;
Summer.Batch.Extra.Ebcdic.EbcdicFileWriter
: to write to an ebcdic file;
Both classes require that a xml version of a Cobol copybook is provided at run time.
EbcdicFileReader
To read records from an ebcdic file, using an EbcdicFileReader, the following elements must be provided :
a xml version of the needed Cobol copybook (Copybook property );
a class in charge of transforming ebcdic record into a business object (EbcdicReaderMapper property) : this class must implement the Summer.Batch.Extra.Copybook.IEbcdicReaderMapper<T>
interface ;
a path to the ebcdic file to be read (Resource property).
Caution | |
---|---|
The two elements (copybook xml file and ebcdic reader mapper class) are mandatory. Failing to provide either of them will prevent the EbcdicFileReader from working, and the job will likely fail. |
The Cobol copybook is used by the reader to extract ebcdic records from the ebcdic file.
Example 7.1. Sample xml copybook export
<?xml version="1.0" encoding="ASCII"?> <FileFormat ConversionTable="IBM037" dataFileImplementation="IBM i or z System" distinguishFieldSize="0" newLineSize="0" headerSize="0"> <RecordFormat cobolRecordName="BA_EBCDIC_READER" distinguishFieldValue="0"> <FieldFormat Decimal="0" DependingOn="" ImpliedDecimal="true" Name="CODE" Occurs="1" Picture="S9(5)" Signed="true" Size="5" Type="3" Value=""/> <FieldFormat Decimal="0" DependingOn="" ImpliedDecimal="true" Name="NAME" Occurs="1" Picture="X(30)" Signed="false" Size="30" Type="X" Value=""/> <FieldFormat Decimal="0" DependingOn="" ImpliedDecimal="true" Name="DESCRIPTION" Occurs="1" Picture="X(40)" Signed="false" Size="40" Type="X" Value=""/> <FieldFormat Decimal="0" DependingOn="" ImpliedDecimal="true" Name="DATE" Occurs="1" Picture="S9(8)" Signed="true" Size="4" Type="B" Value=""/> </RecordFormat> </FileFormat>
Note | |
---|---|
A remark about the ConversionTable (=encoding) specified in the copybook xml file: this attribute must be given a property that can be understood by the C# API.
This requires to use the C# encoding names (which differ from java encoding names convention -- java uses "Cp037" where C# uses "IBM037" for example).
The |
The xml copybook file must be compliant with the following xsd (full xsd source is given in dedicated appendix section)
Figure 7.1. Ebcdic File Format xml schema
The corresponding bound C# classes are located in the Summer.Batch.Extra.Copybook
namespace:
CopybookElement.cs
FieldFormat.cs
FieldsGroup.cs
FileFormat.cs
IFieldsList.cs
RecordFormat.cs
Then the ebcdic reader mapper is used to transform those records into more convenient business objects. Below is the business object whose properties will be mapped to the ebcdic record described by the xml copybook above.
Example 7.2. Sample business object to which ebcdic records will be mapped
using System;
namespace Com.Netfective.Bluage.Business.Batch.Ebcdic.Bos
{
/// <summary>
/// Entity EbcdicFileBO.
/// </summary>
[Serializable]
public class EbcdicFileBO
{
/// <summary>
/// Property Code.
/// </summary>
public int? Code { get; set; }
/// <summary>
/// Property Name.
/// </summary>
public string Name { get; set; }
/// <summary>
/// Property Description.
/// </summary>
public string Description { get; set; }
/// <summary>
/// Property Date.
/// </summary>
public DateTime? Date { get; set; }
}
}
Now, we need to define a mapper in charge of transforming records into business objects. The mapper must implement the Summer.Batch.Extra.Ebcdic.IEbcdicReaderMapper<T>
interface.
The Summer.Batch.Extra.Ebcdic.AbstractEbcdicReaderMapper<T>
is a convenient super class to inherit from in order to craft ebcdic reader mapper quickly (see example below).
Example 7.3. Sample ebcdic reader mapper
using Com.Netfective.Bluage.Business.Batch.Ebcdic.Bos; using Summer.Batch.Extra.Ebcdic; using System.Collections.Generic; namespace Com.Netfective.Bluage.Business.Batch.Ebcdic.Bos.Mappers { ///<summary> /// Ebcdic mapper for the EbcdicFileBO class. ///</summary> public class EbcdicFileEbcdicMapper : AbstractEbcdicReaderMapper<EbcdicFileBO> { private const int Code = 0; private const int Name = 1; private const int Description = 2; private const int Date = 3; ///<summary> /// Map a collection of properties to a EbcdicFileBO record. ///</summary> /// <param name="values"> list of values to be mapped</param> /// <param name="itemCount"> item count; will be used as identifier /// if this makes sense for the target class.</param> /// <returns>the EbcdicFileBO record build upon the given list of values.</returns> public override EbcdicFileBO Map(IList<object> values, int itemCount) { var record = new EbcdicFileBO { Code = (int) ((decimal) values[Code]), Name = ((string) values[Name]), Description = ((string) values[Description]), Date = ParseDate(values[Date]), }; return record; } } }
Then everything needs to be configured. The EbcdicFileReader is declared as any other reader in the job xml file :
Example 7.4. EbcdicFileReader
declaration in the job xml file
And here is the corresponding Unity configuration part :
Example 7.5. EbcdicFileReader
Unity configuration
… /// <summary> /// Registers the artifacts required for step EbcdicReader. /// </summary> /// <param name="container">the unity container to use for registrations</param> private void RegisterEbcdicReader(IUnityContainer container) { // Reader - EbcdicReader/EbcdicFileReader container.StepScopeRegistration<IItemReader<EbcdicFileBO>, EbcdicFileReader<EbcdicFileBO>> ("EbcdicReader/EbcdicFileReader") .Property("Resource").Resource("#{settings['BA_EBCDIC_READER.EbcdicReader.FILENAME_IN']}") .Property("Copybook").Resource("#{settings['BA_EBCDIC_READER.EbcdicReader.COPYBOOK_IN']}") .Property("EbcdicReaderMapper") .Reference<IEbcdicReaderMapper<EbcdicFileBO>>("EbcdicReader/EbcdicFileReader/Mapper") .Register(); …
Note | |
---|---|
A few details are worth mentioning here:
|
EbcdicFileWriter
To write records to an ebcdic file, using an EbcdicFileWriter, the following elements must be provided:
a list of Cobol copybooks xml versions (Copybooks property);
a class in charge of transforming ebcdic record into a business object (EbcdicWriterMapper property): one can use the Summer.Batch.Extra.Ebcdic.EbcdicWriterMapper
class or a custom sub-class that inherits from it;
a path to the ebcdic file to be written (Resource property).
Caution | |
---|---|
The writer takes a list of xml copybooks but only uses one copybook at a time; the writer has a convenient method ( The three elements (copybook xml files list, ebcdic writer mapper class and path to resource to write to) are mandatory. Failing to provide either of them will prevent the EbcdicFileWriter from working, and the job will likely fail. |
Let's review the corresponding needed configuration. The writer must be declared in the job xml file (as any other writer) :
Example 7.6. EbcdicFileWriter
declaration in the job xml file
Regarding Unity configuration, here is the corresponding part:
Example 7.7. EbcdicFileWriter
Unity configuration
… /// <summary> /// Registers the artifacts required for step EBCDIC_WRITER. /// </summary> /// <param name="container">the unity container to use for registrations</param> private void RegisterEBCDIC_WRITER(IUnityContainer container) { … // Writer - EBCDIC_WRITER/EbcdicFileWriter container .StepScopeRegistration<IItemWriter<EbcdicFileBO>, EbcdicFileWriter<EbcdicFileBO>>("EBCDIC_WRITER/EbcdicFileWriter") .Property("Resource").Resource("#{settings['BA_EBCDIC_WRITER.EBCDIC_WRITER.EbcdicFileWriter.FILENAME_OUT']}") .Property("Copybooks").Resources("#{settings['BA_EBCDIC_WRITER.EBCDIC_WRITER.EbcdicFileWriter.COPYBOOK_OUT']}") .Property("EbcdicWriterMapper").Reference<EbcdicWriterMapper>("EBCDIC_WRITER/EbcdicFileWriter/Mapper") .Register(); // EBCDIC writer mapper for EBCDIC_WRITER/EbcdicFileWriter container .StepScopeRegistration<EbcdicWriterMapper>("EBCDIC_WRITER/EbcdicFileWriter/Mapper") .Register(); …
Note | |
---|---|
|