Author Info
Chris Malek

Chris Malek is a PeopleTools® Technical Consultant with two decades of experience working on PeopleSoft enterprise software projects. He is available for consulting engagements.

About Chris Work with Chris
Looking for pain-free PeopleSoft web services? 😀
PeopleSoft Simple Web Services (SWS)

Introducing a small but powerful PeopleSoft bolt-on that makes web services very easy. If you have a SQL statement, you can turn that into a web service in PeopleSoft in a few minutes.

Contents

OnRouteSend

The OnRouteSend event triggers before the publication contracts are created and allows you to remove or modify the contracts that are created programmatically. You can inspect the message content and override Service Operation routings. We use this OnRouteSend to override node publication and selectivity not publish to certain nodes at certain times. This is used for asynchronous service operations.

The comments in the interface definition have some good information:

/* This interface is the equivalent of the OnRouteSend  and OnRouteReceive 
PeopleCode events in 8.4x tools. OnRouteSend will pass in a message to 
your derived application class method. The return should be an integer. 
%IntBroker_ROUTE_NONE = Do send this operation to any of the possible nodes
%IntBroker_ROUTE_SOME = Send this operation to a selected list of nodes. 
The node list should be an array of strings in the property "destinationNodes".
%IntBroker_ROUTE_ALL = Send this operation to all nodes that have a valid routing.

OnRouteReceive will pass in a message to your derived application 
class method. The return should be a Boolean. 
FALSE = The Operation will not run locally
TRUE = The Operation will run locally.

If an error occurs the OnError method if implemented will be 
automatically invoked. The type of exception can be viewed by using the 
Message object to retrieve the Exception object (&Message.IBException).
Please see the PeopleCode Language Reference guide for 
more information about the Exception class.
*/

interface IRouter
   method OnRouteSend(&message As Message) Returns integer;
   method OnRouteReceive(&message As Message) Returns boolean;
   method OnError(&request As Message);
   property array of any destinationNodes;
end-interface;

In my testing even if you return %IntBroker_ROUTE_NONE, local subscriptions will trigger still. You can’t use this to stop local subscriptions from processing in a local operation instance. You have to do something like this in the subscription handler.

If &_MSG.IsLocal And
         &_MSG.IBInfo.OrigNode <> &_MSG.IBInfo.SourceNode Then
              do not run code because this is a secondary operation instance that got triggered 
  • OnRouteSend will pass in a message to your derived application class method. The return should be an integer.
    • %IntBroker_ROUTE_NONE = Do send this operation to any of the possible nodes
    • %IntBroker_ROUTE_SOME = Send this operation to a selected list of nodes
      • You must populate the destinationNodes property array of strings that reflect the real node name that should receive the message. So if the Integration broker routing table says that 4 nodes get the message and the code determines that there is one node that should NOT get the message then you need to insert the 3 nodes that should get the message.
    • %IntBroker_ROUTE_ALL = Send this operation to all nodes that have a valid routing.

The following is an example handler where the client was setup in a very specific way. Each PeopleSoft NODE had a different OPRID attached. It was trying to stop PERSON_BASIC_SYNC messages from being published outbound that were created by other inbound messages. Basically, this handler says: “If the message was created by the current integration broker user then do NOT publish outbound because the external system already sent it and this message was created from the CI update.”

Do NOT put this code in use unless you fully understand what it is doing.

import PS_PT:Integration:IRouter;


class stopBoomerang implements PS_PT:Integration:IRouter
   property array of any destinationNodes;
   
   method OnRouteSend(&msgParm As Message) Returns integer;
   method getIBRoutings(&msgParm As Message) Returns array of string;
end-class;

method getIBRoutings
   /+ &msgParm as Message +/
   /+ Returns Array of String +/
   
   Local array of string &targetNodes = CreateArrayRept("", 0);
   Local Rowset &IBroutes = CreateRowset(Record.PSIBRTNGDEFN_VW);
   Local number &index, &rowCount;
   
   &rowCount = &IBroutes.Fill("WHERE FILL.IB_OPERATIONNAME = :1 AND FILL.EFFDT = (SELECT MAX(B.EFFDT) FROM PSIBRTNGDEFN_VW B WHERE B.IB_OPERATIONNAME = FILL.IB_OPERATIONNAME AND B.EFF_STATUS = 'A') AND FILL.EFF_STATUS = 'A'", &msgParm.OperationName);
   
   For &index = 1 To &rowCount
      &targetNodes.Push(&IBroutes(&index).PSIBRTNGDEFN_VW.RECEIVERNODENAME.Value);
   End-For;

   Return &targetNodes;
   
end-method;


method OnRouteSend
   /+ &msgParm as Message +/
   /+ Returns Integer +/
   /+ Extends/implements PS_PT:Integration:IRouter.OnRouteSend +/
   
   /***********************************************************************\
   * Send to all, none or some destinationNodes:                           *
   * %IntBroker_ROUTE_SOME; must then set array of any destinationNodes    *
   * %IntBroker_ROUTE_ALL                                                  *
   * %IntBroker_ROUTE_NONE                                                 *
   /***********************************************************************/
   
   
   
   Local string &sReceiverNodeName;
   
   
   %This.destinationNodes = CreateArrayAny();
   Local boolean &bByPassingAReceiverNode = False;
   
   Local array of string &aFullRoutingNodeList;
   &aFullRoutingNodeList = %This.getIBRoutings(&msgParm);
   Local integer &i;
   Local string &sGetNodeUser, &sNodeUser;
   &sGetNodeUser = "SELECT USERID FROM PSMSGNODEDEFN WHERE MSGNODENAME = :1";
   For &i = 1 To &aFullRoutingNodeList.Len
      
      
      SQLExec(&sGetNodeUser, &aFullRoutingNodeList [&i], &sNodeUser);
      
      If &sNodeUser = %OperatorId Then
         &bByPassingAReceiverNode = True;
         Local string &sMsg;
         &sMsg = "Bypassing node: " | &aFullRoutingNodeList [&i] | " because the node sent the orignal update.";
         MessageBox(%MsgStyle_OK, "", 0, 0, &sMsg);
      Else
         %This.destinationNodes.Push(&aFullRoutingNodeList [&i]);
      End-If;
   End-For;
   
   &aFullRoutingNodeList = Null;
   If %This.destinationNodes.Len = 0 Then
      
      Return %IntBroker_ROUTE_NONE;
   Else
      If &bByPassingAReceiverNode = False Then
         /* No Boomerange condition found */
         
         Return %IntBroker_ROUTE_ALL;
      Else
         
         Return %IntBroker_ROUTE_SOME;
      End-If;
   End-If;
   
end-method;