Java wrapper classes

When you request that a program part be generated as a Java™ wrapper, EGL produces a wrapper class for each of the following:

Later descriptions refer to the wrapper classes for a given program as the program wrapper class, the parameter wrapper classes, the dynamic array wrapper classes, and the substructured-field-array wrapper classes.

EGL generates a BeanInfo class for each parameter wrapper class, dynamic array wrapper class, or substructured-field-array wrapper class. The BeanInfo class allows the related wrapper class to be used as a Java-compliant Java bean. You probably will not interact with the BeanInfo class.

When you generate a wrapper, the parameter list of the called program cannot include parameters of type BLOB, CLOB, Dictionary, ArrayDictionary, or non-structured record.

Overview of how to use the wrapper classes

To use the wrapper classes to communicate with a program generated with VisualAge® Generator or EGL, do as follows in the native Java program:
  • Optionally, instantiate a class of type PowerServer or SharedResourcePowerServer to provide middleware services such as converting data between native Java code and a generated program:
    import com.ibm.javart.JavartException;
    import com.ibm.javart.calls.*;
    
    
      public class MyNativeClass 
      {
        /* declare a variable for middleware */
        PowerServer powerServer = null;
        powerServer = new PowerServerImpl();
      }

    The capabilities provided by a SharedResourcePowerServer object are more extensive than those provided by a PowerServer object. For details on the former, see "SharedResourcePowerServer."

    If you do not specify a PowerServer object, the EGL runtime provides one for you.

  • Instantiate a program wrapper class to do as follows:
    • Allocate data structures, including dynamic arrays, if any
    • Provide access to methods that in turn access the generated program
    The call to the constructor can include a middleware object:
      // use of a PowerServer object is optional
      myProgram = new MyprogramWrapper(PowerServer); 

    You can provide a PowerServer object when invoking the wrapper object or by calling the wrapper-object method setPowerServer.

  • Declare variables that are based on the parameter wrapper classes:
      Mypart  myParm = myProgram.getMyParm();
      Mypart2 myParm2 = myProgram.getMyParm2(); 
    If your program has parameters that are dynamic arrays, declare additional variables that are each based on a dynamic array wrapper class:
      myRecArrayVar myParm3 = myProgram.getMyParm3();

    For details on interacting with dynamic arrays, see Dynamic array wrapper classes.

  • In most cases (as in the previous step), use the parameter variables to reference and change memory that was allocated in the program wrapper object. Here is another example, which uses a Java record (in this case, named inputValue) to populate an EGL main program's input record (in this case, named MyRecord):
      myProgram.setMyRecord(inputValue);
  • Set a userid and password, but only in these cases:
    • The Java wrapper accesses an iSeries-based program by way of the iSeries® Toolbox for Java; or
    • The generated program runs on a CICS® for z/OS® region that authenticates remote access.

    The userid and password are not used for database access.

    You set and review the userid and password by using the callOptions variable of the program object, as in this example:
      myProgram.callOptions.setUserID("myID");
      myProgram.callOptions.setPassword("myWord");
      myUserID = myProgram.callOptions.getUserID();
      myPassword = myProgram.callOptions.getPassword();
  • Consider using the following capabilities, which are available only if the invoked program is an EGL main program:
    • Specify a database connection for the invoked program to use, as in the following example:
      // Connect to the database
      Connection con = DriverManager.getConnection( "jdbc:db2://host:50000/db", "user", "pwd" );
      
      // Turn off auto-commit mode to enable transactions
      con.setAutoCommit( false );
      
      // Create the wrapper and give it the connection
      MWrapper mw = new MWrapper();
      mw.addConnection( con, "con1" );
      
      // Run the program
      mw.execute();
      
      // Commit the work and clean up
      mw.getPowerServer().commit();
      mw.getPowerServer().close();
      con.close();
    • Access the return value (the value of sysVar.returnCode) as in the following example:
        int returnValue = myProgram.returnCode();
  • Access the generated program; for example, by invoking the execute method of the program wrapper object:
      myProgram.execute();  
    Another alternative is to use the call method, in which case you provide arguments in the method invocation. Here is a second example use of execute:
    myProgram.setParm1( 2 );
    myProgram.setParm2( "sell" );
    myProgram.execute();
    Here is an equivalent invocation of the call method:
    myProgram.call( 2, "sell" );
  • Use the middleware object to establish database transaction control, but only in the following situation:
    • The program wrapper object either is accessing a generated program on CICS for z/OS or is accessing an iSeries-based COBOL program by way of the IBM® Toolbox for Java. In the latter case, the value of remoteComType for the call is JAVA400 or JAVA400J2C.
    • In the linkage options part used to generate the wrapper classes, you specified that the database unit of work is under client (in this case, wrapper) control; for details, see the reference to luwControl in callLink element.
    If the database unit of work is under client control, processing includes use of commit and rollback methods of the middleware object:
      powerServer.commit();
      powerServer.rollBack();

    When using a single PowerServer object, the EGL runtime might commit a change made with an initial connection, but might encounter a problem and fail when committing a change made with a second connection. After a failure, your data is left in an inconsistent state because the commit is a one-phase commit, rather than a two-phase commit such that all resources are committed or none of them are.

  • Close the middleware object. If you did not explicitly declare it, use the wrapper-specific method getPowerServer().close(), as shown earlier.

    You close the middleware object to end the EGL run unit and to allow for garbage collection:

    if ( powerServer != null )
    {
      try
      {
        powerServer.close();
        powerServer = null;
      }
      catch ( JavartException error )
      {
        System.out.println( "Error closing middleware" 
          + error.getMessage() );
        System.exit( 8 );
      }
    }

The program wrapper class

The program wrapper class includes a private instance variable for each parameter in the generated program. If the parameter is a record or form, the variable refers to an instance of the related parameter wrapper class. If the parameter is based on a DataItem part, the variable has a primitive Java type.

A table at the end of this help page describes the conversions between EGL and Java types.

A program wrapper object includes the following public methods:
  • get and set methods for each parameter, where the format of the name is as follows:
      purposeParmname()
    purpose
    The word get or set
    Parmname
    Name of the data item, record, or form; the first letter is upper case, and aspects of the other letters are determined by the naming convention described in Naming conventions for Java wrapper classes
  • An execute method for calling the program; you use this method if the data that will be passed as arguments on the call is in the memory allocated for the program wrapper object
Instead of assigning values to the instance variables, you can do as follows:
  • Allocate memory for parameter wrapper objects, dynamic array wrapper objects, and primitive types
  • Assign values to the memory you allocated
  • Pass those values to the program by invoking the call method of the program wrapper object rather than the execute method
The program wrapper object also includes the callOptions variable, which has the following purposes:
  • If you generated the Java wrapper so that linkage options for the call are set at generation time, the callOptions variable contains the linkage information. For details on when the linkage options are set, see remoteBind in callLink element.
  • If you generated the Java wrapper so that linkage options for the call are set at run time, the callOptions variable contains the name of the linkage properties file. The file name is LO.properties, where LO is the name of the linkage options part used for generation.
  • In either case, the callOptions variable provides the following methods for setting or getting a userid and password:
      setPassword(passWord)
      setUserid(userid) 
      getPassword()
      getUserid()
    The userid and password are used when you set the remoteComType property of the callLink element to one of the following values:
    • CICSECI
    • CICSJ2C
    • JAVA400
    • JAVA400J2C
    Password information can also be stored in the csouidpwd.properties file. See Providing a userid and password for remote calls.
The following methods are available if an EGL main program is being invoked:
  • returnCode() returns the int value of sysVar.returnCode.
  • addConnection() specifies a JDBC Connection object for use by the EGL main program. Each invocation of addConnection() assigns the connection as the current connection for the run unit.

    The run unit can use previously specified connections, if any. However, if the run unit closes a given connection, the connection is released and cannot be reopened. That last restriction is true whether the close occurs in the EGL program or (as shown in an earlier section) by invocation of powerServer.close().

    You invoke addConnection() with as many as three arguments, the last of which is optional. Here is the method signature:
    public void addConnection
       (java.sql.Connection con, java.lang.String name, int disconnectOption)
       throws java.lang.NullPointerException, java.lang.IllegalArgumentException, com.ibm.javart.JavartException
    Parameters are as follows:
    • con (type java.sql.Connection) is a connection to the type of database that was specified in the build descriptor option DBMS.
    • name (type java.lang.String) is the connection name. The main program uses that name in calls to the following system functions: sqlLib.beginDatabaseTransaction(), sqlLib.defineDatabaseAlias(), sqlLib.disconnect(), and sqlLib.setCurrentDatabase().
    • disconnectOption (type int) is the disconnect option, as specified by any of the following constants:
      • DISCONNECT_NEVER is the default value and indicates that an attempt to close the connection will have no effect, even when the invoking Java code calls powerServer.close().

        powerServer.close() commits work and ends the EGL run unit. For all other disconnect options, the end of the run unit closes any open connections.

      • DISCONNECT_AUTOMATIC indicates that the connection closes after a rollback; after a commit; or after the main program calls sqlLib.disconnect() or sqlLib.disconnectAll().
      • DISCONNECT_CONDITIONAL indicates that the connection closes in the following cases: after a rollback; after a commit when the HOLD option is not in effect for any open result set that was created by the connection; or after the main program calls sqlLib.disconnect() or sqlLib.disconnectAll().
      • DISCONNECT_EXPLICIT indicates that the connection does not close after a rollback or commit, but does close after the main program calls sqlLib.disconnect() or sqlLib.disconnectAll().

      All but the first of the previous values have the same meanings as values that you can specify when invoking the system function sqlLib.connect(). The equivalent values are as follows, from the EGL enumeration egl.io.sql.DisconnectKind: DisconnectKind.automatic, DisconnectKind.conditional, DisconnectKind.explicit. A value equivalent to DISCONNECT_NEVER is not valid when you invoke sqlLib.connect().

Finally, consider the following situation: your native Java code requires notification when a change is made to a parameter of primitive type. To make such a notification possible, the native code registers as a listener by invoking the addPropertyChangeListener method of the program wrapper object. In this case, either of the following situations triggers the PropertyChange event that causes the native code to receive notification at run time:
  • Your native code invokes a set method on a parameter of primitive type
  • The generated program returns changed data to a parameter of primitive type

The PropertyChange event is described in the JavaBean specification of Oracle.

The set of parameter wrapper classes

A parameter wrapper class is produced for each record that is declared as a parameter (or input record) in the generated program. In the usual case, you use a parameter wrapper class only to declare a variable that references the parameter, as in the following example:
  Mypart myRecWrapperObject = myProgram.getMyrecord();

In this case, you are using the memory allocated by the program wrapper object.

You also can use the parameter wrapper class to declare memory, as is necessary if you invoke the call method (rather than the execute method) of the program object.

The parameter wrapper class includes a set of private instance variables, as follows:
  • One variable of a Java primitive type for each of the parameter's low-level structure fields, but only for a structure field that is neither an array nor within a substructured array
  • One array of a Java primitive type for each EGL structure field that is an array and is not substructured
  • An object of an inner, array class for each substructured array that is not itself within a substructured array; the inner class can have nested inner classes to represent subordinate substructured arrays
The parameter wrapper class includes several public methods:
  • A set of get and set methods allows you to get and set each instance variable. The format of each method name is as follows:
      purposesiName()
    purpose
    The word get or set.
    siName
    Name of the structure field. The first letter is upper case, and aspects of the other letters are determined by the naming convention described in Naming conventions for Java wrapper classes.
    Note: Structure fields that you declared as fillers are included in the program call; but the array wrapper classes do not include public get or set methods for those structure fields.
  • The method equals allow you to determine whether the values stored in another object of the same class are identical to the values stored in the parameter wrapper object. The method returns true only if the classes and values are identical.
  • The method addPropertyChangeListener is invoked if your program requires notification of a change in a variable of a Java primitive type.
  • A second set of get and set methods allow you to get and set the null indicators for each structure field in an SQL record parameter. The format of each of these method names is as follows:
      purposesiNameNullIndicator()
    purpose
    The word get or set.
    siName
    Name of the structure field. The first letter is upper case, and aspects of the other letters are determined by the naming convention described in Naming conventions for Java wrapper classes.

The set of substructured-field-array wrapper classes

A substructured-field-array wrapper class is an inner class of a parameter class and represents a substructured array in the related parameter. The substructured-field-array wrapper class includes a set of private instance variables that refer to the structure fields at and below the array itself:
  • One variable of a Java primitive type for each of the array's low-level structure fields, but only for a structure field that is neither an array nor within a substructured array
  • One array of a Java primitive type for each EGL structure field that is an array and is not substructured
  • An object of an inner, substructured-field-array wrapper class for each substructured array that is not itself within a substructured array; the inner class can have nested inner classes to represent subordinate substructured arrays
The substructured-field-array wrapper class includes the following methods:
  • A set of get and set methods for each instance variable
    Note: Structure field that you declared as nameless fillers are used in the program call; but the substructured-field-array wrapper classes do not include public get or set methods for those structure fields.
  • The method equals allows you to determine whether the values stored in another object of the same class are identical to the values stored in the substructured-field-array wrapper object. The method returns true only if the classes and values are identical.
  • The method addPropertyChangeListener, for use if your program requires notification of a change in a variable of a Java primitive type
In most cases, the name of the topmost substructured-field-array wrapper class in a parameter wrapper class is of the following form:
  ParameterClassname.ArrayClassName
Consider the following record, for example:
  Record CompanyPart type basicRecord
  10 Departments CHAR(20)[5];
     20 CountryCode CHAR(10);
     20 FunctionCode CHAR(10)[3];
        30 FunctionCategory CHAR(4);
        30 FunctionDetail CHAR(6);
  end

If the parameter Company is based on CompanyPart, you use the string CompanyPart.Departments as the name of the inner class.

An inner class of an inner class extends use of a dotted syntax. In this example, you use the symbol CompanyPart.Departments.Functioncode as the name of the inner class of Departments.

For additional details on how the substructured-field-array wrapper classes are named, see Output of Java wrapper generation.

Dynamic array wrapper classes

A dynamic array wrapper class is produced for each dynamic array that is declared as a parameter in the generated program. Consider the following EGL program signature:
  Program myProgram(intParms int[], recParms MyRec[])

The name of the dynamic array wrapper classes are IntParmsArray and MyRecArray.

You use a dynamic array wrapper class to declare a variable that references the dynamic array, as in the following examples:
  IntParmsArray myIntArrayVar = myProgram.getIntParms();
  MyRecArray    myRecArrayVar = myProgram.getRecParms();

After declaring the variables for each dynamic array, you might add elements:

  // adding to an array of Java primitives 
  // is a one-step process
  myIntArrayVar.add(new Integer(5));

  // adding to an array of records or forms 
  // requires multiple steps; in this case, 
  // begin by allocating a new record object
  MyRec myLocalRec = (MyRec)myRecArrayVar.makeNewElement();
  
  // the steps to assign values are not shown 
  // in this example; but after you assign values, 
  // add the record to the array
  myRecArrayVar.add(myLocalRec);

  // next, run the program
  myProgram.execute();

  // when the program returns, you can determine 
  // the number of elements in the array
  int myIntArrayVarSize = myIntArrayVar.size();

  // get the first element of the integer array 
  // and cast it to an Integer object
  Integer firstIntElement = (Integer)myIntArrayVar.get(0);

  // get the second element of the record array
  // and cast it to a MyRec object
  MyRec secondRecElement = (MyRec)myRecArrayVar.get(1);

As suggested by that example, EGL provides several methods for manipulating the variables that you declared.

Method of the dynamic array class Purpose
add(int, Object) To insert an object at the position specified by int and to shift the current and subsequent elements to the right.
add(Object) To append an object to the end of the dynamic array.
addAll(ArrayList) To append an ArrayList to the end of the dynamic array.
get() To retrieve the ArrayList object that contains all elements in the array
get(int) To retrieve the element that is in the position specified by int
makeNewElement() To allocate a new element of the array-specific type and to retrieve that element, without adding that element to the dynamic array.
maxSize() To retrieve an integer that indicates the maximum (but not actual) number of elements in the dynamic array
remove(int) To remove the element that is in the position specified by int
set(ArrayList) To use the specified ArrayList as a replacement for the dynamic array
set(int, Object) To use the specified object as a replacement for the element that is in the position specified by int
size() To retrieve the number of elements that are in the dynamic array
Exceptions occur in the following cases, among others:
  • If you specify an invalid index in the get or set method
  • If you try to add (or set) an element that is of a class incompatible with the class of each element in the array
  • If you try to add elements to a dynamic array when the maximum size of the array cannot support the increase; and if the method addAll fails for this reason, the method adds no elements

Naming conventions for Java wrapper classes

EGL creates a name in accordance with these rules:
  • If the name is all upper case, lower case all letters.
  • If the name is a keyword, precede it with an underline
  • If a hyphen or underline is in the name, remove that character and upper case the next letter
  • If a dollar sign ($), at sign (@), or pound sign (#) is in the name, replace each of those characters with a double underscore (__) and precede the name with an underscore (_).
  • If the name is used as a class name, upper case the first letter.
The following rules apply to dynamic array wrapper classes:
  • In most cases, the name of a class is based on the name of the part declaration (data item, form, or record) that is the basis of each element in the array. For example, if a record part is called MyRec and the array declaration is recParms myRec[], the related dynamic array wrapper class is called MyRecArray.
  • If the array is based on a declaration that has no related part declaration, the name of the dynamic array class is based on the array name. For example, if the array declaration is intParms int[], the related dynamic array wrapper class is called IntParmsArray.

Data type cross-reference

The next table indicates the relationship of EGL primitive types in the generated program and the Java data types in the generated wrapper.

EGL primitive type Length in chars or digits Length in bytes Decimals Java data type Maximum precision in Java
BIN, SMALLINT 4 2 0 short 4
BIN, INT 9 4 0 int 9
BIN, BIGINT 18 8 0 long 18
BIN 4 2 >0 float 4
BIN 9 4 >0 double 15
BIN 18 8 >0 double 15
BOOLEAN 1 1 NA Boolean NA
CHAR 1-32767 2-32766 NA String NA
DBCHAR 1-16383 1-32767 NA String NA
DATE 8 8 0 java.sql.Date NA
DECIMAL, MONEY, PACF 1-3 1-2 0 short 4
DECIMAL, MONEY, PACF 4-9 3-5 0 int 9
DECIMAL, MONEY, PACF 10-18 6-10 0 long 18
DECIMAL, MONEY, PACF 19-32 10-17 0 java.math.BigInteger 32
DECIMAL, MONEY, PACF 1-5 1-3 >0 float 6
DECIMAL, MONEY, PACF 7-18 4-10 >0 double 15
DECIMAL, MONEY, PACF 19-32 10-17 >0 java.math.BigDecimal 32
FLOAT 18 8 >0 double 15
HEX 2-75534 1-32767 NA byte[] NA
INTERVAL (month- or second-span) 1-21 2-22 0 String NA
MBCHAR 1-32767 1-32767 NA String NA
NUM, NUMC 1-4 1-4 0 short 4
NUM, NUMC 5-9 5-9 0 int 9
NUM, NUMC 10-18 10-18 0 long 18
NUM, NUMC 19-32 19-32 0 java.math.BigInteger 32
NUM, NUMC 1-6 1-6 >0 float 6
NUM, NUMC 7-18 7-18 >0 double 15
NUM, NUMC 19-32 19-32 >0 java.math.BigDecimal 32
SMALLFLOAT 9 4 >0 float 6
STRING 1-16383 2-32766 NA String NA
TIME 6 6 0 java.sql.Time NA
TIMESTAMP 1-20 1-20 0 java.sql. Timestamp NA
UNICODE 1-16383 2-32766 NA String NA