Compiling and Running a JAVA Program

In this section:

When you compile your JAVA program, the ntj2c.jar file (and the ibtrace.jar file when including any ibtrace or log method), located in the EDAHOME etc/java/java15 subdirectory, needs to be accessible. (The etc/java/java15 subdirectory may vary in the future as newer Java releases become available.) If you are manually building with Javac, you can then compile your JAVA program using the CLASSPATH environment variable or the javac -classpath command parameter. If GENCPGM is used to build your JAVA program, including the jars is automatic. Specific details follow the sample.

When you execute your JAVA class, you need to place the client jar file containing the JAVA class to be invoked in the CLASSPATH environment variable prior to starting the Reporting Server or configure the JVM environment of the server using the Web Console to include the jars.

When writing your own application, create a .java file containing the application, then build and run as described in the sections that follow.

Note that the following is a working example that needs no customization. Users are expected to build and test this example in order to confirm a properly configured and usable environment for CALLPGM applications before attempting any custom applications.

The example has two modes: echo back the command line parameters sent to it or display data of the various supported data types. The example does not work with or use external data so it has no external dependencies, such as a configured DBMS. However, in practical use, a real application would typically retrieve data from an external source. (It is the users responsiblity to do the real coding of the application.)


Top of page

Example: Compiling and Running a JAVA CALLPGM Program

You can use the following sample code (cjsamp.java) as a model for writing your own JAVA program.

The main mode is to echo parameters back, and, if the first parameter is a number, the application echoes the parameters back as individual columns of that many tuples of data. If the first parameter is not numeric, the exception handler detects and sets the tuple return count to 1. A number greater than 50 also activates a safety (against excessive processing), and resets the tuple return count to 9. (You can change the safety, if that is what you want. For this example, the safety is simply a precaution against excessive records for the demo sample.)

If the first parameter is numeric and the second is the word datatype, the second test mode activates and returns arbitrary data in the various supported data types, for as many tuples as specified. Within this mode, passing a null for string is used for one of the columns, which, in turn, display as MISSING data (dot) within the tuple sent back.

Remember that a real call java program would use the structure of this example to parse the incoming parameters and take some action, such as setting column sizes and returning data from an sql source, but the coding is left to the user.

/*
 * Title:        cjsamp.java
 * Description:  Example implementation of a JAVA callpgm program
 * Company:      Information Builders, Inc.
*/
/*
   This example has two modes, echo back the command line parms sent to
   it or display data of the various supported data types. It does not
   work with/use external data so has no external dependencies such as a
   configured DBMS, but in practical use would retrieve data from a
   external source; it is left to the user to do such coding.
   The main mode is to echo parms back and if the first parm is a number,
   the application echoes the parms back as individual columns of that
   many tuples of data. If the first parm is not numeric, the exception
   handler detects and sets the tuple return count to 1. A number greater
   than 50 also activates a safety (for excessive processing) and resets
   the tuple return count to 9 (the user is free to change the safety,
   if that is what they really want, it is simply a precaution for the
   example). If no parms are passed, it is detected and a no parms
   message passed back.
   If the first parm is numeric and the second is the word "datatype",
   the second test mode activates and returns arbitrary data in the
   various supported data types for as many tuples as specified. Within
   this mode, the use of passing a null for string is used for one of
   the columns, these in turn display as MISSING data (dot) within the
   tuple sent back.
   As already stated, a real call java program would use the structure
   of this example to parse the incoming parms and take some action
   such as setting column sizes and returning data from an sql source,
   but is left to the user to code.
   Execution syntax is (see full documenation for parm rules):
     CALLJAVA ibi.cjsamples.cjsamp, parm1, parm2, ...
     END
   or
     SET EXORDER=PGM/FEX
     EX java.ibi.cjsamples.cjsamp parm1,parm2,...
   or
     SET SQLENGINE=CPJAVA
     SQL EX ibi.cjsamples.cjsamp parm1,parm2,... ;
     TABLE FILE SQLOUT
     PRINT field [ON TABLE PCHOLD]
     END
     SET SQLENGINE=OFF
   or
     SQL CPJAVA EX ibi.cjsamples.cjsamp parm1,parm2,... ;
     TABLE FILE SQLOUT
     PRINT field [ON TABLE PCHOLD]
     END
   CALLJAVA syntax uses no leading "java.", has a comma after the
   class and requires the END statement. Where EX syntax requires
   a SET EXORDER, a leading "java." and no comma after the class.
   Where SQL EX uses a SET SQLENGINE, no leading "java.", no comma
   after the class and requires a trailing semi-colon. Where SQL
   CPJAVA EX eliminates the SET SQLENGINE step. Which method
   to use is the users choice.
   The functions ibtrace.traceon and ibtrace.println have been deprecated
   (respectively) in flavor of log.isDebugEnabled() and log.debug, but
   the original functions are still active. This example uses the log.*
   functions.
   The indentation and formatting in this sample may seem odd,
   but is done to control wrapping and readability in the printed
   documentation.
*/
package ibi.cjsamples;
/* Required ibi classes */
import ibi.trace.*;
import ibi.callpgm.*;
import ibi.callpgm.ibianswr;
import ibi.trace.IBILogFactory;
import ibi.trace.ILogger;
/* Needed for time/date usage here, but generally typically needed. */
import java.sql.*;
import java.math.*;
import java.util.*;
public class cjsamp implements callpgm{
  private static final ILogger log = IBILogFactory.getLogger(cjsamp.class);
  private ibianswr answr = null;
  private int rownum = 0;
  private int numOfColumns = 0;
  private int Rows = 0;
  private String[] arrParms = null;
  /* Get class name for error messages */
  private String ClassName = getClass().toString();
  /* Array for no parms passed */
  private String[] NoParms = { "No ","Parameter ","Data ","Supplied!" };
  public cjsamp(){}
  /*
   Applications are required to have the next signature due to
   internal interface requirements for graph, but is not for
   customer use. Attempted customer use is not supported.
  */
  public ibianswr
    execute(String username, String password, Object obj, String[] parms)
               throws Exception { return null; }
  /* Actual application ... */
  public ibianswr
       execute(String username, String password, String[] parms)
               throws Exception
  {
  /*
    General init info tracing. Tracing only displays only if server
    tracing on and displays in the stardard server traces jc######.trc.
    log.isDebugEnabled() is used to avoid the overhead of forming strings
    when tracing is not enabled.
  */
  int numParms = (parms != null) ? parms.length : 0;
  if (log.isDebugEnabled())
     {
     log.debug(" ... " + ClassName + ": Constructor ...");
     log.debug(" ... " + ClassName + ": Username: " +
               username + ", Password: " + password);
     log.debug(" ... " + ClassName +
               ": Number of parameter(s): " + numParms);
     for(int i=1; i <= numParms; i++)
        { log.debug(" ... -> Parameter " + i + ": " + parms[i-1]); }
     }
  /* Check parm 1 for numeric and if too high of a repeat value. */
  if(numParms == 0)
    { /* No parms defaults to 1 in echo mode */
      arrParms = NoParms;
      numParms = (arrParms != null) ? arrParms.length : 0;
      Rows = 1;
    }
    else
    {
      arrParms = parms;
      /* Example of exception handling and writing to trace */
      try { Rows = Integer.parseInt(arrParms[0],10);
          } catch (Exception e)
          {
          if (log.isDebugEnabled())
             {
             log.debug(" ... " + ClassName +
                       ": Parm 1 Non Integer: " + e + "\n");
             }
          Rows = 1; /* Reset to 1 if not numeric */
          }
      /* This is an example, reduce unrealistic repeats to 9. */
      if(Rows > 50) { Rows = 9 ; }
    }
  /* Based on array contents, set field attributes for SQLOUT master */
  /* If parm 2 is "datatype", run in datatype mode else echo mode. */
  if(arrParms[1].equalsIgnoreCase("datatype"))
    { /* Create arbitrary number of columns for our datatypes. */
      numOfColumns = 11; /* Actually 10 plus 1 for MISSING example */
      if (log.isDebugEnabled())
         {
         log.debug(" ... " + ClassName +
                   ": Number of Columns: " + numOfColumns);
         }
      answr = new ibianswr(numOfColumns);
      for(int index = 0; index < numOfColumns; index++)
         {
         int colNum = index + 1 ; /* We start at 1 not 0 */
         if (colNum==1 || colNum==2)
         { /* Column 2 for MISSING example */
            answr.setColName(colNum,"FLD_"+colNum+"_IBI_ALPHA");
            answr.setColType(colNum,ibianswr.IBI_ALPHA);
            answr.setColSize(colNum,10);
         }
         else if (colNum == 3)
         {
            answr.setColName(colNum,"FLD_"+colNum+"_IBI_INTEGER");
            answr.setColType(colNum,ibianswr.IBI_INTEGER);
            answr.setColSize(colNum,4);
         }
         else if (colNum == 4)
         {
            answr.setColName(colNum,"FLD_"+colNum+"_IBI_FLOAT");
            answr.setColType(colNum,ibianswr.IBI_FLOAT);
            answr.setColSize(colNum,4);
         }
         else if (colNum == 5)
         {
            answr.setColName(colNum,"FLD_"+colNum+"_IBI_DOUBLE");
            answr.setColType(colNum,ibianswr.IBI_DOUBLE);
            answr.setColSize(colNum,8);
         }
         else if (colNum == 6)
         {
            answr.setColName(colNum,"FLD_"+colNum+"_IBI_TIME");
            answr.setColType(colNum,ibianswr.IBI_TIME);
            answr.setColSize(colNum,10);
         }
         else if (colNum == 7)
         {
            /*
            IBI_DATE must be java.sql.Date class format.
            Dates like DD-MMM-YYYY (ie OpenVMS format) are not,
            either convert to java.sql.Date or use IBI_ALPHA.
            */
            answr.setColName(colNum,"FLD_"+colNum+"_IBI_DATE");
            answr.setColType(colNum,ibianswr.IBI_DATE);
            answr.setColSize(colNum,10);
         }
         else if (colNum == 8)
         {
            answr.setColName(colNum,"FLD_"+colNum+"_IBI_TIMESTAMP");
            answr.setColType(colNum,ibianswr.IBI_TIMESTAMP);
            answr.setColSize(colNum,21);
         }
         else if (colNum == 9)
         {
            answr.setColName(colNum,"FLD_"+colNum+"_IBI_SMALLINT");
            answr.setColType(colNum,ibianswr.IBI_SMALLINT);
            answr.setColSize(colNum,2);
         }
         else if (colNum == 10)
         {
            answr.setColName(colNum,"FLD_"+colNum+"_IBI_BIGINT");
            answr.setColType(colNum,ibianswr.IBI_BIGINT);
            answr.setColSize(colNum,8);
         }
         else if (colNum == 11)
         {
            answr.setColName(colNum,"FLD_"+colNum+"_IBI_DECIMAL");
            answr.setColType(colNum,ibianswr.IBI_DECIMAL);
            answr.setColSize(colNum,18,7);
         }
         }
    }
    else
    { /* Create arbitrary number of columns for number of parms */
      answr = new ibianswr(arrParms.length);
      if (log.isDebugEnabled())
         {
         log.debug(" ... " + ClassName +
                   ": Number of columns: " + answr.getColsNumb()); }
         for(int column = 1; column <= answr.getColsNumb(); column++)
            {
            answr.setColSize(column,(column == 1) ?
                  Math.max(1,arrParms[column-1].length()) :
                             arrParms[column-1].length());
            answr.setColName(column, "Column" + column);
            }
    }
    return answr;
  }
  /* Based on array, return data for as many rows passed in parm 1 */
  public Integer fetch() throws Exception
  {
    if( ++rownum > Rows ) return IBI_EOD;
    /* If parm 2 is "datatype" run in test mode else echo mode. */
    if(arrParms[1].equalsIgnoreCase("datatype"))
      { /* For datatype test, set arbitrary data to send back */
      if (log.isDebugEnabled())
         {
          log.debug(" ... " + ClassName + ": fetching row: " + rownum);
         }
      for(int colNum = 1; colNum <= numOfColumns; colNum++)
      {
         if (colNum == 1)
          {  /* IBI_ALPHA */
          String value = new String("Col"+colNum+" Row"+rownum);
          answr.setColValue(colNum, value);
          }
          else if (colNum == 2)
          { /* IBI_ALPHA - Pass null for IBI_MISSING value behavior */
          String value = null;
          answr.setColValue(colNum, value);
          }
          else if (colNum == 3)
          { /* IBI_INTEGER */
          int vali = 2 ; answr.setColValue(colNum, vali);
          }
          else if (colNum == 4)
          { /* IBI_FLOAT */
          Float fl = new Float(7.0);
          float valf = fl.floatValue(); answr.setColValue(colNum, valf);
          }
          else if (colNum == 5)
          { /* IBI_DOUBLE */
          double vald = 6.0 ; answr.setColValue(colNum, vald);
          }
          else if (colNum == 6)
          { /* IBI_TIME */
          java.sql.Time DV = new java.sql.Time(10000);
          answr.setColValue(colNum, DV);
          }
          else if (colNum == 7)
          { /* IBI_DATE */
          java.sql.Date DV = new java.sql.Date(100000);
          answr.setColValue(colNum, DV);
          }
          else if (colNum == 8)
          { /* IBI_TIMESTAMP */
          Timestamp ts = new Timestamp(100000);
          answr.setColValue(colNum, ts);
          answr.setColSize(colNum,ts.toString().length());
          }
          else if (colNum == 9)
          { /* IBI_SMALLINT */
          short vals= 4 ; answr.setColValue(colNum, vals);
          }
          else if (colNum == 10)
          { /* IBI_BIGINT */
          long vals= 6 ; answr.setColValue(colNum, vals);
          }
          else if (colNum == 11)
          { /* IBI_DECIMAL */
          BigDecimal BD = new BigDecimal("12345678.90876");
          answr.setColValue(colNum, BD);
          }
          }
      }
      else /* For echo test, send back the same parms passed in */
      {
      /* If no parms passed, load array with no parms message */
      if(arrParms == null) { arrParms = NoParms ; }
      /* Return parms received for as many rows passed in parm 1 */
      for(int i = 1; i <= Rows ; i++)
         {
         if (log.isDebugEnabled())
            {
               log.debug(" ... " + ClassName + ": fetching row: " + i);
            }
         for(int column = 1; column <= answr.getColsNumb(); column++)
            { answr.setColValue(column, arrParms[column-1]) ; };
         }
      }
      return IBI_DATA;
  }
}

Top of page

x
Building a JAVA Program and Starting the Server

The following are examples that can be used when building a JAVA program and starting a server.



Example: Building a JAVA Application Manually on UNIX or IBM i

The following example assumes javac compiler is on $PATH.

One might typically build an application manually using code such as the following:

JARS=$HOME/ibi/srv77/home/etc/java/java15
javac cjsamp.java -classpath $JARS/ntj2c.jar:$JARS/ibtrace.jar
mkdir ibi ibi/cjsamples 2> /dev/null
cp cjsamp.class ibi/cjsamples
jar cvf cjsamp.jar ibi/cjsamples/cjsamp.class

The result is a cjsamp.jar file in the current directory. In order to use your application, you must copy the resulting .jar file from the build directory to a production location, such as /usr/local/jars, and place it on the classpath before server start up.



Example: Building a JAVA Application Manually on Windows

The following example assumes javac compiler is on PATH.

One might typically build an application manually using code such as the following:

set JARS=C:\ibi\srv77\home\etc\java\java15
javac cjsamp.java -classpath %JARS%\ntj2c.jar;%JARS%\ibtrace.jar
mkdir ibi ibi\cjsamples 2> nul:
copy cjsamp.class ibi\cjsamples
jar cvf cjsamp.jar ibi\cjsamples\cjsamp.class

The result is a cjsamp.jar file in the current directory. In order to use your application, you must copy the resulting .jar file from the build directory to a production location, such as C:\jars, and place it on the classpath before server start up.



Example: Building a JAVA Application Manually on OpenVMS

The following example assumes that the HP-supplied script for activating Java has been executed so the javac compiler can be found on the system path.

One might typically build an application manually using code such as the following:

$ DEFINE /USER JAVA$CLASSPATH-
  IADMIN:[IADMIN.IBI.SRV77.HOME.ETC.JAVA.JAVA15]NTJ2C.JAR,-
  IADMIN:[IADMIN.IBI.SRV77.HOME.ETC.JAVA.JAVA15]IBTRACE.JAR
$ JAVAC -verbose -d . cjsamp.java 
$ JAR -cvf CJSAMP.jar [.ibi.cjsamples]cjsamp.class 

The result is a cjsamp.jar file in the current directory. In order to use your application, you must copy the resulting .jar file from the build directory to a production location, such as IADMIN:[IADMIN.JARS], and place it on the classpath before server start up.



Example: Building a JAVA Application Using GENCPGM

This example assumes that the javac compiler is on $PATH (UNIX and IBM i), PATH (Windows) or system path (OpenVMS) and that GENCPGM has been copied to the current directory (otherwise, the full path must be used).

Use the following notations to build a class inside a jar (cjsamp in this example).

Platform

Syntax

Windows

gencpgm –m cjava cjsamp.java

UNIX

gencpgm.sh –m cjava cjsamp.java

IBM i (formerly known as i5/OS)

gencpgm.sh –m cjava cjsamp.java

OpenVMS

@gencpgm –m cjava cjsamp.java

For details about setting specific JAR names, see Using GENCPGM. GENCPGM supports building classes in a jar on all platforms.



Example: Starting a Server on UNIX or IBM i

In order for a server to recognize a new or updated CALLJAVA application, the CLASSPATH variable must be set with all required jars (including ntjzc.jar and ibtrace.jar) before you start the server. You must also restart the server if a .jar file is updated. For example, on UNIX you can start the server using the following code:

CLASSPATH=/usr/iadmin/ibi/srv77/home/etc/java/java15/ntj2c.jar:
   /usr/iadmin/ibi/srv77/home/etc/java/java15/ibtrace.jar:
   /usr/local/jars/cjsamp.jar
export CLASSPATH
edastart -start

Alternately, the properties page from the Web Console allows the configuration of CLASSPATH with user built jars as part of the servers configuration. To access the properties page from the Web Console, click Workspace, then Configuration/Monitor, and then Java Services.

For an example of how an application executes a Java class, see the various Execute methods at the start of the chapter.



Example: Starting a Server on Windows

In order for a server to recognize a new or updated CALLJAVA application, you must set the the CLASSPATH variable with all required jars (including ntjzc.jar and ibtrace.jar) before you start the server. You must also restart the server if a .jar file is updated.

For example, on Windows you can start the server by selecting the following options:

My Computer > Properties > Advanced Tab > Environment Variables

Next, either add or edit the CLASSPATH variable and include ntjzc.jar, ibtrace.jar, and the new jar in the value. For example:

CLASSPATH C:\ibi\srv77\home\etc\java\java15\ntj2c.jar; c:\ibi\srv77\home\etc\java\java15\ibtrace.jar;c:\jars\cjsamp.jar;

Then, start the server as a service or use any of the standard Windows start menu options of the server.

For an example of how an application executes a Java class, see the various Execute methods at the start of the chapter.



Example: Starting a Server on OpenVMS

In order for a server to recognize a new or updated CALLJAVA application, you must set the CLASSPATH or JAVA$CLASSPATH variable with all required jars (including ntjzc.jar and ibtrace.jar) before you start the server. You must also restart the server if a .jar file is updated.

If CLASSPATH is used for setting classpath, then UNIX file notation must be used, as described in the Java documentation for HP. Otherwise, JAVA$CLASSPATH may be used with OpenVMS file notation as illustrated next.

On OpenVMS you can start the server using the following code:

DEFINE JAVA$CLASSPATH JAVA$CLASSPATH-
 IADMIN:[IADMIN.IBI.SRV76.HOME.ETC.JAVA.JAVA15]NTJ2C.JAR, -
 IADMIN:[IADMIN.IBI.SRV76.HOME.ETC.JAVA.JAVA15]IBTRACE.JAR, -
 IADMIN:[IADMIN.JARS]CPSAMP.JAR
@EDASTART -START 

For an example of how an application executes a Java class, see the various Execute methods at the start of the chapter.


iWay Software