Progress
External Program
Interfaces
Message Objects
The following sections describe the functions and procedures of the Message Objects, including message headers, message properties, and the various message types.
Message Header Interface
The message header provides envelope information about a message. The message header interface is supported by all message types and all message types have the same header information. Header information is the same for both PTP and Pub/Sub messaging.
The message header is not created directly by the application. When any type of message is created, its header procedure is automatically created. The message procedure delegates header method calls to its header procedure.
All the fields of the header can be seen by either the sender or receiver:
- A receiver can read header information set by the sender or by the JMS system when it receives the message.
- A sender can see header information set by the application immediately after setting the header information and see information set by the JMS system (for example, the messageID) after sending a message.
Setting Message Header Information
Header information is:
- Set by the JMS System. For example, the messageID, timestamp, and reDelivered.
- Calculated by the JMS system but derived from information set by the application. For example, if the application sets the time to live, the JMS system calculates the expiration time.
- Set explicitly by the application. For example, the replyTo destination and correlationID.
The following procedure sets a destination for replies. Note that the destination can be a name of a queue even if the message is sent by a Pub/Sub session and the destination can be the name of the topic even if the message is sent by a PTP session. However, in that case, setReplyToDestinationType must be called to set the correct destination type:
The following procedure sets the type of the destination specified by setJMSReplyTo; the type can be “queue” or “topic” If setReplyToDestinationType is not called, a default type is automatically set when the message is sent, according to the type of the session:
The following procedure sets the correlationID. This value is application-defined; typically it is set to the ID of the message replied to:
The following procedure sets the bytes correlationID; the bytesCorrelation ID usage is proprietary (JMS provider-dependent). (A JMS provider is a messaging system that implements the JMS interface.) When accessing SonicMQ, the bytesCorrelationID field can be used for storing application-defined values:
The following procedure sets the type name; the type name is proprietary (JMS provider-dependent). When accessing SonicMQ, the JMSType field can be used for storing application-defined values:
Getting Message Header Information
The following functions return message header information.
The following function returns the SonicMQ Adapter message type: TextMessage, MapMessage, StreamMessage, BytesMessage, HeaderMessage, or XMLMessage:
The following function returns the message ID, a unique ID that the JMS server assigns to each message:
The following function returns the message sending time, which is the difference in milliseconds between the message creation time and midnight, January 1, 1970 UTC:
The following function returns the name of the destination this message was sent to. The value is valid after the message was sent (at the sender side) and in the received message (at the receiver side):
The following function returns true (at the receiver side) if this is not the first delivery of this message. A second delivery can take place if the first delivery is not acknowledged by the receiver or the transaction was rolled back, in a transacted session:
The following function returns the correlationID. This value is application-defined, typically the ID of the message replied to:
The following function returns a proprietary (JMS provider-dependent) correlation ID. When accessing SonicMQ, the bytesCorrelationID field can be used for storing application-defined values:
The following function returns the delivery mode. This value is PERSISTENT, NON_PERSISTENT, or DISCARDABLE. The message receiver never gets the NON_PERSISTENT_ASYNC value. A message sent using NON_PERSISTENT_ASYNC is received with the standard NON_PERSISTENT value:
The following function returns the reply destination. The destination can be the name of a queue, even if the message is received from a Pub/Sub session, and the destination can be the name of a topic even if the message is received from a PTP session. The replyToDestinationType function must be called if both a queue destination and a topic destination might be stored in the received message:
The following function returns “queue,” “topic,” or UNKNOWN. The UNKNOWN value is returned if the message was just created, not sent yet, and setReplyToDestinationType was not called. Call getReplyToDestinationType when the domain of the ReplyTo field is not known:
The following function returns a proprietary (JMS provider-dependent) type name. When accessing SonicMQ, the JMSType field can be used for storing application-defined values:
The following function returns the expiration time (GMT):
The following function returns priority values in the range of 0–9:
The following function returns true if the JMSReplyTo header was set:
Message Properties
Message properties can add more envelope information about a message. There is a fixed number of header fields, but properties are flexible. An application can add any number of properties—property name and value pairs.
The following function returns the message property’s data type. UNKNOWN is returned if the property was not set in the message:
The following function returns a comma-separated list of the properties of the message:
Setting Message Properties
The following procedures set message properties.
NOTE: The server returns a NumberFormatException message for value overflows (for example, if setByteProperty(“prop1”, 1000) is called).The following procedure sets a boolean message property. An UNKNOWN value is considered a false value:
The following procedure sets a bytes message property; the values range from –128 to 127:
The following procedure sets a short message property:
The following procedure sets an int message property:
The following procedure sets a long message property; any fractional part of the DECIMAL value is truncated:
The following procedure sets a float message property:
The following procedure sets a double message property:
The following procedure sets a String message property:
The following procedure clears the body of a message and keeps header and property values unchanged. This procedure transfers a StreamMessage, TextMessage, XMLMessage, and a BytesMessage to write-only mode:
The following procedure clears the properties of the message, keeping header and body values unchanged:
Getting Message Properties
The following function returns a boolean message property:
The following function returns int, short, and byte message properties:
The following function returns any numeric message property:
The following function returns a message property of any data type:
Deleting Messages
The following procedure deletes a message:
Maximum Number Of Messages
The default maximum number of JMS messages in a 4GL session is 50 (the total number of messages created by the application plus messages received from JMS). To change the default to new–val, the following definition must be included in the main procedure of the 4GL application:
Error Display
If setNoErrorDisplay is set to true, messages from errors that occur when methods in a message are called are not automatically displayed. The default value is false. Messages inherit the display/noDisplay property from the session that created them. However, after the message is created, it is independent from the session, and setNoErrorDisplay must be called in the message itself to change the display/noDisplay property:
Message Handler
The message handler is written by an application and must be registered with the Message Consumer object. When a message is received, the message handler is called automatically so the application can process the message.
The messageHandler parameters are:
- message — The message
- messageConsumer — The Message Consumer object that contains this message handler. The application can use the Message Consumer object to get context information about the message (for example, the session handle to the session that received that message) and the context (for example, the session handler).
- reply — The application can reply to the message automatically without having to extract the reply to fields. The application can set the reply parameter with a reply message, and it is automatically sent to the JMSReplyTo destination of the message.
If the setReplyAutoDelete(true) message consumer procedure is called, the reply message is automatically deleted after being sent.
The 4GL programmer implements procedures with the following signature for handling incoming messages (JMS messages and error messages):
TextMessage
An application creates a TextMessage by calling createTextMessage in a Session object with the following output parameter:
The following function returns the total number of characters in the message:
The following function returns true if the last text segment was retrieved:
When a TextMessage is created, it is in a write-only mode. Calling reset changes the mode to read-only and places the cursor before the first text segment. Sending the message causes an implicit reset and the message becomes read-only. The message arrives at the receiver in a reset state:
Setting Text
The following procedure clears the message body and sets a new text value. The call can be made when the message is in write-only or read-only mode. After the call, the message is in write-only mode and additional appendText calls can be made to append more text:
The following procedure can be called in write-only mode to append text to the message in several calls to overcome the Progress 32K limit on the number of characters:
Getting Text
The following function returns all the text in the TextMessage and then implicitly calls reset. A run-time error occurs if the size of the message is too large to be handled by the 4GL interpreter:
The following function can be called in read-only mode to return the next text segment when handling large messages:
Header Messages
A HeaderMessage is a message type that is the 4GL–JMS equivalent of Java’s
javax.jms.Message
, a header-only message. It sends information through message properties without a message body.An application creates a HeaderMessage by calling createHeaderMessage in a Session object with the following output parameter:
StreamMessage
A StreamMessage allows applications to send and receive an unspecified number of items; each item is a Java data type. All basic Java data types are supported. When receiving any arbitrary Java data type, an application uses methods to read and specify a Progress data type. When writing a message from the Progress 4GL, an application uses methods to send any of those Java data types and to specify the data.
To create a StreamMessage, an application calls createStreamMessage in a session object with the following output parameter:
When a StreamMessage is created, it is in a write-only mode. The following procedure changes the mode to read-only. Sending the message causes an implicit reset. The message arrives at the receiver in a reset mode:
The following function returns true if the last item of the stream was retrieved:
Writing Data To a StreamMessage
The following procedures write data to the body of a StreamMessage.
NOTE: The server returns a NumberFormatException message for a value overflow, for example, if writeByte(1000) is called.The following procedure writes boolean data to the body of a StreamMessage. An UNKNOWN value is considered false:
The following procedure writes bytes data to the body of a StreamMessage; byte values are –128 to 127:
The following procedure writes short data to the body of a StreamMessage:
The following procedure writes character data to the body of a StreamMessage; the number of characters in the CHAR value must be one:
The following procedure writes integer data to the body of a StreamMessage:
The following procedure writes long data to the body of a StreamMessage. The fractional part of the DECIMAL value is truncated:
The following procedure writes float data to the body of a StreamMessage:
The following procedure writes double data to the body of a StreamMessage:
The following procedure writes String data to the body of a StreamMessage:
The following procedure writes bytes data to the body of a StreamMessage:
Reading Data From a StreamMessage
The following functions read data from the body of a StreamMessage.
The following function moves the cursor to the next data item and returns its data type, one of the following values: UNKNOWN, boolean, byte, short, char, int, long, float, double, string, or bytes. UNKNOWN is returned when the value of the item is NULL. When the message is received or after reset is called, the cursor is set before the first data item. It is an error to try to move the cursor beyond the last item:
The following function returns boolean data from the body of a StreamMessage:
The following function returns int, short, or bytes data from the body of a StreamMessage:
The following function returns any numeric data from the body of a StreamMessage:
The following function returns any data except bytes data from the body of a StreamMessage:
The following function returns bytes data from the body of a StreamMessage:
MapMessage
A MapMessage contains multiple pairs of item names and item values. When setting the data, the application specifies the Java data type. When getting the data, the application specifies the 4GL data type to convert into. For more information on mapping data types, see the "Data Storage and Extraction Methods" section in this chapter.
An application creates a MapMessage by calling createMapMessage in a Session object with the following output parameter:
The following function returns a comma-separated list of the item names in a MapMessage:
The following function returns the data type of an item in a MapMessage. UNKNOWN is returned if the item does not exist:
Setting Items In a MapMessage
A MapMessage supports setting multiple named item pairs: {item-name, item-value}. The following procedures convert data from 4GL to JMS data types.
NOTE: The server returns a NumberFormatException message for a value overflow, for example, if setByte(“item1”, 1000) is called.The following procedure sets boolean data in a MapMessage. An UNKNOWN value is considered false:
The following procedure sets bytes data in a MapMessage; byte values are –128 to 127:
The following procedure sets short data in a MapMessage:
The following procedure sets character data in a MapMessage; the number of characters in the CHAR value must be one:
The following procedure sets integer data in a MapMessage:
The following procedure sets long data in a MapMessage; any fractional part of the DECIMAL value is truncated:
The following procedure sets float data in a MapMessage:
The following procedure sets double data in a MapMessage:
The following procedure sets String data in a MapMessage:
The following procedure sets bytes data in a MapMessage:
Getting Item Values By Name In a MapMessage
A MapMessage supports getting multiple named item pairs: {item-name, item-value}. The following functions convert data from JMS data types to 4GL data types.
The following function gets a boolean item from a MapMessage:
The following function gets an int, short, or bytes item from a MapMessage:
The following function gets any numeric item from a MapMessage:
The following function gets an item of any data type except bytes from a MapMessage:
The following function gets a bytes item from a MapMessage:
BytesMessage
A BytesMessage is an uninterpreted stream of bytes.
To create a BytesMessage, an application calls createBytesMessage in a Session object with the following output parameter:
The following function returns the number of bytes in a BytesMessage:
The following function returns true if the last bytes segment was retrieved:
NOTE: An application should not call endOfStream if it used getMemptr to extract the data.The following procedure changes the mode of a BytesMessage from write-only mode to read-only mode and places the cursor before the first bytes segment. Sending the message causes an implicit reset. The message arrives at the receiver in a reset state:
MultipartMessage
A multipart message contains one or more message parts. Each message part is identified by a content type and a content ID, and contains a set of message headers and a message body. Message parts can be Sonic messages, character data, and binary data.
When you access a multipart message, you can retrieve each part as a SonicMQ message (if that is how it was sent), as a character data, or as a byte array. The SonicMQ Adapter supports only message parts and byte-array parts returned as a CHARACTER string or a MEMPTR.
The following method creates a multipart message:
The following method adds a Sonic message to a multipart message:
The following method adds binary data to a multipart message:
The following method adds CHARACTER data to a multipart message:
The following method returns the number of parts contained by a multipart message:
The following method returns TRUE if the part specified by the index is a SonicMQ message:
The following method returns the message part corresponding to the given index:
The following method returns the message part corresponding to the given content ID:
The following method returns the bytes part corresponding to the given index:
The following method returns the bytes part corresponding to the given content ID:
Overcoming the 32K RAW Bytes Limit
The RAW data type has a 32K size limit. To bypass this limit, an application can do multiple read... and write... calls as with a TextMessage.
The following procedure can be called in write-only mode to write an additional bytes segment to a BytesMessage:
The following function can be called in read-only mode to return the next bytes segment. The size of all the bytes segments other than the last one is 8192; the size of the last one is 8192 or less:
Writing and Reading MEMPTR Bytes Data
The MEMPTR data type does not have a 32K limit. An application can make one get... or set... MEMPTR call.
The following procedure sets the specified number of bytes from the MEMPTR variable starting at startIndex (the first byte is 1). The setMemptr procedure implicitly calls clearBody before setting the data and resets after setting the data. Therefore, it can be used whether the message is in read-only or write-only mode prior to the call. The call makes a copy of the data. Thus, the memptrVal variable is not modified by the 4GL–JMS implementation and can be modified by the 4GL application after the call without corrupting the message:
The following function returns a reference to a MEMPTR variable that contains exactly all the bytes of the message. The getMemptr function implicitly calls reset. If the message was in a write-only mode, it will be in a read-only/reset mode after the call. The getMemptr function does not create a copy of the MEMPTR variable; it returns a reference to the data maintained by the Message object. The deleteMessage call releases the variable’s memory, and the caller must copy any data it will need or need to modify before deleting the message:
Discardable Messages
Sonic contains a message delivery mode called DISCARDABLE for messages published to a topic. When a message with the delivery mode DISCARDABLE is published to a topic, if the topic’s queue is full, the message is automatically deleted.
The setDefaultPersistency method sets the persistency mode of a session. Its syntax is:
The publish method, which publishes a message to a session, lets you specify the delivery mode. Its syntax is:
XMLMessage
SonicMQ’s XMLMessage is an extension of TextMessage and it supports all the methods of TextMessage. For more information, see the "TextMessage" section in this chapter.
To create an XML message, an application calls createXMLMessage in a Session object with the following output parameter:
XML Code-page Encoding
4GL applications work with the built-in XML parser. It is important to consider the code-page encoding of XML messages. In principle, XML documents can be encoded with any code page. However, XML parsers support some or all code pages, and XML parsers also differ in the code-page conversions they support.
4GL clients set and get XML text using the 4GL CHARACTER data type. CHARACTER data is encoded by the 4GL interpreter using the internal code page (the –cpinternal startup parameter). The 4GL–JMS implementation automatically converts the text to Unicode when sent to the JMS server and from Unicode to the internal client’s code page when sent from the server to client.
In general, when the characters used by the XML document are from the 7 byte ASCII subset, there are no issues the 4GL programmer has to consider. Otherwise, observe the following examples and guidelines.
Example 1
In this example, two 4GL clients use the ISO8859-1 code page:
- Client1 sets XML text in an XML message and sends it.
- Client2 receives the message, extracts the text, stores it in a MEMPTR variable, and creates an XML document. (See the "Publishing, Receiving, and Parsing an XMLMessage" section in Using the SonicMQ Adapter.")
The following code-page conversions take place:
In this example, the XML parser parses the XML document correctly if the header of the document specifies that the encoding is ISO8859-1 and the parser can handle ISO8859-1.
Example 2
In this example, two 4GL clients use ISO8859–1 for their internal code page. Client1 saves a UTF–8 encoded XML document in a MEMPTR variable (using the X–DOC:SAVE() 4GL method) and then uses the 4GL GET–STRING statement to extract the text from the MEMPTR and pass it into the XML message. (This is a deliberate error.) UTF–8 (Unicode Transformation Format) is an 8-bit encoding form that serializes a Unicode scalar value as a sequence of one to four bytes.
A 4GL client cannot mix code pages. The text it sets in the XML message must be encoded in the same code page as the client’s internal code page. In general, a MEMPTR variable must be used carefully, since it can have any data in it. The 4GL programmer must be sure that it contains only NULL free text (no embedded NULL bytes), encoded with the same code page as the internal code page, before loading it into an XML message.
In this example, if the 4GL client cannot be started up with –cpinternal UTF–8, but still wants to use 4GL–JMS to pass that UTF–8 document, it can use a BytesMessage or bytes elements in a StreamMessage. When sent as bytes, the XML data will get to the receiver uninterpreted and unconverted. The 4GL receiver can then set the data in a MEMPTR variable and load the parser. (See the "Publishing, Subscribing, and Receiving an XML Document In a BytesMessage" section in Using the SonicMQ Adapter.") A second option is to convert the text (and the document’s header) to ISO8859–1 using the CODEPAGE–CONVERT 4GL function.
If the 4GL receiver of an XML message is unsure about the XML header encoding declaration, it must check it and perhaps modify it to match its internal code page before loading the parser.
Copyright © 2004 Progress Software Corporation www.progress.com Voice: (781) 280-4000 Fax: (781) 280-4095 |