Javarec Ant Tasks

Introduction

The javarec tasks automate the generation of Java Record Framework (JRF) classes from Cobol copy books.

The JRF is a framework developed by IBM to handle the conversion of native Java types to a format acceptable by legacy transaction managers such as CICS and IMS. The JRF libraries are currently available within IBM's enterprise edition of VisualAge for Java 3.0 - 4.0.

Enterprise Access Builder (EAB) is the tool within VisualAge for Java (VAJ) that is used to create and edit record classes. While primarily a GUI tool, EAB also provides a command line interface for some record creation functionality. It is these command line interfaces that are invoked by the javarec Ant tasks.

Most records will initially be generated using the EAB GUI. But once the code is running successfully, subsequent generation of record classes due to changes in Cobol copy books can be time consuming and monotonous. It is in this scenario that the javarec tasks are expected to provide value.

Record generation is broken into two steps: record type generation and record generation. A record type class consists of metadata for use by the record class and acts as a factory for record objects. The record class is generated using a different EAB tool and requires, among other things, the record type class as input.

There are two javarec tasks corresponding to these two steps: generate-record-type and generate-record.

Set Up

You're probably thinking that if an Ant task document needs a separate section just to describe the set-up, it's likely harder than it needs to be. You're probably right. But here it goes.

  1. Classpath - The Ant tasks themselves and the programs they invoke use libraries provided by EAB. There are three directories that need to be in Ant's classpath for these Ant tasks to work. They are

    1. (vajroot)/eab/runtime30
    2. (vajroot)/ide/tools/com-ibm-ivj-eab-record
    3. (vajroot)/ide/project_resources/IBM IDE Utility class libraires

    The last entry contains spaces which can be problematic in some environments. If this is so in yours, copy its contents to a different directory without spaces in the name. Do not change the original directory name. Otherwise VAJ won't be able to find these resources.

    The Ant startup script will have to modified to include these entries in the classpath of the Ant tasks themselves. (Since they are not JAR files, it is not simply a matter of copying them to (antroot)/lib. But one could JAR them up to avoid changing the Ant startup script.) The following snipet from ant.bat illustrates how this could be done. It uses the Windows batch example rather than the Unix shell example because most VAJ Enterprise installations run on Windows. The added portions are in bold.

     1 :checkJava
     2 rem Added for Java Record Ant tasks.
     3 set RUNTIME30=e:\ibm\vaj\eab\runtime30
     4 set RECLIB=e:\ibm\vaj\ide\tools\com-ibm-ivj-eab-record
     5 set IBMUTIL=e:\ibm\vaj\ide\project_resources\ibmutillib
     6 set EAB_CP=%RUNTIME30%;%RECLIB%;%IBMUTIL%
     7 
     8 set _JAVACMD=%JAVACMD%
     9 set LOCALCLASSPATH=%EAB_CP%;%CLASSPATH%
    10 for %%i in ("%ANT_HOME%\lib\*.jar") do call "%ANT_HOME%\bin\lcp.bat" %%i
    
    Lines 2 - 7 have been added; line 9 has been modified. In the above example, the directory name "IBM IDE Utility class libaries" has been copied to "ibmutillib".

  2. Task Library - place jrectask.jar inside Ant's lib directory. This JAR contains the bytecode for the task.

  3. Task Definitions - The following task definition statements must be placed within the build script to register them with Ant.

    <taskdef name="generate-record-type" 
             classname="org.apache.tools.ant.taskdefs.optional.javarec.RecordTypeTask"/>
    <taskdef name="generate-record" 
             classname="org.apache.tools.ant.taskdefs.optional.javarec.RecordTask"/>
    

Caveats

As if the set-up wasn't enough of a deterent, there are a few situations to avoid.

  1. For some reason, calling the generate-record task from another build file (i.e. using the ant task) fails. I suspect it has to do with the environment carrying over, but I haven't found the problem yet. Using antcall should work fine though.

    It is for this reason that the handling of the return code for the generate-record unit test is ignored. Since the Ant unit test system involves calling ant tasks in external build files, the generate-record test doesn't have a chance.

  2. The EAB tasks themselves don't create new directories for the generated source code. You need to make sure inside your target to create the anticipated directory structure (reflecting the package structure) is created with the mkdir task. The examples reflect this. This will be fixed in a future release.


Generate Record Type

Description

Generate a Cobol record type from a Cobol copy book. This task calls EAB's CobolImport command to generate a record type class extending com.ibm.ivj.eab.record.cobol.CobolDynamicRecordType.

Parameters

AttributeDescriptionRequired
targetDir The directory into which record type source will be generated. Yes
pkgName The package in which to place the record type class. Yes
className The name of the record type class. Yes
ccpfile The name of the file containing the Cobol copy book. Yes
commarea The names of the definition records for the COMMAREAs contained in the Cobol copy book file. Each name in the string is separated by a colon. The default is DFHCOMMAREA. No
nocics Set nocics to true if CICS is not being used (e.g. if the record is being generated for an IMS transaction). Otherwise it is assumed that the record type is intended for a CICS transaction, which is the default behavior. No
genold If set to true, use a Java double to represent decimals. Otherwise use Java java.math.BigDecimal. The default is false. No

Example

In the following example, the copy book is stored in a file named CustSearch.ccp. The record type class will be named CustSearchRecordType and be placed in the file src/com/yourfirm/record/CustSearchRecordType.

<mkdir dir="src/com/yourfirm/record"/>
<generated-record-type targetDir="src"
                       pkgName="com.yourfirm.record"
                       className="CustSearchRecordType"
                       ccpfile="CustSearch.ccp"/>
The creation of the directory for CustSearchRecordType beforehand is necessary for the EAB command line tool to complete successfully. A future version of this task will perform this step automatically.

Generate Record

Description

Generate a record class from a record type class. This Ant task calls the Generator command to create a Record class from a RecordType class. There are no nested tags for this task, only attributes.

Parameters

AttributeDescriptionRequired
targetDir The directory into which record source will be generated. Yes
pkgName The package in which to place the record class. Yes
className The name of the record class. Yes
outputType
  • 0 - Custom Record (default)
  • 1 - Dynamic Record
No
layout The access mode of the record.
  • 0 - Direct Access (default)
  • 1 - Hierarchical Access
  • 2 - Direct access with inner classes
  • 3 - Hierachical access with inner classes
No
style
  • 0 - Notification Support
  • 1 - No Notification Support (default)
No
namingScheme Only used when layout = "2" or "3"
  • 0 - Long names (for VAJ 2.0 compatibility)
  • 1 - Short names (default)
No
j2ee Generate J2EE style record (implements javax.resource.cci.Streamable). Default = "false". No
genPrimArrTypes Generate accessors that return pimitive data types. If set to false, object wrappers such as Integer are returned instead of int. Default = "false". No
recAttrType Record Attribute Type. Default = com.ibm.ivj.eab.record.cobol.CobolRecordAttributes. No

The recAttrType attribute defaults to CobolRecordAttributes to mirror the behavior of the Enterprise Access Builder command line tool on which this Ant task is based. But you will almost always want to specify this attribute to be org.apache.tools.ant.taskdefs.optional.javarec.MVSRecordAttributes. That's because the EAB record generator always assumes the target platform is NT. Since most Cobol programs run on MVS, this assumption will usually cause the wrong record attributes to be generated. MVSRecordAttributes was written to ignore its constructor's input parameters (which is how the NT values get in there) and override them with MVS values.

Example

In the following example, the target depends on the compilation of the record type class. To be safe, the source directory is created although this was mostly likely already done in the record type creation step. Many of the attributes are similar to those of the generate-record-type task. The classpath attribute specifies the location of the compiled record type.

<target name="rec" depends="compile-rec-type">
   <mkdir dir="src/com/bofa/record"/>
   <generate-record targetDir="src"
                    pkgName="${pkgName}"
                    className="${rec}"
                    recType="${pkgName}.${recType}"
                    classpathRef="classpath.rec-type"
                    recAttrType="org.apache.tools.ant.taskdefs.optional.javarec.MVSRecordAttributes"
                    j2ee="true"/>
   <echo>Record generation complete</echo>
</target>

Complete Example

Generating and compiling the record type and record is generally done with the following steps.

  1. Generate the record type from the Cobol copy book
  2. Compile the record type
  3. Use the compiled record type to generate a record class
  4. Compile the record class

For this example, the Cobol copy book is taken from one of the IMS samples provided with VAJ. Below are the contents of adder.ccp.

       identification division.
       program-id. ADDER.
       environment division.
       data division.
       working-storage section.
       LINKAGE SECTION.
       01  DFHCOMMAREA.
           02  op1    PIC S99999 DISPLAY.
           02  op2    PIC S99999 DISPLAY.
           02  res    PIC S99999 DISPLAY.
           02  keyNum PIC X(5) DISPLAY.
       procedure division.
       start-para.
           add op1 to op2 giving res.
           EXEC CICS RETURN
           END-EXEC.

Next are the contents of the build script, build.xml.

<?xml version="1.0"?>

<project name="TestTask" default="main" basedir=".">

<taskdef name="generate-record-type" 
         classname="org.apache.tools.ant.taskdefs.optional.javarec.RecordTypeTask"/>
<taskdef name="generate-record" 
         classname="org.apache.tools.ant.taskdefs.optional.javarec.RecordTask"/>
         

<property name="pkgName"  value="com.yourfirm.record"/>
<property name="recType"  value="AdderRecordType"/>
<property name="rec"      value="AdderRecord"/>

<path id="classpath.rec-type">
   <pathelement location="classes"/>
</path>

<target name="init">
   <tstamp/>
</target>

<target name="rec-type" depends="init">
   <mkdir dir="src/com/yourfirm/record"/>
   <generate-record-type targetDir="src"
                         pkgName="${pkgName}"
                         className="${recType}"
                         ccpfile="Adder.ccp"/>
   <echo>Record Type generation complete</echo>
</target>

<target name="compile-rec-type" depends="rec-type">
   <mkdir dir="classes"/>
   <javac srcdir="src" destdir="classes"/>
</target>

<target name="rec" depends="compile-rec-type">
   <mkdir dir="src/com/yourfirm/record"/>
   <generate-record targetDir="src"
                    pkgName="${pkgName}"
                    className="${rec}"
                    recType="${pkgName}.${recType}"
                    classpathRef="classpath.rec-type"
                    recAttrType="org.apache.tools.ant.taskdefs.optional.javarec.MVSRecordAttributes"
                    j2ee="false"/>
   <echo>Record generation complete</echo>
</target>

<target name="compile-rec" depends="rec">
   <mkdir dir="classes"/>
   <javac srcdir="src" destdir="classes"/>
</target>

<target name="clean">
   <delete dir="src"/>
   <delete dir="classes"/>
</target>

</project>