A Automation and Compensation Examples

This appendix provides automation and compensation examples. You need to create automation plug-ins to use the Oracle Communications Order and Service Management (OSM) automation task and automated notification functionality. For information about the code required for the automation plug-ins, refer to the following topics:

Predefined Automation Plug-ins

The following topics provide automation plug-in examples for the predefined automation plug-in implementations that support XQuery and XSLT automations:

Message Example

The predefined automation plug-in examples presuppose the following sample order:

<?xml version="1.0" encoding="UTF-8"?>
<ws:CreateOrder xmlns:ws="http://xmlns.oracle.com/communications/ordermanagement">
  <ProcessSalesOrderFulfillmentEBM xmlns="http://xmlns.oracle.com/EnterpriseObjects/Core/EBO/SalesOrder/V2" xmlns:sord="http://xmlns.oracle.com/EnterpriseObjects/Core/EBO/SalesOrder/V2" xmlns:aia="http://www.oracle.com/XSL/Transform/java/oracle.apps.aia.core.xpath.AIAFunctions" xmlns:xref="http://www.oracle.com/XSL/Transform/java/oracle.tip.xref.xpath.XRefXPathFunctions">
     <corecom:EBMHeader xmlns:corecom="http://xmlns.oracle.com/EnterpriseObjects/Core/Common/V2">
       <corecom:EBMID>2d323736303332343736363930353735</corecom:EBMID>
       <corecom:EBMName>{http://xmlns.oracle.com/EnterpriseObjects/Core/EBO/SalesOrder/V2} ProcessSalesOrderFulfillmentEBM</corecom:EBMName>
       <corecom:EBOName>{http://xmlns.oracle.com/EnterpriseObjects/Core/EBO/SalesOrder/V2} SalesOrderEBO</corecom:EBOName>
       <corecom:CreationDateTime>2009-03-09T18:46:36-07:00</corecom:CreationDateTime>
       <corecom:VerbCode>process</corecom:VerbCode>
       <corecom:MessageProcessingInstruction>
         <corecom:EnvironmentCode>PRODUCTION</corecom:EnvironmentCode>
       </corecom:MessageProcessingInstruction>
       <corecom:Sender>
       <!-- Information about the sender - for example, a Siebel CRM -->
       </corecom:Sender>
       <corecom:BusinessScope></corecom:BusinessScope>
       <corecom:EBMTracking></corecom:EBMTracking>
     </corecom:EBMHeader>
     <DataArea>
       <corecom:Process xmlns:corecom="http://xmlns.oracle.com/EnterpriseObjects/Core/Common/V2"/>
       <ProcessSalesOrderFulfillment>
           <corecom:Identification xmlns:corecom="http://xmlns.oracle.com/EnterpriseObjects/Core/Common/V2">
                <corecom:BusinessComponentID schemeID="SALESORDER_ID" schemeAgencyID="COMMON">34333939373132333239373135353138</corecom:BusinessComponentID>
                <corecom:ID schemeID="SALESORDER_ID" schemeAgencyID="SEBL_01">ScenarioA2</corecom:ID>
                <corecom:ApplicationObjectKey>
                     <corecom:ID schemeID="SALESORDER_ID" schemeAgencyID="SEBL_01">88-2SGSG</corecom:ID>
                </corecom:ApplicationObjectKey>
                <corecom:Revision>
                    <corecom:Number>1</corecom:Number>
                </corecom:Revision>
           </corecom:Identification>
           <OrderDateTime>2009-03-09T18:40:21Z</OrderDateTime>
           <RequestedDeliveryDateTime>2009-03-10T00:00:00Z</RequestedDeliveryDateTime>
           <TypeCode>SALES ORDER</TypeCode>
           <FulfillmentPriorityCode>9</FulfillmentPriorityCode>
           <FulfillmentSuccessCode>DEFAULT</FulfillmentSuccessCode>
           <FulfillmentModeCode>DELIVER</FulfillmentModeCode>
           <SalesChannelCode/>
           <ProcessingNumber/>
           <ProcessingTypeCode/>
           <corecom:Status xmlns:corecom="http://xmlns.oracle.com/EnterpriseObjects/Core/Common/V2">
                <corecom:Code>OPEN</corecom:Code>
                <corecom:Description/>
           </corecom:Status>
           <corecom:BusinessUnitReference xmlns:corecom="http://xmlns.oracle.com/EnterpriseObjects/Core/Common/V2">
                <corecom:BusinessUnitIdentification>
                      <corecom:ID schemeID="ORGANIZATION_ID" schemeAgencyID="SEBL_01">0-R9NH</corecom:ID>
                </corecom:BusinessUnitIdentification>
           </corecom:BusinessUnitReference>
           <corecom:CustomerPartyReference xmlns:corecom="http://xmlns.oracle.com/EnterpriseObjects/Core/Common/V2">
                <corecom:CustomerPartyAccountIdentification>
                      <corecom:BusinessComponentID schemeID="CUSTOMERPARTY_ACCOUNTID" schemeAgencyID="COMMON">2d353537333130353233303536343833</corecom:BusinessComponentID>
                      <corecom:ID schemeID="CUSTOMERPARTY_ACCOUNTID" schemeAgencyID="SEBL_01">88-2PB18</corecom:ID>
                      <corecom:ApplicationObjectKey>
                            <corecom:ID schemeID="CUSTOMERPARTY_ACCOUNTID" schemeAgencyID="SEBL_01">88-2PB18</corecom:ID>
                      </corecom:ApplicationObjectKey>
                </corecom:CustomerPartyAccountIdentification>
                <corecom:CustomerPartyAccountName>Adam,10000</corecom:CustomerPartyAccountName>
                <corecom:CustomerPartyAccountContactIdentification>
                      <corecom:BusinessComponentID schemeID="CUSTOMERPARTY_CONTACTID" schemeAgencyID="COMMON">2d353130393634353031313333353938</corecom:BusinessComponentID>
                      <corecom:ApplicationObjectKey>
                           <corecom:ID schemeID="CUSTOMERPARTY_CONTACTID" schemeAgencyID="SEBL_01">88-2MKA1</corecom:ID>
                      </corecom:ApplicationObjectKey>
                </corecom:CustomerPartyAccountContactIdentification>
                <corecom:CustomerPartyAccountContactAddressCommunication>
                      <corecom:AddressCommunication>
                           <corecom:Address>
                                <!-- Enter Address Nodes -->
                           </corecom:Address>
                      </corecom:AddressCommunication>
                </corecom:CustomerPartyAccountContactAddressCommunication>
                <corecom:CustomerPartyAccountTypeCode>RESIDENTIAL </corecom:CustomerPartyAccountTypeCode>
           </corecom:CustomerPartyReference>
           <corecom:PriceListReference xmlns:corecom="http://xmlns.oracle.com/EnterpriseObjects/Core/Common/V2">
                <corecom:PriceListIdentification>
                    <corecom:ID>88-2D1YC</corecom:ID>
                </corecom:PriceListIdentification>
           </corecom:PriceListReference>
           <corecom:ShipToPartyReference xmlns:corecom="http://xmlns.oracle.com/EnterpriseObjects/Core/Common/V2">
               <corecom:LocationReference>
                    <corecom:Address>
                        <!-- Enter Address Nodes -->
                    </corecom:Address>
               </corecom:LocationReference>
               <corecom:CustomerPartyAccountIdentification>
                    <corecom:BusinessComponentID schemeID="CUSTOMERPARTY_ACCOUNTID" schemeAgencyID="COMMON"/>
               </corecom:CustomerPartyAccountIdentification>
               <corecom:CustomerPartyAccountContactIdentification>
                    <corecom:BusinessComponentID schemeID="CUSTOMERPARTY_CONTACTID" schemeAgencyID="COMMON">2d353130393634353031313333353938</corecom:BusinessComponentID>
                    <corecom:ApplicationObjectKey>
                         <corecom:ID schemeID="CUSTOMERPARTY_CONTACTID" schemeAgencyID="SEBL_01">88-2MKA1</corecom:ID>
                    </corecom:ApplicationObjectKey>
               </corecom:CustomerPartyAccountContactIdentification>
           </corecom:ShipToPartyReference>
           <corecom:ParentSalesOrderReference xmlns:corecom="http://xmlns.oracle.com/EnterpriseObjects/Core/Common/V2">
                <corecom:SalesOrderIdentification>
                    <corecom:BusinessComponentID schemeID="SALESORDER_ID" schemeAgencyID="COMMON"/>
                </corecom:SalesOrderIdentification>
           </corecom:ParentSalesOrderReference>
           <corecom:ProjectReference xmlns:corecom="http://xmlns.oracle.com/EnterpriseObjects/Core/Common/V2">
               <corecom:ProjectIdentfication>
                   <corecom:ID schemeID="PROJECT_ID" schemeAgencyID="SEBL_01"/>
               </corecom:ProjectIdentfication>
           </corecom:ProjectReference>
           <corecom:SalespersonPartyReference xmlns:corecom="http://xmlns.oracle.com/EnterpriseObjects/Core/Common/V2">
               <corecom:PartyIdentification>
                    <corecom:ID schemeID="SALESPERSON_PARTYID" schemeAgencyID="SEBL_01">0-1</corecom:ID>
               </corecom:PartyIdentification>
           </corecom:SalespersonPartyReference>
           <!-- Enter order line items here -->
       </ProcessSalesOrderFulfillment>
       </DataArea>
  </ProcessSalesOrderFulfillmentEBM>
</ws:CreateOrder>

Automation Plug-in XQuery Examples

The following topics provide XQuery automation plug-in examples for automation tasks:

Internal XQuery Sender

The Automated Task editor internal XQuery automator receives task data from OSM and sends data to an external system. You can send a message to an external system using whatever protocol that system requires, such as, Telnet, HTTP, CORBA, SOAP, or web services.

The XQuery has the following characteristics:

  • XQuery context in prolog: The input document for any automated task automation plug-in is the order data defined in the Automation Task editor Task Data tab. You can access this data by declaring the TaskContext OSM Java class. Always declare this class along with the $context java binding. For example:

    declare namespace context = "java:com.mslv.oms.automation.TaskContext";
    ...
    declare variable $context external; 
    
  • Prolog: You must declare ScriptSenderContextInvocation in any internal XQuery automator which extends ScriptReceiverContextInvocation. Always declare this class along with the $automator java binding. For example:

    declare namespace automator = "java:oracle.communications.ordermanagement.automation.plugin.ScriptSenderContextInvocation";
    ...
    declare variable $automator external; 
    

    Oracle recommends that you use the standard Apache log class. Always declare this class along with the $log java binding.

    declare namespace log = "java:org.apache.commons.logging.Log";
    ...
    declare variable $log external; 
    

    You must use the TextMessage class for sending JMS based messages. Always declare this class along with the $outboundMessage Java binding. You can use JMS text based messages to send OSM Web Service messages to other OSM systems, such as a service order from an OSM COM system to an OSM SOM system.

    declare namespace outboundMessage = "java:javax.jms.TextMessage";
    ...
    declare variable $outboundMessage external;
    

    Note:

    If you need to support any other protocol for sending messages, you can implement a custom Java automation plug-in for the protocol or import a helper function implementation that supports the protocol.

  • Body: The body for an internal XQuery sender can contain the following elements:

    • Use outboundMessage to set up the standard WebLogic JMS message properties for web services:

      outboundMessage:setStringProperty($outboundMessage, '_wls_mimehdrContent_Type', 'text/xml; charset=&quot;utf-8&quot;'),
      
    • Use outboundMessage to set up the OSM Web Service URI JMS message property:

      outboundMessage:setStringProperty($outboundMessage, 'URI', '/osm/wsapi'),
      
    • You can optionally use outboundMessage with the XML API to populate a JMS property value from order data. For example this code sets up an Ora_OSM_COM_OrderId parameter that is populated with the OSM order ID:

      outboundMessage:setStringProperty($outboundMessage, 'Ora_OSM_COM_OrderId', /oms:GetOrder.Response/oms:OrderID),
      
    • You can optionally use outboundMessage to set the JMS Correlation ID for the automation task before sending the message. This allows OSM to route a return message with the same corresponding JMS property value to an external XQuery automator on the same automation task as the original sender automation plug-in. For example, the following code sets the JMS correlation ID using the original OSM COM order:

      outboundMessage:setJMSCorrelationID($outboundMessage, concat($order/oms:_root/oms:messageXmlData/ebo:ProcessSalesOrderFulfillmentEBM/ebo:DataArea/ebo:ProcessSalesOrderFulfillment/corecom:Identification/corecom:ID/text(),'-COM')),
      

      If this code were applied to "Message Example," the return value would be a concatenation of ScenarioA2 and -COM: ScenarioA2-COM.

      Note:

      Other correlation scenarios are possible. For example, you may send a message from an automation task without expecting any response to the same automation task. In this scenario, another automation task further down in the process may be dedicated to receiving the response message, in which case an automation plug-in would be required that would set the correlation ID expected from the return message for that automated task. See "Using Automation" for more information about asynchronous communication scenarios.

    • Access to the task level order data (the task view) using the XML API GetOrder.Response function call. For example, the following code provides access to all order data passed into the task as a variable that is then used in other variables to access different parts of the data:

      let $order := /oms:GetOrder.Response
      let $othervariable := $order/oms:_root/oms:orderid
      
    • Any XQuery logic your plug-in requires, such as if-then or if-then-else statements that evaluate based on one or more parameters within the response message. For example, there could be a choice of two or more messages that could be sent depending on the order data values, or you might log a message.

    • A completeTaskOnExit method statement that completes the plug-in and transitions the task to the next task based on the status selected if the plug-in is intended to end the task. Typically, an automated task would contain an internal XQuery sender plug-in for sending a message and an external XQuery receiver plug-in for receiving a message, but you can also create an automation that only sends an order with another automation that receives the order. This can be useful if the response message takes a long time to return. If you are expecting the system to respond that you sent the message to, you must configure the internal XQuery sender with a reply to queue that listens for a message acknowledgement, whether the response is returned to an external automator on the same automation task or on another automation task.

The following example provides the code for an XQuery that sends a message from an OSM system in the COM role to an OSM system in the SOM role using the OSM Web Service interface and assumes JMS communication over T3S.

declare namespace automator = "java:oracle.communications.ordermanagement.automation.plugin.ScriptSenderContextInvocation";
declare namespace context = "java:com.mslv.oms.automation.TaskContext";
declare namespace log = "java:org.apache.commons.logging.Log";
declare namespace outboundMessage = "java:javax.jms.TextMessage";
declare namespace oms="urn:com:metasolv:oms:xmlapi:1";
declare namespace to="http://TechnicalOrder";
declare namespace provord="http://xmlns.oracle.com/EnterpriseObjects/Core/EBO/ProvisioningOrder/V1";
declare namespace corecom="http://xmlns.oracle.com/EnterpriseObjects/Core/Common/V2";
declare namespace env="http://schemas.xmlsoap.org/soap/envelope/";
declare namespace cord="http://oracle.communications.c2a.model/internal/order";
declare namespace ebo="http://xmlns.oracle.com/EnterpriseObjects/Core/EBO/SalesOrder/V2";
 
declare variable $automator external; 
declare variable $context external;
declare variable $log external;  
declare variable $outboundMessage external;
 
let $order := /oms:GetOrder.Response
let $technicalActions := $order/oms:_root/oms:TechnicalActions
let $ebm := $order/oms:_root/oms:messageXmlData
let $bi := $order/oms:_root/oms:CaptureInteractionResponse
 
return(
outboundMessage:setStringProperty($outboundMessage, '_wls_mimehdrContent_Type', 'text/xml; charset=&quot;utf-8&quot;'),
outboundMessage:setStringProperty($outboundMessage, 'URI', '/osm/wsapi'),
outboundMessage:setStringProperty($outboundMessage, 'Ora_OSM_COM_OrderId', /oms:GetOrder.Response/oms:OrderID),
outboundMessage:setJMSCorrelationID($outboundMessage, concat($order/oms:_root/oms:messageXmlData/ebo:ProcessSalesOrderFulfillmentEBM/ebo:DataArea/ebo:ProcessSalesOrderFulfillment/corecom:Identification/corecom:ID/text(),'-COM')),
log:info($log,concat('Sending Service Order for COM order: ', $order/oms:OrderID)),
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ord="http://xmlns.oracle.com/communications/ordermanagement">
        <soapenv:Header>
        <wsse:Security xmlns:wsse = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" soapenv:mustUnderstand="1">
        <wsse:UsernameToken xmlns:wsu = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="UsernameToken-4799946">
        <wsse:Username>demo</wsse:Username>
        <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">passw0rd</wsse:Password>
        </wsse:UsernameToken>
        </wsse:Security>
        </soapenv:Header>
   <soapenv:Body>
      <ord:CreateOrder>
                <ebo:ProcessProvisioningOrderEBM xmlns:ebo="http://xmlns.oracle.com/EnterpriseObjects/Core/EBO/ProvisioningOrder/V1">
<ebo:DataArea>
                             <corecom:Process xmlns="http://xmlns.oracle.com/EnterpriseObjects/Core/EBO/ProvisioningOrder/V1" xmlns:corecom="http://xmlns.oracle.com/EnterpriseObjects/Core/Common/V2" xmlns:aia="http://www.oracle.com/XSL/Transform/java/oracle.apps.aia.core.xpath.AIAFunctions" xmlns:xref="http://www.oracle.com/XSL/Transform/java/oracle.tip.xref.xpath.XRefXPathFunctions" xmlns:oms="urn:com:metasolv:oms:xmlapi:1" xmlns:provord="http://xmlns.oracle.com/EnterpriseObjects/Core/EBO/ProvisioningOrder/V1"/>
                             <provord:ProcessProvisioningOrder xmlns="http://xmlns.oracle.com/EnterpriseObjects/Core/EBO/ProvisioningOrder/V1" xmlns:aia="http://www.oracle.com/XSL/Transform/java/oracle.apps.aia.core.xpath.AIAFunctions" xmlns:xref="http://www.oracle.com/XSL/Transform/java/oracle.tip.xref.xpath.XRefXPathFunctions" xmlns:oms="urn:com:metasolv:oms:xmlapi:1" xmlns:provord="http://xmlns.oracle.com/EnterpriseObjects/Core/EBO/ProvisioningOrder/V1">
                             <corecom:SalesOrderReference>
                                  <corecom:SalesOrderIdentification>
                                      {$order/oms:_root/oms:ServiceOrder/cord:Order/cord:CustomerDetails/cord:OrderNumber/corecom:Identification/*}
                                  </corecom:SalesOrderIdentification>
                             </corecom:SalesOrderReference>
                             <provord:RequestedDeliveryDateTime>2010-07-16T08:24:38Z </provord:RequestedDeliveryDateTime>
                             <provord:TypeCode>SALES ORDER</provord:TypeCode>
                             <provord:FulfillmentPriorityCode>5</provord:FulfillmentPriorityCode>
                             <provord:FulfillmentSuccessCode>DEFAULT </provord:FulfillmentSuccessCode>
                             <provord:FulfillmentModeCode>DELIVER</provord:FulfillmentModeCode>
                             <provord:ProcessingNumber/>
                             <provord:ProcessingTypeCode/>
                             <corecom:Status xmlns:corecom="http://xmlns.oracle.com/EnterpriseObjects/Core/Common/V2">
                                 <corecom:Code>IN PROGRESS</corecom:Code>
                             </corecom:Status>
                             <corecom:BusinessUnitReference xmlns:corecom="http://xmlns.oracle.com/EnterpriseObjects/Core/Common/V2">
                                 <corecom:BusinessUnitIdentification>
                                     <corecom:ID schemeID="ORGANIZATION_ID" schemeAgencyID="SEBL_01">0-R9NH</corecom:ID>
                                 </corecom:BusinessUnitIdentification>
                             </corecom:BusinessUnitReference>
                             {$order/oms:_root/oms:ServiceOrder/cord:Order/cord:CustomerDetails/cord:CustomerParty/corecom:CustomerPartyReference}
                             <corecom:ParentProvisioningOrderReference xmlns:corecom="http://xmlns.oracle.com/EnterpriseObjects/Core/Common/V2">
                                 <corecom:ProvisioningOrderIdentification>
                                     <corecom:BusinessComponentID schemeID="SALESORDER_ID" schemeAgencyID="COMMON"/>
                                 </corecom:ProvisioningOrderIdentification>
                             </corecom:ParentProvisioningOrderReference>
                             {
                                 for $x in $order/oms:_root/oms:ServiceOrder/cord:Order/cord:ServiceOrderLine
                                 return
                                 <provord:ProvisioningOrderLine>
                                 <corecom:Identification xmlns:corecom="http://xmlns.oracle.com/EnterpriseObjects/Core/Common/V2">
                                      <corecom:BusinessComponentID>{concat($x/@id,'')} </corecom:BusinessComponentID>
                                      <corecom:ID schemeID="SALESORDER_LINEID" schemeAgencyID="SEBL_01">{concat($x/@id,'')}</corecom:ID>
                                      <corecom:ApplicationObjectKey>
                                           <corecom:ID schemeID="SALESORDER_LINEID" schemeAgencyID="SEBL_01">{concat($x/@id,'')}</corecom:ID>
                                      </corecom:ApplicationObjectKey>
                                 </corecom:Identification>
                                 <provord:OrderQuantity>1</provord:OrderQuantity>
                                 <provord:ServiceActionCode>{$x/cord:Action/text()} </provord:ServiceActionCode>
                                 <provord:ServicePointCode/>
                                 <corecom:Status xmlns:corecom="http://xmlns.oracle.com/EnterpriseObjects/Core/Common/V2">
                                     <corecom:Code>IN PROGRESS</corecom:Code>
                                 </corecom:Status>
                                 <corecom:ServiceAddress xmlns:corecom="http://xmlns.oracle.com/EnterpriseObjects/Core/Common/V2">
                                      <corecom:Identification>
                                          <corecom:BusinessComponentID schemeAgencyID="COMMON" schemeID="CUSTOMERPARTY_ADDRESSID">2d323733323231313531313836313331</corecom:BusinessComponentID>
                                          <corecom:ApplicationObjectKey>
                                               <corecom:ID schemeAgencyID="SEBL_01" schemeID="CUSTOMERPARTY_ADDRESSID">88-2KKNH</corecom:ID>
                                          </corecom:ApplicationObjectKey>
                                      </corecom:Identification>
                                      <corecom:LineOne>{$x/cord:Address/cord:LineOne/text()} </corecom:LineOne>
                                      <corecom:CityName>{$x/cord:Address/cord:CityName/text()} </corecom:CityName>
                                      <corecom:StateName>{$x/cord:Address/cord:StateName/text()} </corecom:StateName>
                                      <corecom:ProvinceName>{$x/cord:Address/cord:ProvinceName/ text()}</corecom:ProvinceName>
                                      <corecom:CountryCode>{$x/cord:Address/cord:CountryCode /text()}</corecom:CountryCode>
                                      <corecom:PostalCode>{$x/cord:Address/cord:PostalCode /text()}</corecom:PostalCode>
                                 </corecom:ServiceAddress>
                                 <corecom:ItemReference xmlns:corecom="http://xmlns.oracle.com/EnterpriseObjects/Core/Common/V2">
                                 <corecom:ItemIdentification>
                                      <corecom:BusinessComponentID schemeAgencyID="COMMON" schemeID="ITEM_ITEMID"/>
                                      <corecom:ApplicationObjectKey>
                                          <corecom:ID schemeID="ITEM_ITEMID" schemeAgencyID="SEBL_01">{concat($x/cord:InstanceID/text(),'')}</corecom:ID>
                                      </corecom:ApplicationObjectKey>
                                      <corecom:AlternateObjectKey>
                                          <corecom:ContextID/>
                                      </corecom:AlternateObjectKey>
                                      <corecom:SupplierItemID/>
                                 </corecom:ItemIdentification>
                                 <corecom:Name>{concat($x/@name,'')}</corecom:Name>
                                     <corecom:ClassificationCode listID="PermittedTypeCode"></corecom:ClassificationCode>
                                     <corecom:ClassificationCode listID="BillingProductTypeCode"/>
                                     <corecom:ClassificationCode listID="FulfillmentItemCode">{concat($x/@name,'')}</corecom:ClassificationCode>
                                     <corecom:ServiceIndicator>false</corecom:ServiceIndicator>
                                     <corecom:TypeCode>SERVICE</corecom:TypeCode>
                                     <corecom:Description/>
                                     <corecom:SpecificationGroup>
                                         <corecom:Name>ExtensibleAttributes</corecom:Name>
                                         {
                                              for $y in $x/cord:Attribute
                                              return
                                              <corecom:Specification>
                                                  <corecom:ServiceActionCode> </corecom:ServiceActionCode>
                                                  <corecom:Name>{concat($y/@name,'')} </corecom:Name>
                                                  <corecom:DataTypeCode>Text</corecom:DataTypeCode>
                                                  <corecom:Value>{$y/cord:Value/cord:value/text()} </corecom:Value>
                                              </corecom:Specification>
                                         }
                                     </corecom:SpecificationGroup>
                                     <corecom:PrimaryClassificationCode>{concat($x/@name,'')} </corecom:PrimaryClassificationCode>
                                     <corecom:ServiceInstanceIndicator>true </corecom:ServiceInstanceIndicator>
                                 </corecom:ItemReference>
                                 <provord:ProvisioningOrderLineSpecificationGroup>
                                     <corecom:SpecificationGroup>
                                          <corecom:Name>ExtensibleAttributes</corecom:Name>
                                          <corecom:Specification>
                                               <corecom:Name>ParentSalesOrderLine</corecom:Name>
                                               <corecom:Value>{$x/cord:primaryMapping/text()} </corecom:Value>
                                          </corecom:Specification>
                                         {
                                              for $z in $x/cord:secondaryMapping
                                              return
                                              <corecom:Specification>
                                                  <corecom:Name>ParentSalesOrderLine</corecom:Name>
                                              <corecom:Value>{$z/text()}</corecom:Value>
                                              </corecom:Specification>
                                         }
                                     </corecom:SpecificationGroup>
                                 </provord:ProvisioningOrderLineSpecificationGroup>
                                 </provord:ProvisioningOrderLine>
                             }
                          </provord:ProcessProvisioningOrder>
                      </ebo:DataArea>
                 </ebo:ProcessProvisioningOrderEBM>
      </ord:CreateOrder>
   </soapenv:Body>
</soapenv:Envelope>
External XQuery Automator

The Automated Task editor external XQuery automator receives task data from an external system and optionally updates OSM order data. The XQuery has the following characteristics:

  • XQuery context in prolog: The input document for any automated task automation plug-in is the order data defined in the Automation Task editor Task Data tab. You can access this data by declaring the TaskContext OSM Java class. Always declare this class along with the $context java binding. For example:

    declare namespace context = "java:com.mslv.oms.automation.TaskContext";
    ...
    declare variable $context external;
    
  • Prolog: You must declare ScriptReceiverContextInvocation in any external XQuery automator. Typically, you can use the getOrderAsDOM method to receive external messages and the setUpdateOrder method to update the order data. Always declare this class along with the $automator java binding. For example:

    declare namespace automator = "java:oracle.communications.ordermanagement.automation.plugin.ScriptReceiverContextInvocation";
    ...
    declare variable $automator external;
    

    Oracle recommends that you use the standard Apache log class. Always declare this class along with the $log java binding.

    declare namespace log = "java:org.apache.commons.logging.Log";
    ...
    declare variable $log external;
    

    Another necessary declaration includes the xmlapi namespace, that you can use with the ScriptReceiverContextInvocation getOrderAsDom method to retrieve the order data for the task as a variable. This task data variable can be used in an OrderDataUpdate to update the order data with the data values received in the response message, if an update to the order data is required. For example:

    declare namespace oms="urn:com:metasolv:oms:xmlapi:1"; 
    let $taskData := fn:root(automator:getOrderAsDOM($automator))/oms:GetOrder.Response
    
  • Body: The body for an external XQuery automator can contain the following elements:

    • Any XQuery logic your plug-in requires, such as if-then or if-then-else statements that evaluate based on one or more parameters within the response message, or you might log a message.

    • A setUpdateOrder method statement that indicates whether there is an order data update. This method should be identical to what you selected in the Design Studio automation plug-in Properties View XQuery Tab Update Order check box.

    • A completeTaskOnExit method statement that completes the plug-in and transitions the task to the next task based on the status selected, if the plug-in is intended to end the task. Since there can be multiple plug-ins within a task, you would only need this method in the last plug-in listed. For example, the Failed status might transition to a fallout task, and the Succeed status may transition to the next task in the process.

    • An OrderDataUpdate statement that updates the order data based on the information returned in the response. For more information about structuring order update code, see "Using OrderDataUpdate Elements to Pass Order Modification Data."

    • Indexing: Order data in OSM often includes multiple data instances. For example, an orchestration order must include the ControlData/OrderItem and ControlData/Functions multi-instance nodes. Multi-instance nodes in solution cartridges are possible for any data element where the maximum cardinality of the node is greater than 1. When updating a multi-instance data node using automations use the node index to reference the specific node instance you want to update. The node index is available in the XML API GetOrder.Response. See OSM XML API Developer's Guide for an example of a GetOrder response message with indexing.

The following example triggers different order data updates based on the status message returned from an external system. In this case, the external system is another OSM instance running in the SOM role:

declare namespace oms="urn:com:metasolv:oms:xmlapi:1";
declare namespace automator = "java:oracle.communications.ordermanagement.automation.plugin.ScriptReceiverContextInvocation";
declare namespace context = "java:com.mslv.oms.automation.TaskContext";
declare namespace log = "java:org.apache.commons.logging.Log";
declare namespace su="http://StatusUpdate";
declare namespace so="http://xmlns.oracle.com/EnterpriseObjects/Core/EBO/SalesOrder/V2";
declare namespace corecom="http://xmlns.oracle.com/EnterpriseObjects/Core/Common/V2";
 
declare variable $automator external;
declare variable $context external;
declare variable $log external;
 
let $response := fn:root()/su:StatusUpdate (: fn:root(.) :)
let $items := fn:root()/su:StatusUpdate/su:OrderItem
 
let $taskData := fn:root(automator:getOrderAsDOM($automator))/oms:GetOrder.Response
let $component := if (fn:exists($taskData/oms:_root/oms:ControlData/oms:Functions/*/oms:componentKey)) then $taskData/oms:_root/oms:ControlData/oms:Functions/*[fn:position()=1] else ()
 
return (
if($response/su:status/text()='SOM_Completed') then (
    log:info($log,concat('Received SOM Status Update: SOM_Completed; ', $response/su:status/text())),
    automator:setUpdateOrder($automator,"true"),
    context:completeTaskOnExit($context,"success"),
    (
        <OrderDataUpdate xmlns="http://www.metasolv.com/OMS/OrderDataUpdate/2002/10/25">
            {
            for $item in $items
            for $parent in $item/su:ParentLineId
            for $orderComponentItem in $component/oms:orderItem[oms:orderItemRef/oms:LineXmlData/so:SalesOrderLine/corecom:Identification/corecom:ApplicationObjectKey/corecom:ID/text() = $parent/text()]
            return (
                    <Update path="{fn:concat("/ControlData/Functions/Provision/orderItem[@index='",fn:data($orderComponentItem/@index),"']")}">
                       <ExternalFulfillmentState>{$item/su:Status/text()}</ExternalFulfillmentState>
                    </Update>    
              )
                 
            }
        </OrderDataUpdate>
    )
) else if($response/su:status/text()='SOM_Failed') then (
 
    log:info($log,concat('Received SOM Status Update: SOM_Failed; ', $response/su:status/text())),
    automator:setUpdateOrder($automator,"true"),
    context:completeTaskOnExit($context,"failure"),
    (
        <OrderDataUpdate xmlns="http://www.metasolv.com/OMS/OrderDataUpdate/2002/10/25">
            {
            for $item in $items
            for $parent in $item/su:ParentLineId
            for $orderComponentItem in $component/oms:orderItem[oms:orderItemRef/oms:LineXmlData/so:SalesOrderLine/corecom:Identification/corecom:ApplicationObjectKey/corecom:ID/text() = $parent/text()]
            return (
                    <Update path="{fn:concat("/ControlData/Functions/Provision/orderItem[@index='",fn:data($orderComponentItem/@index),"']")}">
                       <ExternalFulfillmentState>{$item/su:Status/text()}</ExternalFulfillmentState>
                    </Update>    
              )
                 
            }
        </OrderDataUpdate>
    )
) else (
    log:info($log,concat('Received SOM Status Update: SOM_InProgress or SOM_Canceled; ', $response/su:status/text())),
    automator:setUpdateOrder($automator,"true"),
    (
        <OrderDataUpdate xmlns="http://www.metasolv.com/OMS/OrderDataUpdate/2002/10/25">
            {
            for $item in $items
            for $parent in $item/su:ParentLineId
            for $orderComponentItem in $component/oms:orderItem[oms:orderItemRef/oms:LineXmlData/so:SalesOrderLine/corecom:Identification/corecom:ApplicationObjectKey/corecom:ID/text() = $parent/text()]
            return (
                    <Update path="{fn:concat("/ControlData/Functions/Provision/orderItem[@index='",fn:data($orderComponentItem/@index),"']")}">
                       <ExternalFulfillmentState>{$item/su:Status/text()}</ExternalFulfillmentState>
                    </Update>    
              )
                 
            }
        </OrderDataUpdate>
    )
)
)
External XQuery Sender

The Automated Task editor external XQuery sender receives task data from an external system, then sends the data (after possibly transforming the data) to another external system or even returns the data back to the original external system. This XQuery combines characteristics of external XQuery automators and internal XQuery senders. For more information, see "External XQuery Automator" and "Internal XQuery Sender."

Note:

You must declare ScriptSenderContextInvocation in any external XQuery sender which inherits the ScriptReceiverContextInvocation class and methods used in internal or external automators.

Internal XQuery Automator

The Automated Task editor internal XQuery automator receives task data from OSM, then processes the data. For example, such an automation might perform computational actions on the data or other similar logic. This XQuery combines characteristics of external XQuery automators and internal XQuery senders. For more information, see "External XQuery Automator" and "Internal XQuery Sender."

Note:

You must declare ScriptReceiverContextInvocation class in an internal XQuery automator.

Automation Plug-in XSLT Examples

The following topics provide XSLT automation plug-in examples for automation tasks.

Internal XSLT Sender

The Automated Task editor internal XSLT automator receives task data from OSM and sends data to an external system. You can send a message to an external system using whatever protocol that system requires, such as, Telnet, HTTP, CORBA, SOAP, or web services.

The XSLT has the following characteristics:

  • XSLT context: The input document for any automated task automation plug-in is the order data defined in the Automation Task editor Task Data tab. You can access this data by declaring the TaskContext OSM Java class. Always declare this class along with the context java variable. For example:

    xmlns:context="java:com.mslv.oms.automation.TaskContext"
    ...
    <xsl:param name="context"/>
    
  • Initial namespace declarations: You must declare ScriptSenderContextInvocation in any internal XSLT automator which extends ScriptReceiverContextInvocation. Always declare this class along with the automator java variable. For example:

    xmlns:automator="java:oracle.communications.ordermanagement.automation.plugin.ScriptSenderContextInvocation"
    ...
    <xsl:param name="automator"/>
    

    Oracle recommends that you use the standard Apache log class. Always declare this class along with the log java variable.

    xmlns:log="java:org.apache.commons.logging.Log"
    ...
    <xsl:param name="log"/>
    

    You must use the TextMessage class for sending JMS based messages. Always declare this class along with the outboundMessage Java variable. You can use JMS text based messages to send OSM Web Service messages to other OSM systems, such as a service order from an OSM COM system to an OSM SOM system.

    xmlns:outboundMessage="java:javax.jms.TextMessage"
    ...
    <xsl:param name="outboundMessage"/>
    

    Note:

    If you need to support any other protocol for sending messages, you can implement a custom Java automation plug-in for the protocol or import a helper function implementation that supports the protocol.

  • Body: The body for an internal XSLT sender can contain the following elements:

    • Use outboundMessage to set up the standard WebLogic JMS message properties for web services:

      <xsl:variable name="outboundMessage" select="java:setStringProperty($outboundMessage, '_wls_mimehdrContent_Type', 'text/xml; charset=&quot;utf-8&quot;')"/>
      
    • Use outboundMessage to set up the OSM Web Service URI JMS message property:

      <xsl:variable name="outboundMessage" select="java:setStringProperty($outboundMessage, 'URI', '/osm/wsapi')"/>
      
    • You can optionally use outboundMessage with the XML API to populate a JMS property value from order data. For example this code sets up an Ora_OSM_COM_OrderId parameter that is populated with the OSM order ID:

      <xsl:variable name="outboundMessage" select="java:setStringProperty($outboundMessage, 'Ora_OSM_COM_OrderId', /oms:GetOrder.Response/oms:OrderID)"/>
      
    • You can optionally use outboundMessage to set the JMS Correlation ID for the automation task before sending the message. This allows OSM to route a return message with the same corresponding JMS property value to an external XQuery automator on the same automation task as the original sender automation plug-in. For example, the following code sets the JMS correlation ID using the original OSM COM order:

      <xsl:variable name="void" select="java:setJMSCorrelationID($outboundMessage, concat($order/oms:_root/oms:messageXmlData/ebo:ProcessSalesOrderFulfillmentEBM/ebo:DataArea/ebo:ProcessSalesOrderFulfillment/corecom:Identification/corecom:ID/text(),'-COM'))"/>
      

      If this code were applied to "Message Example," the return value would be a concatenation of ScenarioA2 and -COM: ScenarioA2-COM.

      Note:

      Other correlation scenarios are possible. For example, you may send a message from automation task without expecting any response to the same automation task. In this scenario, another automation task further down in the process may be dedicated to receiving the response message, in which case an automation plug-in would be required that would set the correlation ID expected from the return message for that automated task. See "Using Automation" for more information about asynchronous communication scenarios.

    • Access to the task level order data (the task view) using the XML API GetOrder.Response function call. For example, the following code provides access to all order data passed into the task as a variable that is then used in other variables to access different parts of the data:

          <xsl:template match="/">
              <xsl:variable name="order" select="oms:GetOrder.Response"/>
              <xsl:variable name="othervariable" select="$order/oms:_root/oms:orderid"/>
      
    • Any XSLT logic your plug-in requires, such as if-then or if-then-else statements that evaluate based on one or more parameters within the response message. For example, there could be a choice of two or more messages that could be sent depending on the order data values, or you might log a message.

    • A completeTaskOnExit method statement that completes the plug-in and transitions the task to the next task based on the status selected if the plug-in is intended to end the task. Typically, an automated task would contain an internal XSLT sender plug-in for sending a message and an external XSLT receiver plug-in for receiving a message, but you can also create an automation that only sends an order with another automation that receives the order. This can be useful if the response message takes a long time to return. If you are expecting the system to respond that you sent the message to, you must configure the internal XSLT sender with a reply to queue that listens for a message acknowledgement, whether the response is returned to an external automator on the same automation task or on another automation task.

The following example provides the code for an XSLT that sends a message from an OSM system in the COM role to an OSM system in the SOM role using the OSM Web Service interface and assumes JMS communication over T3S.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns="http://www.metasolv.com/OMS/OrderDataUpdate"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:java="http://xml.apache.org/xslt/java" 
    xmlns:xalan="http://xml.apache.org/xslt"
    xmlns:oms="urn:com:metasolv:oms:xmlapi:1" 
xmlns:automator="java:oracle.communications.ordermanagement.automation.plugin.ScriptSenderContextInvocation"
    xmlns:context="java:com.mslv.oms.automation.TaskContext"
    xmlns:log="java:org.apache.commons.logging.Log"
    xmlns:outboundMessage="java:javax.jms.TextMessage"
    xmlns:to="http://TechnicalOrder"
    xmlns:provord="http://xmlns.oracle.com/EnterpriseObjects/Core/EBO/ProvisioningOrder/V1"
    xmlns:corecom="http://xmlns.oracle.com/EnterpriseObjects/Core/Common/V2"
    xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
    xmlns:ebo="http://xmlns.oracle.com/EnterpriseObjects/Core/EBO/SalesOrder/V2"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    exclude-result-prefixes="xsl java xalan oms com ser soapenv xsi"
    xmlns:fn="http://www.w3.org/2005/02/xpath-functions">

    <!-- * -->
    <xsl:param name="automator"/>
    <xsl:param name="log"/>
    <xsl:param name="context"/>
    <xsl:param name="outboundMessage"/>
 
    <!-- * -->

    <xsl:output method="xml" indent="yes" omit-xml-declaration="no" xalan:indent-amount="5"/>
    <xsl:template match="/">
        <xsl:variable name="order" select="oms:GetOrder.Response"/>
        <xsl:variable name="technicalActions" select="$order/oms:_root/oms:TechnicalActions"/>
        <xsl:variable name="ebm" select="$order/oms:_root/oms:messageXmlData"/>
        <xsl:variable name="bi" select="$order/oms:_root/oms:CaptureInteractionResponse"/>
        <xsl:variable name="outboundMessage" select="java:setStringProperty($outboundMessage, '_wls_mimehdrContent_Type', 'text/xml; charset=&quot;utf-8&quot;')"/>
        <xsl:variable name="outboundMessage" select="java:setStringProperty($outboundMessage, 'URI', '/osm/wsapi')"/>
        <xsl:variable name="outboundMessage" select="java:setStringProperty($outboundMessage, 'Ora_OSM_COM_OrderId', /oms:GetOrder.Response/oms:OrderID)"/>
        <xsl:variable name="void" select="java:setJMSCorrelationID($outboundMessage, concat($order/oms:_root/oms:messageXmlData/ebo:ProcessSalesOrderFulfillmentEBM/ebo:DataArea/ebo:ProcessSalesOrderFulfillment/corecom:Identification/corecom:ID/text(),'-COM'))"/>
        <xsl:variable name="log" select=java:info($log,concat('Sending Service Order for COM order: ', $order/oms:OrderID))"/>
        <xsl:call-template name="sendSomOrder"/>
    </xsl:template>
    <!-- ==================================
         Create the SOAP message for the sendSomOrder call
         ==================================== -->
    <xsl:template name="sendSomOrder">

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ord="http://xmlns.oracle.com/communications/ordermanagement">
        <soapenv:Header>
        <wsse:Security xmlns:wsse = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" soapenv:mustUnderstand="1">
        <wsse:UsernameToken xmlns:wsu = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="UsernameToken-4799946">
        <wsse:Username>demo</wsse:Username>
        <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">passw0rd</wsse:Password>
        </wsse:UsernameToken>
        </wsse:Security>
        </soapenv:Header>
   <soapenv:Body>
      <ord:CreateOrder>
                <ebo:ProcessProvisioningOrderEBM xmlns:ebo="http://xmlns.oracle.com/EnterpriseObjects/Core/EBO/ProvisioningOrder/V1">
<ebo:DataArea>
                             <corecom:Process xmlns="http://xmlns.oracle.com/EnterpriseObjects/Core/EBO/ProvisioningOrder/V1" xmlns:corecom="http://xmlns.oracle.com/EnterpriseObjects/Core/Common/V2" xmlns:aia="http://www.oracle.com/XSL/Transform/java/oracle.apps.aia.core.xpath.AIAFunctions" xmlns:xref="http://www.oracle.com/XSL/Transform/java/oracle.tip.xref.xpath.XRefXPathFunctions" xmlns:oms="urn:com:metasolv:oms:xmlapi:1" xmlns:provord="http://xmlns.oracle.com/EnterpriseObjects/Core/EBO/ProvisioningOrder/V1"/>
                             <provord:ProcessProvisioningOrder xmlns="http://xmlns.oracle.com/EnterpriseObjects/Core/EBO/ProvisioningOrder/V1" xmlns:aia="http://www.oracle.com/XSL/Transform/java/oracle.apps.aia.core.xpath.AIAFunctions" xmlns:xref="http://www.oracle.com/XSL/Transform/java/oracle.tip.xref.xpath.XRefXPathFunctions" xmlns:oms="urn:com:metasolv:oms:xmlapi:1" xmlns:provord="http://xmlns.oracle.com/EnterpriseObjects/Core/EBO/ProvisioningOrder/V1">
                             <corecom:SalesOrderReference>
                                  <corecom:SalesOrderIdentification>
                                      {$order/oms:_root/oms:ServiceOrder/cord:Order/cord:CustomerDetails/cord:OrderNumber/corecom:Identification/*}
                                  </corecom:SalesOrderIdentification>
                             </corecom:SalesOrderReference>
                             <provord:RequestedDeliveryDateTime>2010-07-16T08:24:38Z </provord:RequestedDeliveryDateTime>
                             <provord:TypeCode>SALES ORDER</provord:TypeCode>
                             <provord:FulfillmentPriorityCode>5</provord:FulfillmentPriorityCode>
                             <provord:FulfillmentSuccessCode>DEFAULT </provord:FulfillmentSuccessCode>
                             <provord:FulfillmentModeCode>DELIVER</provord:FulfillmentModeCode>
                             <provord:ProcessingNumber/>
                             <provord:ProcessingTypeCode/>
                             <corecom:Status xmlns:corecom="http://xmlns.oracle.com/EnterpriseObjects/Core/Common/V2">
                                 <corecom:Code>IN PROGRESS</corecom:Code>
                             </corecom:Status>
                             <corecom:BusinessUnitReference xmlns:corecom="http://xmlns.oracle.com/EnterpriseObjects/Core/Common/V2">
                                 <corecom:BusinessUnitIdentification>
                                     <corecom:ID schemeID="ORGANIZATION_ID" schemeAgencyID="SEBL_01">0-R9NH</corecom:ID>
                                 </corecom:BusinessUnitIdentification>
                             </corecom:BusinessUnitReference>
                             {$order/oms:_root/oms:ServiceOrder/cord:Order/cord:CustomerDetails/cord:CustomerParty/corecom:CustomerPartyReference}
                             <corecom:ParentProvisioningOrderReference xmlns:corecom="http://xmlns.oracle.com/EnterpriseObjects/Core/Common/V2">
                                 <corecom:ProvisioningOrderIdentification>
                                     <corecom:BusinessComponentID schemeID="SALESORDER_ID" schemeAgencyID="COMMON"/>
                                 </corecom:ProvisioningOrderIdentification>
                             </corecom:ParentProvisioningOrderReference>
                             {
                                 for $x in $order/oms:_root/oms:ServiceOrder/cord:Order/cord:ServiceOrderLine
                                 return
                                 <provord:ProvisioningOrderLine>
                                 <corecom:Identification xmlns:corecom="http://xmlns.oracle.com/EnterpriseObjects/Core/Common/V2">
                                      <corecom:BusinessComponentID>{concat($x/@id,'')} </corecom:BusinessComponentID>
                                      <corecom:ID schemeID="SALESORDER_LINEID" schemeAgencyID="SEBL_01">{concat($x/@id,'')}</corecom:ID>
                                      <corecom:ApplicationObjectKey>
                                           <corecom:ID schemeID="SALESORDER_LINEID" schemeAgencyID="SEBL_01">{concat($x/@id,'')}</corecom:ID>
                                      </corecom:ApplicationObjectKey>
                                 </corecom:Identification>
                                 <provord:OrderQuantity>1</provord:OrderQuantity>
                                 <provord:ServiceActionCode>{$x/cord:Action/text()} </provord:ServiceActionCode>
                                 <provord:ServicePointCode/>
                                 <corecom:Status xmlns:corecom="http://xmlns.oracle.com/EnterpriseObjects/Core/Common/V2">
                                     <corecom:Code>IN PROGRESS</corecom:Code>
                                 </corecom:Status>
                                 <corecom:ServiceAddress xmlns:corecom="http://xmlns.oracle.com/EnterpriseObjects/Core/Common/V2">
                                      <corecom:Identification>
                                          <corecom:BusinessComponentID schemeAgencyID="COMMON" schemeID="CUSTOMERPARTY_ADDRESSID">2d323733323231313531313836313331</corecom:BusinessComponentID>
                                          <corecom:ApplicationObjectKey>
                                               <corecom:ID schemeAgencyID="SEBL_01" schemeID="CUSTOMERPARTY_ADDRESSID">88-2KKNH</corecom:ID>
                                          </corecom:ApplicationObjectKey>
                                      </corecom:Identification>
                                      <corecom:LineOne>{$x/cord:Address/cord:LineOne/text()} </corecom:LineOne>
                                      <corecom:CityName>{$x/cord:Address/cord:CityName/text()} </corecom:CityName>
                                      <corecom:StateName>{$x/cord:Address/cord:StateName/text()} </corecom:StateName>
                                      <corecom:ProvinceName>{$x/cord:Address/cord:ProvinceName/ text()}</corecom:ProvinceName>
                                      <corecom:CountryCode>{$x/cord:Address/cord:CountryCode /text()}</corecom:CountryCode>
                                      <corecom:PostalCode>{$x/cord:Address/cord:PostalCode /text()}</corecom:PostalCode>
                                 </corecom:ServiceAddress>
                                 <corecom:ItemReference xmlns:corecom="http://xmlns.oracle.com/EnterpriseObjects/Core/Common/V2">
                                 <corecom:ItemIdentification>
                                      <corecom:BusinessComponentID schemeAgencyID="COMMON" schemeID="ITEM_ITEMID"/>
                                      <corecom:ApplicationObjectKey>
                                          <corecom:ID schemeID="ITEM_ITEMID" schemeAgencyID="SEBL_01">{concat($x/cord:InstanceID/text(),'')}</corecom:ID>
                                      </corecom:ApplicationObjectKey>
                                      <corecom:AlternateObjectKey>
                                          <corecom:ContextID/>
                                      </corecom:AlternateObjectKey>
                                      <corecom:SupplierItemID/>
                                 </corecom:ItemIdentification>
                                 <corecom:Name>{concat($x/@name,'')}</corecom:Name>
                                     <corecom:ClassificationCode listID="PermittedTypeCode"></corecom:ClassificationCode>
                                     <corecom:ClassificationCode listID="BillingProductTypeCode"/>
                                     <corecom:ClassificationCode listID="FulfillmentItemCode">{concat($x/@name,'')}</corecom:ClassificationCode>
                                     <corecom:ServiceIndicator>false</corecom:ServiceIndicator>
                                     <corecom:TypeCode>SERVICE</corecom:TypeCode>
                                     <corecom:Description/>
                                     <corecom:SpecificationGroup>
                                         <corecom:Name>ExtensibleAttributes</corecom:Name>
                                         {
                                              for $y in $x/cord:Attribute
                                              return
                                              <corecom:Specification>
                                                  <corecom:ServiceActionCode> </corecom:ServiceActionCode>
                                                  <corecom:Name>{concat($y/@name,'')} </corecom:Name>
                                                  <corecom:DataTypeCode>Text</corecom:DataTypeCode>
                                                  <corecom:Value>{$y/cord:Value/cord:value/text()} </corecom:Value>
                                              </corecom:Specification>
                                         }
                                     </corecom:SpecificationGroup>
                                     <corecom:PrimaryClassificationCode>{concat($x/@name,'')} </corecom:PrimaryClassificationCode>
                                     <corecom:ServiceInstanceIndicator>true </corecom:ServiceInstanceIndicator>
                                 </corecom:ItemReference>
                                 <provord:ProvisioningOrderLineSpecificationGroup>
                                     <corecom:SpecificationGroup>
                                          <corecom:Name>ExtensibleAttributes</corecom:Name>
                                          <corecom:Specification>
                                               <corecom:Name>ParentSalesOrderLine</corecom:Name>
                                               <corecom:Value>{$x/cord:primaryMapping/text()} </corecom:Value>
                                          </corecom:Specification>
                                         {
                                              for $z in $x/cord:secondaryMapping
                                              return
                                              <corecom:Specification>
                                                  <corecom:Name>ParentSalesOrderLine</corecom:Name>
                                              <corecom:Value>{$z/text()}</corecom:Value>
                                              </corecom:Specification>
                                         }
                                     </corecom:SpecificationGroup>
                                 </provord:ProvisioningOrderLineSpecificationGroup>
                                 </provord:ProvisioningOrderLine>
                             }
                          </provord:ProcessProvisioningOrder>
                      </ebo:DataArea>
                 </ebo:ProcessProvisioningOrderEBM>
      </ord:CreateOrder>
   </soapenv:Body>
</soapenv:Envelope>
</xsl:template>
    <!-- * -->
    <xsl:template match="* | @* | text()">
        <!-- do nothing -->
        <xsl:apply-templates/>
    </xsl:template>
</xsl:stylesheet>
External XSLT Automator

The Automated Task editor external XSLT automator receives task data from an external system and optionally updates OSM order data. The XSLT has the following characteristics:

  • XSLT context in prolog: The input document for any automated task automation plug-in is the order data defined in the Automation Task editor Task Data tab. You can access this data by declaring the TaskContext OSM Java class. Always declare this class along with the context java binding. For example:

    xmlns:context="java:com.mslv.oms.automation.TaskContext"
    ...
    <xsl:param name="context"/>
    
  • Prolog: You must declare ScriptReceiverContextInvocation in any external XQuery automator. Typically, you can use the getOrderAsDOM method to receive external messages and the setUpdateOrder method to update the order data. Always declare this class along with the automator java binding. For example:

        xmlns:automator="java:oracle.communications.ordermanagement.automation.plugin.ScriptReceiverContextInvocation"
    ...
    <xsl:param name="automator"/>
    

    Oracle recommends that you use the standard Apache log class. Always declare this class along with the $log java binding.

    xmlns:log="java:org.apache.commons.logging.Log"
    ...
    <xsl:param name="log"/>
    

    Another necessary declaration includes the xmlapi namespace, that you can use with the ScriptReceiverContextInvocation getOrderAsDom method to retrieve the order data for the task as a variable. This task data variable can be used in an OrderDataUpdate to update the order data with the data values received in the response message, if an update to the order data is required. For example:

    xmlns:oms="urn:com:metasolv:oms:xmlapi:1"
    <xsl:variable name="taskData" select="fn:root(java:getOrderAsDOM($automator))/oms:GetOrder.Response"/>
    
  • Body: The body for an external XSLT automator can contain the following elements:

    • Any XSLT logic your plug-in requires, such as if-then or if-then-else statements that evaluate based on one or more parameters within the response message, or you might log a message.

    • A setUpdateOrder method statement that indicates whether there is an order data update. This method should be identical to what you selected in the Design Studio automation plug-in Properties View XSLT Tab Update Order check box.

    • A completeTaskOnExit method statement that completes the plug-in and transitions the task to the next task based on the status selected, if the plug-in is intended to end the task. Since there can be multiple plug-ins within a task, you would only need this method in the last plug-in listed. For example, the Failed status might transition to a fallout task, and the Succeed status may transition to the next task in the process.

    • An OrderDataUpdate statement that updates the order data based on the information returned in the response. For more information about structuring order update code, see "Using OrderDataUpdate Elements to Pass Order Modification Data."

    • Indexing: Order data in OSM often includes multiple data instances. For example, an orchestration order must include the ControlData/OrderItem and ControlData/Functions multi-instance nodes. Multi-instance nodes in solution cartridges are possible for any data element where the maximum cardinality of the node is greater than 1. When updating a multi-instance data node using automations use the node index to reference the specific node instance you want to update. The node index is available in the XML API GetOrder.Response. See OSM XML API Developer's Guide for an example of a GetOrder response message with indexing.

The following example triggers different order data updates based on the status message returned from an external system. In this case, the external system is another OSM instance running in the SOM role:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns="http://www.metasolv.com/OMS/OrderDataUpdate" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:java="http://xml.apache.org/xslt/java" 
    xmlns:xalan="http://xml.apache.org/xslt"
    xmlns:oms="urn:com:metasolv:oms:xmlapi:1"
    xmlns:automator="java:oracle.communications.ordermanagement.automation.plugin.ScriptReceiverContextInvocation"
    xmlns:context="java:com.mslv.oms.automation.TaskContext"
    xmlns:log="java:org.apache.commons.logging.Log"
    xmlns:su="http://StatusUpdate"
    xmlns:so="http://xmlns.oracle.com/EnterpriseObjects/Core/EBO/SalesOrder/V2"
    xmlns:corecom="http://xmlns.oracle.com/EnterpriseObjects/Core/Common/V2"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    exclude-result-prefixes="xsl java xalan oms soapenv xsi">
 
    <!-- * -->
    <xsl:param name="automator"/>
    <xsl:param name="log"/>
    <xsl:param name="context"/>
 
    <!-- * -->
    <xsl:output method="xml" indent="yes" omit-xml-declaration="no" xalan:indent-amount="5"/>

    <xsl:template match="/">
     <xsl:variable name="taskData" select="fn:root(java:getOrderAsDOM($automator))/oms:GetOrder.Response"/>
     <xsl:variable name="response" select="fn:root()/su:StatusUpdate (: fn:root(.) :)"/>
     <xsl:variable name="items" select="fn:root()/su:StatusUpdate/su:OrderItem"/>
    <xsl:variable name="component" select="if (fn:exists($taskData/oms:_root/oms:ControlData/oms:Functions/*/oms:componentKey)) then $taskData/oms:_root/oms:ControlData/oms:Functions/*[fn:position()=1] else ()"/>
        <xsl:apply-templates/>
</xsl:template>

<!-- Match the status SOM_Complete -->
    <xsl:template match="$response[su:status/text()='SOM_Completed']">
     <xsl:variable name="log" select="java:info($log,concat('Received SOM Status Update: SOM_Completed; ', $response/su:status/text()))"/>
     <xsl:variable name="automator" select="java:setUpdateOrder($automator, true())"/>
     <xsl:variable name="context" select="java:completeTaskOnExit($context, success())"/>
     <OrderDataUpdate xmlns="http://www.metasolv.com/OMS/OrderDataUpdate/2002/10/25">
        <xsl:for-each select="su:ParentLineId">
            <xsl:variable name="parent" select="."/>
            <xsl:for-each select="$component/oms:orderItem[oms:orderItemRef/oms:LineXmlData/so:SalesOrderLine/corecom:Identification/corecom:ApplicationObjectKey/corecom:ID/text() = $parent/text()]">
                 <xsl:variable name="index" select="@index"/>
                     <Update path="{fn:concat("/ControlData/Functions/Provision/orderItem[@index='",fn:data($orderComponentItem/@index),"']")}>
                      <ExternalFulfillmentState>{$item/su:Status/text()}</ExternalFulfillmentState>
                    </Update> 
            </xsl:for-each>
        </xsl:for-each>			
     </OrderDataUpdate>
    </xsl:template>
 
<!-- Match the status SOM_Failed -->
    <xsl:template match="$response[su:status/text()='SOM_Failed']">
     <xsl:variable name="log" select="java:info($log,concat('Received SOM Status Update: SOM_Failed; ', $response/su:status/text()))"/>
     <xsl:variable name="automator" select="java:setUpdateOrder($automator, true())"/>
     <xsl:variable name="context" select="java:completeTaskOnExit($context, success())"/>
     <OrderDataUpdate xmlns="http://www.metasolv.com/OMS/OrderDataUpdate/2002/10/25">
        <xsl:for-each select="su:ParentLineId">
            <xsl:variable name="parent" select="."/>
            <xsl:for-each select="$component/oms:orderItem[oms:orderItemRef/oms:LineXmlData/so:SalesOrderLine/corecom:Identification/corecom:ApplicationObjectKey/corecom:ID/text() = $parent/text()]">
                 <xsl:variable name="index" select="@index"/>
                     <Update path="{fn:concat("/ControlData/Functions/Provision/orderItem[@index='",fn:data($orderComponentItem/@index),"']")}>
                      <ExternalFulfillmentState>{$item/su:Status/text()}</ExternalFulfillmentState>
                     </Update> 
            </xsl:for-each>
        </xsl:for-each>
     /OrderDataUpdate>
    </xsl:template>
 
    <xsl:template match="$response[su:status/text()='']">
     <xsl:variable name="log" select="java:info($log,concat('Received SOM Status Update: SOM_InProgress or SOM_Canceled; ', $response/su:status/text()))"/>
     <xsl:variable name="automator" select="java:setUpdateOrder($automator, false())"/>
     <xsl:variable name="context" select="java:completeTaskOnExit($context, success())"/>
     <OrderDataUpdate xmlns="http://www.metasolv.com/OMS/OrderDataUpdate/2002/10/25">
        <xsl:for-each select="su:ParentLineId">
            <xsl:variable name="parent" select="."/>
            <xsl:for-each select="$component/oms:orderItem[oms:orderItemRef/oms:LineXmlData/so:SalesOrderLine/corecom:Identification/corecom:ApplicationObjectKey/corecom:ID/text() = $parent/text()]">
                 <xsl:variable name="index" select="@index"/>
                     <Update path="{fn:concat("/ControlData/Functions/Provision/orderItem[@index='",fn:data($orderComponentItem/@index),"']")}>
                      <ExternalFulfillmentState>{$item/su:Status/text()}</ExternalFulfillmentState>
                     </Update> 
            </xsl:for-each>
        </xsl:for-each>
     </OrderDataUpdate>
    </xsl:template>
 
<!-- * -->
    <xsl:template match="* | @* | text()">
        <!-- do nothing -->
        <xsl:apply-templates/>
    </xsl:template>
</xsl:stylesheet>
External XSLT Sender

The Automated Task editor external XSLT sender receives task data from an external system, then sends the data (after possibly transforming the data) to another external system or even returns the data back to the original external system. This XSLT combines characteristics of external XSLT automators and internal XSLT senders. For more information, see "External XSLT Automator" and "Internal XSLT Sender."

Note:

You must declare ScriptSenderContextInvocation in any external XSLT sender which inherits the ScriptReceiverContextInvocation class and methods used in internal or external automators.

Internal XSLT Automator

The Automated Task editor internal XSLT automator receives task data from OSM, then processes the data. For example, such an automation might perform computational actions on the data or other similar logic. This XSLT combines characteristics of external XSLT automators and internal XSLT senders. For more information, see "External XSLT Automator" and "Internal XSLT Sender."

Note:

You must declare ScriptReceiverContextInvocation class in an internal XSLT automator.

Automation Plug-in Examples for Events, Jeopardies, and Notifications

The following topics provide XQuery automation plug-in examples for:

Event Automators

An event automation plug-in can be triggered when an order or a task transitions into a defined milestone. The automation can be any internal XQuery, XSLT, or custom automation since the milestone event, by definition, can only be triggered by milestones happening within an order or a task. For more information about the characteristics for these automations, see "Automation Plug-in XQuery Examples," "Automation Plug-in XSLT Examples," and "Custom Java Automation Plug-ins."

Note:

For an event automation plug-in you must declare the OrderNotificationContext instead of TaskContext. For example:

declare namespace context = "java:com.mslv.oms.automation.OrderNotificationContext";

The following example is an internal sender automation plug-in that uses methods available to the OrderNotificationContext class to get milestone data from the order and sends an notification message to an external system. Because this sender does not expect a response message (a fire-and-forget message), you must use the OrderNotificationContext class ackNotificationOnExit method to clear the JMS correlation ID for the notification. Also, events do not transition tasks, so you must not specify completeTaskOnExit in a notification.

declare namespace saxon="http://saxon.sf.net/";
declare namespace xsl="http://www.w3.org/1999/XSL/Transform";
declare namespace log = "java:org.apache.commons.logging.Log";
declare namespace outboundMessage = "java:javax.jms.TextMessage";
declare namespace oms="urn:com:metasolv:oms:xmlapi:1";
declare namespace osm="http://xmlns.oracle.com/communications/ordermanagement/model";
declare namespace context = "java:com.mslv.oms.automation.OrderNotificationContext";
 
declare variable $context external;
declare variable $log external;
declare variable $outboundMessage external;
 
let $taskData := fn:root(.)/oms:GetOrder.Response
let $correlationId := $taskData/oms:_root/oms:Id/text() 
let $controlDataArea := if (fn:exists($taskData/oms:_root/oms:ControlData)) 
                            then $taskData/oms:_root/oms:ControlData 
                            else ()
 
return
(
log:info($log, fn:concat('COMCartridge: Invoking orderCompletionNotification for order[',$taskData/oms:OrderID/text(),'] with correlation [', $correlationId,']')),
context:ackNotificationOnExit($context),
outboundMessage:setStringProperty($outboundMessage, "COMCorrelationID", $correlationId),
outboundMessage:setStringProperty($outboundMessage, "SUB_FOLDER_NAME", $taskData/oms:_root/oms:OrderNumber/text()),
outboundMessage:setStringProperty($outboundMessage, "COMMilestone", "COMOrderCompleteEvent"),
<orderNotification xmlns="http://xmlns.oracle.com/communications/sce/dictionary/CommonResourcesCartridge/Notifications"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <OSMOrderId>{$taskData/oms:OrderID/text()}</OSMOrderId>
    <Id>{$correlationId}</Id>
    <OrderNumber>{$taskData/oms:_root/oms:OrderNumber/text()}</OrderNumber>
    {
    for $serviceInstance in $controlDataArea/oms:OrderItem
    return
        <Instance>
            <InstanceID>{$serviceInstance/oms:instanceID/text()}</InstanceID>
            <OrderLineId>{$serviceInstance/oms:orderLineId/text()}</OrderLineId>
            <Status>{$serviceInstance/oms:status/text()}</Status>
        </Instance>
    }
</orderNotification>
)
Jeopardy Automators

An order jeopardy automation plug-in can be triggered when a particular condition is met, such as when a task exceeds the expected duration configured for the task or when the process that the task is a part of exceeds its excepted process duration. The automation can be any internal XQuery, XSLT, or custom automation since the jeopardy, by definition, can only be triggered by events happening within the task or the process. For more information about the characteristics for these automations, see "Automation Plug-in XQuery Examples," "Automation Plug-in XSLT Examples," and "Custom Java Automation Plug-ins."

Note:

For an order level jeopardy automation plug-in you must declare the OrderNotificationContext instead of TaskContext. For example:

declare namespace context = "java:com.mslv.oms.automation.OrderNotificationContext";

For a task level jeopardy automation plug-in, if the task level jeopardy condition Multiple events per Task instance is set indicating that the task is a multi-instance task and the event should be triggered for each instance, then you must declare TaskNotificationContext so that the task data is passed to each instance of the event. If the task is not a multi-instance task, then OrderNotificationContext should be declared.

The following example is an internal automator plug-in that uses methods available to the OrderNotificationContext class to get notification details from the task in combination with the XML API Notification.Request that logs the jeopardy notification details. Other jeopardy examples could also send an email or trigger a pager.

declare namespace oms="urn:com:metasolv:oms:xmlapi:1";
declare namespace automator = "java:oracle.communications.ordermanagement.automation.plugin.ScriptReceiverContextInvocation";
declare namespace context = "java:com.mslv.oms.automation.OrderNotificationContext";
declare namespace log = "java:org.apache.commons.logging.Log";
 
declare option saxon:output "method=xml";
declare option saxon:output "saxon:indent-spaces=2";
 
declare variable $automator external;
declare variable $context external;
declare variable $log external;
 
declare variable $exitStatus := "success";
 
let $thisOrderId := context:getOrderId($context)
(: let $taskMnemonic := context:getTaskMnemonic($context) :)
let $notificationName := context:getNotificationName($context)
let $notificationType := context:getNotificationType($context)
let $orderId := fn:root(.)/oms:GetOrder.Response/oms:_root/oms:orderId
let $xmlRequest := '<Notifications.Request xmlns="urn:com:metasolv:oms:xmlapi:1" />'
let $notifications := context:processXMLRequest($context, $xmlRequest)
return (
  log:info($log, fn:concat("XQuery jeopardy: order[", $thisOrderId, 
    "], notificationContext [", context:getClass($context), 
    "], notificationName[", $notificationName, 
    "], notificationType[", $notificationType, 
    "], notifications[", $notifications, 
    "] entered order ID [", $orderId/text(), "]")),
  <placeholder/>
)
Order Notification Automation Plug-ins

An order notification automation plug-in can be triggered when specified data changes in the order. For example, you can monitor order status changes using the orchestration data element ControlData/OrderFulfillmentState or individual order item status changes using ControlData/OrderItem/OrderItemFulfillmentState so OSM triggers an internal XQuery sender automation plug-in that sends these status changes to another system, such as from a SOM OSM system to a COM OSM system, or from a COM OSM system to a CRM.

The automation can be any internal XQuery, XSLT, or custom automation since the notification, by definition, can only be triggered by a change in the internal order data. For more information about the characteristics for these automations, see "Automation Plug-in XQuery Examples," "Automation Plug-in XSLT Examples," and "Custom Java Automation Plug-ins."

Note:

For an order notification automation plug-in you must declare the OrderDataChangeNotificationContext instead of TaskContext. For example:

declare namespace context = "java:com.mslv.oms.automation.OrderDataChangeNotificationContext";

The following example is an internal XQuery sender that sends any order and order item fulfillment state changes to another OSM system. It also provides stubs for transforming the fulfillment states to external system message formats.

declare namespace osm="urn:com:metasolv:oms:xmlapi:1";
declare namespace log = "java:org.apache.commons.logging.Log";
declare namespace to="http://TechnicalOrder";
declare namespace automator = "java:oracle.communications.ordermanagement.automation.plugin.ScriptSenderContextInvocation";
declare namespace su="http://StatusUpdate";
declare namespace context = "java:com.mslv.oms.automation.OrderDataChangeNotificationContext";
declare namespace outboundMessage = "java:javax.jms.TextMessage";

declare variable $log external;
declare variable $outboundMessage external;

(: 
   This function is for indication purposes only.
   OSM Fulfillment State can be mapped according the expectation of Upstream 
:)
declare function local:getUpstreamFulfillmentState($fulfillmentState as xs:string) as xs:string {
    (: fn:concat('Order_Upstream_' , $fulfillmentState) :)
    fn:concat('' , $fulfillmentState)
};

(: 
   This function is for indication purposes only.
   OSM Fulfillment State can be mapped according the expectation of Upstream 
:)
declare function local:getUpstreamOrderItemFulfillmentState($fulfillmentState as xs:string) as xs:string {
    (: fn:concat('OrderItem_Upstream_' , $fulfillmentState) :)
    fn:concat('' , $fulfillmentState)
};

let $order := ..//osm:GetOrder.Response
let $orderFulfillmentState := $order/osm:_root/osm:ControlData/osm:OrderFulfillmentState
let $mappedUpstreamFulfillmentState := if(exists($orderFulfillmentState)) then local:getUpstreamFulfillmentState($orderFulfillmentState/text()) else ()

return
(
log:info($log,'Sending Upstream Fulfillment State'),
outboundMessage:setStringProperty($outboundMessage, "SOMTOMCorrelationHeader", concat($order/osm:_root/osm:messageXmlData/to:TechnicalOrder/to:SOMOrderId/text(),'-SOM')),
if (fn:count($order/osm:_root/osm:ControlData/osm:OrderItem)=0) then (
<StatusUpdate xmlns="http://StatusUpdate">
<numSalesOrder>{$order/osm:Reference/text()}</numSalesOrder>
<numOrder>{$order/osm:OrderID/text()}</numOrder>
<typeOrder>{$order//osm:OrderHeader/osm:typeOrder/text()}</typeOrder>
<errorCode>0</errorCode>
<status>cancelled</status>
</StatusUpdate>
) else (
<StatusUpdate xmlns="http://StatusUpdate">
<numSalesOrder>{$order/osm:Reference/text()}</numSalesOrder>
<numOrder>{$order/osm:OrderID/text()}</numOrder>
<typeOrder>{$order//osm:OrderHeader/osm:typeOrder/text()}</typeOrder>
<errorCode>0</errorCode>
<status>{$mappedUpstreamFulfillmentState}</status>
{
    for $orderItem in $order/osm:_root/osm:ControlData/osm:OrderItem
    where exists($orderItem/osm:OrderItemFulfillmentState)
    return 
        <OrderItem>
            <LineName>{$orderItem/osm:LineName/text()}</LineName>
            <LineId>{$orderItem/osm:LineId/text()}</LineId>
            <ParentLineId>{$orderItem/osm:ParentLineId/text()}</ParentLineId>
            <SpecificationName>{$orderItem/osm:TypeCode/text()}</SpecificationName>
            <Status>{local:getUpstreamOrderItemFulfillmentState($orderItem/osm:OrderItemFulfillmentState/text())}</Status>
        </OrderItem>
    }
</StatusUpdate>
)
)

Custom Java Automation Plug-ins

This topic provides common usage examples for custom Java automation plug-ins.

Internal Custom Java Automator

A basic internal custom Java automator has the following characteristics:

  • The name of the custom automation package. For example:

    package com.mslv.oms.sample.atm_frame;
    
  • Import statements required for this custom automation plug-in. For example:

      import com.mslv.oms.automation.plugin.*;
      import com.mslv.oms.automation.*;
      import java.rmi.*;
    
  • An arbitrary class name that extends AbstractAutomator. For the automation framework to call an internal custom Java automator, the plug-in must extend the AbstractAutomator class. This class resides in the com.mslv.automation.plugin package. For example:

      public class MyPlugin extends AbstractAutomator {
    
  • The required run method, as dictated by the parent class, AbstractAutomator

       protected void run(String inputXML, AutomationContext context)
                       throws com.mslv.oms.automation.AutomationException {
    
  • Cast the AutomationContext object to the TaskContext object. This example assumes that the custom automation plug-in is triggered by an automated task, so the code is expecting the context input an argument to be an instance of the TaskContext object.

            TaskContext taskContext = (TaskContext)context;
    

    Note:

    You can use the TaskContext object to do many things, such as complete the task, suspend it, and so on. For more information about this class, see the OSM Javadocs.

  • Call a method on the TaskContext object to retrieve the task name.

            String taskName = taskContext.getTaskMnemonic();
    
  • Add any require business logic.

        this.performAutomation(taskname);
    

The following example shows the minimal amount of code required for a custom automation plug-in to run. This example assumes that it is triggered by an automated task.

package com.mslv.oms.sample.atm_frame;

  import com.mslv.oms.automation.plugin.*;
  import com.mslv.oms.automation.*;
  import java.rmi.*;
 
  public class MyPlugin extends AbstractAutomator {
   protected void run(String inputXML, AutomationContext context)
                   throws com.mslv.oms.automation.AutomationException {
      try {
        TaskContext taskContext = (TaskContext)context;
        String taskName = taskContext.getTaskMnemonic();
        this.performAutomation(taskname);
      catch(RemoteException ex) {
        throw new AutomationException(ex); }
      catch(AutomationException x) {
        throw x; }
    }
  }

Internal Custom Java Sender

A basic internal custom Java sender has the following characteristics:

  • The name of the custom automation package. For example:

    package com.mslv.oms.sample.atm_frame;
    
  • Import statements required for this custom automation plug-in. For example:

      import com.mslv.oms.automation.plugin.*;
      import com.mslv.oms.automation.*;
      import java.rmi.*;
    
  • An arbitrary class name that extends AbstractSendAutomator. For the automation framework to call an internal custom Java sender, the plug-in must extend the AbstractSendAutomator class. This class resides in the com.mslv.automation.plugin package. For example:

      public class MyPlugin extends AbstractSendAutomator {
    
  • The required run method, as dictated by the parent class, AbstractSendAutomator

       protected void run(String inputXML, AutomationContext context)
                       throws com.mslv.oms.automation.AutomationException {
    
  • Cast the AutomationContext object to the TaskContext object. This example assumes that the custom automation plug-in is triggered by an automated task, so the code is expecting the context input an argument to be an instance of the TaskContext object.

            TaskContext taskContext = (TaskContext)context;
    

    Note:

    You can use the TaskContext object to do many things, such as complete the task, suspend it, and so on. For more information about this class, see the OSM Javadocs.

  • Call a method on the TaskContext object to retrieve the task name.

            String taskName = taskContext.getTaskMnemonic();
    
  • Sets the text for the outbound message, which is sent to the external message queue defined by the automation definition. The custom code does not establish a connection to an external system or send the message; the automation framework handles the connection and sends the message upon completion of the makeRequest method.

            outboundMessage.setText("Received task event for task = " + taskName);}
    

    Note:

    OSM provides outboundMessage in the OSM automation framework as a JMS message with text content. If you require other message formats or protocols, do not use outboundMessage. You must implement an internal custom java automator or helper class with the required code.

The following example shows the minimal amount of code required for a custom automation plug-in that sends data to run. This example assumes that it is triggered by an automated task.

  package com.mslv.oms.sample.atm_frame;

  import com.mslv.oms.automation.plugin.*;
  import com.mslv.oms.automation.*;
  import javax.jms.TextMessage;
  import java.rmi.*;
  
  public class MyPlugin extends AbstractSendAutomator {
    protected void makeRequest(String inputXML, AutomationContext context,
                   TextMessage outboundMessage)
                   throws com.mslv.oms.automation.AutomationException {
      try {
        TaskContext taskContext = (TaskContext)context;
        String taskName = taskContext.getTaskMnemonic();

        // optional - You can use this code if you want to define your own correlation ID rather than an autogenerated correlation ID.
        Correlator correlator = getCorrelator(context);
        correlator.add(createCustomCorrelationId(taskContext));

        outboundMessage.setText("Received task event for task = " + taskName);}
      catch(javax.jms.JMSException ex) {
        throw new AutomationException(ex); }
      catch(RemoteException x) {
        throw new AutomationException(x); }
    }

    private String createCustomCorrelationId(TaskContext taskContext) {
     // Create a custom correlation ID using task name and unique order history ID
     // Actual correlation calculation depends on solution logic
        String corrId = taskContext.getTaskMnemonic() 
                        + "-" 
                        + String.valueOf(taskContext.getOrderHistoryId());
        return corrId;
    }

  }

External Custom Java Automator that Changes the OSM Task Status

A basic external custom Java automator that changes the OSM task status has the following characteristics:

  • The name of the custom automation package. For example:

    package com.mslv.oms.sample.atm_frame;
    
  • Import statements required for this custom automation plug-in. For example:

      import com.mslv.oms.automation.plugin.*;
      import com.mslv.oms.automation.*;
      import java.rmi.*;
    
  • An arbitrary class name that extends AbstractAutomator. For the automation framework to call an external custom Java sender, the plug-in must extend the AbstractAutomator class. This class resides in the com.mslv.automation.plugin package. The name reflects that this example is an external event receiver, receiving information from ASAP. For example:

      public class AsapResponseHandler extends AbstractAutomator {
    
  • The required run method, as dictated by the parent class, AbstractAutomator.

        public void run(String inputXML, AutomationContext task)
                    throws AutomationException {
    
  • Cast the AutomationContext object to the TaskContext object. This example assumes that the custom automation plug-in is triggered by an automated task, so the code is expecting the context input an argument to be an instance of the TaskContext object.

            TaskContext taskContext = (TaskContext)context;
    

    Note:

    You can use the TaskContext object to do many things, such as complete the task, suspend it, and so on. For more information about this class, see the OSM Javadocs.

  • Call a method on the TaskContext object to retrieve the task name.

            String taskName = taskContext.getTaskMnemonic();
    
  • Logs the information regarding the response that the plug-in is handling. AtmFrameCatalogLogger is available to this example plug-in based on the package in which the plug-in resides. You must replace this with your own solution logic.

            AtmFrameCatalogLogger.logTaskEventResponse
              (taskName,tctx.getOrderId(),tctx.getOrderHistoryId(),inputXML);
    

    Note:

    The automation framework keeps track of the order ID and the order history ID of the task that triggered the automation. There are two ways you can get the Order History ID:

    • By parsing the inputXML

    • By calling the TaskContext.getOrderHistoryId method as shown in this example.

    In most cases, these return the same order history ID. However, if you use automation to handle task events, the order history ID obtained from:

    • Parsing the inputXML returns the order history ID as it was when the task was generated

    • Calling the TaskContext.getOrderHistoryID method returns the order history ID as it is now (current)

  • Update the task status by calling a method on the TaskContext object.

            tctx.completeTaskOnExit("activation_successful"); }
    

The following example shows an external custom automator that updates the OSM task status. This example assumes that the automation definition is an external event receiver that is receiving a message from ASAP, and that it is triggered by an automated task.

  package com.mslv.oms.sample.atm_frame;
 
  import com.mslv.oms.automation.plugin.*;
  import com.mslv.oms.automation.*;
  import java.rmi.*;

  public class AsapResponseHandler extends AbstractAutomator {
    public void run(String inputXML, AutomationContext task)
                throws AutomationException {
      try {
        TaskContext tctx = (TaskContext)task;
        String taskName = tctx.getTaskMnemonic();
        AtmFrameCatalogLogger.logTaskEventResponse
          (taskName,tctx.getOrderId(),tctx.getOrderHistoryId(),inputXML);
        tctx.completeTaskOnExit("activation_successful"); }
      catch(RemoteException ex) {
        throw new AutomationException(ex); }
      catch(AutomationException x) {
        throw x; }
    }
  }

External Custom Java Automator that Updates Order Data

If an automated task sends data to an external system and the external system sends a response back, you may need to update OSM with the data received from the external system.

The following example shows how to update data in OSM. The code is an example of updating OSM with data received from Oracle Communications Unified Inventory Management (UIM) when calling the server extension FRDemo.AssignFacilities.

  package com.mslv.oms.sample.atm_frame;

  import com.mslv.oms.automation.plugin.*;
  import com.mslv.oms.automation.*;
  import java.rmi.*;
  import java.util.*;
  import java.io.*;
  import java.net.*;
  import org.xml.sax.*;
  import org.w3c.dom.*;
  import javax.xml.parsers.*;

  public class UIMResponseHandler extends AbstractAutomator {
  
    public void run( String inputXML, AutomationContext task)
                throws AutomationException {
      try {
        TaskContext tctx = (TaskContext)task;
        String taskName = tctx.getTaskMnemonic();
        AtmFrameCatalogLogger.logTaskEventResponse
          (taskName,tctx.getOrderId(),tctx.getOrderHistoryId(),inputXML);
 
        // Using the data returned from UIM, update the OSM order data
        String updateXml = generateOMSUpdateString(inputXML);
        tctx.updateOrderData(updateXml);

        // Complete the OSM task with the correct status
        tctx.completeTaskOnExit( "success" ); }

      catch(OrderUpdateException ex) {
        throw new AutomationException( ex ); }
      catch(RemoteException ex) {
        throw new AutomationException( ex ); }
     catch(AutomationException x ) {
       throw x; }
    }

    static private String generateOMSUpdateString(String inputXML) {
      StringBuffer osmUpdate = new StringBuffer("");
      try {
        osmUpdate = new StringBuffer
         ("<OrderDataUpdate xmlns=\"http://www.w3.org/2001/XMLSchema\""+
          " xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"" +
          " xmlns:odu=\"http://www.oracle.com/OMS/OrderDataUpdate\"" +
          " targetNameSpace=\"http://www.oracle.com/OMS/OrderDataUpdate\">");
 
        // Use updates from UIM to update OSM
        osmUpdate.append("<AddMandatory>true</AddMandatory>");
        DocumentBuilderFactory docBuilderFactory =
          DocumentBuilderFactory.newInstance();
        DocumentBuilder parser = docBuilderFactory.newDocumentBuilder();
        Document doc = parser.parse(new StringBufferInputStream(inputXML));
        Element root = doc.getDocumentElement();
        root.normalize();
        NodeList a_site_list = root.getElementsByTagName("a_site information");
        NodeList a_site_data = a_site_list.item(0).getChildNodes();

        for(int i=0;i<a_site_data.getLength();i++) {
          Element e = (Element)a_site_data.item(i);
          osmUpdate.append("<Add path=\"/a_site_information/");
          osmUpdate.append(e.getTagName());
          osmUpdate.append("\">");
          osmUpdate.append(e.getFirstChild().getNodeValue());
          osmUpdate.append("</Add>"); 
        }

        NodeList z_site_list = root.getElementsByTagName("z_site_information");
        NodeList z_site_data = z_site_list.item(0).getChildNodes();

        for(int i=0;i<a_site_data.getLength();i++) {
          Element e = (Element)a_site_data.item(i);
          osmUpdate.append("<Add path=\"/z_site_information/");
          osmUpdate.append(e.getTagName());
          osmUpdate.append("\">");
          osmUpdate.append(e.getFirstChild().getNodeValue());
          osmUpdate.append("</Add>");
        }

        osmUpdate.append("</OrderDataUpdate>");

        System.out.println(omsUpdate.toString()); }

    catch(Exception e) {
      System.out.println(e.getMessage()); }
 
    return omsUpdate.toString();
    }
  }

The following code snippets from this example show:

  • How to display where OSM data is updated, using XML input to describe which data nodes to update.

            tctx.updateOrderData(updateXml);
    
  • How to build the OrderDataUpdate XML string to update the data in OSM using data garnered by parsing the UIM XML. See "Using OrderDataUpdate Elements to Pass Order Modification Data" for more information. This differs for every order template and every external system. This code represents the translation step where you convert the data from the format of an external system to the format that OSM expects.

        static private String generateOMSUpdateString(String inputXML) {
          StringBuffer osmUpdate = new StringBuffer("");
          try {
            osmUpdate = new StringBuffer
             ("<OrderDataUpdate xmlns=\"http://www.w3.org/2001/XMLSchema\""+
              " xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"" +
              " xmlns:odu=\"http://www.oracle.com/OMS/OrderDataUpdate\"" +
              " targetNameSpace=\"http://www.oracle.com/OMS/OrderDataUpdate\">");
     
            // Use updates from UIM to update OSM
            osmUpdate.append("<AddMandatory>true</AddMandatory>");
            DocumentBuilderFactory docBuilderFactory =
              DocumentBuilderFactory.newInstance();
            DocumentBuilder parser = docBuilderFactory.newDocumentBuilder();
            Document doc = parser.parse(new StringBufferInputStream(inputXML));
            Element root = doc.getDocumentElement();
            root.normalize();
            NodeList a_site_list = root.getElementsByTagName("a_site information");
            NodeList a_site_data = a_site_list.item(0).getChildNodes();
    
            for(int i=0;i<a_site_data.getLength();i++) {
              Element e = (Element)a_site_data.item(i);
              osmUpdate.append("<Add path=\"/a_site_information/");
              osmUpdate.append(e.getTagName());
              osmUpdate.append("\">");
              osmUpdate.append(e.getFirstChild().getNodeValue());
              osmUpdate.append("</Add>"); 
            }
    
            NodeList z_site_list = root.getElementsByTagName("z_site_information");
            NodeList z_site_data = z_site_list.item(0).getChildNodes();
    
            for(int i=0;i<a_site_data.getLength();i++) {
              Element e = (Element)a_site_data.item(i);
              osmUpdate.append("<Add path=\"/z_site_information/");
              osmUpdate.append(e.getTagName());
              osmUpdate.append("\">");
              osmUpdate.append(e.getFirstChild().getNodeValue());
              osmUpdate.append("</Add>");
            }
    
            osmUpdate.append("</OrderDataUpdate>");
    
            System.out.println(omsUpdate.toString()); }
    
        catch(Exception e) {
          System.out.println(e.getMessage()); }
     
        return omsUpdate.toString();
        }
    

    The structure of the XML document to update OSM data is as follows:

    <OrderDataUpdate xmlns=\"http://www.w3.org/2001/XMLSchema\"
    xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"
    xmlns:odu=\"http://www.oracle.com/OMS/OrderDataUpdate\"
    targetNameSpace=\"http://www.oracle.com/OMS/OrderDataUpdate\">
    <AddMandatory>true</AddMandatory>
    <Add path=\"/service_details/new_number\">98765</Add>
    <Update path=\"/customer_details/service_address/street\">55 Updated St</Update>
    <Delete path=\"/service_details/current_account_number\"></Delete>
    </OrderDataUpdate>
    

    This example illustrates adding a data node (Add path), updating a data node (Update path), and deleting a data node (Delete path).

  • How to specify a mandatory parameter. If set to true, the following rules apply:

            osmUpdate.append("<AddMandatory>true</AddMandatory>");
    
    • If you delete a mandatory node, AddMandatory replaces the node and populates it with the default value.

    • If the update is missing a mandatory node, AddMandatory adds the missing node and populates it with the default value.

      Note:

      If you add a mandatory field, but do not include a value, AddMandatory will not add a default value and the request will generate an error-error code 200.

Using OrderDataUpdate Elements to Pass Order Modification Data

You use OrderDataUpdate XML elements to pass data add, modify and delete data nodes in an order.

OrderDataUpdate elements can be passed as a parameter to updateOrderData(). XSL translations whose results are passed to setUpdateOrder() must be in OrderDataUpdate format. See the OSM Javadocs for details on both methods. You can also pass OrderDataUpdate format elements to the DataChange Web Service (see the SDK schema OrderManagementWS.xsd) and UpdateOrder.request XML API call (see the SDK schema oms-xmlapi.xsd).

For update and delete operations on multi-instance nodes, you must specify the order node index as it exists in the input XML. Specify the order node index as "[@index='index_value']" where index_value is the order node index.

The following example shows how to specify the addition of an order node with OrderDataUpdate. The path attribute identifies the parent node under which to add the element:

<OrderDataUpdate>
  <Add path="/">
    <ProvisioningOrderResponse>
      <OrderInformation>
        <OrderNumber>1238723</OrderNumber>
      </OrderInformation>
    </ProvisioningOrderResponse>
  </Add>
</OrderDataUpdate>

The following example shows a combined update and delete operation on a multi-instance node using OrderDataUpdate. In Delete attributes, the path attribute identifies the data to delete. In Update attributes, the path attribute identifies the data to update. Indexes are required on Update and Delete attributes when modifying multi-instance nodes. Note how the order node index values are specified in the Update and Delete attributes.

<OrderDataUpdate>
  <Delete path="/client_info/address[@index='80132']/city" />
  <Update path="/client_info/address[@index='76579']/city">Newark</Update>
  <Update path="/customer_details/service_address/street">55 Updated St</Update>"
  <Delete path="/service_details/current_account_number"></Delete>
</OrderDataUpdate>

See "External Custom Java Automator that Updates Order Data" for an example in which OrderDataUpdate XML data is created dynamically within Java code and passed to UpdateOrderData().

The schema for OrderDataUpdate is as follows:

<?xml version="1.0" encoding="UTF-8"?>
<schema targetNamespace="http://
www.metasolv.com/OMS/OrderDataUpdate" xmlns:odu="http://www.metasolv.com/
OMS/OrderDataUpdate" xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
 
  <element name="OrderDataUpdate">
  <complexType>
    <choice maxOccurs="unbounded">
      <element ref="odu:Add"/>
      <element ref="odu:Delete"/>
      <element ref="odu:Update"/>
    </choice>
  </complexType>
  </element>
 
  <element name="Add">
    <annotation>
      <documentation>It contains a node to be added. The path attribute identifies the parent node under which to add the element.</documentation>
    </annotation>
    <complexType>
      <sequence>
        <any/>
      </sequence>
      <attribute name="path" type="string" use="required"/>
    </complexType>
  </element>
 
  <element name="Delete">
    <annotation>
      <documentation>It contains a node to be deleted. The path attribute identifies the node to delete.</documentation>
    </annotation>
    <complexType>
      <attribute name="path" type="string" use="required"/>
    </complexType>
  </element>
 
  <element name="Update">
    <annotation>
      <documentation>It contains a node to update. The path attribute identifies the node to update.</documentation>
    </annotation>
    <complexType>
      <simpleContent>
        <extension base="string">
          <attribute name="path" type="string" use="required"/>
        </extension>
      </simpleContent>
    </complexType>
  </element>
</schema>

Examples of Sending Messages to External Systems

Automation simplifies the process of sending messages to external systems. The automation framework does the following:

  • Assumes the protocol is JMS. The products (Siebel, OSM, UIM, ASAP, IP Service Activator) all have JMS APIs.

  • Takes care of establishing and maintaining the various JMS connections.

  • Constructs the JMS messages, setting the required message properties.

  • Guarantees delivery of the message and handles any errors or exceptions. It retries until the message is delivered.

  • Automatic message correlation.

  • Poison message handling.

An OSM event that is sent to an external system follows this process flow:

  1. OSM runs an automation that triggers an automation plug-in.

  2. Internally, the automation framework maps the plug-in, using the automationMap.xml configuration, onto custom business logic and calls the makeRequest method on the custom automator class.

  3. The makeRequest method performs some business logic and sets the content of the outbound message.

  4. The automation framework adds properties to the outbound message to aid in correlating external system responses to requests.

  5. The automation framework uses information from the automationMap.xml to send the JMS message to the JMS queue representing the external system.

The following example shows a custom automation plug-in that sends data to an external system.

 package com.mslv.oms.sample.atm_frame;
 
 import com.mslv.oms.automation.plugin.*;
 import com.mslv.oms.automation.*;
 import javax.jms.TextMessage;
 import java.rmi.*;
 
 public class ObjectelPlugin extends AbstractSendAutomator {
 
 protected void makeRequest(String inputXML, AutomationContext context, TextMessage outboundMessage) throws com.mslv.oms.automation.AutomationException {

 try {
 TaskContext taskContext = (TaskContext)context;
 String taskName = taskContext.getTaskMnemonic();
 AtmFrameCatalogLogger.logTaskEvent(taskName, taskContext.getOrderId(), taskContext.getOrderHistoryId(), inputXML);

 //
 // Set the outgoing message
 //
 String xmlRequest = "<Message type=\"ni\"><iLibPlus:findFunctionalPortOnLocation.Request xmlns:iLibPlus=\"http://www.oracle.com/objectel\"><location><DS><AG2ObjectID>189438</AG2ObjectID><AG2ParentID>189428</AG2ParentID><CLLIX>XML.CO.1</CLLIX><SiteName>XML.CO.1</SiteName></DS></location><feType>PP</feType><portType>$FEP</portType><selectionMethod>LOAD_BALANCE</selectionMethod><portSelectionAttribName><string>AG2ObjectID</string><string>AG2ParentID</string><string>AG2PortLabel</string></portSelectionAttribName><portSelectionAttribValue><string>189508</string><string>189478</string><string>F-31-OC-48</string></portSelectionAttribValue><portUpdateAttribName/><portUpdateAttribValue/></iLibPlus:findFunctionalPortOnLocation.Request></Message>";
 outboundMessage.setText( xmlRequest );

 } catch( javax.jms.JMSException x ) {
 throw new AutomationException( x );
 } catch(RemoteException ex){
 throw new AutomationException( ex );
 }
 }
 }

The following code snippets from this example show:

  • how to generate an output XML string. In this example it is hard coded. In a business case you would use business logic to transform OSM data into what the external system expects

     String xmlRequest = "<Message type=\"ni\"><iLibPlus:findFunctionalPortOnLocation.Request xmlns:iLibPlus=\"http://www.oracle.com/objectel\"><location><DS><AG2ObjectID>189438</AG2ObjectID><AG2ParentID>189428</AG2ParentID><CLLIX>XML.CO.1</CLLIX><SiteName>XML.CO.1</SiteName></DS></location><feType>PP</feType><portType>$FEP</portType><selectionMethod>LOAD_BALANCE</selectionMethod><portSelectionAttribName><string>AG2ObjectID</string><string>AG2ParentID</string><string>AG2PortLabel</string></portSelectionAttribName><portSelectionAttribValue><string>189508</string><string>189478</string><string>F-31-OC-48</string></portSelectionAttribValue><portUpdateAttribName/><portUpdateAttribValue/></iLibPlus:findFunctionalPortOnLocation.Request></Message>";
    
  • how to set the output data:

     outboundMessage.setText( xmlRequest );
    
  • How this code does not establish a connection to an external system or send a message. After the data is set in the code, the message is automatically sent upon exit of the makeRequest method.

Examples of Handling Responses from External Systems

In Message Property Correlation, the following steps describe how responses from external systems are handled.

  1. The plug-in populates the message content.

  2. The plug-in sets a property on the outbound JMS message, with name of the value set for correlationproperty in the automationMap.xml file, and a value decided by the business logic. For example, you could use this to correlate on a reference number.

  3. If the value of the correlationproperty in the automationMap.xml file is set to the value JMSCorrelationID, the plug-in is not required to set the property on the outbound message (as described in Step 2). The automation framework does this automatically.

  4. The automation framework saves the message properties set for each message with the event information.

  5. The automation framework sets the replyTo property on the JMS message.

  6. The external system copies the properties on the request message to the response message.

  7. The external system sends the message to the reply queue specified in the automationMap.xml file.

  8. The automation framework uses the configuration in the automationMap.xml file to map messages from external systems to plug-ins. The plug-ins are automators written by system integrators. Configuration of an automator for receiving messages from an external system are defined within Design Studio and saved to the automationMap.xml file.

  9. The automation framework uses the message properties of the response, plus the correlation information saved in step four above, to reload a Context for the response message.

  10. The run method of the external system automator is called and is passed the Context created in step 9.

  11. The automator performs business logic, such as completing the task.

The following example shows a custom automation plug-in that handles and processes response messages from an external system.

 package com.mslv.oms.sample.atm_frame;

 import com.mslv.oms.automation.plugin.*;
 import com.mslv.oms.automation.*;
 import java.rmi.*;

 public class UIMResponseHandler extends AbstractAutomator {

 public void run( String inputXML, AutomationContext task)
 throws AutomationException {

 try {
 TaskContext tctx = (TaskContext)task;

 tctx.completeTaskOnExit( "success" );

 } catch(RemoteException ex){
 throw new AutomationException( ex );
 } catch(AutomationException x ) {
 throw x;
 }
 }
}

This automation plug-in does not need to send JMS messages to any system, so it extends AbstractAutomator and is intended to process Task automation responses, so it casts the Context to a TaskContext then completes the task.

The following example shows what the external system is expected to do for the message property correlation to work.

 public void sendMessage(Message originalMessage) {
 try {
 //
 // Set up the JMS connections
 //
 QueueConnectionFactory connectionFactory = (QueueConnectionFactory)jndiCtx.lookup(connectionFactoryName); 
 QueueConnection queueConnection = connectionFactory.createQueueConnection();
 QueueSession queueSession = queueConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
 Queue replyQueue = (Queue)originalMessage.getJMSReplyTo();
 QueueSender queueSender = queueSession.createSender(replyQueue);

 //
 // Create the message
 //
 TextMessage textMessage = queueSession.createTextMessage(((TextMessage)originalMessage).getText());
 textMessage.setStringProperty("MESSAGE_NAME","ActivationResponse");
 textMessage.setJMSCorrelationID(originalMessage.getJMSCorrelationID());

 //
 // Send the message
 //
 queueSender.send(textMessage, javax.jms.DeliveryMode.PERSISTENT, javax.jms.Message.DEFAULT_PRIORITY, 1800000);

 } catch(javax.jms.JMSException ex){
 ex.printStackTrace();
 } catch(javax.naming.NamingException ex){
 ex.printStackTrace();
 }
 }

The following code snippets from this example show:

  • how the external system chooses which JMS destination to send the reply to.

    Queue replyQueue = (Queue)originalMessage.getJMSReplyTo();
    QueueSender queueSender = queueSession.createSender(replyQueue);
    
  • the external system setting a property that identifies the nature of the JMS message. This implies that the automation was defined with a message property selector select statement that matches these parameters.

    textMessage.setStringProperty("MESSAGE_NAME","ActivationResponse");
    
  • the external system echoing the correlation information onto the reply message. This implies that the automation was defined to correlate based on JMSCorrelationID.

    textMessage.setJMSCorrelationID(originalMessage.getJMSCorrelationID());

Compensation XQuery Expressions

The following topics provide information about automation and manual task compensation XQuery expressions.

For general OSM XQuery information, see OSM Modeling Guide.

Task Re-Evaluation and Rollback XQuery Expressions

You can dynamically assign compensation strategies to tasks by creating XQuery expressions in the Design Studio Task Editor Compensation tab for re-evaluation compensation strategies or compensation strategies for when a task is no longer required.

Note:

If the XQuery expression is invalid OSM logs the error but does not rollback the transaction. Instead, OSM uses the static compensation strategy as the default.

This section refers to the Design Studio OSM Automated Task or Manual Task editor, Compensation tab Compensation Expression XQuery field for re-evaluation compensation strategies:

  • Context: The context for this XQuery is the current order data. You can get the current order data using the XML API GetOrder.Response function.

  • Prolog: You can declare the XML API namespace to use the GetOrder.Response function in the XQuery body to extract the order information. You must declare the java:oracle:communications.ordermanagement.compensation. ReevaluationContext OSM Java package that provides methods that access the contemporary and historical order perspectives and compares the two. You can use the results of this comparison to determine what compensation strategy is required for a task based on revision order data.

    For example:

    declare namespace osm = "urn:com:metasolv:oms:xmlapi:1";
    declare namespace context = "java:oracle.communications.ordermanagement.compensation.ReevaluationContext";
    declare namespace log =  "java:org.apache.commons.logging.Log";
    
    declare variable $log external; 
    declare variable $context external;
    

    For more information about the classes in the OSM packages, install the OSM SDK and extract the OSM Javadocs from the SDK/osm7.w.x.y.z-javadocs.zip file (where w.x.y.z represents the specific version numbers for OSM). See OSM Installation Guide for more information about installing the OSM SDK.

  • Body: The body must return a valid compensation option.

    For example, the following XQuery expression creates variables for the ReevaluationContext methods. The expression then checks that a specific value exists in the $value variable and that the value in the $significantValue variable both exists and is significant. If the value exists and is significant, then the expression sets the compensation strategy for the task to Undo then Do (undoThenDo in the ReevaluationContext Java class). If not, then the expression sets the compensation strategy to Redo (redo in the ReevaluationContext Java class).

    let $inputDoc := self::node()
    let $hopDoc := context:getHistoricalOrderDataAsDOM($context)
    let $ropDoc := context:getCurrentOrderDataAsDOM($context) 
    let $diffDoc := context:getDataChangesAsDOM($context)
    let $value := $inputDoc/GetOrder.Response/_root/service[name='BB']//orderItemRef/specificationGroup//specification[value='100']
    let $significantValue := $diffDoc/Changes/Add[@significant='true']/specification[value='100']
    let $currentValue := $ropDoc/ GetOrder.Response/_root/service[name='BB']//orderItemRef/specificationGroup//specification[value='100']
     
    return if (fn:exists($value) and fn:exists($significantValue))
    then
        context:undoThenDo($context)
    else
        context:redo($context)
    

This section refers to the Design Studio OSM Automated Task or Manual Task editor, Compensation tab Compensation Expression XQuery field for when a task is no longer required. The context, prolog, and body are similar to the XQuery expression for the re-evaluation strategy, except that the XQuery expression implements the java:oracle:communications.ordermanagement.compensation.RollbackContext package.

For example:

declare namespace osm = "urn:com:metasolv:oms:xmlapi:1";
declare namespace context = "java:oracle.communications.ordermanagement.compensation.RollbackContext";
declare namespace log =  "java:org.apache.commons.logging.Log";
 
declare variable $log external; 
declare variable $context external;
 
let $inputDoc := self::node()
let $hopDoc := context:getHistoricalOrderDataAsDOM($context)
let $ropDoc := context:getCurrentOrderDataAsDOM($context) 
let $diffDoc := context:getDataChangesAsDOM($context)
 
let $value := $inputDoc/GetOrder.Response/_root/service[name='BB']//orderItemRef/specificationGroup//specification[value='100']
return if (fn:exists($value))
then
    context:undo($context)
else
    context:doNothing($context)

In Progress Compensation Include XQuery Expressions

You can determine if an in progress task should be compensated by writing an XQuery expression in the Design Studio Task Editor Compensation tab.

Note:

If the XQuery expression is invalid OSM logs the error and includes the in progress task in the compensation plan as it defaults the expression to true.

This section refers to the Design Studio OSM Automated Task or Manual Task editor, Compensation tab, In Progress Compensation Include Expression XQuery field for dynamically defining when in progress tasks should be included in compensation. This XQuery expression runs when OSM first analyzes the task for compensation:

  • Context: The context for this XQuery is the current task order data. You can get the current task order data using the XML API GetOrder.Response function.

  • Prolog: You can declare the XML API namespace to use the GetOrder.Response function in the XQuery body to extract the order information.

    For example:

    declare namespace osm = "urn:com:metasolv:oms:xmlapi:1";
    declare namespace log =  "java:org.apache.commons.logging.Log";
    
    declare variable $log external; 
    declare variable $context external;
    
  • Body: Based on task context data, the body must return true if the in progress task requires compensation or false if it does not.

For example:

declare namespace osm = "urn:com:metasolv:oms:xmlapi:1";
declare namespace log =  "java:org.apache.commons.logging.Log";
declare variable $log external; 
 
let $inputDoc := self::node()
let $value := $inputDoc/GetOrder.Response/_root/data
 
return (
    if (fn:contains($value, "includeInCompensation")) then
        fn:true()
    else
        fn:false()
)

In Progress Compensation Complete XQuery Expressions

You can determine when the compensation for an in progress task is complete by writing an XQuery expression in the Design Studio Task Editor Compensation tab.

Note:

If the XQuery expression is invalid OSM logs the error and includes the in progress task in the compensation plan as it defaults the expression to true.

This section refers to the Design Studio OSM Automated Task or Manual Task editor, Compensation tab, In Progress Compensation Complete Expression XQuery field for dynamically defining when in progress tasks completes compensation activities. This XQuery expression runs whenever data changes on the compensating task:

  • Context: The context for this XQuery is the current task order data. You can get the current task order data using the XML API GetOrder.Response function.

  • Prolog: You can declare the XML API namespace to use the GetOrder.Response function in the XQuery body to extract the order information.

    For example:

    declare namespace osm = "urn:com:metasolv:oms:xmlapi:1";
    declare namespace log =  "java:org.apache.commons.logging.Log";
    
    declare variable $log external; 
    declare variable $context external;
    
  • Body: Based on task context data, the body must return true if the in progress task has completed all compensation activities or false if it has not.

For example:

declare namespace osm = "urn:com:metasolv:oms:xmlapi:1";
declare namespace log =  "java:org.apache.commons.logging.Log";
declare variable $log external; 
let $inputDoc := self::node()
let $value := $inputDoc/GetOrder.Response/_root/data
return (
    if (fn:contains($value, "compensationDone")) then
                fn:true()
    else
                fn:false()

In Progress Compensation Grace Period XQuery Expressions

You can determine whether a grace period should be observed before starting compensation for an in progress task by writing an XQuery expression in the Design Studio Task Editor Compensation tab.

Note:

If the XQuery expression is invalid OSM logs the error and includes the in progress task in the compensation plan as it defaults the expression to true.

This section refers to the Design Studio OSM Automated Task or Manual Task editor, Compensation tab, When an amendment occurs if this task is in progress it will: tab, Dynamic Expression XQuery field for dynamically defining the grace period for an in progress task based on task data. This XQuery expression runs after OSM has determined whether the in progress task needs to be compensated:

  • Context: The context for this XQuery is the current task order data. You can get the current task order data using the XML API GetOrder.Response function.

  • Prolog: You can declare the XML API namespace to use the GetOrder.Response function in the XQuery body to extract the order information. You can also declare the $gracePeriod variable in the XQuery prolog which contains the grace period specified on the order life-cycle policy.

    For example:

    declare namespace osm = "urn:com:metasolv:oms:xmlapi:1";
    declare namespace log =  "java:org.apache.commons.logging.Log";
    
    declare variable $gracePeriod external; 
    declare variable $log external; 
    declare variable $context external;
    
  • Body: The XQuery body returns a duration value based on the XQuery you enter:

    PyYmMdDThHmMsS
    

    where

    • P begins the expression.

    • yY specifies the year.

    • mM specifies the month.

    • dD specifies the day.

    • T separates the parts of the expression indicating the date from the parts of the expression indicating the time.

    • hH specifies the hour.

    • mM specifies the minutes.

    • sS specifies the seconds.

For example, this XQuery uses order data to define the specific grace period duration for the task. The last statement calls the $gracePeriod variable which represents the grace period duration specified on the order life-cycle policy:

declare namespace osm = "urn:com:metasolv:oms:xmlapi:1";
declare namespace log =  "java:org.apache.commons.logging.Log";
declare variable $log external; 
declare variable $gracePeriod external; 
 
let $inputDoc := self::node()
let $value := $inputDoc/GetOrder.Response/_root/data
 
return (
    if (fn:contains($value, '-immediate-')) then
        xs:duration('PT0S')
    else if (fn:contains($value, '-override-')) then
        xs:duration('PT20S')
    else if (fn:contains($value, '-negative-')) then
        xs:duration('-PT10S')
    else if (fn:contains($value, '-invalidNumber-')) then
        fn:number(0)
    else if (fn:contains($value, '-invalidString-')) then
        xs:string('UNKNOWN')
    else 
        xs:duration(fn:concat('PT', $gracePeriod, 'S'))

Order Jeopardy Automation XQuery Plug-ins

This topic provides information about order jeopardy XQuery expressions. These XQuery expressions apply to order jeopardies configured in the Order Jeopardy editor, not order jeopardies configured in the Order editor.

For general OSM XQuery information, see OSM Modeling Guide.

You can configure automations for order jeopardies in the Order Jeopardy editor, Automation tab. If you choose to use an XQuery automation type, create an XQuery file and reference it in the Script subtab Script field.

  • Context: The context for this XQuery is the Order Jeopardy Notification context.

  • Prolog: You should declare the XML namespace for the Order Jeopardy Notification context, and if you are using a date (rather than a duration) you can declare a namespace for the date format as well.

    For example:

    declare namespace context = "java:oracle.communications.ordermanagement.orderjeopardy.automation.OrderJeopardyNotificationContext";
    declare namespace dateFormat = "java:java.text.DateFormat";
    

    You should then declare the $context variable to contain the actual context:

    declare variable $context external;
    

    Then if you want to use order data in your XQuery, you can get the order data into a variable. For example:

    let $orderData := fn:root(automator:getOrderAsDOM($automator))/oms:GetOrder.Response
    

    You can then access individual data elements on the order. For example:

    let $date := $orderData/oms:_root/oms:ojPostponeDate/text()
    
  • Body: There are several calls you can use in the order jeopardy XQuery file in addition to the normal calls available for notification plug-ins. Following are brief descriptions of the available calls:

    • postponeTimerOnExit(interval): If this call receives a numeric parameter, it postpones the due date for the number of milliseconds contained in the parameter.

    • postponeTimerOnExit(dateTime): If this call receives a date/time parameter, it postpones the due date to the indicated date/time.

    • logAndParkNotificationOnExit(logMessage): This call acknowledges the notification with the passed-in message, but does not reset/deactivate the notification. It will still be available in the Order Management web client.

    • ackNotificationOnExit: This call acknowledges and resets/deactivates the notification.

    • getNotificationAckStatus: This call returns true if the notification has been acknowledged, and false if it has not.

    The following example postpones the jeopardy to a specified date:

    declare namespace context = "java:oracle.communications.ordermanagement.orderjeopardy.automation.OrderJeopardyNotificationContext";
    declare namespace dateFormat = "java:java.text.DateFormat";
     
    declare variable $context external;
     
    let $dateFormat := dateFormat:getDateTimeInstance(3, 3)
    let $date := dateFormat:parse($dateFormat, "09/30/15 03:30 PM")
    return
        context:postponeTimerOnExit($context, $date)