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
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
One Response to SOA 11g Tutorial: Policy Based Fault Handling