Fault Handling




After completing this Lesson, you should be able to do the following:




  • List the possible sources of faults  
  • Understand how to throw faults
  • Understand the constructs available for making a process ‘fault tolerant’ - catch, catchAll
  • Understand empty and terminate activities
  • Understand compensation handler
  • Understand Fault Policy Framework




What’s a Fault in BPEL


  • In BPEL, a Fault is a disruption of process execution that results in a signal being sent from the system. Fault Handling is what we do when this happens. 
  • Fault Handling can be thought of as a "mode switch" from the normal processing of the scope or process.
  • Its aim is to undo the partial and unsuccessful work of the scope in which the fault occurred.




Sources of Faults in BPEL process





nFaults in BPEL can be from various sources:



qA fault can be thrown automatically by the BPEL runtime environment, either due to a certain condition in the BPEL process itself (such as a join failure), as a consequence of error conditions in the runtime environment, or related to network communication or other reasons. For such situations, BPEL defines several System faults.


q


qA fault can occur when the BPEL process invokes a Web service operation. The operation might return a fault message, which results in a Business fault.









qA BPEL process can explicitly raise (throw) a custom fault, which is also a kind of Business fault.





When an event occurs that disrupts the normal flow of our business process, this is called a fault. How do we classify these faults? There are lots of ways that organizations classify faults, here is a simple one. Faults can be divided between those generated by our (or by our partner’s) Business Logic and those generated by the system at Runtime, either locally or remotely.Examples:When a fault is thrown, normal processing halts and control is sent to Fault Handler, if one is defined.






Taxonomy of Faults










nBPEL Standard Faults


§Are the faults that come directly from the BPEL Specification






nRuntime faults


§will not be defined by the user, so we need to design parts in the process to handle them. In bpel we will make use of the catch-activity for this. In the catch itself we can invoke our own fault-handling processes or do some other activities (retry etc) which are needed to get a valid situation again.


nBusiness Faults





§Are application specific faults and will occur when we use the “throw”-activity or if we invoke a partnerlink which returns with some fault. It’s up to the “business” to decide what needs to be done when the fault occurs and what activities are needed for handling it.



BPEL Standard Faults





nambiguousReceive


ncompletionConditionFailure


nconflictingReceive


nconflictingRequest


ncorrelationViolation


ninvalidBranchCondition


ninvalidExpressionValue


ninvalidVariables


njoinFailure





nmismatchedAssignmentFailure


nmissingReply


nmissingRequest


nscopeInitializationFailure


nselectionFailure


nsubLanguageExecutionFault


nuninitializedParterRole


nuninitializedVariable


nunsupportedReference


nxsltInvalidSource


nxlstStylesheetNotFound





Runtime Faults = Are generated by the system and includes all standard BPEL faults•invalid variable type used as a parameter (local)•site of the invoked service is temporarily down (remote)








Possible Binding Faults







Possible Remote Faults







Business Faults from partnerlinks





nInvoking synchronous operations on partner –provided Web services may return a WSDL fault message


qWSDL faults are identified in BPEL by their qualified name





nComprised of the WSDL's target namespace and the ncname of the fault












Business Faults = Use the Throw and ReThrow activities•invalid Customer number (local) throws a fault defined in our WSDL•credit check problems (remote) throws a fault defined in our partner’s WSDL Here we see an example of a fault that is thrown when a bad argument is used in a process. Starting at the top in the WSDL file: The portType is “CalculatorPortType”, the Operation is “CalculatorOperation”, and there are both input and output messages, “CalculatorInput” and “CalculatorOutput.” In this example, the fault’s name is “calcFault” and the Fault’s QName is “tns:BadArgumentFault”, which is defined somewhere in one of our other WSDL files.






Business Faults - Signaled (thrown) explicitly





nBPEL provides the <throw> activity


qSyntax <throw faultName="name" />


qBPEL does not require definition of fault names prior to their use in the <throw> activity


§This flexible approach can be error-prone, because there is no compile-time checking of fault names. In the case of typos, misspelled faults will not be handled by the designated fault handler.


qFaults can also have an associated variable that contains fault data


qIf such a variable is required, you have to specify it when throwing a fault, by using the optional faultVariable





§<throw faultName="name" faultVariable="variable-name" />





nThe throw activity has three elements: its name, the name of the faultName, and the faultVariable


qThe faultVariable is optional





qIn case a faultVariable is used, it has to be a messageType defined in the WSDL of the process. In other words, it cannot be a simpleType like string.












nThe faults raised with the <throw> activity have to be handled in the BPEL process.


nFaults that are not handled will be returned to the client if the process is synchronous, not otherwise


qIf you want to propagate the faults to the client,


nadd a fault messageType to WSDL, and then specify the <fault …> in operation element.


nIn a synchronous operation, the reply activity can return the fault.





nIn an asynchronous operation, the invoke activity performs this function. This is because in an asynchronous interaction, the client does not wait for a reply. The reply activity is not used to return a fault. Instead, the BPEL process returns a fault using a callback operation on the same port type that normally receives the requested information, with an invoke activity.


Making a fault tolerant process





nUse Fault handler


qUseful to handle standard faults, runtime faults (remote and binding), explicitly raised faults or faults coming from partnerlinks during a scope


qSo, whats left ?....notice the definition says “during a scope”. What if the fault occurs after current scope, say in a subsequent scope


nUse Compensation handler


qUseful if you want to undo a previously completed scope.


qDo I need to do fault handling from scratch, every time.


qNot really.


nUsing Fault Policy Framework

Handle commonly occurring faults in a central way


Handling Faults using Fault Handler





nA Fault handler can be associated with a scope. As the BPEL process can have multiple scopes and scope within scope, every scope can have its own fault handler


n


nWithin a fault handler, the business process defines custom activities that should recover from the fault and possibly reverse the partial (unsuccessful) work of the activity where the fault has occurred.


n


nBPEL Process can complete successfully even when there was a fault


nThis is possible if the fault is caught in a catch block of a scope


n


nOnce a scope receives a fault, normal processing of all nested activities is halted





nscope is considered to have ended abnormally



Designing a Fault Handler





nFault handlers provide a way to separate out normal process logic from error handling logic


nMakes normal processing logic less cluttered and therefore easier to read


nPosition fault handlers strategically





nCatch and handle all exceptions from where you want your process to recover





Now let's step back and look at fault handlers from a higher level. We don’t need Fault Handling, but we should have it. Like airbags and smoke alarms, you don’t need them, but they are highly recommended. Fault Handlers separate normal process logic from fault logic, i.e., the execution of normal activities vs. error handling logic that is in the Fault Handler. You should position your Fault Handlers strategically. By doing this, you don’t have to add fault logic for each individual activity, but rather only for logical units of work. This reduces the overall volume of fault handling code and makes the process less cluttered and much easier to read.
Position Fault Handlers at those points where you would want the process to recover from, or to, depending on how you look at it.






Adding the Fault Handler





nFault handlers can be defined


qFor the process


qFor a scope





qInline for the invoke activity












nTo handle the faults, catch and catchAll are used. These are placed within the FaultHandler












Here is the BPEL Fault Handler syntax.<faultHandlers>?<!-- Note: There must be at least one faultHandler --> <catch faultName="QName"? faultVariable="BPELVariableName"? ( faultMessageType="QName" | faultElement="QName" )? > activity </catch>* <catchAll>? activity </catchAll></faultHandlers>•If we declare a “faultHandlers” section we must have something inside that definition. Therefore, we need to define one or more Catches and/or a catchAll.
•If we define a Catch, it will optionally have a single associated faultName and optionally a single associated faultVariable.
•The faultVariable can also optionally have data that is of the faultMessageType or faultElement type.
•If you notice the “*” character after the closing angle bracket of the Catch, you can see that we can declare as many Catches as are needed.
•The catchAll is optional, and if we declare a catchAll, we can have only one. Both Catches and catchAlls have a primary activity to handle the actual fault recovery's actions.










catch Overview





nEach catch is created to handle a specific fault.


ncatch provides a flexible structure when it comes to matching catch to a fault





Type 1: By Fault Name only (which must be a globally unique QName)


Type 2: By FaultName and faultVariable type


Type 3: By faultVariable Type





nFault Variables must be explicitly defined inside the Catch that will handle that particular fault.



Catching a fault that has no variable or a fault that was not defined as such







Catching a fault that carries some data





nTo catch such a fault, we use a variable same in type as that of the fault. We can use the same variable itself or a variable with same type.





nAs discussed earlier, this variable has to of a messageType, that is defined in the WSDL








Catching a Remote Fault





nBPEL run-time faults can be caught as a named BPEL fault.














nWe can access the details of the fault by clicking on the green plus icon to create a fault variable





nUsing this faultVariable (which is of messageType RuntimeFaultMessage), the fault code, fault summary and details of the fault can be accessed.








catchAll Overview






nThe catchAll activity is provided to catch possible faults


nIf you use catchAll, you cannot access the fault variable as BPEL does not provide a method for obtaining additional information about the captured fault.


nUse the getFaultAsString() XPath extension function to obtain additional information.


<catchAll>


<sequence>


<assign>


<copy>


<from expression="ora:getFaultAsString()"/>


<to variable="outputVariable" part="payload"


query="/client:ErrorTesterProcessResponse/client:result"/>


</copy>


</assign>


</sequence>

</catchAll>


Terminate





nThe terminate activity immediately terminates the behavior of a business process instance within which the terminate activity is performed


Unhandled Exception





nIf no catch or catchAll is selected, the fault is not caught by the current scope and is rethrown to the immediately enclosing scope.


nIf the fault occurs in (or is rethrown to) the global process scope, and there is no matching fault handler for the fault at the global level, the process would error out.


nFor synchronous processes, this unhandled fault shall be returned to client


nFor asynchronous processes, an unhandled fault shall not be returned to client. The client will error out due to timeout.





nFor one way processes, the fault is not returned to client



Returning Faults from Sync and Async processes





nIf you want to return errors from synchronous processes that the client can handle,


qRecommended approach is to add fault message to WSDL and use the reply activity. Then add appropriate fault handler in client


qSimply throwing a fault without catching it is also an option, but it is comparatively difficult for the client to handle such an error (as no info is obtained from the WSDL)


nIf you want to return errors from asynchronous process to a client,

we must use a invoke activity. We need not have a separate porttype defined. The BPEL process returns a fault using a callback operation on the same port type that normally receives the requested information, with an invoke activity. (See http://download.oracle.com/docs/cd/B31017_01/integrate.1013/b28981/faults.htm#BABIBAFC). The client should have a pick activity to deal with different messages


No-op





nThere is often a need to use an activity that does nothing.


nAn example is when a fault must be caught and suppressed





nYou can use the empty activity to insert a no-op instruction into a business process



Interesting scenario





nA travel portal wants to offer a service TravelFlow that can book airline, car, hotel and tourism booking in one go. If any of the bookings cannot be done, nothing should get booked







Using Fault Handlers









A better approach would be….









….. Compensation






nThe fault-handling concept in BPEL is similar to exception-handling in Java and other programming languages. However, business processes require additional error- handling steps. When intermediate results are made persistent, they must be reversed explicitly. Let's now take a closer look at such compensation steps



Compensation Handler





nlet you specify compensation logic to undo successfully completed activities in the case of a fault.


nA compensation handler specifically defines how to reverse the result of the particular unit it's associated with.


nThe unit of compensation is, in its simplest form, one activity.





nIt can also be a BPEL scope that forms a logical unit of work consisting of several activities and therefore needs to be compensated as such.



When will it work





nDuring runtime processing, compensation handlers become active once the corresponding invoke activity or scope has completed successfully.





nA compensation handler never becomes active for an invoke activity or scope that terminated abnormally (for example, by means of a fault). If an invoke activity fails, BPEL presumes that no compensation is needed for the invoked service. In the case where a scope terminated abnormally, its fault handler must have taken care of compensating its nested activities already.



How will it work





nA snapshot of the data accessible to the invoke activity or scope at that point in time is taken.





nThis ensures that the compensation activity will ultimately have access to the same data that was current upon invocation of the original activity, so it can reverse what the original activity did.


How to trigger it





nIf you don't specify a fault handler or compensation handler for your activity or scope, there will be a default implementation


nDefault implementation - all active compensation handlers of activities enclosed by that scope are triggered


nBPEL also provides a special activity, the compensate activity, to explicitly trigger compensation handlers


nThis construct can only be used from within a fault handler or compensation handler.


nIt's applicable to immediately enclosed invoke activities and scopes only.





nUsing the scope attribute of the compensate activity, you select the unit to be compensated—that is, the name of the scope or invoke activity.


Fault Policy Management Framework





nThis framework gives us the opportunity to handle all the business and runtime faults for an “invoke” activity. With the framework we can define one policy for every bpel domain.


qSo, using this, you can say –


§ Whenever there is fault X, do this..





nThe framework cannot completely replace Fault Handlers or Compensation as it can only handle faults that are returned from partnerlinks


How to Implement





nDefine a bindings file in the composite fault-bindings.xml


nDefine a policy file in the composite fault-policies.xml


Both files are placed at same level as the composite.xml.


That’s it



If you want to use java actions,


nDeploy the java code onto the server, and then refer to it from the policy file.





n


Default available actions





nora-retry ( retry the activity )


nora-replay-scope ( replay the scope in which the fault occurred )


nora-rethrow-fault ( system will throw the fault to the bpel fault handlers )


nora-human-intervention ( the current activity will freeze. In the console the user will be able to take several actions on this


ninstance )


nora-terminate ( terminate instance )





nora-java ( execute custom java )



Dealing with Faults - Summary





Here are some of your options for dealing with faults


nUse a terminate activity to stop the execution of a process or an activity altogether so that somebody can step in and make the necessary repairs.


nUse a reply activity with a fault name associated with it so that it will respond with a fault.


nUse a throw activity to signal an internal fault.


nUse a fault handler to catch a fault and attempt to deal with it.


nUse compensation to rollback or "undo" a process that has failed after committing either itself as a whole (a microflow) or at least one of its activities (a long-running process).

For handling faults when invoking a partnerlink, one can use fault policy framework.



Challenge Exercise





nCreate a process that reads PO Data. PO Data contains header and lines. The process delivers two files – header.txt and lines.txt. If there is any issue in delivering lines.txt, header.txt should also be not delivered.


nHint: You should create two scopes, delivering one file in each scope, and add the compensation logic for the first scope.





nNote: You can attempt this exercise after we have discussed File adapters.






nCreate a process that inserts data into a database. After deploying the process, delete the table. So when you invoke the process it will error out. Use a fault policy framework to retry the error after 5 minutes. During this 5 minutes, create the table again. So that in next try, data will be inserted.





nFind out what happens when – in a flow activity containing two branches, one of the branches error out and the error goes unhandled in the branch, but is handled in a higher scope. If we have inserted a row in a table in the other branch, will it stay, or rollback.






nPlace the fault policy and binding files in MDS and use them in two composites.

Leave a Reply

Subscribe to Posts | Subscribe to Comments

About This Site

Howdy! My name is Suersh Rohan and I am the developer and maintainer of this blog. It mainly consists of my thoughts and opinions on the technologies I learn,use and develop with.
Powered by Blogger.

- Copyright © My Code Snapshots -Metrominimalist- Powered by Blogger - Designed by Suresh Rohan -