Monday, January 5, 2015

Comparing Apache Avro to Protocol Buffers, XML and JSON payloads

Comparing Avro to Protocol Buffers, XML and JSON payloads

In a previous blog post I compared Mainframe COBOL payloads to Protocol Buffers, XML and JSON.

The idea was to compare the number of bytes needed to encode structured data in these various languages.

The results were:

LanguageBytes size
Mainframe 422
XML1960
JSON1275
Protobuf 403

Since we have recently introduced legstar support for Apache Avro, I was curious to get a sense of how optimized Avro is. So I performed the same test and came out with 370 bytes.

Of course, you will get different results with different COBOL structures and a different data mix but you can be practically sure you will get a smaller Avro payload than the Mainframe payload.

This is because a lot of optimization has gone into the Avro binary encoder (testing was done using Avro 1.7.7).

Taking the same example as in the previous blog post, with this COBOL structure:

05 QUERY-DATA.
              10 CUSTOMER-NAME               PIC X(20).
              10 MAX-REPLIES                 PIC S9(4) COMP VALUE -1.

these 22 bytes of mainframe data :
0xe25c4040404040404040404040404040404040400005

gets translated to just 4 Avro bytes:
0x04532A0A

The corresponding Avro schema being:
{
      "type":"record",
      "name":"QueryData",
      "fields":[{
          "name":"customerName",
          "type":"string"
        },
        {
          "name":"maxReplies",
          "type":"int"
        }
      ],
      "namespace":"com.legstar.avro.samples.lsfileaq"
    }

This is interesting because it means that if you take a large mainframe file and convert it to Avro, you are likely to get a smaller file. About 12% smaller in the particular case used in my testing.

If you are using Hadoop, and have a use case where the same mainframe file is read by several MapReduce jobs, then it could make sense to convert your mainframe file using legstar.avro before you store it in HDFS as Avro encoded.

Reading that file later will be faster as the volume of data read off HDFS will be smaller.

Tuesday, December 9, 2014

LegStar V2 is underway

LegStar has been around for a while now, 8 years since the first release in 2006.

Since then a lot of things have changed:

  • The java SDK is now in version 8. It was version 4 in 2006 and things like generics were unheard of
  • Programming patterns have become common practice
  • Multi-threading techniques have improved and are better understood
  • Use cases which used to be centered around remote procedure calls to CICS programs, now deal with massive imports of mainframe data for Big Data Analytics


Some parts of LegStar are showing their age and I have finally found some time to start rewriting some of the core features. The LegStar core project is the older in the product so this is where I started.

The legstar-core2 project is where I placed the new developments.

You should not consider this as a replacement to the current LegStar though:

  • There are far less functionalities in legstar-core2 at the moment than in LegStar
  • The API V2 will not be backward compatible 


That second point may come as a surprise for mainframe users but in the world of open source, breaking compatibility is an "art de vivre". A primary benefit is that the code you get is much cleaner and readable when it does not need to deal with legacy. When the project evolves though, we might want to work on a migration guide of some form.

The new legstar-core2 project contains a simplified version of the legstar-cob2xsd module which is the venerable COBOL to XML schema translator. The changes are minor in this module so far. Neither COBOL, nor the XML schema specs have changed much.

From an architecture standpoint the major change is that JAXB is no longer central to the conversion process. So far, we were always going through the JAXB layer even if the target was Talend, Pentaho, JSON, or any other format.

Now the conversion logic has been abstracted out in a legstar-base module. There is also an associated legstar-base-generator module that produces artifacts for legstar-base. The legstar-base module can be considered a complete low-level solution for mainframe to java conversions. This new legstar-base module has replaced the legstar-coxbapi and legstar-coxbrt modules.

JAXB is still supported of course with 2 new modules, legstar-jaxb and legstar-jaxb-generator which cover the old legstar-coxbgen features.

Besides the architectural changes, there are 2 important changes you need to be aware of:

  • The legstar-core2 project is hosted on Github, not on Google code. Therefore source control has moved from SVN to Git.
  • The licence is GNU Affero GPL which is not as business friendly as the LGPL used by LegStar


Again, this is just the beginning on this new project and its likely to make its way to the newest developments first (such as legstar-avro). Over time, I will describe the new features in more details. In the meanwhile please send any feedback.

Fady

Friday, November 7, 2014

Announcing LegStar for Apache Avro

legStar has dealt with mapping COBOL structures to other languages for a long time now. Such a mapping has not always been straightforward because COBOL has a number of constructs that sets it appart, namely:

  • Deep hierarchies. Structures in COBOL tend to be several levels deep with the parent hierarchy providing a namespace system (the same field name can appear in several places in a structure).
  • Variable size arrays (Arrays whose dimension is given at runtime by another field in the structure).
  • Redefines which are similar to C unions.
  • Decimal data types which have a fixed number of digits in the fractional part (fractions whose denominator is a power of ten). I am surprised at how many languages try to get away with double/float as the only way to represent fractions.

Data serialization and RPC

Over the last few years, a series of new data serializing languages for structures have appeared. These derive mainly from the need to perform fast Remote Procedure Calls (RPC) over a network with complex data being passed back and forth. For high frequency calls, XML or JSON would be too expensive.

The RPC serializing languages I came across recently are:

Protocol Buffers (PB) was one for which we developed a LegStar translator which was an interesting experience.

Data serialization and Big Data Analytics

Besides RPC, the Big Data Analytics domain is now generating the need for efficient data serialization as well.

One aspect of dealing with large amounts of data is that you need to process records as fast as possible. Traditionally, in the Business Intelligence domain, data was serialized as SQL records or CSV (comma separated) records.

Not suprisingly all first generation ETL tools dealt primarily with SQL and CSV records.

The problem is that SQL and CSV are very bad at storing complex, structured data. Particularly deep hierarchies, arrays and unions.

So when your Big Data is made of such structured data (for instance data originating from a Mainframe), traditional ETL tools are generally sub optimal.

Apache Hadoop, a popular Big Data system, does not impose SQL or CSV. It offers a native serialization mechanism called Writable which allows passing structured data efficiently between Map and Reduce jobs.

Even better, there is an alternative approach called Apache Avro which is a standalone project similar to Protocol Buffers or Thrift but tightly integrated into Hadoop.

Importing Mainframe data into Hadoop

In a scenario where you need to import very large volumes of data from a Mainframe and perform analytics on them, it would make sense to use the Avro format to pass the records between the various steps of the analytics process (Map and Reduce jobs in Hadoop parlance).

The reason is that Mainframe records, described by a COBOL copybook, can translate to Avro records while preserving the hierarchy, arrays and redefines. This saves a lot of processing otherwise needed to 'flatten' the COBOL structures to a columnar representation (SQL, CSV, ...).

What is left to be done is a COBOL to Avro Translator so I have started a new legstar.avro project.

It is an early phase for the project of course and I intend to decribe it further in future installements of this blog. So if you are interested, please stay tuned.

Monday, June 18, 2012

Comparing Protocol Buffers to XML and JSON payloads

Following up on my last blog entry, I was interested in getting some figures comparing payload sizes for data encoded using protocol buffers against XML and JSON.

Since the major argument in favor of protocol buffers is the reduced network impact, I thought it would be interesting to measure that in a mainframe integration environment.

I built my test scenario with a CICS program called LSFILEAQ. LSFILEAQ is part of the legstar test programs and uses a VSAM file that comes with an IBM demo application commonly found in CICS development partitions.

LSFILEAQ takes simple query parameters on input and sends back an array of replies. This is the COBOL structure that describes the LSFILEAQ commarea (its CICS communication area):

        01 DFHCOMMAREA.
           05 QUERY-DATA.
              10 CUSTOMER-NAME               PIC X(20).
              10 MAX-REPLIES                 PIC S9(4) COMP VALUE -1.
                  88 UNLIMITED     VALUE -1.
           05 REPLY-DATA.
              10 REPLY-COUNT                 PIC 9(8) COMP-3.
              10 CUSTOMER OCCURS 1 TO 100 DEPENDING ON REPLY-COUNT.
                  15 CUSTOMER-ID             PIC 9(6).
                  15 PERSONAL-DATA.
                     20 CUSTOMER-NAME        PIC X(20).
                     20 CUSTOMER-ADDRESS     PIC X(20).
                     20 CUSTOMER-PHONE       PIC X(8).
                  15 LAST-TRANS-DATE         PIC X(8).
                  15 FILLER REDEFINES LAST-TRANS-DATE.
                     20 LAST-TRANS-DAY       PIC X(2).
                     20 FILLER               PIC X.
                     20 LAST-TRANS-MONTH     PIC X(2).
                     20 FILLER               PIC X.
                     20 LAST-TRANS-YEAR      PIC X(2).
                  15 LAST-TRANS-AMOUNT       PIC $9999.99.
                  15 LAST-TRANS-COMMENT      PIC X(9).

I ran the program using a query yielding a result of 5 customers and measured the raw size of the commarea in bytes. I came up with 422 bytes. Note that this includes both the input and output parameters. These are untranslated bytes, in z/OS format.

Using the legstar transformers I than generated XML and JSON representations of that same z/OS data. This time, the data is translated to ASCII and formatted using XML or JSON. I than measured the sizes of the corresponding XML and JSON payloads and got:

XML:1960 bytes
JSON:1275 bytes

What these results mean is that if I choose to send XML to CICS instead of the raw z/OS data, I will increase the network load by a factor of 364% (almost 5 times to raw data payload).

If I select the less greedy JSON to encode the payload, the network load increases by 202% (3 times the raw payload).

Now, what would be the equivalent protocol buffers payload?

To answer that, I first wrote a protocol buffer "proto" file using the protocol's Interface Description Language:

package customers;
option java_package = "com.example.customers";
option java_outer_classname = "CustomersProtos";

message CustomersQuery {
  required string customer_name_pattern = 1;
  optional int32 max_replies = 2;
}

message CustomersQueryReply {
  repeated Customer customers = 1;

  message Customer {
    required int32 customer_id = 1;
    required PersonalData personal_data= 2;
    optional TransactionDate last_transaction_date = 3;
    optional double last_transaction_amount = 4;
    optional string last_transaction_comment = 5;

    message PersonalData {
      required string customer_name = 1;
      required string customer_address = 2;
      required string customer_phone = 3;
    }

    message TransactionDate {
      required int32 transaction_year = 1;
      required int32 transaction_month = 2;
      required int32 transaction_day = 3;
    }
  }
}

This is close to the target LSFILEAQ commarea structure.

I then used protobuf-cobol to generate COBOL parsers and writers for each of the protocol buffers messages.

Rather than using the command line generation utility though, I used simple java code that looks like this:

HasMaxSize maxSizeProvider = new HasMaxSize() {

    public Integer getMaxSize(String fieldName, Type fieldType) {
        if (fieldName.equals("customer_name_pattern")) {
            return 20;
        } else if (fieldName.equals("customer_name")) {
            return 20;
        } else if (fieldName.equals("customer_address")) {
            return 20;
        } else if (fieldName.equals("customer_phone")) {
            return 8;
        } else if (fieldName.equals("last_transaction_comment")) {
            return 9;
        }
        return null;
    }

    public Integer getMaxOccurs(String fieldName,
                                JavaType fieldType) {
        if (fieldName.equals("Customer")) {
            return 1000;
        }
        return null;
    }

};
new ProtoCobol()
  .setOutputDir(new File("target/generated-test-sources/cobol"))
  .setQualifiedClassName("com.example.customers.CustomersProtos")
  .addSizeProvider(maxSizeProvider)
  .run();

The "HasMaxSize" provider allows the generated COBOL code to implement the size limitations which are specific to COBOL.

Besides the parsers and writers, protobuf-cobol also generates copybooks for the various messages. This is what we get for the input and output messages:

01  CustomersQuery.
           03  customer-name-pattern    PIC X(20) DISPLAY.
           03  max-replies PIC S9(9) COMP-5.

       01  CustomersQueryReply.
           03  OCCURS-COUNTERS--C.
             05  Customer--C PIC 9(9) COMP-5.
           03  Customer OCCURS 0 TO 1000 DEPENDING ON Customer--C.
             05  customer-id PIC S9(9) COMP-5.
             05  PersonalData.
               07  customer-name PIC X(20) DISPLAY.
               07  customer-address PIC X(20) DISPLAY.
               07  customer-phone PIC X(8) DISPLAY.
             05  TransactionDate.
               07  transaction-year PIC S9(9) COMP-5.
               07  transaction-month PIC S9(9) COMP-5.
               07  transaction-day PIC S9(9) COMP-5.
             05  last-transaction-amount COMP-2.
             05  last-transaction-comment PIC X(9) DISPLAY.

It is not exactly the same as the original commarea but is pretty close.

Using the protobuf-cobol parsers and writers and the same input and output data as for XML and JSON, I than obtained a protocol buffers payload size of 403 bytes (sum of input and output payloads).

Protocol buffers payload is even smaller than the raw z/OS data!

That might sound surprising but is the result of the extremely efficient way protocol buffers encodes data.

As an example, the COBOL group item QUERY-DATA size is 22 bytes on the mainframe. In my testing it contains hexadecimal:

"e25c4040404040404040404040404040404040400005".

The equivalent protocol buffer payload though is only 6 bytes long and contains hexadecimal:

"0a02532a1005".
This confirms that protocol buffers brings important benefits in terms of network traffic. For distributed applications and under heavy load, this is bound to make a big difference with XML and JSON based systems.

Saturday, May 5, 2012

Protocol Buffers for the mainframe


Protocol Buffers is a technology used internally at Google, which was made available as open source in 2008.

The idea is that XML and JSON are too verbose for communication-intensive systems.

XML and JSON bring two important benefits over binary protocols. They are:

  • Human readable (self documenting)
  • Resilient to changes (fields order is usually not imposed, fields can be missing or partially filled)

But these benefits come at a price:

  • Network load (the ratio of overhead metadata over actual data is quite high)
  • Parsing and writing relatively complex structures is CPU intensive

For systems that exchange isomorphic (same structure) data, millions of times a day, this price is too high.

Not surprisingly, that same diagnostic has stopped XML and JSON from being widely used on mainframes, although IBM introduced an XML parser quite early on z/OS.

Protocol Buffers is a binary protocol. In that sense, human readability and self description is lost. But it is resilient to changes. That second property turns out to be very important in heterogeneous, distributed systems.

Mainframes, and particularly COBOL-written applications, are by now completely immersed in heterogeneous, distributed systems. All IT departments, even those who claim to be very mainframe centric, run dozens of java or .Net applications alongside the mainframe (or sometimes even on the mainframe).

The rise of Enterprise mobile applications is bringing yet more heterogeneity in terms of Operating Systems and programming languages. Mainframe COBOL applications will necessarily have to interoperate with these newcomers too.

So after reading a lot about Protocol Buffers (and its competing sibling Thrift , developed originally at facebook then donated to the Apache Foundation), I came to the conclusion that such protocols might be exactly what COBOL on the mainframe need to better interoperate with Java, C++, ObjectiveC, etc.

To keep up with the spirit of LegStar, I started a new open source project called protobuf-cobol. I hope many of you will try it and let me know what you think.






Monday, February 20, 2012

z/OS float numerics and IEEE754


On z/OS, float and double numerics have been available for a long time but are seldom used with languages such as COBOL. The reason is that COBOL is primarily used for business rather than scientific applications and accountants prefer fixed decimal numerics.

In the java and C/C++ worlds though, floats and doubles are often used, even in business applications.

For COBOL to Java integration it is therefore important to understand how such numerics can be interchanged.

z/OS does not encode float and double data items in the usual IEEE754 way expected by Java and C/C++ developers.

To illustrate the differences lets use a COBOL program with a data item defined like this:

   01 W-ZOS-FLOAT  USAGE COMP-1 VALUE -375.256.

If we look at the content of this data item, it's hexadecimal representation is:

   X'C3177419'

or in binary:

   11000011 00010111 01110100 00011001
   ^^-----^ ^------------------------^
   |   |               |-mantissa
   |   |-biased exponent
   |-sign

The sign bit is turned on as we have stored a negative number. This is pretty much the only thing that is common with IEEE754.

The biased exponent is stored on 7 bits. The bias is X'40' (decimal 64). In our case, the decimal value stored in the biased exponent is 67, therefore the exponent is 67 - 64 (bias) = 3. Beware that this is an hexadecimal exponent, not a decimal one.

Finally, the content of the last 3 bytes is the mantissa, in our case: X'177419'. Now, since the exponent is 3, the integer part is X'177' (375 decimal as expected). The fractional part, X'419' is trickier to convert back to decimal. This is because most calculators have decimal to hexadecimal converters that do not work on fractions.

X'419' should be interpreted as 4 * (16**-1) + 1 * (16**-2) + 9 * (16**-3). You can use the calculator again if you observe that multiplying by 16**3, you get 4 *(16**2) + 1 * (16**1) + 9 * (16**0). In other words you can divide X'419'(decimal 1049) by 16**3 (decimal 4096) and you get 0,256103515625 which is our fractional part in decimal.

In summary, z/OS float items are Hexadecimal-based with a 7 bit exponent and 24 bit mantissa.

By contrast, IEEE754 floats are binary based, with an 8 bit exponent and 23 bit mantissa (called significand in the distributed world).

The internal representation of our -375.256 value is therefore:

   X'C3BBA0C5'

or in binary:

   11000011 10111011 10100000 11000101
   ^^-------^^-----------------------^
   |   |               |-mantissa
   |   |-biased exponent
   |-sign

Sign digit is same as z/OS as already mentioned.

The 8 bit biased exponent is 10000111 or 135 decimal. Float exponents in IEEE754 have a 127 decimal bias, the exponent is therefore 135 - 127 (bias) = 8. Beware that this is a binary exponent not a decimal one.

The 23 bit mantissa is 01110111010000011000101, BUT, there is an implied 1 as the most significant bit (msb). The real mantissa is therefore: 101110111010000011000101.

The integer part starts right after the implicit msb. Since we have an 8 exponent, the integer part is: 101110111 or 375 decimal.

Now for the fractional part, 010000011000101, again you can use a regular calculator which gives a decimal value of 8389 but you must divide that by 2**15 (23 bits - 8 exponent bits) or 8389 / 32768 = 0,256011962890625 which is our fractional part in decimal.

As you can see, although z/OS floats and IEEE754 floats are both 4 bytes long, they store numbers in quite a different way so don't attempt to push Java floats directly to COBOL buffers!


Sunday, November 27, 2011

LegStar for PDI, a primer

Introduction

Mainframes, such as IBM z/OS, are still operating in many large corporations and will probably continue to do so for the foreseeable future.

Mainframe file systems contain huge amounts of data that are still waiting to be unlocked and made available to modern applications.

Traditionally, mainframe data is processed by batch programs often written in COBOL. Usually several batch programs are organized as sequential steps in a flow. On z/OS, the flow description language is JCL, a rather complex and proprietary language.

Assuming you would like to exploit mainframe data but would rather not write COBOL or JCL, this article shows an approach harnessing the power of ETL tools such as Pentaho Data Integration. With this type of solution, mainframe data can be made available to a very large and growing set of technologies.

The primary destination of mainframe data is BI systems, data warehouses and so forth. Such systems impose constraints on data models in order to achieve the usability and performance levels that users expect when they run complex queries. Mainframe data on the other hand, being optimized for OLTP activity and storage optimization, is rarely organized in a BI friendly way. Hence the need to transform it.

In this article we will walk you through a rather common use case where mainframe data is optimized to reduce storage and needs to be normalized with the help of ETL technology.

While this type of transformation has been possible in the past, the novelty here is that we can now achieve identical results for a fraction of the cost, using Open Source technologies.

Use case

In our use case the source data is stored in a mainframe sequential file (QSAM in mainframe parlance).

Records in such files are not delimited by a special character, such as carriage return or line feed, as is common on distributed systems. Furthermore, a record content is a mix of characters and non-characters. Characters are usually encoded in EBCDIC, while non-characters represent various forms of numeric data. Numeric data is often encoded in mainframe specific formats such as compressed numerics (COMP-3).

Mainframe file records are often variable in size. This was important to save storage resources at a time when these were very expensive.

Although there are yet more difficulties involved in interpreting mainframe data, it should be clear by now that you can’t do so without some meta data that describes records. On mainframes, such metadata is often a COBOL copybook. A copybook is a fragment of COBOL code that describes a data structure (very similar to a C structure). This is a sample of such a copybook we will be using as a use case:

       01  CUSTOMER-DATA.
           05 CUSTOMER-ID                    PIC 9(6).
           05 PERSONAL-DATA.
              10 CUSTOMER-NAME               PIC X(20).
              10 CUSTOMER-ADDRESS            PIC X(20).
              10 CUSTOMER-PHONE              PIC X(8).
           05 TRANSACTIONS.
              10 TRANSACTION-NBR             PIC 9(9) COMP.
              10 TRANSACTION OCCURS 0 TO 5
                 DEPENDING ON TRANSACTION-NBR.
                 15 TRANSACTION-DATE         PIC X(8).
                 15 TRANSACTION-AMOUNT       PIC S9(13)V99 COMP-3.
                 15 TRANSACTION-COMMENT      PIC X(9).

Things to notice about this record description are:

  • This is 5 levels deep hierarchy
  • PIC X(n) denotes text fields containing EBCDIC encoded characters
  • CUSTOMER-ID, TRANSACTION-NBR and TRANSACTION-AMOUNT are 3 different forms of numerics
  • The array described with OCCURS and DEPENDING ON is a variable size array whose actual size is given by the TRANSACTION-NBR variable.

Now assuming we take a peek, with an hexadecimal editor, at a file record containing data described by this COBOL copybook, we would see something like this:

    00000000h: F0 F0 F0 F0 F0 F1 C2 C9 D3 D3 40 E2 D4 C9 E3 C8 ;
    00000010h: 40 40 40 40 40 40 40 40 40 40 C3 C1 D4 C2 D9 C9 ;
    00000020h: C4 C7 C5 40 40 40 40 40 40 40 40 40 40 40 F3 F8 ; 
    00000030h: F7 F9 F1 F2 F0 F6 00 00 00 00                   ;

This first record size is only 58 bytes long. This is because the TRANSACTION-NBR field contains a value of zero, hence there are no array items stored.

The second record though, which starts at offset 59, looks like this:

    0000003ah: F0 F0 F0 F0 F0 F2 C6 D9 C5 C4 40 C2 D9 D6 E6 D5 ; 
    0000004ah: 40 40 40 40 40 40 40 40 40 40 C3 C1 D4 C2 D9 C9 ;
    0000005ah: C4 C7 C5 40 40 40 40 40 40 40 40 40 40 40 F3 F8 ; 
    0000006ah: F7 F9 F1 F2 F0 F6 00 00 00 04 F3 F0 61 F1 F0 61 ; 
    0000007ah: F1 F0 00 00 00 00 00 03 68 2C 5C 5C 5C 5C 5C 5C ; 
    0000008ah: 5C 5C 5C F3 F0 61 F1 F0 61 F1 F0 00 00 00 00 00 ; 
    0000009ah: 17 59 3C 5C 5C 5C 5C 5C 5C 5C 5C 5C F3 F0 61 F1 ; 
    000000aah: F0 61 F1 F0 00 00 00 00 00 11 49 2C 5C 5C 5C 5C ; 
    000000bah: 5C 5C 5C 5C 5C F1 F0 61 F0 F4 61 F1 F1 00 00 00 ; 
    000000cah: 00 00 22 96 5C 5C 5C 5C 5C 5C 5C 5C 5C 5C       ; 

This one is 158 bytes long because the TRANSACTION-NBR field contains a value of 4. There are 4 items in the variable size array.

As you can see, there is not a single byte of excess storage in that file!

Now let us assume this file was transferred in binary mode to our workstation and that we want to create an excel worksheet out of its content.

Building a simple PDI Transform

To transform the mainframe file into an Excel worksheet, we will be using Pentaho Data Integration (PDI) and the LegStar plugin for PDI. LegStar for PDI provides the COBOL processing capabilities that are needed to transform the mainframe data into PDI rows.

The PDI community edition product is open source and freely available from this download link. This article was written using version 4.1.0.

LegStar for PDI is also an open source product, freely available at this download link. For this article, we used release 0.4.

Once you download legstar-pdi, you need to unzip the archive to the PDI plugins/steps folder. This will add the z/OS File Input plugin to PDI standards plugins.

The PDI GUI designer is called Spoon, it can be started using the spoon.bat or spoon.sh scripts.

On the first Spoon screen we create a new Transformation (using menu option File→New→Transformation).

From the designer palette’s Input folder, we drag and drop the z/OS file input step:

This will be the first step of our transformation process. Let us double click on it to bring up the settings dialog:

On the File tab, we pick up the z/OS binary File which was transferred to our workstation. Since this is a variable length record file, we check the corresponding box on the dialog.

This file does not contain record descriptor words. RDWs are 4 bytes that z/OS adds to each variable record. When these are present, LegStar can more efficiently process the file.

The z/OS character set is the EBCDIC encoding used for text fields. For french EBCDIC for instance, with accented characters and Euro sign, you would pick up IBM01147.

We now select the COBOL tab and copy/paste the COBOL structure that describes our file records:

At this stage, we need to click the Get Fields button which will start the process of translating the COBOL structure into a PDI row.

A PDI row is a list of fields, similar to a database row. The row model is fundamental in ETL tools as it nicely maps to the RDBMS model.

The Fields tab shows the result:

As you can see, several things happened:

  • The COBOL hierarchy has been flattened (LegStar has a name conflict resolution mechanism)
  • Data items, according to their COBOL type, have been mapped to Strings, Integers or BigNumbers with the appropriate precision
  • The array items have been flattened using the familiar _n suffix where n is the item index in the array

We are now done with setting up the z/OS file input step but before we continue building our PDI Transformation, it is a good idea to use one of the great features in PDI, which is the Preview capability. The Preview button should now be enabled, if you click on it and select a number of rows you would like to preview, you should see this result:

Time to go back to the PDI Transformation, add an Excel output step and create a hop between the z/OS file input step and the Excel output step:

You can now run the Transformation, this will require that you save your work. In our case we named our Transformation rcus-simple.ktr. Ktr files are XML documents that completely describe the PDI Transformation.

There is a launch dialog on which we simply chose to click launch and then the result showed up as this:

As you can see, 10000 records were read off the z/OS file and an identical number of rows were written in the Excel worksheet (plus a header row).

It is time to take a look at the Excel worksheet we created:

Everything is in there but you might notice the variable size array results in a lot of oolumns and a lot of empty cells since we need to fill all columns. Indexed column names and sparsely filled cells result in a worksheet that is hard to play with.

This reveals the fundamental issue with mainframe data models, they were not intended for end users to see. So putting such raw data in an excel worksheet is unlikely to be satisfactory.

This is where ETL tools take all their meaning. To illustrate the point we will next enhance our transformation to get rid of the variable size array effect.

Enhancing the PDI Transformation

Our first enhancement it to reduce the number of columns. We will apply a normalization transformation that is best described with an example.

This is a partial view of our current result row:

CustomerId CustomerName TransactionAmount_0 TransactionAmount_1 TransactionAmount_2 TransactionAmount_3
2 FRED BROWN 36,82 175,93 114,92 229,65

The COBOL array flattening has had the effect of multiplying the number of columns. Here would be a more desirable, normalized, view of that same data:

CustomerId CustomerName TransactionIdx TransactionAmount
2 FRED BROWN 0 36,82
2 FRED BROWN 1 175,93
2 FRED BROWN 2 114,92
2 FRED BROWN 3 229,65

What happened here is that Columns were traded for Rows. Instead of 5 TransactionAmount_n columns there is a single one and the new TransactionIdx column identifies each transaction. The result is a normalized table in the sense of the first normal form in RDBMS theory.

Normalizing has an effect on volumes of course but the result is much easier to manipulate with traditional RDBMS semantics.

Let us now modify our PDI Transformation and introduce a Normalizer step (Palette’s Transform category):

Setting up the Normalizer involves specifying the new TransactionIdx column and then mapping the indexed columns to a TransactionIdx value and the single column that will replace each repeatable group:

If we now run our transformation, this is how the result looks like:

This is already much nicer and easier to manipulate. From the original 20 columns, we are now down to 9.

The PDI execution statistics should show that 50000 rows were created in the Excel worksheet out from the 10000 that we read from the z/OS file. This is an negative effect of normalizing that we should now try to alleviate.

You might notice that the Excel worksheet still contains a large number of empty cells corresponding to empty transactions.

Our next step will be to get rid of these empty transactions. For that purpose, we will use the PDI Filter Rows step (under the palette’s Flow category).

The Filter step will be setup to send empty transaction rows to the trash can and forward rows with transactions to the Excel worksheet. The PDI equivalent of a trash can is the Dummy step, also found under the Flow category so we go ahead an add it to the canvas too:

Let us now double click on the Filter step to bring up the setting dialog:

Here we specify that the filter condition is true if the TransactionDate column is not empty. Back to the canvas, we can now create 2 hops, one for the true condition that will lead to the Excel worksheet and one for the false condition which brings to the Dummy step:

We are now ready to execute the PDI Transformation. The metrics should display something like this:

Now, only 25163 rows made it to the Excel worksheet while 24837 were trashed. The resulting Excel worksheet is finally much closer to what an end user might expect:


Conclusion

In this article we have seen how mainframe data, which is by construct obscure and hardly usable by non-programmers, can be transformed into something as easy to manipulate as an Excel worksheet.

Of course, the example given remains simplistic compared to true life COBOL structures and mainframe data organizations but we have seen a small part of the PDI capabilities, some of which are pretty powerful.

Historically the type of features that you have seen in this article were only available from very expensive and proprietary products. The fact that you can now do a lot of the same things, entirely with open source software, will hopefully trigger many more opportunities to exploit the massive untapped mainframe data.

We hope that readers with mainframe background, as well as readers with open systems background, will find this useful and come out with new ideas for Open Source mainframe integration solutions.

Friday, November 18, 2011

A LegStar Commercial License

Entreprises still intensively using mainframes these days tend to be very large. Although most of these companies are more and more comfortable using open source software, they are not comfortable at all with running unsupported code in production.

That creates a specific problem to LegStar since it is both Open Source an primarily of use for such large companies.

After receiving several requests from customers at LegSem we started looking into building some kind of commercial offering around LegStar.

Of course, we are not the first open source company to bang our head against this thorny issue, infoworld has a honest and funny write-up about this.

So this is what we came up with:

Committed to Open Source:

  • First, LegStar is and will remain Open Source
  • The core features will stay under the permissive LGPL as they are today and the advanced features will be GPL
  • There won't be an entreprise product separate from the Open Source one. This means every single line of code will be available under an Open Source license

For Customers who need it:

  • Besides the Open Source licenses, there will be a Commmercial License available. Yes, this a dual-licensing scheme
  • The Commercial License describes the level of support that LegSem, or a business partner, provides
  • LegSem will also shield Commercial Licensees from backward compatibility issues

This last point requires a little bit of explanation:

As we add new features or fix bugs in LegStar we generally pay attention to backward compatibility but we don't necessarily test it. As a result, new releases are not guaranteed to be backward compatible with your own developments. With the commercial offering, we will do additional, less frequent, releases that we will explicitly check for backward compatibility. These extra releases will only be available to commercial licensees.

LegSem is a small company and will not cover the entire world with that commercial license. What we intend to do is to work with business partners in territories where we are not present. So if your company would be interested in entering this type of deal with us please send a mail at contact@legsem.com.




Thursday, October 13, 2011

Finally a LegStar JCA Connector

This article refers to JCA, the Java Connector Architecture, not the Java Cryptography Architecture.

When we considered J2EE several years ago as a potential target for mainframe integration, I was horrified and decided not to pursue that route. This has proven the right choice and the J2EE reputation was so bad that the name was later changed to Java EE.

The idea that overly complex technologies provide great opportunities to sell services and consulting is not new. Some very large companies made a fortune this way. Some of these same companies were very active during the J2EE specifications...

Of course J2EE completely failed to become the universal web engine it was meant to be, but it made it to most large Entreprise Systems. Or at least part of the technology was adopted by large IT departements and some of the complexity alleviated thanks to frameworks like Spring.

So the reality today is that most companies still using mainframes also use Java EE.

Another interesting development concerns the latest Java EE specifications (5 and 6). I don't know if the J2EE designers were humbled by their past failures but I have to say they did a much better job this time. Today, the technology is almost usable without Spring. For instance, you can inject a JNDI resource with a single annotation which would have taken about 10 lines of Java code previously. If you want to learn more about the latest Java EE, I recommend reading Antonio Goncalves's blog.

So with Java EE specs getting better and almost all mainframe shops using it, I thought it was time for LegStar to start supporting Java EE containers. The result is part of a series of extensions to LegStar that I am working on.

The first deliverable is a JCA Resource Adapter that uses CICS Sockets as its underlying connectivity.

It is conformant to the JCA 1.0 specifications but does not implement some of the CCI chapter (which is optional anyway). In practice we do not support CCI Records which are awkward indexed or mapped objects. In my view, Records are not suitable to represent COBOL structures. With the LegStar JCA connector, Instead of Records, you simply use regular LegStar Transformers.

I am convinced that separating Resource Adapter fonctionalities (Connection pooling, Transactions and Security) from Transformation is a much better approach than what most JCA connectors available on the market do. For one thing, you can reuse the Transformers outside Java EE which is good because, even if Java EE is largely used by mainframe shops, they also use many other java based technologies (ESBs, ETLs, ...).

I intend to support the other LegStar transports (HTTP, WebSphere MQ) in the future as well as some other transports I have in mind. There will be a different JCA Resource Adapter for each transport.

One thing you might notice is that the licence has changed for these extensions. While the core LegStar project remains LGPL for the time being, the extensions use the more restrictive GPL. LGPL is often used when OSS projects start and need to get the wider acceptance possible, while GPL is for more mature OSS projects. LegStar is 7 years old now and if you look at what Google has to say about open source mainframe integration:

You will agree with me that it has gained sufficient traction to become part of the higher class GPL projects out there.

This is all thanks to you of course since I haven't devised a scheme to get Google to better rank my sites and never paid Google a dime either :-).

Saturday, July 23, 2011

Mapping Dates from COBOL to Java

Date (and Time) types are difficult to map between COBOL and java. Here a few comments on why this is hard.

Dates in COBOL

For a very long time, the COBOL compiler on IBM mainframes didn't know anything about dates. Developers typically used structures and managed dates semantics by hand. The Y2K issue was largely a consequence of this situation since the compiler couldn't solve the problem all by itself.

Recently ("recently" on the mainframe time scale means in the last 15 years or so), IBM introduced the DATE FORMAT keyword. This is used to further qualify a regular numeric or alphabetic data item. It introduces some restrictions on what you can store in the data item but fundamentally, the data item remains a numeric (binary, compressed or zoned decimal) or an alphanumeric.

The DATE FORMAT keyword must be followed by a pattern using Y and X characters (no relationship to chromosomes) such as YYXXXX or YYYYXXXX.

  • YY designates a "windowed" date. This is relative to a century window given by the YEARWINDOW compiler option.
  • YYYY is an "expanded" date. This is a regular century + year date.

MOVE of a windowed date to an expanded date will expand it as expected. There are also intrinsic functions such as DATEVAL and UNDATE to convert dates to non date data items.

For more details, see the programming reference in IBM COBOL documentation.

Dates in Java

If dates are messy in COBOL, well, they are even messier in Java.

At the beginning there was an overly simple java.util.Date (with a weird java.sql.Date variation with 9 methods, 6 of which are deprecated!).

Then came java.sql.Timestamp which inherits from java.util.Date but about which the documentation states: "it is recommended that code not view Timestamp values generically as an instance of java.util.Date". It is as if to say: Timestamp inherits from Date, but please don't use that fact in your programs...

But worst, came the dreaded java.util.Calendar. In this article, Joshua Bloch, an ex Sun engineer, says:

As an extreme example of what not to do, consider the case of java.util.Calendar. Very few people understand its state-space -- I certainly don't -- and it's been a constant source of bugs for years.

java.util.Calendar was designed at a time (long gone now) when Java was to overtake the programming world, so this monster was born and several, often used, java.util.Date methods were deprecated as a consequence.

To further complexify things, JAXB has introduced the javax.xml.datatype.XMLGregorianCalendar in order to map the XML Schema date and time.

All in all, at least 5 different ways of representing a Date

Mapping COBOL dates to Java Dates

So far, Legstar has taken the, rather lame, approach of not attempting to map COBOL dates to Java dates automatically.

When starting from COBOL, this means you will never get a java Date/Timestamp/Calendar property, even if the corresponding COBOL data item is marked with a DATE FORMAT. Date semantics are lost in translation...

When starting from Java though, chances are that some property is a Date/Timestamp/Calendar. Actually Date/Calendar, because with Timestamp you would get "error: java.sql.Timestamp does not have a no-arg default constructor" from JAXB.

LegStar maps Java Date/Calendar properties to a COBOL PIC X(32).

At runtime, the PIC X(32) content is assumed to follow the form: "yyyy-mm-dd hh:mm:ss.fffffffff" known as the JDBC timestamp escape format.

This is rudimentary but following this conversation, the latest LegStar has introduced a new annotation, inspired from Patrick's comment: @CobolJavaTypeAdapter(value = SomeClass.class) where SomeClass is code that a developer implements. (Here is a sample).

An extension mechanism is probably the best way to handle COBOL to Java date binding.

Sunday, April 10, 2011

Migrating off the CTG?

CTG, the CICS Transaction Gateway, is an IBM product that has been around for a long time and is largely deployed in mainframe shops.

CTG is usually used from a Java client to make outbound, synchronous, calls to a CICS program. In this case, the API offered to Java clients is known as ECI (External Call Interface ). Because ECI is how most users access the CTG some of them refer to the CTG itself as ECI.

CTG is a separate product from CICS itself. Some people confuse both (probably because the names are so close: CICS Transaction Server and CICS Transaction Gateway).

CTG runs in a Java VM that could sit on z/OS (in the Unix System Services environment) but most frequently runs off a distributed server. It is also frequently used in conjunction with WebSphere and as such, can be thought of as middleware between WebSphere and CICS.

CTG’s major strength is transaction support and J2EE integration. It supports the JCA connector architecture and provides 2-phase commit and XA support.

Although CTG might sound like the definitive solution for CICS/java integration, a number of users are considering moving away from it.

I can see 3 reasons why this is happening:

  • The emergence of integration standards such as Web Services (and the slow erosion of older standards such as J2EE/JCA)
  • Loose coupling as a preferred architecture pattern over tight coupling
  • The Open Source revolution which drives more and more enterprises to consider Open Source software as a valid alternative to closed products

An uncomfortable position within IBM

Today, CTG is competing internally with other IBM integration features particularly when it comes to SOA. You can of course create Web Services on top of JCA but there are more efficient alternatives within IBM.

CICS itself has built-in support for SOAP Web Services. This feature, known as CICS Web Services, offers programmers a standard way to call CICS programs without the need for CTG.

WebSphere, when it is installed on z/OS, also now offers CICS integration directly (an option known as OLA for Optimized Local Adapters).

WebSphere MQ can also be used to support Web Services.

CTG seems to have less and less room within the IBM offering.

Not a serious contender for loose coupling

CTG has support for asynchronous calls but it is hard to justify the heavyweight 2-phase commit support in such a setting.

Asynchronous calls can’t support 2-phase commit and therefore could run with a much more lightweight infrastructure.

Furthermore, IBM has WebSphere MQ as its preferred asynchronous programming interface so it is hard to see how CTG could be justified to support a loosely coupled architecture.

Not Open Source

CTG is not Open Source and is a complex black box that users struggle to operate.

It is hard to tell how much this costs companies but I have met with very frustrated customers.

CTG is not free of charge but it is often bundled with WebSphere, CICS and other products and it is difficult to isolate its cost from the rest.

The true cost becomes apparent though for customers migrating off WebSphere because the bundle offer does not apply anymore.

Poor and confusing tooling

So far we have discussed the runtime aspects of CTG but how about the development time tooling? How do you map the target COBOL data structures to java beans?

Here there is some confusion. This mainly stems from IBM changing names and branding several times over the last few years.

The COBOL mapping tools are usually an option buried deep into a much larger developer product:

  • Enterprise Application Builder (EAB) within VisualAge for Java (No longer supported)
  • J2C within RAD (Rational Application Developer for WebSphere Software which used to be named WSAD for WebSphere Application Developer)
  • J2C(?) within RDz (Rational Developer for z/OS which seems to have been recently renamed Rational Developer for zEnterprise)

I am not sure about J2C being part of RDz. RDz seems to cover CICS Web Services with tooling that looks quite different from J2C. I know CICS had a “Web Service Assistant” a sort of command line utility to map COBOL to XML. RDz might have some GUI on top of that.

Although these tools are Eclipse based, they are not open source. There is usually a per seat license to be purchased.

There are several issues with J2C:

Users complain that the java beans mapping COBOL structures that J2C produces are awkward, the morphology does not always match the original COBOL structure (flattening), property names derived from COBOL data items are unfriendly (use of double underscores), arrays are turned to java arrays instead of more flexible java.util.List, no support for REDEFINES, …

J2C also produces java classes that intermingle java to COBOL transformation with remote execution of CICS programs. This tight coupling of language translation features with RPC mechanism was customary 10 years ago but has proven quite limited since then. This is because integration today is a lot more than calling CICS programs. Mainframe data can originate from files, messages, non IBM transaction monitors, etc… Also data might have to be processed asynchronously, as part of a flow (BPEL) or even in batch which was completely missed by the JCA specs.

If LegStar was architected on the same principles, it would be impossible to support ESB’s or ETL’s for instance.

LegStar might help

To summarize the CTG situation today, it has relatively limited tooling, is tightly related to JCA and has a weak position within the IBM offering.

For users considering Open Source and loosely coupled alternatives to CTG, LegStar could come handy.

At LegSem, with help from some of our pioneer users, we are building a service offering to help customers move away from RAD/CTG.

Our first step is to develop migration tools that can exploit meta data produced by tools such as RAD.

We are also working on an ECI transport for users who want to adopt LegStar COBOL Transformers (to replace the J2C beans) but would rather stick to CTG to get to their mainframe.

If you are interested, drop us a message at admin (at) legsem (dot) com or use this form.

Saturday, March 26, 2011

When it comes to Mainframes, nothing is simple

The IEEE Software review has published an article by Belgian researchers who made an attempt at re-engineering a mainframe application using automated tooling they knew worked in other environments.

Although the article mentions important lessons learned, it proved once more that it is extremely difficult to reconstruct mainframe applications knowledge automatically from static code analysis.

They typically ran into an issue, I for one, encountered several times, where an apparently autonomous set of COBOL programs actually calls some Assembler magic that turns control to other hidden programs only identified at runtime. There is little you can't do on a mainframe using Assembler. One thing you can do, is load executables dynamically.

During the 80's, the heydays of Mainframe programming, every IT shop had one or more Assembler guru's. With much looser budget controls than today, it was possible to spend considerable time developing in-house frameworks, optimizing performances and so forth. Not to say that this only had negative effects, these optimized assembler routines probably saved large amounts of money by reducing CPU consumption, a major parameter on IBM bills.

Most code analysis tools are COBOL centric. One reason for that is that COBOL is not that hard to parse. To my knowledge, there are no automatic code analysis tools for MVS Assembler (DataTek has an impressive tool for Assembler to COBOL but it usually requires some level of human assistance). That's probably because the level of complexity such a tool would require would be several levels of magnitude higher than COBOL.

For a typical Mainframe shop, the volume of MVS Assembler programs is much smaller than COBOL. That might explain why vendors would have a hard time cost justifying writing a very complex Assembler code analysis tool.

So the result of such a situation is that COBOL code analysis tools fail on multilanguage boundaries. Of course there are other multilanguage boundaries on Mainframes for instance: COBOL to BMS or MFS macros, COBOL to JCL, COBOL to SQL, COBOL to CICS, COBOL to IMS not to mention all third party tools one can find on Mainframes. One thing for sure, I have never seen a pure COBOL application.

The problem is that without reliable code analysis tools, you can't reconstruct knowledge in a bottom up approach. What you end up doing is taking the top down approach, by chasing the last application expert on site, hoping that he hasn't retired yet.

The complexity revealed by this IEEE article explains a good part of the Mainframe applications longevity. I know IBM prefers the reliability, availability, security explanation. But I know many IT shops who would have happily migrated off their mainframes if it was easy.

LegStar is also affected by this complexity of course. I often have a hard time explaining to Java developers why the Java side of LegStar works so easily while the Mainframe side, which has much less code in it, is often much harder to get to work properly...

Monday, February 21, 2011

COBOL in a flat world

We just released a version of LegStar for Talend Open Studio. Talend is a well known ETL tool that also expands to the MDM and ESB spaces.

This is the second ETL tool we interface with. The first one was Pentaho Data Integration a.k.a Kettle for which we released legstar-pdi back in November 2010.

With this experiences behind us it becomes clear that ETL tools are row centric. This means that data flowing from one step to another needs to be modeled as a flat, fixed, list of fields. This exactly maps to a classical database row. Not surprising as ultimately, an ETL, must feed database tables somewhere.

When the starting point is COBOL though, where data structures tend to be very hierarchical, fitting in a flat model is challenging. Here are some considerations to keep in mind.

Name conflicts:

Flattening a simple hierarchy such as:

is relatively easy, it intuitively maps to: [ItemB:String, ItemD:Short].

Now what happens for this one (perfectly valid in COBOL):

In a flat model, field names must be unique so [ItemB:String, ItemB:Short] does not work. You need to disambiguate names and produce something like [ItemB:String, ItemC_ItemB:Short].

Arrays:

Assuming a COBOL data item such as:

we have an new issue since arrays are usually not handled by database schemas.

Now the solution is to expand each item into a different field. Something like [ItemA_0:String, ItemA_1:String, ItemA_2:String, ItemA_3:String, ItemA_4:String].

This is quite wasteful but no real alternatives here.

In COBOL, the DEPENDING ON clause is often used to limit array sizes and processing time. Here we hit another limitation of the flat models, they are usually fixed in the sense that all fields declared must be present in each row.

Filling unused fields with null values is a common technique used to tell downstream steps that fields have no value.

Redefines:

The COBOL REDEFINES clause, a cousin of the C union, is another interesting challenge. Since the flat model is fixed it can't be dynamically changed depending on the REDEFINES alternatives.

The best solution here is to manage a different set of flat fields for each combination of alternatives. This can be demonstrated with a simple example:

Here the COM-SELECT field value determines if COM-DETAIL1 or COM-DETAIL2 is present in the COBOL data.

This would result in 2 field sets (schemas in ETL parlance):

  • set1: [ComSelect:Short, ComName:String]
  • set2: [ComSelect:Short, ComAmount:Decimal]

The number of field sets you need to contemplate depends on the number of alternatives in each REDEFINE group (an ITEM followed by a set of items redefining its location). Furthermore, if a COBOL structure contains multiple such REDEFINE groups, than all combinations are possible. So lets say a COBOL structure has a first group of 3 alternatives and another of 2 alternatives, there are 6 (3 x 2) possible field sets.

Fortunately, the number of REDEFINE groups and the number of alternatives in each groups are usually small.

What this all means is that COBOL structures need somehow to be shoehorned to fit the ETL data model. This is an important difference with ESBs where the data model is usually a much more versatile Java object.

Tuesday, February 8, 2011

See you at Maven central

Maven central has long been restricted to a few very large players such as the Apache foundation.

This has changed recently thanks to a new free offering by Sonatype for OSS projects.

LegStar has been using Maven from the very beginning and more and more users rely on the availability of artifacts in the LegStar Maven repository.

This proprietary repository is not very secure and not always available. Now that it is possible to push artifacts to Maven central I have been busy figuring out how to take advantage of this.

The major issue is that Maven central's policy is to host artifacts only if their dependencies are also in central. And of course LegStar has dependencies on oss libraries which are not in central

One of the bad players is the Eclipse foundation. So far, no complete sets of Eclipse bundles are available as Maven artifacts. There are lengthy discussions going on but no results yet.

Besides Eclipse the only other annoying dependency we have in LegStar is Websphere MQ. Of course this one being proprietary, it will never make it to central.

In order to bootstrap the process of moving to Maven central, I have started to split the modules into separate release units. the first, very limited, release is now in Maven central. You can see the result at this location by entering the legstar keyword.

It feels good to be part of the big league

Thursday, January 6, 2011

Batch integration with CICS, ETL integration with ESB

On mainframes, integration between batch and online processes is not simple. In an IBM CICS environment for instance, if files and databases need to be shared between batch and CICS (and they most always do), you have to deal with a number of issues such as:

  • Batch processes might update numerous records. It is usually inefficient to commit those changes after each record change. Large number of uncommitted changes means large numbers of locks which in turn affect online activity by slowing down response times or even leading to time out errors.
  • Batch processes often deal with files in addition to databases. The most widely used technique to restart a batch after a failure is to backup these files before the batch is started and restore them in case of failure so that the batch can be restarted. Any online activity that dealt with the same files between the batch start and failure worked on uncommitted data.

To avoid such issues, many mainframe shops initially segregated batch and online activities in different time frames. Typically CICS systems were brought down in the evening while batch processes were running and restarted in the morning.

Because of this strong separation between online and batch activity, very little integration between batch and CICS systems was developed. There was some degree of code reuse with COBOL copybooks but you would never see binary reuse (a batch program calling a CICS program for instance). Actually this was not even possible before IBM introduced the EXCI technology.

The mainframe nightly batch window rapidly came under pressure though. As mainframes grew larger and merged with one another, they started serving populations across many time zones. It is not uncommon that users are all over the world. This forced mainframe shops to rearchitect their batch processes and lead IBM to develop new technologies such as EXCI and VSAM Record Level Sharing.

At the same time, the need for business logic reuse between batch and CICS became more important because systems became more complex. Mainframe developers resorted to database triggers, stored procedures or WebSphere MQ triggers, probably beyond the original intent of such technologies, because there was no other way of sharing logic at the binary level.

I am seeing some similarity with the ETL versus ESB situation in the Java world. These systems do very little to integrate with one another today.

By nature, ETL is similar to batch in the sense that it deals with large amounts of records and multiple file systems and databases. ESB is closer to online as it deals with smaller transactional events.

Both ETL and ESB products claim to be transformation engines though and indeed the term "Transformation" is widely used in both type of products documentation. So you might wonder why it is almost impossible to reuse a transformation written for an ETL in an ESB.

If IBM was forced to introduce EXCI for Batch to CICS communication, I wouldn't be surprised if users forced ETL and ESB vendors to integrate with one another more closely.

I don't mean that ETL and ESB technologies need to be tightly integrated, after all they do different jobs, but yet it would be nice if some level of transformation reusability can be achieved.

Monday, December 13, 2010

Mapping COBOL level 88 to Java

Once in a while comes the issue of mapping COBOL data items with associated level 88 condition values to Java. Since this is a complex question, I thought it deserves an entry of its own.

This is an example of simple COBOL level 88 data item descriptions.

     01  MY-ITEM PIC S9(4) COMP.
         88 WRONG-DATA VALUE -1.
         88 NULL-DATA VALUE 0.

First notice that the 88 levels are associated with an actual data item (MY-ITEM). Level 88 items do not occupy any space in memory themselves.

The way they are used is that somewhere in the code, you can state:

         IF WRONG-DATA THEN ...

The condition will be true if, and only if, MY-ITEM contains -1.

Such code is more readable than the equivalent:

         IF MY-ITEM = -1 THEN ...

So this is what it's all about, an improvement to the readability of your COBOL code.

So how can such a thing map to Java?

First of all, it is easy to confuse COBOL Level 88 with java enums . After all, enums are also a readibility improvement feature and they can be used to replace a value with a meaningful label.

It is tempting to map MY-ITEM with:

    enum MyItem {
        WRONG_DATA(-1), NULL_DATA(0);
        private MyItem(int value) {
            _value = value;
        }

        private int _value;

        final int getValue() {
            return _value;
        }
    };

But there is a fundamental issue in doing so: Enums are actually restrictions. This means only the values that are enumerated (-1 and 0 in our case) are possible.

In the case of COBOL level 88, there are no restrictions on actual values. This means MY-ITEM can contain value 2, which is not described by any level 88.

Furthermore, level 88 are not necessarily atomic values. They can be ranges:

       01  ANOTHER-ITEM PIC S9(4) COMP.
           88 CUST-DATA VALUE 9 THRU 975.

Or even list of values:

       01  YET-ANOTHER-ITEM PIC S9(4) COMP.
           88 VALID-DATA VALUE 2, 7, 15, 245.

By now it should be clear why COBOL level 88 does not automatically map to a java variable of some sort with LegStar.

The legstar-cob2xsd module actually offers an option to map level 88 to XML Schema restrictions in the unlikely case where you are sure the COBOL variable never contains any value outside the enumerated values and enumerated values are atomic. But past that, there is no real support for level 88.

Monday, October 25, 2010

LegStar for Pentaho Data Integration (Kettle)

I have spent the last few weeks digging into open source ETL tools.

The 3 most quoted products are:

It turns out Clover is only partially open source. The GUI is proprietary. So I spent more time on PDI and Talend.

PDI is the oldest product and, perhaps as a consequence, has the largest community. You can get a sense of that by comparing the Ohloh page for PDI to the Ohloh page for Talend.

But if you compare new threads per day on the PDI forum to that of the Talend forum, you can see that Talend is doing good too.

I decided to try out PDI first and developed a proof of concept implementation of LegStar for PDI

You can see the result on Google code as usual.

I have to say that I am very impressed with PDI, a product originally called Kettle and developed by Matt Casters.

PDI comes with a framework for people to develop additional plugins. For those who are interested, there is an excellent blog entry by Slawomir Chodnicki to get started.

I was able to reuse part of the PDI internal test framework to automate testing of my plugin. I have automated unit tests and integration tests

It is also quite easy to deploy new plugins in PDI. It is a matter of packaging the plugin as a jar, and dropping it to a particular location.

As usual, it is extremely helpful that the product is open source. In particular, I could easily debug my plugin in Eclipse, stepping through PDI code as well as my code.

My only regrets with PDI is that there is little Maven support and that the code is often not commented. This being said, that did not prevent me from using Maven for all lifecycle phases of my plugin and was able to find my way into the PDI code which is usually readable enough.

PDI also has support for parallel processing and clustering that I did not explore yet. I am looking forward to playing with these features next.

Tuesday, October 12, 2010

VSAM to CSV using LegStar

I was wondering how hard it would be to translate a z/OS VSAM file content to a CSV file using LegStar.

So I started with a very trivial case:

CICS comes with a sample VSAM KSDS file called FILEA (see hlq.CICS.SDFHINST(DFHDEFDS)). FILEA is an 80 characters, fixed sized record file.

The records in FILEA are described by a COBOL copybook called DFH0CFIL (in hlq.CICS.SDFHSAMP). The content of DFH0CFIL looks like this:

My first step was to extract the VSAM file content to a sequential file using a JCL like this one on z/OS:

I then downloaded the sequential file to my workstation using regular FTP in binary mode:

On the java side now, I created a LegStar Transformer from the DFH0CFIL COBOL copybook. This results in a FilerecTransformers class.

The following code snippet, is what I needed to write to get my CSV file:

Of course this is a very contrived example, both because the VSAM file is fixed size and the record data is only made of characters.

In a more realistic case, the records will contain all sorts of numerics: compressed, zoned or edited and chances are that some redefines and arrays will complexify the setting. This is where LegStar should really become useful.

There are other interesting questions when you get to that point:

  • Assuming you need to regularly extract the content of a file, how do you automate a distributed process like this one?
  • How would you do that reliably; meaning you don't process the same data twice or miss part of it?

ETL (Extract Transfer Load) tools are typically focused on these issues. I became quite curious about them recently.

Sunday, August 22, 2010

Mule 3.0 is here

Mule ESB is undergoing its next mutation with the upcoming version 3.0. Mule ESB has always been one of the easiest ESB's to setup and work with. The intelligent combination of Spring and other open source technologies gives outstanding results.

An example of a unique feature, is the JUnit-based framework that comes with Mule. It is enormously convenient to be able to create a complete test case and run the entire Mule server from a single JUnit class! When I work with other ESB's I really miss this one.

Another example is the Spring-based configuration system. It is difficult to grasp all the power that you get from this. By contrast, ESB's that use proprietary DSL's for their configurations are limited to the features they build. With Spring, you can pretty much inject anything into you Mule configuration and reference that from anywhere else in the configuration.

A third example is the leveraging of Maven in various areas. Build management of course but also providing partners with Maven archetypes to help them bootstrap their transports and modules developments. That's so much better than documentation and samples.

These features alone could explain why Mule has become so popular.

Inevitably though, as larger companies and organizations started using it, demand for entreprise-class features has increased. Message flows that users needed to describe to Mule have become more complex. The limitations of the "endpoint/transformer/service" buiding blocs became apparent (Behaviors such as "Remote Sync" are still pretty obscure to me).

Mule 3.0 is introducing a new "flow" concept that should allow description of complete pipelines. I haven't played much with that yet but really looking forward to.

When you deploy large number of services in a single server instance, the class loading mechanism comes under stress. Typical problems are the need to share libraries and multiple versions of libraries having to coexist.

You don't solve problems like these without some major overhaul. Mule 3.0 is introducing a completely new deployment mechanism with features such as hot deployment.

Because there are major architectural changes, Mule 3.0 is not backward compatible. This might sound like an heresy to Mainframe people but remember how IBM CICS went from macro-level API to command-level APIs.

The reality is that you can't deal with core architectural issues without fundamental refactoring.

The good news is that the migration process is not that painful and is well documented. It took me only a few days of work to migrate the LegStar for Mule transport.

In the mainframe world, version 3 was usually the most complete and stable version. Looking at Mule 3.0 feature set, it could very well be the case for Mule too.