SOA 11g Tutorial: Policy Based Fault Handling

This is part of the Oracle SOA11g hands on tutorials.

Overview

* See this post

Fault Types

System Faults

* Examples
– Service not available
– Network failure

Business Faults

* Examples
– Invalid data
– Violation of business rules

Fault Handling Policies

* They are attached to composite.
* They are not defined in code.

Define a Policy

* Fault policies are defined in a file called fault-policies.xml.
* Fault policies are attached to composite via a binding file called fault-bindings.xml.
* A fault policy consists of:
– Fault policy name
– A list of faults
– A set of fault conditions
– A set of fault recovery actions

Simulate Service Unavailable

Shutdown validateioniForCC Service

* Login EM
* Click validationForCC application (SOA -> soa-infra -> default -> validationForCC[1.0])
* On right panel, click Shut Down… button and click yes button on confirmation dialog.

Test POProcessing App

* Input message

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Body xmlns:ns1="http://xmlns.oracle.com/ns/order">
        <ns1:PurchaseOrder>
            <ns1:CustID>1111</ns1:CustID>
            <ns1:ID>2222</ns1:ID>
            <ns1:productName>iPod shuffle</ns1:productName>
            <ns1:itemType>Electronics</ns1:itemType>
            <ns1:price>145</ns1:price>
            <ns1:quantity>30</ns1:quantity>
            <ns1:status>Initial</ns1:status>
            <ns1:ccType>Mastercard</ns1:ccType>
            <ns1:ccNumber>1234-1234-1234-1234</ns1:ccNumber>
        </ns1:PurchaseOrder>
    </soap:Body>
</soap:Envelope>

* Click Launch Flow Trace button to see the message flow.

Faulted while invoking operation "execute" on provider "getCreditCardStatus". 

Create a Fault Policy

* Create a new XML file named fault-policies.xml in POProcessing application:

<?xml version="1.0" encoding="UTF-8" ?>
<faultPolicies xmlns="http://schemas.oracle.com/bpel/faultpolicy">
  <faultPolicy version="2.0.1" 
	       id="POProcessingFaults"
               xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
               xmlns:xs="http://www.w3.org/2001/XMLSchema"
               xmlns="http://schemas.oracle.com/bpel/faultpolicy"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <Conditions>
      <!-- Step #1: Add your fault handler for remote fault here: -->
    <faultName xmlns:bpelx="http://schemas.oracle.com/bpel/extension"  
        name="bpelx:remoteFault">     
        <condition>
            <action ref="ora-human-intervention"/>
       </condition>
    </faultName>
 
     <!-- Step #2: Add your fault handler for binding fault here: -->
 
     <!-- Step #3: Add your fault handler for mediator faults here: -->
 
    </Conditions>
 
    <Actions>
      <!-- Step #4: Add the Action definition for handling mediator fauls using custom java here:-->
 
      <!-- Custom Java Handler: Logs the fault details to a log file -->
      <Action id="my-java-handler">
        <javaAction className="soatraining.faulthandling.MyFaultHandler"
                    defaultAction="ora-terminate" propertySet="myProps">
          <returnValue value="OK" ref="ora-rethrow-fault"/>
        </javaAction>
      </Action>
 
      <!-- Retry -->
      <Action id="ora-retry">
        <retry>
          <retryCount>4</retryCount>
          <retryInterval>2</retryInterval>
          <exponentialBackoff/>
        </retry>
      </Action>
 
      <!-- Rethrow action -->
      <Action id="ora-rethrow-fault">
        <rethrowFault/>
      </Action>
 
      <!-- Human Intervention -->
      <Action id="ora-human-intervention">
        <humanIntervention/>
      </Action>
 
      <!-- Terminate -->
      <Action id="ora-terminate">
        <abort/>
      </Action>
 
    </Actions>
 
    <!-- Property sets used by custom Java actions -->
    <Properties>
      <!-- Property set for MyFaultHandler customer java action -->
      <propertySet name="myProps">
        <property name="logFileName">myfaulthandler.log</property>
        <property name="logFileDir">c:\po\log</property>
      </propertySet>
 
      <!-- Step #5: Add new property set for MyFaultHandler for logging Mediator faults here:-->
 
    </Properties>
  </faultPolicy>
</faultPolicies>

* Create a new XML file named fault-bindings.xml in POProcessing application. This file binds POProcessingFaults policy to composite.xml since they reside in the same directory.

<?xml version="1.0" encoding="UTF-8" ?>
<faultPolicyBindings version="2.0.1"
                     xmlns="http://schemas.oracle.com/bpel/faultpolicy"
                     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <composite faultPolicy="POProcessingFaults"/>
</faultPolicyBindings>

* Handle all remoteFault occurrences

<faultName xmlns:bpelx="http://schemas.oracle.com/bpel/extension"  
    name="bpelx:remoteFault">     
    <condition>
        <action ref="ora-human-intervention"/>
   </condition>
</faultName>

Test Fault Policy

* Redeploy POProcessing application
* Retry test input xml fle
* Click Launch Flow Trace button to see the message flow.

[FAULT RECOVERY] Marked Invoke activity as "pending manual recovery".

Manual Recover

* Start validationForCC application

Retry

* Click on last POProcessing instance ID to open flow trace page.
* Click approveLargeOrder BPEL process
* Click Fault tab
* Click on the row containing the previous fault.
* Click Recover button
* Click on Yes on confirmation dialog
* Check that process is recovered.

Handle BPEL Exceptions

* Simulate credit card validation application error.
* Learn how to handle BPEL exception.

Create VALIDATECC Stored Function

* Login Oracle database as soademo
* Run the following script:

CREATE OR REPLACE FUNCTION VALIDATECC(cc_number IN VARCHAR2) 
RETURN VARCHAR2 AS
    l_status  CREDITCARDINFO.STATUS%TYPE;
BEGIN
     SELECT STATUS
     INTO  l_status
     FROM   creditcardinfo
     WHERE  ccnumber = cc_number;
     RETURN l_status;
EXCEPTION
      WHEN NO_DATA_FOUND THEN
          raise_application_error(-20001, 'UNKNOWN CREDIT CARD');
END VALIDATECC;
/

Create a New DB Adapter: validateCC

* Open ValidationForCC application
* Open composite.xml
* Drag and drop a Database Adapter onto External References lane.
* Configure db adapter with following values:
– Service Name: validateCC
– Connection: soademoDatabase
– Schema: select SOADEMO
– JNDI Name: eis/DB/soademoDatabase
– Operation Type: Call a Stored Procedure or Function
– Procedure: Browse and select VALIDATECC

Wire up RouteRequest to validateCC Database Adapter

* Wire RouteRequest mediator component to validateCC database adapter.
* Open RouteRequest mediator by double clicking it.
* Add a filter for getCreditValidation::getCreditValidationSelect to route all requests whose credit card numbers don’t start with 2.

not(starts-with($in.creditcardStatusRequestPart/inp1:creditcardStatusRequest/inp1:CCNumber, '2'))

* Add a filter for validateCC::validateCC to route all requests whose credit card numbers do start with 2.

starts-with($in.creditcardStatusRequestPart/inp1:creditcardStatusRequest/inp1:CCNumber, '2')

* Create a new transformation for validateCC route. Map inp1:CCNumber to db:CC_NUMBER
*Save all

Test

* Redeploy validationForCC application.
* Test with credit card number 1234-1234-1234-1234. Should return VALID status.
* Test with credit card number 2234-1234-1234-1234. Should get UNKNOWN CREDIT CARD exception.

...
Cause: java.sql.SQLException: ORA-20001: UNKNOWN CREDIT CARD
...

Handle Application Error in BPEL

Add a Scope Fault Catcher

* Open POProcessing composite.xml file.
* Open approvelargeOrder BPEL process by double clicking it.
* Add a new scope activity under assignCCNumber and above invokeCCStatusService. Rename it to checkCC (double clicking it to set value).
* Move invokeCCStatusService into the scope.
* On the new scope’s left side vertical bar, click the Add Catch icon (third one from top) to add a Catch branch.
* Double click Catch icon to bring up the Catch dialog.
– Click the magnifying glass inside Fault Name panel, browse to System Faults -> BindingFault.
~ Namespace URI: http://schemas.oracle.com/bpel/extension
~ Local Part: bindingFault
– Click green plus sign to the right of Fault Variable to bring up the Create Variable dialog. Accept all default name.
~ Fault Variable: FaultVar
– Click OK
* Drop a Switch activity inside the catch block.
* Click new switch activity’s condition block and enter
– Label: InvalidCreditCard
– Condition: bpws:getVariableData(‘FaultVar’) = ‘20001’
* Add an Assign activity inside InvalidCreditCard branch. Name it AssignUnknownCC.
* Assign ‘UNKNOWN CC’ string to invokeCCStatusService_execute_OutputVariable -> creditCardStatusPart -> creditcardStatus.
* Drag and drop a Throw activity in the otherwise block. Name it Throw_Binding_Fault.
* Double click Throw icon to bring up the Throw dialog.
– Click the magnifying glass inside Fault QName panel, browse to System Faults -> BindingFault.
~ Namespace URI: http://schemas.oracle.com/bpel/extension
~ Local Part: bindingFault
– Click magnifying glass sign to the right of Fault Variable and select previously created FaultVar variable.
~ Fault Variable: FaultVar
– Click OK
* Save all

Configure fault-policies.xml to Catch Fault Code

* Open fault-policies.xml and add to conditions block:

      <faultName xmlns:bpelx="http://schemas.oracle.com/bpel/extension" 
                 name="bpelx:bindingFault"> 
          <condition> 
                  <!-- Let the component handle this specific binding fault --> 
                  <test>$fault.code="20001"</test> 
                  <action ref="ora-rethrow-fault"/> 
          </condition> 
      </faultName>

Test BPEL Fault Catcher

* Redeploy POProcessing application.
* Input message (note that credit card number stats with 2):

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Body xmlns:ns1="http://xmlns.oracle.com/ns/order">
        <ns1:PurchaseOrder>
            <ns1:CustID>1111</ns1:CustID>
            <ns1:ID>2222</ns1:ID>
            <ns1:productName>iPod shuffle</ns1:productName>
            <ns1:itemType>Electronics</ns1:itemType>
            <ns1:price>145</ns1:price>
            <ns1:quantity>30</ns1:quantity>
            <ns1:status>Initial</ns1:status>
            <ns1:ccType>Mastercard</ns1:ccType>
            <ns1:ccNumber>2234-1234-1234-1234</ns1:ccNumber>
        </ns1:PurchaseOrder>
    </soap:Body>
</soap:Envelope>

* Click Launch Flow Trace button to see the message flow.

Faulted while invoking operation "execute" on provider "getCreditCardStatus". 

Errors

{http://schemas.oracle.com/bpel/extension}bindingFault not defined

* BPEL compiler error:

WSDL messageType "{http://schemas.oracle.com/bpel/extension}bindingFault" of variable "CheckCCFaultVar" is not defined in any of the WSDL files

* Possible cause:
Fault variable CheckCCFaultVar was auto-generated from Catch diaglog.
* Fix:
Redefine CheckCCFaultVar variable:
– Locate CheckCCFaultVar variable.
– Double click it to open the Edit Variable dialog.
– Click magnifying glass icon to the right of Message Type field.
– Click Import WSDL File… icon on the upper right corner of Type Choose dialog.
– Click the magnifying glass search icon on the import WSDL file dialog.
– Browse to RuntimeFault.wsdl file in the C:\Oracle\Middleware\jdeveloper\integration\seed\soa\shared\bpel directory.
– Click OK
– Check Copy to Project and click OK on import WSDL file dialog.
– Click OK on Localize Files dialog.

Custom Java Fault Handler

Create Custom Java Fault Handler

public class MyFaultHandler implements IFaultRecoveryJavaClass {
    public MyFaultHandler() {
        super();
    }
 
    public void handleRetrySuccess(IFaultRecoveryContext ifc) {
        ...
    }
 
    public String handleFault(IFaultRecoveryContext ifc) {
        ...
    }

Install Custom Java Fault Handler

* Copy myfalthandler.jar to soa domain lib direcotry: /opt/oracle/Middleware/home_11gr1/user_projects/domains/soa_domain/lib
* Restart soa server

Use Custom Java Handler

* Modify fault-policies.xml
– Add condition to use custom handler

    <Conditions>
    <faultName xmlns:bpelx="http://schemas.oracle.com/bpel/extension"  
        name="bpelx:remoteFault">     
        <condition>
            <action ref="my-java-handler"/>
       </condition>
    </faultName>
...

– Define custom action:

    <Actions>
      <!-- Custom Java Handler: Logs the fault details to a log file -->
      <Action id="my-java-handler">
        <javaAction className="soatraining.faulthandling.MyFaultHandler"
                    defaultAction="ora-terminate" propertySet="myProps">
          <returnValue value="OK" ref="ora-rethrow-fault"/>
        </javaAction>
      </Action>
...

– Set custom handler properties:

    <Properties>
      <!-- Property set for MyFaultHandler customer java action -->
      <propertySet name="myProps">
        <property name="logFileName">myfaulthandler.log</property>
        <property name="logFileDir">/tmp/po/log</property>
      </propertySet>
...

Test

* Redeploy
* Test with input message

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Body xmlns:ns1="http://xmlns.oracle.com/ns/order">
        <ns1:PurchaseOrder>
            <ns1:CustID>1111</ns1:CustID>
            <ns1:ID>2222</ns1:ID>
            <ns1:productName>iPod shuffle</ns1:productName>
            <ns1:itemType>Electronics</ns1:itemType>
            <ns1:price>145</ns1:price>
            <ns1:quantity>30</ns1:quantity>
            <ns1:status>Initial</ns1:status>
            <ns1:ccType>Mastercard</ns1:ccType>
            <ns1:ccNumber>2234-1234-1234-1234</ns1:ccNumber>
        </ns1:PurchaseOrder>
    </soap:Body>
</soap:Envelope>

* Check log file at /tmp/po/log/myfaulthandler.log

Handle Mediator Faults

* Policy based fault handler is the only way to catch and handle mediator exceptions.

Configure Fault Policy for Mediator

* Add to fault-policies.xml
– Add condition to use custom handler

    <Conditions>
      <faultName xmlns:medns="http://schemas.oracle.com/mediator/faults" 
                 name="medns:mediatorFault">
        <condition>
          <action ref="my-mediator-fault-handler"/>
        </condition>
      </faultName>
...

– Define mediator fault action:

    <Actions>
      <Action id="my-mediator-fault-handler">
        <javaAction className="soatraining.faulthandling.MyFaultHandler" 
                    defaultAction="ora-terminate" 
                    propertySet="myMediatorProps">
          <returnValue value="OK" ref="ora-human-intervention">
          </returnValue>
        </javaAction>
      </Action>
...

– Set mediator handler properties:

    <Properties>
      <propertySet name="myMediatorProps">
      <propertySet name="myMediatorProps">
         <property name="logFileName">mediator- faults. log</property>
        <property name="logFileDir">/tmp/po/log</property>
      </propertySet>
...

Configure Mediator Component

* Open routePO mediator component (routePO.mplan)
* Change price * quantity < 1000 route from sequential to parallel. This is needed in order for fault policy handler to intercept the exception.

Test

* Redeploy POProcessing
* make log directory un-writable: chmod -w /tmp/po
* Test with input message that has price * quantity < 1000

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Body xmlns:ns1="http://xmlns.oracle.com/ns/order">
        <ns1:PurchaseOrder>
            <ns1:CustID>1111</ns1:CustID>
            <ns1:ID>2222</ns1:ID>
            <ns1:productName>iPod shuffle</ns1:productName>
            <ns1:itemType>Electronics</ns1:itemType>
            <ns1:price>145</ns1:price>
            <ns1:quantity>30</ns1:quantity>
            <ns1:status>Initial</ns1:status>
            <ns1:ccType>Mastercard</ns1:ccType>
            <ns1:ccNumber>1234-1234-1234-1234</ns1:ccNumber>
        </ns1:PurchaseOrder>
    </soap:Body>
</soap:Envelope>

* Check log file at /tmp/po/log/mediator- faults. log

This entry was posted in soa11g. Bookmark the permalink.

One Response to SOA 11g Tutorial: Policy Based Fault Handling

Leave a Reply

Your email address will not be published. Required fields are marked *


*

This site uses Akismet to reduce spam. Learn how your comment data is processed.