Communications Server

Client/Server Communications Programming


Chapter 21. Using CPIC-C for Java


Figure COMHH not displayed.
This is only available for Communications Server Windows 95, Windows NT, and Windows 2000 SNA API clients.

This chapter describes the Common Programming Interface for Communications (CPI-C) for Java API and its usage, including:


What is CPI-C for Java?

CPI-C for Java is a programming toolkit that allows developers to use the Common Programming Interface for Communications (CPI-C) API in the Java language. CPI-C is an open API for SNA LU 6.2. Refer to Common Programming Interface Communications CPI-C Reference (SC26-4399), included in IBM eNetwork Communications Server Version 6.0 for Windows NT, for more details on the CPI-C API.

A primary goal of the toolkit is to ease the transition from traditional C to Java. Because of this, the toolkit calls look quite similar to those used in C. CPI-C for Java is provided as a layer above the native CPI-C API and this native code must be installed in order for CPI-C to work.

The toolkit provides programmer reference documentation for every class, method, and variable in the toolkit. The documentation is in HTML format, and provides cross-references for ease of use.

This programming toolkit also provides a set of Java classes with objects to hold CPI-C parameters as well as a CPIC class, which defines methods that map to the CPI-C functions in C. You can run the sample application (JPing.class) included in the toolkit, as well as write your own.

The CPI-C for Java binding allows a Java application to use an SNA network and to use CPI-C as a networking API. These Java applications can connect to partners that are:


Installing CPI-C for Java

The following items are installed with the CPI-C for Java toolkit:


CPI-C for Java Samples

The following sections describe the client and server samples for CPI-C for Java.

Client Sample

The sample included in the toolkit performs the same function as the APING client utility. It sends data to a server process that echoes the data back to the APING utility. The sample client has been compiled and placed into the CPICJAVA.JAR file. The source file (JPing.java) is installed in the IBMCS\SDK\JAVA\CPIC\SAMPLES subdirectory when the ECL for Java is installed.

The API is supplied as a Java package called COM.ibm.eNetwork.cpic. The first line of code in the following sample is required in order to access the classes supplied with the toolkit. The CPIC class is the main interface to the native CPI-C code. The CPIC class contains many constants defined in CPI-C, such as, the length of a conversation ID, along with methods that are passed through to the native CPI-C calls.

You need only declare one CPIC object per class. Java will load the dynamic link library (DLL) containing the native methods (CPICJAVA.DLL) when the CPIC object is instantiated.

The following sample describes the CPI-C pipeline; it does not replicate the information in the JPing.java source file.
Note:The following sample includes code interleaved with commentary.

/*---------------------------------------------------------------
 * Pipeline transaction, client side.
 *---------------------------------------------------------------*/
import COM.ibm.eNetwork.cpic.*;
public class Pipe extends Object {
   public static void main(String args[]) {
 
   // Make a CPIC object
   CPIC cpic_obj = new CPIC();   

Each type of parameter has its own class, and each of these classes has associated constants defined as class variables. For example, the CPICReturnCode class has the success return code, CM_OK, defined.

There are two major reasons for having a class for each type of parameter. Because Java passes all parameters by value, there is no way to return data in simple types, such as integer. If we pass an object as a parameter to a method, the method can set a variable in that object, thus returning data to the caller. Secondly, the use of objects encapsulates constants within the objects that understand those constants. This is a standard information-hiding technique.

   // Return Code
   CPICReturnCode cpic_return_code =
      new CPICReturnCode(CPICReturnCode.CM_OK);
 
   // Request to send received?
   CPICControlInformationReceived rts_received =
      new CPICControlInformationReceived(
         CPICControlInformationReceived.CM_NO_CONTROL_INFO_RECEIVED);
 
 

The CPI-C send function expects a C-language buffer, that is, allocated space of no specific type. Unlike C, Java has no facility to allocate untyped memory. Other than primitives, everything in Java is an object. Whatever the program sends must be converted from its object type into a C-style array of bytes.

Java provides methods that facilitate these conversions. For example, Java can convert a string into a Java array of bytes. While an array of bytes is an object in Java, Java allows you to extract the data from an array of bytes with a native method.

 // String to Send
   String sendThis = "Test of the PipeLine Transaction";
 
   // Length of String to send
   CPICLength send_length = new CPICLength(sendThis.length());
 
   // Convert String to send to a Java array of bytes
   byte[] stringBytes = new byte[ send_length.intValue()];
   sendThis.getBytes(0,send_length.intValue(),stringBytes,0);

Like buffer processing, the CPI-C native calls expect symbolic destination names to be C-strings, not Java Strings. The toolkit automatically converts them from Java strings to C-strings as necessary. In general, automatic conversion is possible when the toolkit expects a specific Java type.

The conversation ID is a Java array of bytes which is converted automatically by the toolkit to a C array consisting of a simple block of bytes.

   // this hardcoded sym_dest_name must
   // be 8 chars long & blank padded
   String sym_dest_name = "PIPE    ";
 
   // Space to hold a conversation ID
   // (which is just a bunch of bytes)
   byte[] conversation_ID = new byte[CPIC.CM_CID_SIZE];
 

The program starts making CPI-C calls which are very similiar to those used in C. However, the method calls are prefixed with the name of the CPI-C object, and the parameters are not prefixed by the pass-by-reference (&) symbol.

  //
   // Initialize CPI-C
   //
   cpic_obj.cminit(             /* Initialize_Conversation        */
             conversation_ID,   /*  O: returned conversation ID   */
             sym_dest_name,     /*  I: symbolic destination name  */
             cpic_return_code); /*  O: return code from this call */
   //
   // ALLOCATE
   //
   cpic_obj.cmallc(             /* Allocate Conversation          */
             conversation_ID,   /*  I: conversation ID            */
             cpic_return_code); /*  O: return code from this call */
   //
   // SEND
   //
   cpic_obj.cmsend(             /* Send_Data                      */
             conversation_ID,   /*  I: conversation ID            */
             stringBytes,       /*  I: send this buffer           */
             send_length,       /*  I: length to send             */
             rts_received,      /*  O: was RTS received?          */
             cpic_return_code); /*  O: return code from this call */
   //
   // DEALLOCATE
   //
   cpic_obj.cmdeal(             /* Deallocate                     */
             conversation_ID,   /*  I: conversation ID            */
             cpic_return_code); /*  O: return code from this call */
   } // end main method
} // end the class
 
 

Server Sample

The server initializes itself, accepts a conversation, receives data, and prints diagnostic information. As in the client, we instantiate classes to hold the CPI-C parameters, many of which have only an integer as instance data. By using objects, we can mimic call by reference. We also allocate a byte array to hold the received data.
Note:The following sample includes code interleaved with commentary.

   /*---------------------------------------------------------------
    * Pipeline transaction, server side.
    *---------------------------------------------------------------*/
   import COM.ibm.eNetwork.cpic.*;
   import Java.io.IOException;
 
   public class PipeServer extends Object {
      public static void main(String args[]) {
 
       CPIC cpic_obj = new CPIC();
 
       // Space to hold the received data
       byte[] data_buffer;
       data_buffer =  new byte[101];
 
       CPICLength requested_length = new CPICLength(101);
       CPICDataReceivedType data_received =
          new CPICDataReceivedType(0);
       CPICLength received_length = new CPICLength(0);
       CPICStatusReceived status_received =
          new CPICStatusReceived(0);
       CPICControlInformationReceived rts_received =
          new CPICControlInformationReceived(0);
       CPICReturnCode cpic_return_code =
          new CPICReturnCode(0);
 
       // Space to hold a conversation ID -- a bunch of bytes
       // The first line declares conversation_ID to be a reference to
       // a byte array object.  The second line creates such an object,
       // and assigns the reference to the byte array object.
       byte[] conversation_ID;
       conversation_ID = new byte[cpic_obj.CM_CID_SIZE];
 
 

The CPI-C receive call (cmrcv) returns a Java array of bytes while the pipe transaction expects a string. The programmer can translate the array of bytes into a string by using the string class-constructor that takes an array of bytes as an argument.

       //
       // ACCEPT
       //
       cpic_obj.cmaccp(         /* Accept_Conversation            */
           conversation_ID,     /*  O: returned conversation ID   */
           cpic_return_code);   /*  O: return code                */
       //
       // RECEIVE
       //
       cpic_obj.cmrcv(          /* Receive                        */
           conversation_ID,     /*  I: conversation ID            */
           data_buffer,         /*  I: where to put received data */
           requested_length,    /*  I: maximum length to receive  */
           data_received,       /*  O: data complete or not?      */
           received_length,     /*  O: length of received data    */
           status_received,     /*  O: has status changed?        */
           rts_received,        /*  O: was RTS received?          */
           cpic_return_code);   /*  O: return code from this call */
      //
      // Do some return code processing
      //
      System.out.println("  Data from Receive:");
      System.out.println("    cpic_return_code        = " +
                         cpic_return_code.intValue());
      System.out.println("    cpic_data_received      = " +
                         data_received.intValue());
      System.out.println("    cpic_received_length    = " +
                         received_length.intValue());
      System.out.println("    cpic_rts_received       = " +
                         rts_received.intValue());
      System.out.println("    cpic_status_received    = " +
                         status_received.intValue());
      // Create a Java String from the array of bytes that you received
      // and print it out.
      String receivedString = new String(data_buffer,0);
      System.out.println(
         "    Recevied string                 = "
         + receivedString );
 
      //
      // BLOCK so that the Server Window doesn't disappear
      //
      try{
           System.out.println("Press any key to continue");
           System.in.read();
         }
      catch
         (IOException e){ e.printStackTrace(); }
      }
    }
 


[ Top of Page | Previous Page | Next Page | Table of Contents | Index ]