IWAYEVT2 Sample Program

Topics:

The IWAYEVT2 sample program (iwayevt2.cobol) is a sample program that tests request/response event handling in the iWay Transaction Adapter for IMS. It sends out a message, prefixed by a 4-byte length, and expects the exact same message as the response.

Sample Program Location and Directory Structure

Topics:

The IWAYEVT2 sample program and related program files are located in the following directory:

<iway_home>\etc\samples\ims\iwayevt2

where:

<iway_home>

Is the location on your system where iWay Service Manager is installed.

The following subdirectories are included for the IWAYEVT2 sample program:

  • cobolfd
  • java
  • src

Cobolfd Subdirectory

Reference:

The cobolfd subdirectory contains the COBOL copybook (IWAYEVT0_IN.CBL) to map the data that is sent from, and returned to, IMS.

Reference: IWAYEVT0_IN.CBL COBOL Copybook

The following is the structure of the IWAYEVT0_IN.CBL COBOL copybook:

05 ALPHA01               PIC X(8).                            
05 INT01                 PIC S9(4) BINARY.
05 PACK01                PIC S9(15) PACKED-DECIMAL.  
05 ZONE01                PIC  9(4).

Java Subdirectory

Reference:

The java subdirectory contains the message-driven Java Bean (InboundEchoBean.java) that actually performs the echo.

Reference: InboundEchoBean.Java Bean

The following is the structure of the Java Bean (InboundEchoBean.java):

/*
 * Created on Feb 11, 2005
 *
 * Copyright (C) 2003-2004, iWay Software/Information Builders, Inc.
 * All Rights Reserved.                                             
 */
package com.iwaysoftware.afjca15.samples;
import javax.ejb.EJBException;
import javax.ejb.MessageDrivenBean;
import javax.ejb.MessageDrivenContext;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Properties;
import java.util.logging.*;
import javax.naming.*;
import javax.resource.cci.MessageListener;
import javax.resource.cci.Record;
import com.ibi.common.IContext;
import com.iwaysoftware.afjca15.IIWAFRecord;
import com.iwaysoftware.afjca15.CCIRecordFactory;
/**
 * A simple message-driven bean. The code illustrates the requirements of a
 * message-driven bean class:
 * <ul>
 * <li>It implements the <code>MessageDrivenBean</code> and
 * <code>CCI MessageListener</code> interfaces.
 * <li>The class is defined as <code>public</code>.
 * <li>The class cannot be defined as <code>abstract</code> or
 * <code>final</code>.
 * <li>It implements one <code>onMessage</code> method.
 * <li>It implements one <code>ejbCreate</code> method and one
 * <code>ejbRemove</code> method.
 * <li>It contains a public constructor with no arguments.
 * <li>It must not define the <code>finalize</code> method.
 * </ul>
 * 
 * Unlike session and entity beans, message-driven beans do not have the remote
 * or local interfaces that define client access. Client components do not
 * locate message-driven beans and invoke methods on them. Although
 * message-driven beans do not have business methods, they may contain helper
 * methods that are invoked internally by the onMessage method.
 *  
 */
public class InboundEchoBean implements MessageDrivenBean, MessageListener {
  static final Logger logger = Logger
   .getLogger("com.iwaysoftware.afjca15.samples");
  private transient MessageDrivenContext mdc = null;
  private Context context;
  /**
   * Default constructor. Creates a bean.
  */
  public InboundEchoBean() {
    logger.info("<MDB> In InboundEchoBean.InboundEchoBean()");
  }
  /**
   * Sets the context for the bean.
   *
   * @param mdc the message-driven-bean context
  */
  public void setMessageDrivenContext(MessageDrivenContext mdc) {
    logger.info("<MDB> In InboundMessageBean.setMessageDrivenContext()");
    this.mdc = mdc;
  }
  /**
   * Creates a bean. Required by EJB spec.
  */
  public void ejbCreate() {
    logger.info("<MDB> In InboundEchoBean.ejbCreate()");
  }
  /**
   * When the IWAF Channel receives a record, the EJB container invokes the
   * <code>onMessage</code> method of the message-driven bean. The
   * <code>onMessage</code> method displays data from the record
   *
   * @param record incoming record
  */
  public Record onMessage(Record record) {
    if (!(record instanceof IIWAFRecord)){
      throw new EJBException("Received 'Record' must be of type 'IWAFRecord'");
    }
  IIWAFRecord iwafRecord = (IIWAFRecord)record;
  try {
    logger.info("<MDB> ---- Got a message ");
    //Event context
    IContext iCtx = iwafRecord.getIContext();
    if (iCtx == null) {
      logger.info("IContext is null");
    } else {
       StringBuffer buf = new StringBuffer();
       buf.append("IContext is [");
       Iterator i = iCtx.attributeNames();
       while (i.hasNext()) {
         String key = (String)i.next();
         Object value = iCtx.getAttribute(key);
         buf.append(" ");
         buf.append(key);
         buf.append("=");
         buf.append(value);
         buf.append(" ");
       }
       buf.append("]");
       logger.info(buf.toString());
    }
    //Event record
    String xmlData = iwafRecord.getRootXML();
    if (xmlData != null) {
      logger.info("<MDB> XML DATA: " + xmlData);
    } else if (iwafRecord.getChars() != null) {
      logger.info("<MDB> CHAR[] DATA: " + new String(iwafRecord.getChars()));
    } else if (iwafRecord.getBytes() != null) {
      logger.info("<MDB> BYTE[] DATA: " + iwafRecord.getBytes());
    }
    //Reply record
    String reply = xmlData;
    //Reply context
    Properties replyContextProperties = new Properties();
    InputStream replyContextStream = this.getClass().getClassLoader().getResourceAsStream("reply_context.properties");
    if (replyContextStream != null) {
      replyContextProperties.load(replyContextStream);
    }
    logger.info("Reply properties: " + replyContextProperties);
    IIWAFRecord replyRecord = (new CCIRecordFactory()).createIWAFRecord("output");
    replyRecord.setRootXML(reply);
    IContext replyContext = replyRecord.getIContext();
    if (iCtx != null) {
      Enumeration e = replyContextProperties.keys();
      while (e.hasMoreElements()) {
        String name = (String)e.nextElement();
        String value = replyContextProperties.getProperty(name);
        replyContext.setAttribute(name, value);
      }
    }
    //return
    return replyRecord;
    } catch (Exception e) {
      logger.throwing(this.getClass().getName(), "OnMessage", e);
      throw new EJBException(e.getMessage());
    }
  } // onMessage
  /**
   * Removes the bean. Required by EJB specification.
  */
  public void ejbRemove() {
    logger.info("<MDB> In InboundMessageBean.remove()");
  }
} // class

SRC Subdirectory

Reference:

The src subdirectory contains the COBOL program (IWAYEVT2.COBOL).

Reference: IWAYEVT2.COBOL Program

The following is the structure of the COBOL program (IWAYEVT2.COBOL):

CBL TRUNC(BIN)
       ID DIVISION.
       PROGRAM-ID. IWAYEVT2.
      ***************************************************************
      * IWAYEVT2 - THIS SAMPLE PROGRAM DEMONSTRATES SENDING A       *
      * RECORD TO THE IWAY IMS ADAPTER USING CICS SOCKETS, AND      *
      * THEN RECEIVING THE SAME DATA BACK (ECHO).  THE DATA RECORD, *
      * MAPPED BY A COPYBOOK, MUST BE PRECEEDED BY A 4 BYTE BINARY  *
      * LENGTH.                                                     *
      *                                                             *
      * THE IMS ADAPTER MUST BE CONFIGURED WITH AN EVENT TO         *
      * RECEIVE THIS DATA.  SELECT "IS LENGTH PREFIX", SYNCHRON-    *
      * IZATION TYPE "REQUEST", AND USE IWAYEVT0.CBL AS THE         *
      * PREPARSER AND PREEMITTER FD.                                *
      *                                                             *
      * HOST AND PORT MUST BE SET BELOW (PROCEDURE DIVISION)        *
      *                                                             *
      * THE EZASOKET INTERFACE IS DOCUMENTED IN THE Z/OS            *
      * COMMUNICATIONS SERVER IP IMS SOCKETS GUIDE.                 *
      *                                                             *
      * USES: IWAYEVT0_IN.CBL     (INPUT RECORD)                    *
      *                                                             *
      ***************************************************************
       ENVIRONMENT DIVISION.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       77  GU                         PIC   X(04) VALUE 'GU  '.
       77  CHNG                       PIC   X(04) VALUE 'CHNG'.
       77  ISRT                       PIC   X(04) VALUE 'ISRT'.
       01 SOCKET-GROUP.
          05 SOC-FUNCTION              PIC X(16) VALUE SPACES.
          05 ERRNO                     PIC 9(8) BINARY VALUE ZEROES.
          05 RETCODE                   PIC S9(8) BINARY VALUE ZEROES.
          05 AF                        PIC 9(8) BINARY VALUE 2.
          05 SOCTYPE                   PIC 9(8) BINARY VALUE 1.
          05 PROTO                     PIC 9(8) BINARY VALUE 0.
          05 NAMELEN                   PIC 9(8) BINARY.
          05 HOSTNAME                  PIC X(255).
          05 HOSTENT                   POINTER.
          05 NAME.
             10 FAMILY                 PIC 9(4) BINARY VALUE 2.
             10 PORT                   PIC 9(4) BINARY.
             10 IP-ADDRESS             PIC 9(8) BINARY.
             10 IP-ADDRESS-ALPHA REDEFINES IP-ADDRESS PIC X(4).
             10 RESERVED               PIC X(8) VALUE LOW-VALUES.
          05 FLAGS                     PIC 9(8) BINARY VALUE 0.
          05 SOCKET                    PIC 9(4) BINARY.
          05 NBYTE                     PIC 9(8) BINARY.
          05 CMD                       PIC 9(8) BINARY.
          05 REQARG                    PIC 9(8) BINARY.
       01 WORKAREA.
          05 LLEN                         PIC 9(8) BINARY VALUE 4.
          05 ERRMSG                       PIC X(41)
             VALUE 'ERROR ENCOUNTERED DURING '.
          05 TMSG                         PIC X(44)
             VALUE 'IWAYEVT2: DATA SENT SUCCESSFULLLY.          '.
          05 RMSG                         PIC X(44)
             VALUE 'IWAYEVT2: DATA RECEIVED SUCCESSFULLY        '.
      ***************************************************************
      * SAMPLE INBOUND DATA RECORD WITH VARIOUS COBOL TYPES.        *
      ***************************************************************
       01 INBOUND-RECORD.
          05 ALPHA01               PIC X(8)
             VALUE 'ABCDEFGH'.
          05 INT01                 PIC S9(4) BINARY VALUE 25.
          05 PACK01                PIC S9(15) PACKED-DECIMAL VALUE 50.
          05 ZONE01                PIC 9(4) VALUE 75.
      ***************************************************************
      * ECHO RESPONSE.                                              *
      ***************************************************************
       01 RESPONSE-BUF.
          02 RESPONSE-LEN          PIC 9(8) BINARY.
          02 RESPONSE              REDEFINES RESPONSE-LEN
                                   PIC X OCCURS 4 TIMES.
          02 OUTBOUND-RECORD.
             05 ALPHA01            PIC X(8).
             05 INT01              PIC S9(4) BINARY.
             05 PACK01             PIC S9(15) PACKED-DECIMAL.
             05 ZONE01             PIC 9(4).
       01 MSG-OUT.
          05  IMS-LL               PIC 9(4) BINARY VALUE 70.
          05  IMS-ZZ               PIC 9(4) BINARY.
          05  MSG                  PIC X(70).
       01  PARM-IN.
          05  SLEN                 PIC S9(4) BINARY.
          05  SCRN-IOA             PIC X(255).
       01 USED                     PIC 9(8) BINARY.
          LINKAGE SECTION.
          01  HOSTENT-STRUCT.
              05  HOSTNAME-PTR   POINTER.
              05  HOSTALIASL-PTR POINTER.
              05  HOSTFAMILY     PIC S9(8) BINARY.
              05  HOSTADR-LEN    PIC S9(8) BINARY.
              05  HOSTADRL-PTR   POINTER.
          01  HOST-ENTRY-PTR     POINTER.
          01  HOST-ENTRY         PIC 9(8) BINARY.
      *********************************************************
      *    I/O PCB                                            *
      *********************************************************
          01  IOPCB.
              05  LTERM                  PIC   X(08).
              05  FILLER                 PIC   X(02).
              05  IOPCB-STATUS           PIC   X(02).
              05  FILLER                 PIC   X(28).
       PROCEDURE DIVISION.
       MAINLINE.
           ENTRY 'DLITCBL' USING IOPCB
           PERFORM GETPARM
      ***************************************************************
      * CHANGE HOSTNAME AND PORT TO SITE SPECIFIC LOCATION OF THE   *
      * IMS ADAPTER.                                                *
      ***************************************************************
           MOVE 'INFORMAT-16C9AB.ibi.com' TO HOSTNAME
           MOVE 4773 TO PORT
           PERFORM GETSOCK
           PERFORM GETHOSTBYNAME
           PERFORM SETBLOCK
           PERFORM CONNECTTOHOST
           PERFORM SENDDATA
           MOVE SPACE TO MSG
           MOVE TMSG  TO MSG
           CALL 'CBLTDLI' USING ISRT, IOPCB, MSG-OUT
           PERFORM RECVDATA
           PERFORM CLOSESOCK
           MOVE RMSG TO MSG
           CALL 'CBLTDLI' USING ISRT, IOPCB, MSG-OUT
           MOVE SPACE TO MSG
           MOVE ALPHA01 OF OUTBOUND-RECORD  TO MSG
           MOVE INT01 OF OUTBOUND-RECORD    TO MSG(10:4)
           MOVE PACK01 OF OUTBOUND-RECORD   TO MSG(16:15)
           MOVE ZONE01 OF OUTBOUND-RECORD   TO MSG(34:4)
           CALL 'CBLTDLI' USING ISRT, IOPCB, MSG-OUT
           GOBACK.
       GETPARM.
           CALL 'CBLTDLI' USING GU, IOPCB, SCRN-IOA
           IF IOPCB-STATUS NOT = SPACES
              PERFORM WRITERR-EXIT
           END-IF
      *    DISPLAY 'INPUT PARM: ' SCRN-IOA
           .
       GETSOCK.
           MOVE 'SOCKET          ' TO SOC-FUNCTION
           CALL 'EZASOKET' USING SOC-FUNCTION,
                AF,
                SOCTYPE,
                PROTO,
                ERRNO,
                RETCODE
           MOVE RETCODE TO SOCKET
           IF RETCODE < 0
              PERFORM WRITERR-EXIT
           END-IF.
       GETHOSTBYNAME.
           MOVE 'GETHOSTBYNAME   ' TO SOC-FUNCTION
           MOVE LENGTH OF HOSTNAME TO NAMELEN
           CALL 'EZASOKET' USING SOC-FUNCTION NAMELEN HOSTNAME
                HOSTENT RETCODE
                IF RETCODE EQUAL ZERO
                   SET ADDRESS OF HOSTENT-STRUCT TO HOSTENT
                   SET ADDRESS OF HOST-ENTRY-PTR TO HOSTADRL-PTR
                   SET ADDRESS OF HOST-ENTRY TO HOST-ENTRY-PTR
                ELSE
                   PERFORM WRITERR-EXIT
                END-IF.
       SETBLOCK.
           MOVE 'FCNTL           ' TO SOC-FUNCTION
           MOVE 4 TO CMD
           MOVE 0 TO REQARG
           CALL 'EZASOKET' USING SOC-FUNCTION, SOCKET, CMD, REQARG,
                           ERRNO, RETCODE.
       CONNECTTOHOST.
           MOVE HOST-ENTRY TO IP-ADDRESS
           MOVE 'CONNECT         ' TO SOC-FUNCTION
           CALL 'EZASOKET' USING SOC-FUNCTION,
                SOCKET,
                NAME,
                ERRNO,
                RETCODE
           IF RETCODE = 0
                CONTINUE
           ELSE
              PERFORM WRITERR-EXIT
           END-IF.
       SENDDATA.
      ***************************************************************
      * PRECEDE THE RECORD WITH 4 BYTE BINARY RECORD LENGTH         *
      ***************************************************************
           MOVE 'SEND            ' TO SOC-FUNCTION
           MOVE LENGTH OF INBOUND-RECORD TO NBYTE
           MOVE 4 TO LLEN
           MOVE 0 TO RETCODE
           CALL 'EZASOKET' USING SOC-FUNCTION,
                 SOCKET,
                 FLAGS,
                 LLEN,
                 NBYTE,
                 ERRNO,
                 RETCODE
           IF RETCODE = -1
              PERFORM WRITERR-EXIT
           END-IF
      ***************************************************************
      * SEND THE ACTUAL RECORD                                      *
      ***************************************************************
           CALL 'EZASOKET' USING SOC-FUNCTION,
                SOCKET,
                FLAGS,
                NBYTE,
                INBOUND-RECORD,
                BY REFERENCE ERRNO,
                RETCODE
           IF RETCODE = -1
              PERFORM WRITERR-EXIT
           END-IF
           .
       RECVDATA.
      ***************************************************************
      * RECEIVE A RESPONSE                                          *
      ***************************************************************
           MOVE LOW-VALUES TO RESPONSE-BUF.
           MOVE LENGTH OF RESPONSE-BUF TO NBYTE.
           MOVE 1 TO USED.
      *
           PERFORM READ-BYTES UNTIL NBYTE < 1.
      *
       READ-BYTES.
           MOVE 'READ            ' TO SOC-FUNCTION
           CALL 'EZASOKET' USING SOC-FUNCTION,
                 SOCKET,
                 NBYTE,
                 RESPONSE(USED),
                 ERRNO,
                 RETCODE.
           IF RETCODE < 0
               PERFORM WRITERR-EXIT
           END-IF
      *
           IF RETCODE = 0
             MOVE 0 TO NBYTE
           ELSE
             ADD RETCODE TO USED
             SUBTRACT RETCODE FROM NBYTE
           END-IF
           .
       CLOSESOCK.
           MOVE ZEROES TO RETCODE ERRNO
           MOVE 'CLOSE           ' TO SOC-FUNCTION
           CALL 'EZASOKET' USING SOC-FUNCTION,
              SOCKET,
              ERRNO,
              RETCODE
           IF RETCODE < 0
              PERFORM WRITERR-EXIT
           END-IF.
       WRITERR-EXIT.
           MOVE SOC-FUNCTION TO ERRMSG(26:15)
           DISPLAY 'ERROR IN PROGRAM FUNCTION: ' ERRMSG.
           GOBACK.