Sending and Receiving Messages

This chapter discusses how to:

Click to jump to top of pageClick to jump to parent topicUnderstanding Sending and Receiving Messages

To send and receive messages you use PeopleCode to:

Note. You can also send messages directly to the integration gateway, thereby bypassing processing on the integration engine.

Click to jump to top of pageClick to jump to parent topicPrerequisites for Sending and Receiving Messages

Before you can define PeopleCode to generate, send, receive, and process messages, you must define the message channel and message in PeopleSoft Application Designer.

Note. Once you create PeopleCode, you must also define associated nodes and transactions to implement a complete integration.

Click to jump to top of pageClick to jump to parent topicMessaging Process Flows

The integration engine uses asynchronous request processes and synchronous request processes to manage outbound and inbound messages. These processes examine the messaging elements that you create to determine how to treat each message.

Outbound Message Processing Flow

This section discusses message processing flow for outbound messages. In this section, the term process is uses, and refers to either the integration engine's asynchronous request process or its synchronous request process, depending on the type of integration you are preforming.

When a message is sent, it goes through the following steps:

  1. The application triggers the sending PeopleCode that you developed.

  2. The PeopleCode program populates and sends the message by using an asynchronous or synchronous method or function.

  3. The method that the PeopleCode uses to send the message triggers a request process in the application’s integration engine.

  4. The process searches the outbound transaction definitions that are associated with that message definition to determine the valid target nodes for the message.

    The asynchronous process examines only asynchronous transactions, and the synchronous process examines only synchronous transactions. If a processes doesn't find a node definition that contains an outbound transaction specifying that message, the sending method returns an error.

    Note. Any outbound transaction that is found, the message to which it applies, and the node for which it’s defined must all have an active status for the process to proceed.

  5. For each outbound transaction that it finds, the process submits the message to the local gateway, along with transaction information about the node and the target connector that should be used to send the message.

  6. The local gateway transmits the message to the specified target node through the specified target connector.

  7. If this is a synchronous message, the process waits for the target node to pass a response message back through the gateway, then returns it to the calling PeopleCode method or function.

Inbound Message Processing Flow

Each received message goes through the following steps:

  1. The application’s local gateway receives a request message from a remote node or gateway, which specifies the application as its target node.

  2. The local gateway submits the message to the application’s integration engine, which searches the inbound transaction definitions to find one that is associated with the sending node that specifies the same message, version, and transmission type.

  3. If a matching transaction isn’t found, the integration engine returns an error message through the gateway to the sending node.

    If a transaction is found, the integration engine invokes either the asynchronous request process or the synchronous request process, as appropriate, to handle the message.

    Note. Any inbound transaction that is found, the message to which it applies, and the node for which it’s defined must all have an active status for the process to proceed.

  4. The process accesses the message definition that matches the inbound message name and passes the message to the definition’s associated receiving PeopleCode.

  5. If this is a synchronous transaction, the process waits for the receiving PeopleCode to generate and return a response message, then passes it back to the sending node through the gateway.

Click to jump to top of pageClick to jump to parent topicUnderstanding Integration PeopleCode

This section discusses the PeopleCode used for integrations and describes:

Click to jump to top of pageClick to jump to parent topicSending and Receiving PeopleCode

This section discusses the PeopleCode you use for sending messages from PeopleSoft Integration Broker to other systems, as well as the PeopleCode you use for receiving messages into Integration Broker from other systems.

Sending PeopleCode

PeopleCode for sending messages can be located in PeopleCode events associated with records, record fields, and components, and in application engine programs.

In addition to using the Message class for manipulating message content, you also use it to send messages in rowset-based and nonrowset-based formats as described in this section.

PeopleCode used to send messages is highlighted in the following table.

Transmission Type

Message Structure

Sending PeopleCode

Comments

Synchronous

Rowset-based

SyncRequest method.

The SyncRequest method belongs of the Message class.

Synchronous

Nonrowset-based

SyncRequestXMLDoc built-in function.

None.

Asynchronous

Rowset-based

Publish method.

The Publish method belongs to the Message class.

Asynchronous

Nonrowset-based

PublishXMLDoc built-in function.

None.

To work with messages in SOAP format, transform the SOAP documents into XML documents and then use the SyncRequestXMLDoc or PublishXMLDoc built-in functions.

Receiving PeopleCode

The PeopleCode that you use to receive a message must be associated with the message definition. The transmission type of the message determines the location of the PeopleCode program. Place PeopleCode for synchronous messages in the OnRequest event. Place PeopleCode for asynchronous messages in the Subscription event for the message. You access both of these events in PeopleSoft Application Designer.

Transmission Type

Message Structure

Receiving PeopleCode

Comments

Synchronous

Rowset-based.

GetMessage built-in function.

Enter the PeopleCode in the OnRequest event.

Synchronous

Nonrowset-based

GetMessageXMLDoc built-in function.

Enter the PeopleCode in the OnRequest event.

Asynchronous

Rowset-based

GetMessage built-in function.

Enter the PeopleCode in the Subscription event.

Asynchronous

Nonrowset-based

GetMessageXMLDoc built-in function.

Enter the PeopleCode in the Subscription event.

To get content data out of a message, use the following guidelines.

Message Structure

PeopleCode

Comments

Rowset-based.

GetRowSet

None.

Nonrowset-based

GetXMLDoc

You can also use Message class functionality with nonrowset-based messages.

See Using Message Object Functionality With Nonrowset-Based Messages.

Click to jump to top of pageClick to jump to parent topicRouting Events

Routing events determine how a message is routed to or from PeopleSoft Integration Broker. Routing events are accessed on message definitions.

OnRouteSend Event

Use OnRouteSend on outbound synchronous and asynchronous messages to specify to what node PeopleSoft Integration Broker routes a message. This event enables you to apply PeopleCode that filters the destination nodes to which PeopleSoft Integration Broker routes messages.

When the application PeopleCode is invoked to send a message, the transaction definitions in the local database provide a list of target nodes to which PeopleSoft Integration Broker can route the message. The integration engine’s request handler invokes the message definition’s OnRouteSend event, which enables you to apply additional PeopleCode that determines the final target nodes. You can employ this event regardless of how the message is sent.

You can use OnRouteSend to validate the outbound message target node list, prevent the message from transmitting, or redirect it to a completely different set of targets.

OnRouteSend enables you to account for multiple synchronous targets. Only one target node at a time can receive a request message sent with a synchronous transaction. Even though you can define the same outbound synchronous transaction for multiple nodes, you must make sure the transaction resolves to a single target node or the transaction fails.

See Accessing Integration Events.

OnRouteReceive Event

Use OnRouteReceive on inbound synchronous and asynchronous messages to apply PeopleCode that determines whether the default local node accepts the inbound message.

When the integration engine receives a message, the transaction definitions in the local database provide a list of source nodes from which the application can accept the message. The integration engine’s request handler invokes the message definition’s OnRouteReceive event, which enables you to apply PeopleCode that determines whether the default local node accepts the inbound message. You can employ this event regardless of the message transmission type.

See Accessing Integration Events.

ReturnToServer Function

Routing events can get and examine messages that are being routed, but they cannot modify message content in any way. Only one statement in the routing code affects the message: the Message class built-in function ReturnToServer.

In the routing events, only some of the parameters of ReturnToServer are valid. The following table outlines the effect of each valid parameter:

Routing Event

Statement

Effect

OnRouteSend

ReturnToServer(True);

The outbound message target node list is accepted. The message is sent to all nodes on the list.

Note. With more than one target node, an outbound synchronous message fails.

OnRouteSend

ReturnToServer(False);

The outbound message target node list is rejected. The message isn’t sent.

OnRouteSend

ReturnToServer(&node_array);

The outbound message target node list is compared to the list in &node_array. The message is sent only to the nodes on both lists.

OnRouteReceive

ReturnToServer(True);

The inbound message is accepted by the default local node.

OnRouteReceive

ReturnToServer(False);

The inbound message is rejected by the default local node.

Outbound Routing PeopleCode Example

The following OnRouteSend example routes the message according to a newly generated target node list that’s based on a field value in the message:

local message &MSG; local array &NODE_ARRAY; &MSG = GetMessage(); &EMPLID = &MSG.GetRowset()(1).QA_INVEST_HDR.EMPLID.Value; &SELECT_SQL = CreateSQL("select PUBNODE from PS_EMPLID_NODE where EMPLID = :1", &EMPLID); &NODE_ARRAY = CreateArray(); While &SELECT_SQL.Fetch(&PUBNODE) &NODE_ARRAY.Push(&PUBNODE); End-While; ReturnToServer(&NODE_ARRAY);

Inbound Routing PeopleCode Example

The following OnRouteReceive example accepts the message if it contains a field value that’s matched in the local database:

local message &MSG; &MSG = GetMessage(); &BUSINESS_UNIT = &MSG.GetRowset()(1).PO_HDR.BUSINESS_UNIT.Value; SQLExec("Select BUSINESS_UNIT From PS_BUSINESS_UNIT where BUSINESS_UNIT = :1",&BUSINESS_UNIT,&FOUND); If all(&FOUND) Then ReturnToServer(True); Else ReturnToServer(False); End-if;

Click to jump to top of pageClick to jump to parent topicMessaging Events

This section describes events used in messaging.

Outbound Messaging Events

This section describes events used on outbound messages from PeopleSoft to other systems.

OnSend

Use on outbound synchronous and asynchronous messages to override connector properties before sending a message to the integration gateway.

See Setting and Overriding Target Connector Properties at Runtime.

Subscription

Use on outbound asynchronous messages when another system subscribes to a message. This event is used for subscription processing, and for validating and loading message data.

See Creating Message Subscriptions.

Inbound Messaging Events

This section describes events used on inbound messages to PeopleSoft from other systems.

OnRequest

Use on inbound synchronous messages when a response is required.

OnAckReceive

Use on inbound asynchronous messages to access the body of a message acknowledgement to check for SOAP faults.

See Handling Inbound Asynchronous Transactions.

Click to jump to top of pageClick to jump to parent topicMessaging PeopleCode

Messaging PeopleCode enables you to manipulate message content. The three messaging PeopleCode classes you can use for this purpose are:

Message class

Use for rowset or nonrowset-based messages.

XMLDoc class

Use for XML DOM-compliant messages.

SOAPDoc class

Use for SOAP-compliant messages.

XML DOM-compliant and SOAP-compliant messages are nonrowset-based messages. You can use their respective classes to manipulate message content, or use the Message class.

See Also

Using Message Object Functionality With Nonrowset-Based Messages

Message Class

SOAPDoc Class

XmlDoc Class

Click to jump to top of pageClick to jump to parent topicAccessing Integration Events

You access integration events in PeopleSoft Application designer, either from the Message Structure section or from the Message Subscription section of the message definition. The following table lists the integration events and in what section of the message definition you access them.

Integration Event

Where Accessed

OnRouteSend

Message Structure section.

OnRouteReceive

Message Structure section.

OnRequest

Message Structure section.

OnAckReceive

Message Structure section.

OnSend

Message Structure section.

Subscription

Message Subscription section.

Click to jump to top of pageClick to jump to parent topicAccessing Integration Events From the Message Structure Section

To access integration events from the Message Structure section:

  1. In PeopleSoft Application Designer, open the message definition for which you want to apply routing.

  2. Right-click anywhere in the Message Structure section of the message structure view.

  3. Select View PeopleCode.

    The PeopleCode editor for the message definition appears. Make sure the message name appears in the left dropdown list.

  4. Select the event with which to work from the drop-down list on the right. The valid options are:

    The PeopleCode editor for the selected event appears. Enter or modify the program code.

See Also

Using the PeopleCode Editor

Click to jump to top of pageClick to jump to parent topicAccessing Integration Events From the Message Subscription Section

To access integration events from the Message Subscription section:

  1. In PeopleSoft Application Designer, open the message definition for which you want to apply routing.

  2. Right-click the message subscription under the Message Subscriptions section and select View PeopleCode.

The PeopleCode editor for the message subscription appears. To verify that you are accessing the Subscription event, Subscription should appear in the drop-down list on the right side of the editor. Modify the program code as desired.

If no message subscription PeopleCode program name displays under the Message Subscriptions section, no subscription PeopleCode program has been created for the message definition.

See Also

Creating Message Subscriptions

Using the PeopleCode Editor

Click to jump to top of pageClick to jump to parent topicCreating Message Subscriptions

You can create multiple message subscriptions for a message, each with a different name. Each subscription runs parallel with the others, processing its own copy of the message. In this way, a single inbound message can simultaneously be processed for different purposes.

The only purpose of a message subscription is to represent a PeopleCode program associated with the Subscription event. An event does not fire if you do not define at least one message subscription.

To create a message subscription:

  1. Open a message definition in PeopleSoft Application Designer.

  2. Right-click anywhere in the message structure view and select Insert Message Subscription.

    The Message Subscription Properties dialog box appears.

  3. Select the Active check box to enable the subscription.

  4. Enter a name for the subscription program.

  5. Select the Generate Subscription Process Instance check box to automatically produce a unique number that identifies the process request each time that PeopleSoft Process Scheduler runs the subscription in batch mode.

  6. Click OK.

    The Subscription PeopleCode Editor for the subscription appears, and you can write the asynchronous subscription program.

Note. You can modify the subscription properties at any time. Right-click on the subscription name in the Message Structure view and select Message Subscription Properties to open the Message Subscription Properties dialog box.

See Also

Using the PeopleCode Editor

Click to jump to top of pageClick to jump to parent topicGenerating and Sending Messages

This section provides an overview of outbound messaging and discusses how to handle:

Click to jump to top of pageClick to jump to parent topicUnderstanding Outbound Messaging

Successful outbound messaging relies on sending messages in the proper order and on testing the messages. Messages containing non-XML data have special considerations.

Message Order

PeopleSoft Integration Broker guarantees that messages are delivered in the order in which they were sent and that they’re single-threaded at the PeopleSoft receiving node. However, message order is not part of the channel definition. You must send messages in the proper order.

Note. You can modify this behavior by using channel partitioning.

See Applying Channel Partitioning.

Message Testing

Make sure that you adequately unit-test and system-test your messages.

Unit-test a message by triggering the PeopleCode that sends the message, then viewing it in the Integration Broker Monitor. From the Integration Broker Monitor, you can view the contents of each field to verify that the message data is formatted correctly.

See Using Integration Broker Monitor.

You can also trigger a message with the Test Message feature in PeopleSoft Application Designer.

See Generating Test Messages.

Message Class Outbound PeopleCode

Use SelectByKey whenever possible to get data that isn’t in the component buffer.

If the record names are the same, use the standard record methods, such as SelectByKey, Insert, and Update, on the message records.

Use If &Msg.Size > %MaxMessageSize at Level 0 to control message size when dealing with multiple transactions.

Note. The OnRouteSend event that is associated with the message definition enables you to apply PeopleCode that filters the destination nodes.

See Accessing Integration Events.

Non-XML Data

If you’re generating a non-XML outbound message, it’s up to you to insert the message content into a special XML section containing a CDATA tag:

<xml psnonxml="yes"> <![CDATA[nonXML_message_data]]>

Click to jump to top of pageClick to jump to parent topicHandling Outbound Asynchronous Transactions

Use the Publish method in the PeopleCode Message class or the PublishXmlDoc built-in function. To send a message asynchronously, you can employ Publish or PublishXmlDoc in:

Message Class Outbound Asynchronous Example

The following example uses the Publish method in the PeopleCode Message class:

Local Message &MSG; Local Rowset &SALES_ORDER, &RS; /*Get a pointer to the component buffer rowset */ &SALES_ORDER = GetLevel0(); /*Create an instance of the SALES_ORDER_ASYNC message object */ &MSG = CreateMessage(Message.SALES_ORDER_ASYNC); /*Copy the rows from the rowset to the message object */ &MSG.CopyRowset(&SALES_ORDER); /*Send the message */ &MSG.Publish();

XmlDoc Class Outbound Asynchronous Example

The following example uses the PublishXmlDoc built-in function in the PeopleCode XmlDoc class:

Local XmlDoc &xmlRequestDoc; /* Create an XmlDoc object */ &xmlRequestDoc = CreateXmlDoc(); /* Parse an input XML file into an XmlDoc */ &bool = &xmlRequestDoc.ParseXmlFromURL("C:\pt\appserv\files\input.xml"); /* Send request */ PublishXmlDoc(&xmlRequestDoc, Message.MyMessage, Node.MyNode);

Identifying SOAP Faults

You can use the PeopleCode event OnAckReceive to access IBInfo data. This enables you to read the content of acknowledgements returned by recipient systems of asynchronous SOAP messages. The ability to access acknowledgement content is useful when sending SOAP messages, since although there may be no HTTP protocol errors while sending them, SOAP faults may occur.

If the message is nonrowset-based, use &MSG.GetXmlDoc() to get the response data. This returns an XmlDoc object.

If the message is rowset-based, use &MSG.GetXMLString() to get the response data. This returns a string object which you can load into an XmlDoc object.

If SOAP faults are found, you can set the status equal to Error so that the errors appear in Integration Broker Monitor for the Publication Contract.

The following code example shows how to use &MSG.GetXmlDoc() and &MSG.GetXMLString() in the OnAckReceive event. Valid status overrides are %Message_Done, %Message_Error, and %Message_Retry.

Local Message &MSG; Local string &str; Local XmlDoc &xmldoc; &MSG = GetMessage(); /* if message is nonrowset-based */ &xmldoc = &MSG.GetXmlDoc(); /* if message is rowset-based */ &str = &MSG.GenXMLString(); ReturnToServer(%Message_Done);

You can also use the OnAckReceive PeopleCode event to read response content data returned from third-party systems when using the HTTP target connector.

See Also

XmlDoc Class

Click to jump to top of pageClick to jump to parent topicHandling Outbound Synchronous Transactions

Use the SyncRequest method in the PeopleCode Message class or the SyncRequestXmlDoc built-in function. To send a message synchronously, you can employ SyncRequest or SyncRequestXmlDoc in:

Note. The OnRequest event and subscription programs are triggered only when an inbound transaction occurs, but when the receiving PeopleCode runs, it can also send messages.

The response message that is returned from an outbound synchronous transaction is no different from an inbound request message. Once you have it in a Message, XmlDoc, or SoapDoc object, it has the same properties as any other object of that type and can, therefore, be treated exactly the same way.

See Receiving and Processing Messages.

Message Class Outbound Synchronous Example 1

The following example uses the SyncRequest method in the PeopleCode Message class:

Local Message &MSG, &response; Local Rowset &SALES_ORDER; &SALES_ORDER = GetLevel0(); &MSG = CreateMessage(Message.SALES_ORDER_SYNC); &MSG.CopyRowsetDelta(&SALES_ORDER); /* send the synchronous request; the return value is the response message object */ &response = &MSG.SyncRequest(); /* check the response status; 0 means OK */ If (&response.ResponseStatus = 0) Then /* process the response */ MY_SALES_ORDER_SYNC.ORDER_ID = &response.GetRowset().GetRow(1) .GetRecord(Record.SO_RESPONSE).GetField(Field.ORDER_ID).Value); else /* do error handling */ End-If;

Message Class Outbound Synchronous Example 2

The following example shows the use of CopyTo to get the data back from the response and into the component buffer, and therefore the page:

Local Message &msgZipRequest, &msgZipResponse; Local Rowset &RS, &rsMessageRowset; &RS = GetLevel0(); &msgZipRequest = CreateMessage(Message.ZIP_REQUEST); &msgZipRequest.CopyRowset(&RS); /* send the synchronous request; the return value is the response message object */ &msgZipResponse = &msgZipRequest.SyncRequest(Node.ZIPTOCITYANDSTATE); /* check the response status; 0 means OK */ If (&msgZipResponse.ResponseStatus = 0) Then /* process the response */ &rsMessageRowset = &msgZipResponse.GetRowset(); &rsMessageRowset.CopyTo(&RS); else /* do error handling */ End-If;

XmlDoc Class Outbound Synchronous Example

The following example uses the SyncRequestXmlDoc built-in function:

Local string &xmlString; Local XmlDoc &xmlRequestDoc; Local XmlDoc &xmlResponseDoc; Local Field &DescrLong; &DescrLong = GetLevel0().GetRow(1).GetRecord(Record.QE_FUNCLIB_IB).DESCRLONG; /* Get the input XML string */ &xmlString = &DescrLong.Value; /* Parse the input XML string into an XmlDoc */ &xmlRequestDoc = CreateXmlDoc(&xmlString); /* Send request */ &xmlResponseDoc = SyncRequestXmlDoc(&xmlRequestDoc, Message.XMLSYNCREQ); /* Display the output XML string */ &DescrLong.Value = &xmlResponseDoc.GenXmlString();

SoapDoc Class Outbound Synchronous Example

The following example uses the SyncRequestXmlDoc built-in function.

Note. Because SyncRequestXmlDoc is an XmlDoc built-in function, you must convert the SoapDoc request message to an XmlDoc object before sending it. Likewise, the response message is an XmlDoc object, so you must convert it to a SoapDoc object to process it with SOAP methods.

Local File &MY_FILE; Local XmlDoc &request, &response; Local string &strXml; Local SoapDoc &soapReq, &soapRes; &soapReq = CreateSoapDoc(); &bool = &soapReq.ParseXmlFromURL("C:\pt\appserv\files\inputSoap.xml"); &strXml = &soapReq.GenXmlString(); &MY_FILE = GetFile("c:\temp\syncInput.txt", "w", "a", %FilePath_Absolute); &MY_FILE.WriteLine("YEAH!"); &MY_FILE.WriteLine(&strXml); &MY_FILE.Close(); /* Convert request from SoapDoc to XmlDoc before sending */ &request = &soapReq.XmlDoc; &response = SyncRequestXmlDoc(&request, Message.QE_SOAP_REQ, Node.UNDERDOG); &soapRes = CreateSoapDoc(); /* Convert response from XmlDoc back to SoapDoc */ &soapRes.XmlDoc = &response; &OK = &soapRes.ValidateSoapDoc(); &strXml = &soapRes.GenXmlString(); &MY_FILE = GetFile("c:\temp\sync.txt", "w", "a", %FilePath_Absolute); &MY_FILE.WriteLine(&strXml); &MY_FILE.Close();

See Also

XmlDoc Class

Click to jump to top of pageClick to jump to parent topicOverriding Synchronous Timeout Intervals at Runtime

For long-running outbound synchronous transactions, you can override the default timeout period the transaction at runtime using the SyncServiceTimeout property. The default synchronous timeout period is five minutes.

The HTTP header file is modified to take this parameter. The value you set is sent to the integration gateway where it is used for the HTTP timeout.

The SyncServiceTimeout property takes a time (in seconds). The property is read-write.

The following code example shows how to use the property. To use this property, note that you must override and setup the target connector properties for the transaction. As the example demonstrates, there are helper methods that load properties based on node or transaction.

&MSG.SetXmlDoc((&xmlReq); &MSG.IBInfo.LoadConnectorPropFromNode(Node.EAI) &MSG.IBInfo.SyncServiceTimeout(360000); &MSG.IBInfo.ConnectorOverride = true; &MSG_Resp = SyncRequest(&MSG, Node.EAI); &xmlResponseDoc = &MSG.GetXmlDoc();

See Also

Setting and Overriding Target Connector Properties at Runtime

PeopleSoft Timeout Settings

Click to jump to top of pageClick to jump to parent topicHandling Cookies

PeopleSoft Integration Broker provides basic cookie handling for exchanges that are initiated by your PeopleSoft application. You can accept a synchronous response message containing cookies, save those cookies in a global variable, and later return them to the remote node in an outbound synchronous or asynchronous request message. This is a typical application of cookies in a web interaction.

Cookies are implemented as a property, Cookies, of a Message object or as part of IBInfo. You can access this property only in an inbound synchronous response message or an outbound request message.

Receiving Cookies Example

The following example retains the cookies from a response message to a global variable:

Local Message &SalesRequest, &SalesResponse; Local Rowset &SALES_ORDER; Global string &SalesCookies; &SALES_ORDER = GetLevel0(); &SalesRequest = CreateMessage(Message.SALES_ORDER_SYNC); &SalesRequest.CopyRowsetDelta(&SALES_ORDER); /* Send the synchronous request; the return value is the response message object */ &SalesResponse = &SalesRequest.SyncRequest(); /* Retrieve cookies from the response message */ &SalesCookies = &SalesResponse.Cookies;

Returning Cookies Example

The following example retrieves the previously retained cookies from the global variable and inserts them into a new request message:

Local Message &SalesRequest, &SalesResponse; Local Rowset &SALES_ORDER; Global string &SalesCookies; &SALES_ORDER = GetLevel0(); &SalesRequest = CreateMessage(Message.SALES_ORDER_SYNC); &SalesRequest.CopyRowsetDelta(&SALES_ORDER); /* Insert the cookies in the request message */ &SalesRequest.Cookies = &SalesCookies; /* Send the asynchronous request */ &SalesRequest.Publish();

Click to jump to top of pageClick to jump to parent topicSetting and Overriding Target Connector Properties at Runtime

PeopleSoft Integration Broker enables you to dynamically override target connector properties at runtime that have previously been set at the node, connector and transaction levels. To set or override target connectors at runtime, use the PeopleCode IBInfo object, the Connector Info object and the OnSend event.

Note. Properties set at the PeopleCode level take precedence over those set at the node, connector and transaction level.

IBInfo object

The IBInfo object is a member of the Message object. The methods and properties can be accessed by the IBInfo property on the Message object.

You can use this object in publishing or synchronous request PeopleCode, or by adding an OnSend event to a message definition.

ConnectorInfo object

The ConnectorInfo object is a member of the IBInfo object. The methods and properties for this object can be accessed by the IBInfo property on the Message object. Use this object for reading and writing connector name/value pair information to and from the IBRequest.

You can use this object in publishing or synchronous request PeopleCode, or by adding an OnSend event to a message definition.

OnSend Event

The OnSend event is associated with a message definition and enables you to override target connector properties at runtime for a subscribing node transaction.

This event executes before any transformations are processed.

You can use this event for asynchronous and synchronous messages.

Since data is always carried with the message, you can use the IBInfo object, ConnectorInfo object and OnSend event to populate connector information in the publishing PeopleCode and then override it for a specific node.

Setting and Overriding Target Connector Properties Using the OnSend Event

You can use the OnSend event to override IBInfo and connector properties at runtime for a subscribing node transaction.

Any content data that is changed on the message or XMLDoc is sent to the subscribing node or used within a transformation.

To override the properties of a target connector, you must set the following statement to true:

&MSG.IBInfo.ConnectorOverride=true

If a publication contract fails as a result of using the OnSend event to override connector properties at runtime, correct the PeopleCode in the OnSend event and resubmit the message.

Example: Setting Target Connector Properties Using the OnSend Event

The following example shows loading all connectors that exist for the node and adding one additional property, Filename.

Local Message &Msg; //Get Message &Msg = GetMessage(); &Bo = &MSG.IBInfo.LoadConnectorPropFromNode("nodename"); &Bo = &MSG.IBInfo.IBConnectorInfo.AddConnectorProperties ("FILENAME", "temp", %Property); &MSG.IBInfo.ConnectorOverride = True; ReturnToServer(&MSG);

Example: Overriding Connector Properties Using the OnSend Event

The following example demonstrates overriding target connector properties using the OnSend event for a rowset-based asynchronous message.

Local MESSAGE &MSG; Local Boolean &bRet; &MSG = GetMessage(); &bRet= &MSG.IBInfo.LoadConnectorProp("FILEOUTPUT"); &MSG.IBInfo.ConnectorOverride = True; &bRet= &MSG.IBInfo.IBConnectorInfo.AddConnectorProperties ("sendUncompressed", "Y", %Header); &bRet= &MSG.IBInfo.IBConnectorInfo.AddConnectorProperties ("FilePath", "c:\temp", %Property); ReturnToServer(&MSG);

The following example demonstrates overriding target connector properties using the OnSend event for a nonrowset-based asynchronous message.

Local MESSAGE &MSG; Local XmlDoc &xmldoc; Local Boolean &bRet; &MSG = GetMessage(); // if you have to access the content data for content based decisions, do this &xmldoc = &MSG.GetXmlDoc(); &bRet= &MSG.IBInfo.LoadConnectorProp("FILEOUTPUT"); &MSG.IBInfo.ConnectorOverride = True; &bRet= &MSG.IBInfo.IBConnectorInfo.AddConnectorProperties ("sendUncompressed", "Y", %Header); &bRet= &MSG.IBInfo.IBConnectorInfo.AddConnectorProperties ("FilePath", "c:\temp", %Property); ReturnToServer(&MSG);

See Also

IBInfo Class

ConnectorInfo Collection

Message Class

Click to jump to top of pageClick to jump to parent topicReceiving and Processing Messages

This section discusses how to handle:

Note. The OnRouteReceive event that is associated with the message definition enables you to apply PeopleCode that determines whether the default local node accepts the inbound message.

Click to jump to top of pageClick to jump to parent topicUnderstanding Publication IDs and Subscription PeopleCode

Generally, if a message is successfully published, the PubID and PubNodeName properties are set to the publication ID and publishing system node name, respectively. The only exception is when a publish is performed as part of subscription PeopleCode. In this situation, the subscription process is always executed in deferred mode, due to performance considerations, and so the PubID is not populated.

Click to jump to top of pageClick to jump to parent topicHandling Inbound Asynchronous Transactions

Use the GetMessage or GetMessageXmlDoc built-in function and insert your PeopleCode in a message subscription.

Message Class Inbound Asynchronous Example 1

The following example uses the GetMessage built-in function:

Local Message &MSG; Local Rowset &LEVEL0; Local Record &SALES_ORDER_INFO, &REC; &MSG = GetMessage(); &SALES_ORDER_INFO = CreateRecord(Record.QE_SALES_ORDER); &LEVEL0 = &MSG.GetRowset(); &REC = &LEVEL0(1).QE_SALES_ORDER; &REC.CopyFieldsTo(&SALES_ORDER_INFO); SQLExec("DELETE FROM PS_QE_SALES_ORDER"); &SALES_ORDER_INFO.Insert();

Message Class Inbound Asynchronous Example 2

The following example shows subscription PeopleCode that checks the PSCAMA to determine the audit action code and that examines the language code to determine whether related language processing is needed:

/* Simple PeopleCode Subscribe- - Check the PSCAMA*/ Local Message &MSG; Local Rowset &MSG_RS; Local Record &REC_NAME_PREFIX, &REC, &REC_RL; &MSG = GetMessage(); &MSG_RS = &MSG.GetRowset(); For &I = 1 To &MSG_RS.RowCount /* Loop through all transactions */ &REC = &MSG_RS.GetRow(&I).GetRecord(Record.NAME_PREFIX_TBL); /* Get Audit Action for this transaction */ &ACTION = &MSG_RS.GetRow(&I).PSCAMA.AUDIT_ACTN.Value; /* Get Language code for this transaction */ &LNG = &MSG_RS.GetRow(&I).PSCAMA.LANGUAGE_CD.Value; &BASE_LNG = %Language; Evaluate &ACTION /*****************************/ /******** Add a Record *******/ /*****************************/ When "A" /* Add the base language record */ &REC_NAME_PREFIX = CreateRecord(Record.NAME_PREFIX_TBL); &REC.CopyFieldsTo(&REC_NAME_PREFIX); &REC_NAME_PREFIX.ExecuteEdits(); If &REC_NAME_PREFIX.IsEditError Then /* error handling */ Else &REC_NAME_PREFIX.Insert(); /* Need error handling here if insert fails */ If &LNG <> %Language Then /* add related language record */ &RELLNG = &REC.RelLangRecName; &REC_RL = CreateRecord(Record.NAME_PREFIX_LNG); &REC.CopyFieldsTo(&REC_RL); &REC_RL.LANGUAGE_CD.Value = &LNG; &REC_RL.Insert(); /* Need error handling here if insert fails */ End-If; End-If; /*****************************/ /***** Change a Record *******/ /*****************************/ /**** Using record objects ***/ When "C" /* Get the Record - insert it */ &KEY1 = &REC.GetField(Field.NAME_PREFIX).Value; &REC_NAME_PREFIX = CreateRecord(Record.NAME_PREFIX_TBL); &REC_NAME_PREFIX.NAME_PREFIX.Value = &REC.GetField(Field.NAME_PREFIX).Value; If &REC_NAME_PREFIX.SelectByKey() Then &REC.CopyFieldsTo(&REC_NAME_PREFIX); &REC_NAME_PREFIX.ExecuteEdits(); If &REC_NAME_PREFIX.IsEditError Then /* error handling */ Else &REC_NAME_PREFIX.Update(); End-If; Else &REC.CopyFieldsTo(&REC_NAME_PREFIX); &REC_NAME_PREFIX.ExecuteEdits(); If &REC_NAME_PREFIX.IsEditError Then /* error handling */ Else &REC_NAME_PREFIX.Insert(); End-If; End-If; /*****************************/ /****** Delete a Record ******/ /*****************************/ /*** Using SQLExec ***********/ When "D" /* Get the Record using SQLExec- error */ &KEY1 = &REC.GetField(Field.NAME_PREFIX).Value; SQLExec("Select NAME_PREFIX from PS_NAME_PREFIX_TBL where NAME_PREFIX = :1", &KEY1, &KEY2); If None(&KEY2) Then /* Send to error log */ Else SQLExec("Delete from PS_NAME_PREFIX_TBL where NAME_PREFIX = :1", &KEY1); SQLExec("Delete from PS_NAME_PREFIX_LNG where NAME_PREFIX = :1", &KEY1); End-If; End-Evaluate; End-For;

Message Class Inbound Asynchronous Example 3

The following example shows subscription PeopleCode with multiple transactions:

Local Message &STOCK_MSG; Local Rowset &HDR_RS, &LN_RS; Local Record &HDR_REC, &hdr_rec_msg, &LN_REC, &LN_REC_MSG; /* This subscription peoplecode processes messages that may contain multiple Header (MSR_HDR_INV) transactions that may have multiple line (DEMAND_INF_INV) transactions. The data is inserted into identically structured header/line tables (MSR_HDR_INV2 and DEMAND_INF_INV2) */ /* Get the STOCK_MSG App. Message rowset */ &STOCK_MSG = GetMessage(); /* Create record objects for the Header and Lines that will be inserted into */ &HDR_REC = CreateRecord(Record.MSR_HDR_INV2); &LN_REC = CreateRecord(Record.DEMAND_INF_INV2); /* Create an App. Message Rowset that includes the MSR_HDR_INV (Header) and DEMAND_INF_INV (Line)*/ &HDR_RS = &STOCK_MSG.GetRowset(); /* Clear out all the Headers and Lines */ SQLExec("DELETE FROM PS_MSR_HDR_INV2 WHERE BUSINESS_UNIT = 'M04A1'"); SQLExec("DELETE FROM PS_DEMAND_INF_INV2 WHERE BUSINESS_UNIT = 'M04A1'"); /* Loop through all the headers in the message */ For &I = 1 To &HDR_RS.ActiveRowCount /* Instantiate the row within the Header portion of the /* App Message rowset to which data will be copied */ &hdr_rec_msg = &HDR_RS.GetRow(&I).GetRecord(Record.MSR_HDR_INV); /* Copy data from the level 0 (Header portion) of /* &STOCK_MSG message structure into the Header record object */ &hdr_rec_msg.CopyFieldsTo(&HDR_REC); &HDR_REC.Insert(); /* Create Rowset that includes the DEMAND_INF_INV (Line) portion of the App Message Rowset */ &LN_RS = &HDR_RS(&I).GetRowset(1); /* Loop through all the lines within this header transaction */ For &J = 1 To &LN_RS.ActiveRowCount /* Instantiate the row within the Line portion of the /* App Message rowset to which data will be copied */ &LN_REC_MSG = &LN_RS.GetRow(&J).GetRecord(Record.DEMAND_INF_INV); /* copy data into the Level 1 (Line portion) of &STOCK_MSG object */ &LN_REC_MSG.CopyFieldsTo(&LN_REC); &LN_REC.Insert(); End-For; End-For;

Message Class Inbound Asynchronous Example 4

There’s a practical limit to how large a message can be, and this can be controlled by a system-wide variable called %MaxMessageSize. The system administrator can change this size in the PSOPTIONS settings. This size can be set only for all messages, not for individual definitions.

PeopleCode that populates a Message object should include code that is similar to the following example to check the message size before inserting a new Level 0 row.

Note. Always code the %MaxMessageSize checkpoint at the Level 0 record. A batch of transactions can be split across multiple messages, but do not split a single transaction (logical unit of work) into multiple messages.

Local SQL &hdr_sql, &ln_sql; Local Message &STOCK_MSG; Local Rowset &hdr_rs, &ln_rs; Local Record &hdr_rec, &ln_rec, &hdr_rec_msg, &ln_rec_msg; /* This PeopleCode will publish messages for a simple Header/Line record combination. Multiple Header/Lines are copied to the message until the %MaxMessageSize is exceeded at which point a new message is built. This references MSR_HDR_INV (Header) and DEMAND_INF_INV (Line) records */ /* Create an instance of the STOCK_REQUEST message */ &STOCK_MSG = CreateMessage(Message.STOCK_REQUEST); /* Create an App. Message Rowset that includes the MSR_HDR_INV (Header) and DEMAND_INF_INV (Line)*/ &hdr_rs = &STOCK_MSG.GetRowset(); /* Create a SQL object to select the Header rows */ &hdr_sql = CreateSQL("Select * from PS_MSR_HDR_INV WHERE BUSINESS_UNIT='M04A1' AND ORDER_NO LIKE 'Z%' ORDER BY BUSINESS_UNIT,ORDER_NO"); &I = 1; /* Create record objects for the Header and Lines */ &ln_rec = CreateRecord(Record.DEMAND_INF_INV); &hdr_rec = CreateRecord(Record.MSR_HDR_INV); /* Loop through each Header row that is fetched */ While &hdr_sql.Fetch(&hdr_rec) /* Publish the message if its size exceeds the MaxMessageSize /* specified in Utilities/Use/PeopleTools Options */ If &STOCK_MSG.Size > %MaxMessageSize Then &STOCK_MSG.Publish(); &I = 1; /* Create a new instance of the message object */ &STOCK_MSG = CreateMessage(Message.STOCK_REQUEST); &hdr_rs = &STOCK_MSG.GetRowset(); End-If; If &I > 1 Then &hdr_rs.InsertRow(&I - 1); End-If; /* Instantiate the row within the Header portion of the App Message rowset to which data will be copied */ &hdr_rec_msg = &hdr_rs.GetRow(&I).GetRecord(Record.MSR_HDR_INV); /* Copy data into the level 0 (Header portion) of /* &STOCK_MSG message structure */ &hdr_rec.CopyFieldsTo(&hdr_rec_msg); /* Publish the last message if it has been changed*/ If &hdr_rec_msg.IsChanged Then &STOCK_MSG.Publish(); End-If; End-While;

Message Class Inbound Asynchronous Example 5

The following code example shows how to get data out of the IBInfo object for a rowset-based message.

Local Message &MSG; Local Rowset &rs, &rs1; Local Record &FLIGHTDATA, &REC; Local string &acnumber_value, &msi_sensor_value, &ofp_value, &actype_value, &callsign_value, &squadron_value, &comm1_value, &comm2_value, &ecm_value, &datetime; Local XmlDoc &xmldoc; Local string &data; Local boolean &bo; &CRLF = Char(13) | Char(10); &MSG = GetMessage(); /* this is how one wouild access data from IBinfo and /* IBConnectorInfo objects*/ &bo = &MSG.IBInfo.ConnectorOverride; For &i = 1 To &MSG.IBInfo.IBConnectorInfo.GetNumberOfConnectorProperties() &data = &MSG.IBInfo.IBConnectorInfo.GetQueryStringArgName(&i); &data = &MSG.IBInfo.IBConnectorInfo.GetQueryStringArgValue(&i); End-For; &MSG.IBInfo.IBConnectorInfo.ClearConnectorProperties(); &data = &MSG.IBInfo.IBConnectorInfo.ConnectorName; &data = &MSG.IBInfo.IBConnectorInfo.ConnectorClassName; &data = &MSG.IBInfo.IBConnectorInfo.RemoteFrameworkURL; &data = &MSG.IBInfo.IBConnectorInfo.PathInfo; &data = &MSG.IBInfo.IBConnectorInfo.Cookies; For &i = 1 To &MSG.IBInfo.IBConnectorInfo.GetNumberOfQueryStringArgs() &data = &MSG.IBInfo.IBConnectorInfo.GetConnectorPropertiesName(&i); &data = &MSG.IBInfo.IBConnectorInfo.GetConnectorPropertiesValue(&i); &data = &MSG.IBInfo.IBConnectorInfo.GetConnectorPropertiesType(&i); End-For; &MSG.IBInfo.IBConnectorInfo.ClearQueryStringArgs(); &datao = &MSG.IBInfo.MessageType; &data = &MSG.IBInfo.RequestingNodeName; &data = &MSG.IBInfo.OrigUser; &data = &MSG.IBInfo.OrigNode; &data = &MSG.IBInfo.AppServerDomain; &data = &MSG.IBInfo.OrigProcess; &data = &MSG.IBInfo.OrigTimeStamp; &data = &MSG.IBInfo.DestinationNode; &data = &MSG.IBInfo.FinalDestinationNode; &data = &MSG.IBInfo.SourceNode; &data = &MSG.IBInfo.MessageName; &data = &MSG.IBInfo.MessageVersion; &data = &MSG.IBInfo.VisitedNodes; /* get the content data from the message rowset*/ &rs = &MSG.GetRowset(); &REC = &rs(1).QE_FLIGHTDATA; &FLIGHTDATA = CreateRecord(Record.QE_FLIGHTDATA); &REC.CopyFieldsTo(&FLIGHTDATA); /* Parse out Message Data */ &acnumber_value = &FLIGHTDATA.QE_ACNUMBER.Value; &msi_sensor_value = &FLIGHTDATA.QE_MSI_SENSOR.Value; &ofp_value = &FLIGHTDATA.QE_OFP.Value; &actype_value = &FLIGHTDATA.QE_ACTYPE.Value; &callsign_value = &FLIGHTDATA.QE_CALLSIGN.Value; &squadron_value = &FLIGHTDATA.QE_SQUADRON.Value; &comm1_value = &FLIGHTDATA.QE_COMM1.Value; &comm2_value = &FLIGHTDATA.QE_COMM2.Value; &ecm_value = &FLIGHTDATA.QE_ECM.Value; &datetime = &FLIGHTDATA.ACTIONDTTM.Value; &outstring = "Send Async FLight test"; /* Construct Output String */ &outstring = &outstring | &acnumber_value | &CRLF | &msi_sensor_value | &CRLF | &ofp_value | &CRLF | &actype_value | &CRLF | &callsign_value | &CRLF | &squadron_value | &CRLF | &comm1_value | &CRLF | &comm2_value | &CRLF | &ecm_value | &datetime; /* Log Output String into page record */ &FLIGHTDATA.GetField(Field.DESCRLONG).Value = &outstring; SQLExec("DELETE FROM PS_QE_FLIGHTDATA"); &FLIGHTDATA.Insert();

Message Class Inbound Asynchronous Example 6

The following code example shows how to get data out of the IBInfo object for a nonrowset-based message.

Local Message &MSG; Local XmlDoc &xmldoc; Local XmlNode &node, &root, &acct_id_node, &acct_name_node, &address_node, &phone_node; Local string &outstring, &CRLF; Local Record &FLIGHT_DATA_INFO, &REC; Local string &data; Local boolean &bo; &MSG = GetMessage(); /* this is how one wouild access data from IBinfo and /* IBConnectorInfo objects*/ &bo = &MSG.IBInfo.ConnectorOverride; For &i = 1 To &MSG.IBInfo.IBConnectorInfo.GetNumberOfConnectorProperties() &data = &MSG.IBInfo.IBConnectorInfo.GetQueryStringArgName(&i); &data = &MSG.IBInfo.IBConnectorInfo.GetQueryStringArgValue(&i); End-For; &MSG.IBInfo.IBConnectorInfo.ClearConnectorProperties(); &data = &MSG.IBInfo.IBConnectorInfo.ConnectorName; &data = &MSG.IBInfo.IBConnectorInfo.ConnectorClassName; &data = &MSG.IBInfo.IBConnectorInfo.RemoteFrameworkURL; &data = &MSG.IBInfo.IBConnectorInfo.PathInfo; &data = &MSG.IBInfo.IBConnectorInfo.Cookies; For &i = 1 To &MSG.IBInfo.IBConnectorInfo.GetNumberOfQueryStringArgs() &data = &MSG.IBInfo.IBConnectorInfo.GetConnectorPropertiesName(&i); &data = &MSG.IBInfo.IBConnectorInfo.GetConnectorPropertiesValue(&i); &data = &MSG.IBInfo.IBConnectorInfo.GetConnectorPropertiesType(&i); End-For; &MSG.IBInfo.IBConnectorInfo.ClearQueryStringArgs(); &data = &MSG.IBInfo.MessageType; &data = &MSG.IBInfo.RequestingNodeName; &data = &MSG.IBInfo.OrigUser; &data = &MSG.IBInfo.OrigNode; &data = &MSG.IBInfo.AppServerDomain; &data = &MSG.IBInfo.OrigProcess; &data = &MSG.IBInfo.OrigTimeStamp; &data = &MSG.IBInfo.DestinationNode; &data = &MSG.IBInfo.FinalDestinationNode; &data = &MSG.IBInfo.SourceNode; &data = &MSG.IBInfo.MessageName; &data = &MSG.IBInfo.MessageVersion; &data = &MSG.IBInfo.VisitedNodes; &xmldoc = &MSG.GetXmlDoc(); &CRLF = Char(13) | Char(10); /* get the content data from the message into an xmldoc object*/ &xmldoc = GetMessageXmlDoc(); &root = &xmldoc.DocumentElement; /* Get values out of XMLDoc */ &node_array = &root.GetElementsByTagName("actype"); &ac_type_node = &node_array.Get(1); &ac_type_value = &ac_type_node.NodeValue; &node_array = &root.GetElementsByTagName("msi_sensor"); &msi_sensor_node = &node_array.Get(1); &msi_sensor_value = &msi_sensor_node.NodeValue; &node_array = &root.GetElementsByTagName("callsign"); &callsign_node = &node_array.Get(1); &callsign_value = &callsign_node.NodeValue; &node_array = &root.GetElementsByTagName("ofp"); &ofp_node = &node_array.Get(1); &ofp_value = &ofp_node.NodeValue; &outstring = "GetDataout of xmldoc Test"; &outstring = &outstring | &CRLF | &ac_type_value | &CRLF | &msi_sensor_node | &CRLF | &callsign_value | &CRLF | &ofp_value; /* Write out the result string */ SQLExec("DELETE FROM PS_QE_FLIGHT_DATA"); &FLIGHT_DATA_INFO = CreateRecord(Record.QE_FLIGHT_DATA); &FLIGHT_DATA_INFO.GetField(Field.DESCRLONG).Value = &outstring; &FLIGHT_DATA_INFO.Insert();

Message Class Inbound Asynchronous Example 7

The following example show a message subscription using a component interface in the subscription. This example shows error trapping and has multilanguage support:

PanelGroup string &PUBNODENAME; /* save pubnodename to prevent circular publishes */ Local Message &MSG; Local Rowset &MSG_ROWSET, &cur_rowset; Local ApiObject &oSession; Local ApiObject &CONTACT_CI; Local number &I; Local string &KEY1; Local Record &REC; Local boolean &BC_CREATE, &ADD; Local boolean &TRANSACTION_ERROR, &MSG_ERROR; /** Transaction/Message Error Flags **/ Function errorHandler() Local ApiObject &oPSMessageColl; Local ApiObject &oPSMessage; Local string &strErrMsgSetNum, &strErrMsgNum, &strErrMsgText, &strErrType; &oPSMessageColl = &oSession.PSMessages; For &I = 1 To &oPSMessageColl.Count &oPSMessage = &oPSMessageColl.Item(&I); &strErrMsgSetNum = &oPSMessage.MessageSetNumber; &strErrMsgNum = &oPSMessage.MessageNumber; &strErrMsgText = &oPSMessage.Text; &LogFile.WriteLine(&strErrType | " (" | &strErrMsgSetNum | "," | &strErrMsgNum | ") - " | &strErrMsgText); End-For; rem ***** Delete the Messages from the collection *****; &oPSMessageColl.DeleteAll(); End-Function; Function DO_CI_SUBSCRIBE() &oSession = %Session; &CONTACT_CI = &oSession.GETCOMPONENT(CompIntfc.CONTACT); If (&CONTACT_CI = Null) Then /* Replace this message with Tools message set when available */ Error MsgGet(91, 58, " Unable to get the Component Interface."); Exit (1); End-If; /** Set Component Interface Properties **/ &CONTACT_CI.GetHistoryItems = True; &CONTACT_CI.Interactivemode = False; /** set this to True while debugging **/ rem Send messages to the PSMessage Collection; &oSession.PSMessagesMode = 1; &MSG_ERROR = False; For &I = 1 To &MSG_ROWSET.ActiveRowCount /** Set Session Language Code Property **/ &REGIONALSETTINGS = &oSession.RegionalSettings; &REGIONALSETTINGS.LanguageCd = &MSG_ROWSET(&I).PSCAMA.LANGUAGE_CD.Value; &TRANSACTION_ERROR = False; &BC_CREATE = False; /** Instantiate Component Interface **/ &KEY1 = &MSG_ROWSET(&I).CONTACT_TBL.PERSON_ID.Value; &CONTACT_CI.PERSON_ID = &KEY1; Evaluate &MSG_ROWSET(&I).PSCAMA.AUDIT_ACTN.Value When = "A" When = "N" &ADD = True; /* Check if Keys already exist. */ &CONTACT_CIColl = &CONTACT_CI.Find(); /*If None(&EXISTS) Then*/ If &CONTACT_CIColl.Count = 0 Then If &CONTACT_CI.Create() Then &BC_CREATE = True; Else /* Replace this message with Tools message set when available */ Warning MsgGet(18022, 56, "Error creating Component Interface for transaction %1", &I); &TRANSACTION_ERROR = True; End-If; Else If Not &CONTACT_CI.Get() Then /* Replace this message with Tools message set when available */ Warning MsgGet(18022, 59, "Could not Get Component Interface for transaction %1", &I); &TRANSACTION_ERROR = True; End-If; End-If; Break; When = "C" &ADD = False; If Not &CONTACT_CI.Get() Then /* Replace this message with Tools message set when available */ Warning MsgGet(18022, 59, "Could not Get Component Interface for transaction %1", &I); &TRANSACTION_ERROR = True; End-If; Break; When = "D" When = "K" When-Other /* delete and old key action codes not allowed at this time */ &TRANSACTION_ERROR = True; Warning MsgGet(18022, 61, "Audit Action 'D' not allowed on transaction %1", &TRANSACTION); Break; End-Evaluate; &CONTACT_CI.CopyRowset(&MSG_ROWSET, &I); If Not &TRANSACTION_ERROR Then If Not &CONTACT_CI.save() Then /* Replace this message with Tools message set when available */ Warning MsgGet(18022, 57, "Error saving Component Interface for transaction %1", &TRANSACTION); &TRANSACTION_ERROR = True; End-If; End-If; /** close the last Component Interface in preparation for getting the next **/ If Not &CONTACT_CI.Cancel() Then /* Replace this message with Tools message set when available */ Warning MsgGet(18022, 58, "Error Canceling Component Interface for transaction %1", &TRANSACTION); Exit (1); End-If; /* Reset &TRANSACTION_ERROR to "False" for &BusComp.Save() to execute if no /* Transaction Error found in the next Transaction. */ &TRANSACTION_ERROR = False; End-For; If &TRANSACTION_ERROR Then &MSG_ERROR = True; End-If; End-Function; /**** Main Process ****/ &MSG = GetMessage(); &MSG.ExecuteEdits(%Edit_Required + %Edit_TranslateTable); If &MSG.IsEditError Then &MSG_ERROR = True; Else &PUBNODENAME = &MSG.PubNodeName; &MSG_ROWSET = &MSG.GetRowset(); /* Do Component Interface subscribe */ DO_CI_SUBSCRIBE(); End-If; If &MSG_ERROR Then Exit (1); End-If;

XmlDoc Class Inbound Asynchronous Example

The following example uses the GetMessageXmlDoc built-in function:

Local XmlDoc &BIGMAN; Local XmlNode &node, &root; Local string &outstring; Local Rowset &LEVEL0; Local Record &SALES_ORDER_INFO, &REC; &CRLF = Char(13) | Char(10); &BIGMAN = GetMessageXmlDoc(); &root = &BIGMAN.DocumentElement; &child_count = &root.ChildNodeCount; /* Get values out of XmlDoc */ &node_array = &root.GetElementsByTagName("QE_ACCT_ID"); &acct_id_node = &node_array.Get(2); &account_id_value = &acct_id_node.NodeValue; &node_array = &root.GetElementsByTagName("QE_ACCOUNT_NAME"); &acct_name_node = &node_array.Get(2); &account_name_value = &acct_name_node.NodeValue; &node_array = &root.GetElementsByTagName("QE_ADDRESS"); &address_node = &node_array.Get(2); &address_value = &address_node.NodeValue; &node_array = &root.GetElementsByTagName("QE_PHONE"); &phone_node = &node_array.Get(2); &phone_value = &phone_node.NodeValue; &outstring = "GetMessageXmlDoc Test"; &outstring = &outstring | &CRLF | &account_id_value | &CRLF | &account_name_value | &CRLF | &address_value | &CRLF | &phone_value; &SALES_ORDER_INFO = CreateRecord(Record.QE_SALES_ORDER); &SALES_ORDER_INFO.GetField(Field.QE_ACCT_ID).Value = &account_id_value; &SALES_ORDER_INFO.GetField(Field.DESCRLONG).Value = &outstring; &SALES_ORDER_INFO.Update();

Click to jump to top of pageClick to jump to parent topicHandling Inbound Synchronous Transactions

Use the GetMessage or GetMessageXmlDoc built-in function and place your PeopleCode in the message OnRequest event.

When you receive an inbound request message, the response message must conform to the return type that is expected by the sending code. If the sender uses the SyncRequest method  in the PeopleCode Message class, you must respond with a Message object. If the sender uses the SyncRequestXmlDoc built-in function, you must respond with an XmlDoc or SoapDoc object.

Message Class Inbound Synchronous Example

The following example uses the GetMessage built-in function:

Local Message &request, &response; &request = GetMessage(); &response = CreateMessage(Message.QE_SO_SYNC_RESP); &response.GetRowset().GetRow(1).GetRecord(Record.QE_SO_RESPONSE) .GetField(Field.DESCRLONG).Value = "He's a nice person "; ReturnToServer(&response);

XmlDoc Class Inbound Synchronous Example

The following example uses the GetMessageXmlDoc built-in function:

Local XmlDoc &xmlRequestDoc; Local XmlDoc &xmlResponseDoc; Local XmlNode &select; Local array of XmlNode &whereClause; Local string &recordName; Local string &fieldName; Local string &fieldValue; Local Rowset &outputRowset; Local boolean &b; &xmlRequestDoc = GetMessageXmlDoc(); &select = &xmlRequestDoc.DocumentElement; &recordName = &select.GetAttributeValue("record"); &outputRowset = CreateRowset(@("Record." | &recordName)); &whereClause = &select.GetElementsByTagName("where"); If &whereClause <> Null And &whereClause.Len <> 0 Then &fieldName = &whereClause.Get(1).GetAttributeValue("field"); &fieldValue = &whereClause.Get(1).GetAttributeValue("value"); &outputRowset.Fill("WHERE " | &fieldName | "= :1", &fieldValue); Else &outputRowset.Fill(); End-If; &xmlResponseDoc = CreateXmlDoc(); &b = &xmlResponseDoc.CopyRowset(&outputRowset); ReturnToServer(&xmlResponseDoc);

SoapDoc Class Inbound Synchronous Example

The following example uses the GetMessageXmlDoc built-in function:

Note. Because GetMessageXmlDoc is an XmlDoc built-in function, you must receive the inbound request message as an XmlDoc object, then convert it to a SoapDoc object to process it with SOAP methods. Likewise, because the request was sent by using SyncRequestXmlDoc, you must convert the SoapDoc response message to an XmlDoc object before returning it.

Local XmlDoc &request, &response; Local string &strXml; Local SoapDocs &soapReq, &soapRes; &soapReq = CreateSoapDoc(); &request = GetMessageXmlDoc(); &soapReq.XmlDoc = &request; &OK = &soapReq.ValidateSoapDoc(); &parmN = &soapReq.GetParmName(1); &parmV = &soapReq.GetParmValue(1); &soapRes = CreateSoapDoc(); &soapRes.AddEnvelope(0); &soapRes.AddBody(); &soapRes.AddMethod("StockPrice", 1); &soapRes.AddParm(&parmN, &parmV); &soapRes.AddParm("Price", "29"); &OK = &soapRes.ValidateSoapDoc(); &response = &soapRes.XmlDoc; ReturnToServer(&response);

Click to jump to top of pageClick to jump to parent topicSimulating Receiving Messages from External Nodes

You can use PeopleCode to simulate receiving asynchronous messages from external nodes, including running transformations.

Use can use the InboundPublish method, a method of the Message object, to work with rowset-based and nonrowset-based messages. Use the InboundPublishXMLDoc function to work with nonrowset-based messages.

The following example shows an inbound publish off a subscription with a rowset-based message:

Local Message &MSG, &MSG_REMOTE; Local Rowset &rs; &MSG = GetMessage(); &rs = &MSG.GetRowset(); /*create the message to be re-published from a simualted remote node*/ &MSG_REMOTE = CreateMessage(Message.QE_FLIGHTPLAN); &MSG_REMOTE.CopyRowset(&rs); &MSG_REMOTE.InBoundPublish(Node.REMOTE_NODE);

The following example shows an inbound publish off a subscription with a nonrowset-based message:

Local Message &MSG, &MSG_REMOTE; Local XmlDoc &xmldoc; Local Rowset &rs; &MSG = GetMessage(); &rs = &MSG.GetRowset(); /*create the message to be re-published from a simualted remote node*/ &MSG_REMOTE = CreateMessage(Message.QE_FLIGHTPLAN); /* populate the &xmldoc with data to be re-published*/ &MSG_REMOTE.SetXmlDoc(&xmldoc); &MSG_REMOTE.InBoundPublish(Node.REMOTE_NODE);

The following examples shows using InboundPublishXmlDoc off a subscription with a nonrowset-based message.

Local XmlDoc &xmldoc; Local boolean &bReturn; &xmldoc = GetMessageXmlDoc(); &bReturn = InBoundPublishXmlDoc(&xmldoc, Message.QE_FLIGHTPLAN, Node.REMOTE_NODE);

Click to jump to top of pageClick to jump to parent topicProcessing Inbound Errors

This section discusses how to:

Click to jump to top of pageClick to jump to parent topicValidating Data

You validate data differently depending on the PeopleCode class that you’re using to receive the message.

XMLDoc Class Validation

You can validate incoming XML DOM-compliant messages by using the XmlDoc document type definition (DTD) that is delivered with your PeopleSoft application.

See XmlDoc Class.

SoapDoc Class Validation

You can validate SOAP-compliant messages by using the ValidateSoapDoc method in the PeopleCode SoapDoc class.

See SOAPDoc Class.

Message Class Validation

Have a message receiving process validate incoming data by:

The ExecuteEdits method uses the definitional edits to validate the message. You can specify the following system variables alone or in combination. If you don’t specify a variable, all of the edits are processed.

The following example processes all edits for all levels of data in the message structure:

&MYMSG.ExecuteEdits();

The following example processes the Required Field and Prompt Table edits:

&RECPURCHASEORDER.ExecuteEdits(%Edit_Required + %Edit_PromptTable);

ExecuteEdits uses set processing to validate data. Validation by using a component interface or a PeopleCode built-in function is usually done with row-by-row processing. If a message contains a large number of rows per rowset, consider writing the message to a staging table and calling an Application Engine program to do set processing if you want additional error checking.

ExecuteEdits sets several properties on several objects if there are any errors:

If you don’t want to use ExecuteEdits, you can set your own errors by using the field properties. Setting the EditError property to True automatically sets the IsEditError message property to True. You can also specify your own message number, message set number, and so on, for the field. If you use the Exit(1) built-in function, the message status changes to Error when you finish setting the fields that are in error.

Click to jump to top of pageClick to jump to parent topicUsing the Exit Built-in Function

Use the Exit built-in function to invoke a messaging error process when the application finds an error. This works only when you use the PeopleCode Message class to process inbound transactions. The same error processing is invoked automatically if PeopleTools finds an unexpected error, such as a Structured Query Language (SQL) error. The Exit built-in function has an optional parameter that affects how the error is handled.

To handle error processing in application tables, use the Exit built-in function with no parameter, or just let the subscription process finish normally. This marks the message receipt as successful and commits the data.

To handle the error tracking and correction with PeopleSoft Integration Broker, use the Exit built-in function with 1 as a parameter to log the errors, perform a rollback, and stop processing.

Exit( )

In the Exit( ) form, all data is committed and the message is marked as complete. Use this to indicate that everything processed correctly and to stop program processing. Note, though, that the message status is set to Complete; therefore, you can’t detect or access errors in the Integration Broker Monitor. If errors did occur, the subscription code should write them to a staging table, and then you must handle all of the error processing.

The Exit built-in function:

Following is an example of the Exit( ) form:

&MSG.ExecuteEdits(); If &MSG.IsEditError then App_Specific_Error_Processing(); Exit(); Else Specific_Message_Processing(); End-if;

Exit(1)

In this form, the Exit built-in function:

You can view all errors that have occurred for this message in the Integration Broker Monitor, even those errors that are detected by ExecuteEdits.

Following is an example of the Exit(1) form:

&MSG.ExecuteEdits(); If &MSG.IsEditError then Exit(1); Else Process_Message(); End-if;

See Also

Using Integration Broker Monitor

Exit

Click to jump to top of pageClick to jump to parent topicCorrecting Messaging Errors

If you anticipate few errors, correct them on the Message Errors page in the Integration Broker Monitor.

If you have many errors, you may want to create a page that a user can use to correct the data for a particular message. Generally, users will be correcting errors that were detected when running the ExecuteEdits method in the PeopleCode Message class or another built-in function as part of the receiving code.

For the search record for your page, you can create a view based on the MSGNAME and SUBCONSTATUS fields of the PSAPMSGSUBCON record. MSGNAME lists all of the messages that have subscription contracts. The SUBCONSTATUS field has the following values:

Status

Value

ERROR

0

NEW

1

STARTED

2

WORKING

3

DONE

4

RETRY

5

TIMEOUT

6

EDITED

7

CANCELLED

8

If you create a page, you must specify it in the message definition properties. After you define it, you can either use it as a regular page or access it from the Message Details link in the Integration Broker Monitor.

Correcting Message Errors in PeopleCode

The following code is located in the PreBuild event of a page that’s used to fix message errors. It gets the inbound message as specified by the search record (PSAPMSGSUBCON) and loads the fields of a work record (MS_EDIT_WRK) with the data from the XMLDoc &QE_PLAYER:.

Local XmlNode &player_id_node, &root, &player_status_node, &desc_node; &QE_PLAYER = GetSubXmldoc(PSAPMSGSUBCON.PUBID, PSAPMSGSUBCON.PUBNODE, PSAPMSGSUBCON.CHNLNAME, PSAPMSGSUBCON.APMSGVER, PSAPMSGSUBCON.MSGNAME); &root = &QE_PLAYER.DocumentElement; /* Get values out of XMLDoc */ &node_array = &root.GetElementsByTagName("PLAYER ID"); &acct_id_node = &node_array.Get(1); MSG_EDIT_WRK.QE_PLAYER_ID = &player_id_node.NodeValue; &node_array = &root.GetElementsByTagName("PLAYER STATUS"); &player_status_node = &node_array.Get(1); MSG_EDIT_WRK.QE_PLAYER_STATUS = &player_status_node.NodeValue; &node_array = &root.GetElementsByTagName("DESC"); &desc_node = &node_array.Get(1); MSG_EDIT_WRK.DESCRLONG = &desc_node.NodeValue;

The following code is located in the SavePostChange event. It takes the values from the work record and repopulates the rowset. Because the data that is in the rowset is identical to the data in the message, this changes the values of the fields in the message. When you use the Update method, the status of the message in the Integration Broker Monitor is automatically changed to Edited.

Local Rowset &RS_PLAYER; Local Message &MSG_EDIT_TEST; &MSG_EDIT_TEST = GetSubMessage(PSAPMSGSUBCON.PUBID, PSAPMSGSUBCON.PUBNODE, PSAPMSGSUBCON.CHNLNAME, PSAPMSGSUBCON.MSGNAME, PSAPMSGSUBCON.SUBNAME); &RS_PLAYER = &MSG_EDIT_TEST.GetRowset(); &RS_PLAYER(1).QE_PLAYER.QE_PLAYER_ID.Value = MSG_EDIT_WRK.QE_PLAYER_ID; &RS_PLAYER(1).QE_PLAYER.QE_PLAYER_STATUS.Value = MSG_EDIT_WRK.QE_PLAYER_STATUS; &RS_PLAYER(1).QE_PLAYER.DESCRLONG.Value = MSG_EDIT_WRK.DESCRLONG; &MSG_EDIT_TEST.Update();

Correcting Data Errors on Pages

To use a predefined page to correct data errors, specify the page on the Use tab in the Message Properties dialog box.

To open the page, open the Integration Broker Monitor and select the Sub Contracts page. Select the message in error and click Message Details.

See Also

Using Integration Broker Monitor

Click to jump to top of pageClick to jump to parent topicUsing Message Object Functionality With Nonrowset-Based Messages

Prior to the PeopleTools 8.44 release, the were two distinct paths for writing and executing PeopleCode for PeopleSoft Integration Broker which were based on whether you were working with rowset-based XML messages or nonrowset-based XML messages.

For rowset-based XML messages, you could use a rowset and all properties and methods within the Message object. For nonrowset-based XML messages, you could not use the Message object, but instead used built-in functions such as PublishXmlDoc and GetMessageXmlDoc. In addition, when working with nonrowset-based messages and these built-in functions, you could only access content data.

Effective with the PeopleTools 8.44 release, when working with nonrowset-based XML messages you can use all of the functionality of the Message object using two new built-in functions, SetXMLDoc and GetXMLDoc.

SetXMLDoc

Use this built-in function to load and pass nonrowset-based data into the Message object.

GetXMLDoc

Use this built-in function to get nonrowset-based data out of the message object.

Click to jump to top of pageClick to jump to parent topicUsing the SetXMLDoc Built-In Function

The following example shows how to use SetXMLDoc to use the Message object to publish a nonrowset-based message.

//&XmlDoc holds the nonrowset-based data as before. // create an instance of the Message object &MSG = CreateMessage(Message.QE_F18_ASYNC_XMLDOC); // Load the Message object with the xmldoc data. &MSG.SetXmlDoc(&XmlDoc); // perform a publish for the nonrowset-based message &MSG.Publish();

Click to jump to top of pageClick to jump to parent topicUsing the GetXMLDoc Built-In Function

The following code example shows how to use GetXMLDoc to get nonrowset-based XML out of the Message object.

Local MESSAGE &MSG; Local XMLDOC &XmlDoc; // Get the Message object &MSG = GetMessage(); // get an xmldoc object loaded with the content data. &XmlDoc = &MSG.GetXmlDoc();

See Also

Enterprise PeopleTools 8.46 PeopleBook: PeopleCode Language Reference

Click to jump to top of pageClick to jump to parent topicGenerating Test Messages

Because the message is not actually sent, creation of a test message is not a full send-and-receive test; however, it provides useful information about the message definition and its associated PeopleCode.

To create a test message:

  1. In the message definition, right-click the message version that you want to test and select Create Test Message.

    A test message appears showing the structure of the message. Select the Show Common Message Attributes box to display the PeopleSoft Common Application Message Attributes (PSCAMA) fields in the test message.

  2. Enter sample data for the fields in the message.

    To enter sample data for a field, double-click the field and enter a value. You can also right-click the field and select Edit Value.

    Note. To publish every field in the message, you must enter sample data in at least one field of every record.

  3. Click OK to publish the test message.

  4. Use Integration Broker Monitor to view the results of the test message.

See Also

PSCAMA

Using Integration Broker Monitor

Click to jump to top of pageClick to jump to parent topicWorking With Message Segments

This chapter provides an overview of message segments and discusses how to:

Click to jump to top of pageClick to jump to parent topicUnderstanding Message Segments

When you create message segments, you can divide rowset-based and nonrowset-based messages into multiple data containers, or segments, for sending. Depending on the order in which you send a message that contains message segments, the receiving system can process the message as a whole, or process one segment at a time while the others are compressed in memory or held in the application database.

As a result creating message segments can enhance system performance and message exchange, especially when you are working with large messages that exceed one gigabyte (1 GB).

To create and manage message segments, you use several methods and properties of the PeopleCode Message class.

Click to jump to top of pageClick to jump to parent topicUnderstanding PeopleCode used to Work with Message Segments

This section discusses:

Methods Used with Message Segments

The following table lists the PeopleCode methods you can use when you work with message segments.

Method

Class

Description

CreateNextSegment

Message

Designates the end point of one segment and the beginning of a new segment.

CurrentSegment

Message

Returns the segment number of the rowset or XMLDoc to which the data is referring.

DeleteSegment

Message

Deletes a segment.

GetSegment

Message

Gets the segment specified by the passed value. The passed value is the segment number.

UpdateSegment

Message

Use this method to update data within the current segment.

Note. Use the DeleteSegment and UpdateSegment methods only when storing segments data in memory. These methods do not function when segment data is stored in the database.

Properties Used with Message Segments

The following table lists PeopleCode properties that you can use when you work with message segments.

Property

Class

Description

SegmentsUnOrder

IBInfo

Determines whether to process message segments in order or unordered. This property pertains to asynchronous messages only.

The values are:

  • True: Process message segments unordered.

  • False: Process message segments in order. (Default.)

SegmentCount

Message

Returns the total number of segments in a message.

SegmentsByDatabase

Message

Enables you to override where message segment data is stored for a message.

The values are:

  • True: Store message segments awaiting processing in the application database.

  • False: Store message segments awaiting processing in memory. (Default.)

See Also

Enterprise PeopleTools 8.46 PeopleBook: PeopleCode API Reference

Click to jump to top of pageClick to jump to parent topicConfiguring Nodes to Handle Segmented Messages

This section describes how to configure nodes to handle segmented messages.

Understanding Configuring Nodes to Handle Segmented Messages

Before you can send segmented messages, you must configure the remote node defined on the local system to handle segmented messages by setting the Segment Aware option on the Node Definitions page in the PeopleSoft Pure Internet Architecture.

Warning! Do not set the Segment Aware option for remote PeopleSoft 8.45 or earlier nodes, or for third-party systems. If you do so, the receiving system will consume only the first segment of the messages and ignore any subsequent segments.

Configuring a Node to Handle Segmented Messages

To configure a node to handle segmented messages:

  1. Select PeopleTools, Integration Broker, Integration Setup, Node Definitions.

  2. Select a node with which to work and click OK.

    The Node Definitions page appears.

  3. Select the Segment Aware box.

  4. Click the Save button.

Click to jump to top of pageClick to jump to parent topicCreating Message Segments

This section provides an overview of creating message segments and message segment numbers and discusses how to:

Understanding Creating Message Segments

By default every message has one segment.

To create multiple message segments use the CreateNextSegment method in the location in the message where you want one segment to end and next segment to begin. Continue this process until you have created the desired number of segments for the message.

Segments can contain any number of rowsets of data (rowset-based messages) or rows of data (nonrowset-based messages).

Understanding Message Segment Numbers

When you create a message segment, PeopleSoft Integration Broker assigns a message segment number to the segment.

The first message segment has a message segment number or 1, and message segment numbers are increment by one sequentially thereafter. As an example, if you break a message into three segments, the first segment number is 1, the second segment number is 2, and the third segment number is 3.

Creating Message Segments

The following example shows using the CreateNextSegment method to create three segments in the message QE_FLIGHTPLAN, populating each segment with data from the component buffer.

&MSG = CreateMessage(Message.QE_FLIGHTPLAN); &rs=&MSG.GetRowset(); //Now populate rowset // End of first segment. Beginning of second segment. &MSG.CreateNextSegment(); () &rs=&MSG.GetRowset(); //Now populate rowset //End of second segment. Beginning of third segment. &MSG.CreateNextSegment(); () &rs=&MSG.GetRowset(); //Now populate rowset &MSG.Publish();

Counting the Number of Segments in Messages

You might have the need to determine the number of segments in a message. Use the SegmentCount method to determine this information.

Storing Message Segments Awaiting Processing

By default, message segments awaiting processing are stored in memory until all segments are processed. Once all segments are processed, PeopleSoft Integration Broker sends all data as one message.

Use the MessageSegmentFromDB parameter in PSADMIN to specify the number of segments to keep in memory before writing segmented messages to the database. The default value is 10.

For synchronous messages, if the number of segments sent for processing exceeds the set for the MessageSegmentsFromDB parameter, an error occurs.

Overriding Where to Store Message Segments Awaiting Processing

You can override the number of segments to keep in memory before writing segmented messages to the database for a single message using the SegmentsByDatabase property of the Message class.

Storage Location

Description

Memory

When message segments are stored in memory, PeopleSoft Integration Broker writes all segments as one message to the database when you send the message.

To store message segment data in memory, set the SegmentsByDatabase property to False. (Default.)

Application database

When message segments are stored in the database, PeopleSoft Integration Broker writes the segments to the database individually. When you store message segments in the database you can have an infinite number of segments in a message.

To store message segment data in the application database, set the SegmentsByDatabase property to True.

When you store message segments in memory, the number of segments is limited by the value set in the MessageSegmentFromDB parameter in PSADMIN in the Setting for PUB/SUB servers section of the file.

When working with asynchronous messages, if you create more message segments then the value set, all segments are written to the database automatically and the SegmentsByDatabase property will automatically be set to True.

For synchronous messages, attempting to create more segments then the specified value will result in an error message.

Specifying the Order in Which to Process Message Segments

When you work with segmented asynchronous messages you can specify that PeopleSoft Integration Broker process the segments in order or unordered, using the SegmentsUnOrder property of the Message class.

Message Segment Processing

Description

In order

When Integration Broker processes message segments in order, it decompresses all message segments sequentially and then processes the message as a whole. In this situation, only one publication or subscription contract is created.

To process message segment in order, set the SegmentsUnOrder property to False.

Unordered

When Integration Broker processes message segments unordered, it decompresses and processes all segments in parallel. In this situation, the system creates one publication or subscription contract for each message segment.

To process message segment unordered, set the SegmentsUnOrder property to True.

If you attempt to send ordered segmented messages to a node that is not segment aware an error message will be created and can be viewed on the Message Errors tab on the Message Details page in Integration Broker Monitor.

See Using Integration Broker Monitor.

Chunking Asynchronous Segmented Messages

Chunking asynchronous segmented messages sends message in blocks to the receiving node.

When using chunking, messages instances display in Hold status in Integration Broker Monitor until all chunks are received. Once all chunks are received, the message status switches to New.

Note. Chunking applies to ordered asynchronous messages only.

The number of segments to chunk for an asynchronous message is determined by the value you set for the MessageSegmentByDatabase parameter in PSADMIN. The default value is 10.

As an example, if a message has 20 segments and you set MessageSegmentByDatabase to 5, PeopleSoft Integration Broker will send four groups (array of messages) of segments to the integration gateway, and each group will contain five segments.

Click to jump to top of pageClick to jump to parent topicDeleting Message Segments

You can delete message segments in a message only before you publish the message.

Use the DeleteSegment method of the Message class to perform the action.

You cannot delete the first segment in a message.

The following example demonstrates using the DeleteSegment method in an OnSend event.

Local Message &MSG; Local integer segment_number; &MSG = GetMessage(); For &i = 1 To &MSG.SegmentCount &rs = Null; &MSG.GetSegment(&i); &rs = &MSG.GetRowset(); //determine that segment 3 needs to be deleted. &segment_number = &i; End-For; &MSG.DeleteSegment(&segment_number); ReturnToServer(&MSG);

Click to jump to top of pageClick to jump to parent topicSending and Receiving Segmented Messages

To send a segmented message, use sending PeopleCode and events as you would with any other message.

To receive a segmented message, use subscription PeopleCode or the OnRequest event as you would to subscribe to any message.

Click to jump to top of pageClick to jump to parent topicAccessing Segments in Messages

After you receive a segmented message, use the GetSegment method of the Message class to access message segment data.

After you access a message segment, use the GetRowset method of the Message class or the GetXMLDoc built-in function to work with the contents of the segment.

Warning! You can access only one segment in a message at a time. When you access a message segment, PeopleSoft Integration Broker removes the previously accessed message segment from memory.

When you access a message segment, set the existing rowset to null to eliminate storing multiple rowsets in the data cache.

The following example shows using the GetSegment method to access a message segment in the message QE_FLIGHTDATA.

&MSG = GetMessage(); //loop through the segments and perform logic For &i = 1 To &MSG.SegmentCount &rs = Null; //Null the rowset to remove it from memory &MSG.GetSegment(&i); &rs = &MSG.GetRowset(); &REC = &rs(1).QE_FLIGHTDATA; &FLIGHTDATA = CreateRecord(Record.QE_FLIGHTDATA); &REC.CopyFieldsTo(&FLIGHTDATA); /* Parse out Message Data */ &acnumber_value = &FLIGHTDATA.QE_ACNUMBER.Value; &msi_sensor_value = &FLIGHTDATA.QE_MSI_SENSOR.Value; &ofp_value = &FLIGHTDATA.QE_OFP.Value; &actype_value = &FLIGHTDATA.QE_ACTYPE.Value; &callsign_value = &FLIGHTDATA.QE_CALLSIGN.Value; &squadron_value = &FLIGHTDATA.QE_SQUADRON.Value; &comm1_value = &FLIGHTDATA.QE_COMM1.Value; &comm2_value = &FLIGHTDATA.QE_COMM2.Value; &ecm_value = &FLIGHTDATA.QE_ECM.Value; &outstring = "Send Async Flight test"; /* Construct Output String */ &outstring = &outstring | &acnumber_value | &CRLF | &msi_sensor_value | &CRLF | &ofp_value | &CRLF | &actype_value | &CRLF | &callsign_value | &CRLF | &squadron_value | &CRLF | &comm1_value | &CRLF | &comm2_value | &CRLF | &ecm_value; /* Log Output String into page record */ &FLIGHTDATA.GetField(Field.DESCRLONG).Value = &outstring; SQLExec("DELETE FROM PS_QE_FLIGHTDATA"); &FLIGHTDATA.Insert(); End-For;

Click to jump to top of pageClick to jump to parent topicViewing Message Segment Data

The Integration Broker Monitor Message Details page provides information about messages that contain segments.

See Also

Using Integration Broker Monitor

Click to jump to top of pageClick to jump to parent topicUsing Restartable Processing for Publishing Large Messages in Batch

This section provides an overview, prerequisites and setup steps for using restartable processing for publishing large asynchronous segmented messages in batch.

Click to jump to top of pageClick to jump to parent topicUnderstanding Using Restartable Processing

PeopleSoft provides a PeopleSoft Application Engine library module, IB_SEGTEST, that you can use as a template to create a module to aid in processing large messages and messages in batch for outbound asynchronous PeopleSoft Integration Broker segment data with restart capability.

With restart capability, if there is an abnormal program termination, you can correct any data errors and continue processing from the point of the last commit without having to reload message segment data from the beginning.

Click to jump to top of pageClick to jump to parent topicUnderstanding the IB_SEGTEST Application Engine Library Module

This section provides overview information for using the IB_SEGTEST

The IB_SEGTEST library module consists of three sections:

Click to jump to top of pageClick to jump to parent topicPrerequisites

To use the information provided in this section, you should have a thorough understanding of PeopleSoft Application Engine.

See Also

Enterprise PeopleTools 8.46 PeopleBook: PeopleSoft Application Engine

Click to jump to top of pageClick to jump to parent topicUsing the IB_SEGTEST Library Module

This section provides an overview of the high-level list of tasks to perform to set up a PeopleSoft Application Engine program to perform restartable message processing.

  1. Make a copy of IB_SEGTEST, including all sections and PeopleCode.

    From here on, the copy of the application engine library module is referred to as IB_SEGTEST1, but you can use any name you choose.

  2. In the State Records tab of IB_SEGTEST1, verify that PSIBSEGRSTR_AET is the default state record. Replace PT_EIP_ERR_AET with whatever state record is used in the main application engine program that will be calling the Library module.

    Note that IB_SEGTEST1 is flagged as not restartable. Since database commits will be performed in the middle of PeopleCode processing, the only way the commits can take effect is if the module is flagged as not restartable.

  3. The application engine program used to call IB_SEGTEST1 should be restartable.

    Always issue a commit in the step prior to calling the library module IB_SEGTEST1.

  4. In the application engine program that will be calling IB_SEGTEST1, insert a step to call IB_SEGTEST1, section Section1. Insert the step at the point in time when you want to do the message publish. You must issue a commit prior to calling this section, otherwise there will be a ‘Unable to Process Commit’ error issued from within IB_SEGTEST1.

  5. Add PSIBSEGRSTR_AET as an additional state record to the calling application engine program.

  6. Since both programs now share state records, when IB_SEGTEST1 is called, all state record values will be passed on to the called module. Presumably all application values needed to extract application data would be stored in the application state record.

  7. Modify the PeopleCode in IB_SEGTEST1.Section1. Several comments have been added to the code to aid in the modifications. Note the following: