Powered By Blogger

Thursday, January 26, 2012

Making dependency between activities in parallel flows

There is one undocumented feature available in BPEL11g.This feature is all about creating interdependent activities in flow activity.

Let's see how can we model such processes. Please remember that design mode doesn't provide any graphical interface to support this.

Assume we have below process where we wanted to implement this



Requirement statement: Here our requirement is the scope in which invoke_2 activity is placed is depending on invoke_3 activity (until unless  invoke_3 is completed, scope of invoke_2 activity can not be completed )
This  is a typical activity dependency requirement in parallel flows
Steps to implement .
1. Go to source view,create the link inside the flow
2. Add the Target link in side scope activity
3. Add the Source link in invoke activity
See the below code.
<flow name="Flow_1">
          <links>
            <link name="TestDepend"/>
          </links>
            <sequence name="Sequence_1">
                <scope name="Scope_1">
                <target linkName="TestDepend"/>
                    <sequence>
                     
                            <invoke name="Invoke_2"
                                    partnerLink="bpelprocess1_client"
                                    portType="client:BPELProcess1Callback"
                                    operation="processResponse"/>
                      
                    </sequence>
                </scope>
            </sequence>
            <sequence name="Sequence_1">
                <invoke name="Invoke_3" partnerLink="bpelprocess1_client"
                        portType="client:BPELProcess1Callback"
                        operation="processResponse">
                <source linkName="TestDepend"/>
                </invoke>
   </sequence>
</flow>   
                   


Monday, January 16, 2012

Making JCA non-retryable errors to retryable and vice versa

Sometimes we come across  situations where JCA classifies error as non-retryable, but we wanted to make it as retryable.Well here we have solution for it.

WLS throws following error when it encounters  non-retryable error
This exception is considered not retriable, likely due to a modelling mistake.
To classify it as retriable instead add property nonRetriableErrorCodes with value "-2049" to your deployment descriptor (i.e. weblogic-ra.xml).

I have come up with below weblogic-ra.xml based on above suggestion given by adapter.

weblogic-ra.xml

<?xml version="1.0" encoding="UTF-8" ?>
<weblogic-connector xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                    xsi:schemaLocation="http://www.bea.com/ns/weblogic/90 weblogic-ra.xsd"
                    xmlns="http://www.bea.com/ns/weblogic/90">
<!--Just add below chunk under weblogic-connector -->
  <properties>
    <property>
      <name>nonRetriableErrorCodes </name>
      <value>-2049</value>
    </property>
  </properties>
......
  </weblogic-connector>

You can also make retryable errors to non-retryable with following change  in weblogic-ra.xml

weblogic-ra.xml

<?xml version="1.0" encoding="UTF-8" ?>
<weblogic-connector xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                    xsi:schemaLocation="http://www.bea.com/ns/weblogic/90 weblogic-ra.xsd"
                    xmlns="http://www.bea.com/ns/weblogic/90">
<!--Just add below chunk under weblogic-connector -->
  <properties>
    <property>
      <name>nonRetriableErrorCodes </name>
      <value>0</value>
    </property>
  </properties>
......
  </weblogic-connector>

To auto retry a retriable faults set  composite.xml properties for this invoke: jca.retry.interval, jca.retry.count, and jca.retry.backoff. All properties are integers
Please redeploy the adapter and if required restart the server.This will make  adapter to make anonretryable errors to  retryable errors

Saturday, January 14, 2012

Best practices in configuring fault-policies

In this post I talk about some of the best practices we can think of while designing fault-policies.


JCA binding level retry execution within fault policy retries


If you are using retry actions on adapters with both JCA-level retries for the outbound direction and a retry action in the fault policy file for outbound failures, the JCA-level (or binding level) retries are executed within the fault policy retries.
Lets say you have configured below JCA binding properties in composite.xml

       <property name="jca.retry.count">2</property>
        <property name="jca.retry.interval">5</property>
        <property name="jca.retry.backoff">1</property>

and assume you have following retry configuration in fault policies file for reference binding component for remoteFault

      <Action id="ora-retry">
        <retry>
          <retryCount>3</retryCount>
          <retryInterval>10</retryInterval>
          <exponentialBackoff/>
          <retryFailureAction ref="ora-human-intervention"/>
        </retry>
      </Action>

Now when remote fault returned for reference binding component, following retry sequence happens

    * Fault policy retry 1:
          o  JCA retry 1 (with 5 seconds interval)
          o  JCA retry 2 (with 10 seconds interval)
    * Fault policy retry 2:
          o  JCA retry 1 (with 5 seconds interval)
          o  JCA retry 2 (with 10 seconds interval)
    * Fault policy retry 3:
          o  JCA retry 1 (with 5 seconds interval)
          o  JCA retry 2 (with 10 seconds interval)

As a reminder, if your intention is just retrying through fault-policies then do not use JCA level retries in composite.xml

Best practices in Configuring ora-retry fault policy

When you configure a fault policy to recover instances with the ora-retry action and the number of specified instance retries is exceeded, the instance is marked as open.faulted (in-flight state). The instance remains active and keeps running.
Marking instances as open.faulted ensures that no instances are lost and this also causes reattempting retry (even after retry count is over) which you do not like at this point of time.
Here we have a best practice to follow.
You can then configure another fault handling action following the ora-retry action in the fault policy file, such as the following:
•    Configure an ora-human-intervention action to manually perform instance recovery from Oracle Enterprise Manager Fusion Middleware Control Console.
•    Configure an ora-terminate action to close the instance (mark it as closed.faulted) and never retry again.
For example     
      <Action id="ora-retry">
        <retry>
          <retryCount>3</retryCount>
          <retryInterval>3</retryInterval>
          <exponentialBackoff/>
          <retryFailureAction ref="ora-human-intervention"/>
        </retry>
      </Action>
However, if you do not set an action to be performed after an ora-retry action in the fault policy file and the number of instance retries is exceeded, the instance remains marked as open.faulted, and recovery again attempts to handle the instance.
For example, if no action is defined in the following fault policy file after ora-retry:
<Action id="ora-retry">
       <retry>
          <retryCount>2</retryCount>
          <retryInterval>2</retryInterval>
          <exponentialBackoff/>
       </retry>
  </Action>
The following actions are performed:
•    The invoke activity is attempted (using the above-mentioned fault policy code to handle the fault).
•    Two retries are attempted at increasing intervals (after two seconds, then after four seconds).
•    If all retry attempts fail, the following actions are performed:
o    A detailed fault error message is logged in the audit trail
o    The instance is marked as open.faulted (in-flight state)
o    The instance is picked up and the invoke activity is re-attempted
o    Re throws fault to system fault handler
•    Recovery may also fail. In that case, the invoke activity is re-executed. Additional audit messages are logged.

Message rejection handlers

The messages that error out before being posted to the service infrastructure are referred to as rejected messages. For example, the Oracle File Adapter selects a file having data in text format and tries to translate it to XML format (using NXSD). If there is any error in the translation, this message is rejected and will not be posted to the target composite.   
Rejected messages are stored in the database (in the rejected_message table) by default. If you do not configure a message rejection handler then default rejection message handler will handle  it which stores them on the file system. This handler stores the payload and properties of the message on the file system at a predefined location in WLS_HOME. Currently, the Oracle SOA suite does not provide the capability to resubmit rejected messages; consequently it is your responsibility to take care of the resubmission.If we do not have one then rejected messages may go unnoticed which is not good practice .I recommend to have one to handle and resubmit them.


JCA adapters and fault-policies


In nutshell standard practices for JCA EH are:
Error type
Best practise
Inbound  Retryable
Use JCA level retries in composite.xml
Inbound  Non-retryable
Use fault-policies message rejection handlers
Outbound Retryable
Use JCA level retries in composite.xml
Outbound Non-retryable
Use fault-policies

Manual recovery of faulted instances from em console

Fault policy framework provides a way for manual intervention in case of faults (System faults/business faults).
We can use this feature to change the input payload of a invoke activity and resubmit the request.
In this discussion we see how we can configure fault-policies/ bindings to achieve this.
We can perform following fault recovery actions from Oracle Enterprise Manager Fusion Middleware Control
  • Retry the activity
  • Modify a variable (All global variables)
  • Continue the instance (mark the activity as a success)
  • Rethrow the exception
  • Abort the instance
  • Throw a replay scope exception
 As a best practice it is always good to retry faulted invoke activity before we move to manual recovery.
Below fault-policy talks about above strategy

fault-policies.xml

<?xml version="1.0" encoding="UTF-8" ?>
<faultPolicies xmlns="http://schemas.oracle.com/bpel/faultpolicy">
  <faultPolicy version="2.0.1"
           id="ProcessingFaults"
               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>
      <!-- remote fault processing here: -->
    <faultName xmlns:bpelx="http://schemas.oracle.com/bpel/extension"
               name="bpelx:remoteFault">
         <condition>
                <action ref="ora-retry"/>
        </condition>
      <condition>
                <action ref="ora-human-intervention"/>
      </condition>
    </faultName>
   
    <!-- binding fault processing here: -->
    <<aultName xmlns:bpelx="http://schemas.oracle.com/bpel/extension"
                name="bpelx:bindingFault">       
            <condition>
                 <action ref="ora-human-intervention"/>
           </condition>
    </faultName>
    </Conditions>
     <Actions>
    <!-- RetryInterval is in seconds -->
      <Action id="ora-retry">
        <retry>
          <retryCount>3</retryCount>
          <retryInterval>5</retryInterval>
          <exponentialBackoff/>
        </retry>
      </Action>
       <!-- Human Intervention -->
      <Action id="ora-human-intervention">
        <humanIntervention/>
      </Action>
    </Actions>   
  </faultPolicy>
</faultPolicies>

fault-bindings.xml

This file binds the policies in fault-policies xml file with composite application level.
<?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="ProcessingFaults"/>
</faultPolicyBindings>

Place policies and bindings files in same location as composite.xml
Steps for recovery from EM console:
  • Log in  to em console and expand farm and SOA navigation trees on left pane
  • Click on required composite on left pane
  • Click on instanceId which is in running sate
  • Click on recovery 
  • Select the Recoverable record, in the bottom page segment choose required recovery action from drop down and click Recover button
This will recover instance form fault state.
In next post, I would like to talk about few best practices in configuring fault policies.