Flexible reading of multiple input messages

JMP applications can process multiple input messages that require different input data types.

The following car dealership sample application supports requests to list models, show model details, find cars, cancel orders, and record sales. Each of these requests requires different input data.

The following steps explain how to define the messages to support these requests, and how to access the messages from the application.

  1. Define the primary input message.
    The primary input message is the message that you pass to the MessageQueue.getUnique method to retrieve all of your input messages. Your primary input message must have an I/O area that is large enough to contain any of the input requests that your application might receive. It must also contain at least one field in common with all of your input messages. This common field allows you to determine the input request. In the following code example, the common field is CommandCode, and the maximum length of each message is 64 (the number passed to the IMSFieldMessage constructor):
    public class InputMessage extends IMSFieldMessage {   
    
        final static DLITypeInfo[] fieldInfo = 
        {
           new DLITypeInfo("CommandCode", 
              DLITypeInfo.CHAR, 1, 20),
        };  
    
        public InputMessage()
        { 
            super(fieldInfo, 64, false); 
        }
    }
  2. Define separate input messages for each request.

    Each of these input messages contains the same CommandCode field as its first field. Each of these input messages also uses an IMSFieldMessage constructor that takes an IMSFieldMessage object and a DLITypeInfo array. The IMSFieldMessage constructor allows you to remap the contents of the primary input message using the same type of information with each request; therefore, you do not copy the I/O area of the message, only a reference to this area. The following code example illustrates how to create the input messages for the requests ShowModelDetails, FindACar, and CancelOrder.

    public class ShowModelDetailsInput extends IMSFieldMessage {
       final static DLITypeInfo[] fieldInfo = {
          new DLITypeInfo("CommandCode", DLITypeInfo.CHAR, 1, 20),
          new DLITypeInfo("ModelTypeCode", DLITypeInfo.CHAR, 21, 2)
       };
    
       public ShowModelDetailsInput(InputMessage inputMessage) { 
          super(inputMessage, fieldInfo);
       }
    }
    
    public class FindACarInput extends IMSFieldMessage { 
       final static DLITypeInfo[] fieldInfo = {
          new DLITypeInfo("CommandCode", DLITypeInfo.CHAR, 1, 20), 
          new DLITypeInfo("Make", DLITypeInfo.CHAR, 21, 10),
          new DLITypeInfo("Model", DLITypeInfo.CHAR, 31, 10),
          new DLITypeInfo("Year", DLITypeInfo.CHAR, 41, 4),
          new DLITypeInfo("LowPrice", DLITypeInfo.PACKEDDECIMAL, 45, 5),
          new DLITypeInfo("HighPrice", DLITypeInfo.PACKEDDECIMAL, 50, 5),
          new DLITypeInfo("Color", DLITypeInfo.CHAR, 55, 10),
       };
       public FindACarInput(InputMessage inputMessage) { 
          super(inputMessage, fieldInfo);
       }
    }
    
    public class CancelOrderInput extends IMSFieldMessage { 
       final static DLITypeInfo[] fieldInfo = {
          new DLITypeInfo("CommandCode", DLITypeInfo.CHAR, 1, 20), 
          new DLITypeInfo("OrderNumber", DLITypeInfo.CHAR, 21, 6),
          new DLITypeInfo("DealerNumber", DLITypeInfo.CHAR, 21, 6),
       };
       public CancelOrderInput(InputMessage inputMessage) 
       {
          super(inputMessage, fieldInfo);
       }
    }

Note the following details about the previous code examples:

  • The CommandCode field is defined in every message that reads the command code. If you do not define the field, you must adjust the offsets of the following fields to account for the existence of the CommandCode in the byte array. For example, you can delete the DLITypeInfo entry for CommandCode in the CancelOrderInput class, but the OrderNumber field must still start at offset 21.
  • The length of the base class InputMessage must be large enough to contain any of its subclasses. In this example, the InputMessage class is 64 bytes because the fields of the FindACarInput method require it.
  • Each InputMessage subclass must provide a constructor to create itself from an InputMessage object. This constructor uses a new constructor in the IMSFieldMessage class, called a copy constructor.
Given this design, an application can provide message-reading logic like in the following code example.
while (messageQueue.getUnique(inputMessage)) {
  
    string commandCode=inputMessage.getString("CommandCode").trim();  
 
    if (commandCode.equals("ShowModelDetails")) {      
        showModelDetails(new ShowModelDetailsInput(inputMessage));   

    } else if(commandCode.equals("FindACar")) {      
        findACar(new FindACarInput(inputMessage)); 

    } else {      
        //process an error
    }

}