Powered By Blogger

Wednesday, March 28, 2012

Implementing Java Fault Handling for Oracle Composite

Oracle SOA suite comes with  fault handling framework which is a collection of sub modules to automate handling of faults .
For introduction of fault handling in composites, please visit Oracle's FMW Developer's Guide for Oracle SOA Suite 

Two important files in fault framework are
  • fault-policies.xml
  • fault-bindings.xml 
fault-policies.xml: Talks about what kind of faults it can handle and how. Fault policy file defines fault conditions and their corresponding fault recovery actions.
fault-bindings.xml: Talks about binding of fault-policies with  composite and its components or scope of fault-policies.

As part of fault-policies.xml, we can mention various types of recovery actions like retry,re-throw,human-intervention,replay,terminate and many more.Java action is one of them.
Fault-poloicies.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 starts here: -->
    <faultName xmlns:bpelx="http://schemas.oracle.com/bpel/extension"
               name="bpelx:remoteFault">
         <condition>
                <action ref="ora-retry"/>
        </condition>
    </faultName>
   
    <!-- binding fault processing starts here: -->
     <faultName xmlns:bpelx="http://schemas.oracle.com/bpel/extension"
                name="bpelx:bindingFault">       
               <condition>
                       <action ref="ora-retry"/>
               </condition>
    </faultName>

    </Conditions> 

<!-- Above two conditions indicates perform retry actions for binding and remote faults -->
    <Actions>  
    <!-- RetryInterval is in seconds. This action handles our retry requirement and in case retry also  failed then that chains to custom java action -->
      <Action id="ora-retry">
        <retry>
          <retryCount>3</retryCount>
          <retryInterval>5</retryInterval>
          <exponentialBackoff/>
          <retryFailureAction ref="ora-custom-java"/> 

<!--in case retry also failed then that chains control to java action-->
        </retry>
      </Action>      
     
 <Action id="ora-custom-java">
 <!-- this is user provided custom java class. This action handles notification requirement -->
      <javaAction className="
com.fault.handler.JavaFaultHandler"
             defaultAction="ora-human-intervention" propertySet="notification-properties">
            <returnValue value="RETRHOW"  ref="ora-rethrow-fault"/>

<!-- If java class returns RETRHOW then action "ora-rethrow-fault" is invoked -->
            <returnValue value="MANUAL"   ref="ora-human-intervention"/>

<!-- If java class returns MANUAL then action "ora-human-intervention" is invoked -->
       </javaAction>
     </Action>

        
<!-- This action re throws fault back to BPEL Catch/CatchAll-->
        <Action id="ora-rethrow-fault">
           
<rethrowFault/>
       
</Action >
  <!-- Human Intervention. This action handles human intervention part-->
        <Action id="ora-human-intervention">
           <humanIntervention/>
        </Action>

     </Actions>
   &lt!-- Below properties are read from java class--> 
     <Properties>    
          <propertySet name="notification-properties">          
            <property name="email_to">team1@gmail.com</property>
            <property name="email_cc">team2@gmail.com</property>   
            <property name="commonErrorHandlingProcess">CommonErrorHandlingBPEL</property>               
            <property name="domain">default</property>
     </propertySet>
       
  </Properties>
</faultPolicy> 
</faultPolicies>



fault-bindings.xml
<?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>


This bindings file binds fault recovery actions to composite level.i.e all components with in composite.xml
Now let's see how we can write a custom java class plugged into fault handling mechanism.
Co-locate both xml files with composite.xml. 

Please create a java project in Jdev and add following libraries to project class-path.
  1. BPEL Runtime
  2. Oracle.soa.fabric.jar



Custom Java action class
package com.fault.handler;

import com.fault.handler.Exception;
import com.collaxa.cube.engine.fp.BPELFaultRecoveryContextImpl;

import oracle.integration.platform.faultpolicy.IFaultRecoveryContext;
import oracle.integration.platform.faultpolicy.IFaultRecoveryJavaClass;
oracle.integration.platform.faulthandling.recovery.RejectedMsgRecoveryContext;
import java.util.Map;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import java.io.StringWriter;

import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;


public class JavaFaultHandler implements IFaultRecoveryJavaClass {

    public void handleRetrySuccess(IFaultRecoveryContext iFaultRecoveryContext) {
        System.out.println("Retry Success Happend...");
       // handleFault(iFaultRecoveryContext);
    }

    private String nodeToString(Node node) {
         StringWriter sw = new StringWriter();
         try {
             Transformer t = TransformerFactory.newInstance().newTransformer();
             t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
             t.transform(new DOMSource(node), new StreamResult(sw));
             } catch (TransformerException te) {
             System.out.println("nodeToString Transformer Exception");
    }
    return sw.toString();
    }
   //Below method will be invoked by fault handling mechanism when there is a fault. 

public String handleFault(IFaultRecoveryContext iFaultRecoveryContext) {
       
      
        try{
           Exception excObj = new Exception();           
 
         if(iFaultRecoveryContext instanceof BPELFaultRecoveryContextImpl){
      
          // Get BPEL specific context here
             BPELFaultRecoveryContextImpl bpelCtx =
                                         (BPELFaultRecoveryContextImpl)iFaultRecoveryContext;   
             // bit of log statements for debug purpose   
                System.out.println("*** BPEL Context + getComponentInstanceId ***: " +
                bpelCtx.getComponentInstanceId());                    
                System.out.println("*** BPEL Context + getFault ***: " +
                bpelCtx.getFault());              
                System.out.println("***  BPEL Context+ getInstanceId ***: " +
                bpelCtx.getInstanceId());              
                System.out.println("***  BPEL Context + getCompositeTitle ***: " + 
                bpelCtx.getTitle());                             
                System.out.println("***  BPEL Context + FaultedProcess Revision ***:"+
                bpelCtx.getProcessDN().getRevision());              
                                                  
                try{
// This code assumes all BPELs will have a variable called-
faultHandlerVariable which is defined on canonical xsd containing generic error data        
                Element root =(Element) bpelCtx.getVariableData  

  ("faultHandlerVariable", "payload", "/");                  
                Node exception =   root.getFirstChild();
                String errorDataStr   =   nodeToString(
exception);
                
                //Setting business payload  data 
                 excObj.setBusinessPayload(errorDataStr);  
                } catch (Exception e){
                    //Ignore this exception; because setting this business payload data is optional for my requirement
                    ;
                }
                  
                //Setting BPEL specific error data
                excObj.setErrorCode((bpelCtx.getFault().getFaultName().toString().contains("remoteFault"))?"remoteFault":"bindingFault");
                excObj.setErrorMessage(bpelCtx.getFault().getMessage().toString());
                excObj.setErrorInstanceId(bpelCtx.getInstanceId());
                excObj.setErrorProcessId( bpelCtx.getCompositeName());             
                excObj.setErrorProcessVersion(bpelCtx.getProcessDN().getRevision());                                              
                           
                } else if (iFaultRecoveryContext instanceof RejectedMsgRecoveryContext) {
              
                //Get Rejected messages context here
                System.out.println("*** iFaultRecoveryContext is an instanceof RejectedMsgRecoveryContext ***");
                System.out.println("==========================================================");
            
            } else{
             //Get Non-BPEL context here, if error is raised from other than BPEL component
               System.out.println("*** iFaultRecoveryContext is neither instanceof BPELFaultRecoveryContextImpl nor RejectedMsgRecoveryContext***");               

      
              System.out.println("====================================");
            }                      
            
             //Setting Email error data
             excObj.steEmailTo(props.get("email_to").toString().substring(1, props.get("email_to").toString().length()-1));
             excObj.setEmailCC(props.get("email_cc").toString().substring(1, props.get("email_cc").toString().length()-1));          
             excObj.setDomainId(props.get("domain").toString().substring(1, props.get("domain").toString().length()-1));           
          
                   
 //Setting CommonStatusLogger Process invocation context data  
             excObj.setCommonEHProcessName(props.get("commonEH_process").toString().substring(1, props.get("commonEH_process").toString().length()-1));  
                       

//CommonStatusLoggerDirectBinding direct binding Invocation
Please refer to SOA direct binding API This call invokes a composite which sends email.I am passing all error related data and email notification details as an object.
             CommonStatusLoggerDirectBinding ceh =new
CommonStatusLoggerDirectBinding ();
             String status = ceh.invokeCommonErrorStatusDirect(excObj);
             if (status == "S") 
                return "MANUAL";
             else               
                return "RETRHOW";      
            }
            catch(Exception e){
            System.out.println("***JavaFaultHandler Exception******\n"+ e.getMessage());
              e.printStackTrace();
              return "RETRHOW";
    
        }
    }
}

Bean Utility class 

package com.fault.handler;

import java.util.Date;
//This BEAN class represents all the common attributes any fault handler requires.
public class
Exception {
    protected String errorCode;
    protected String errorMessage;
    protected Date errorTime= new Date();
    protected String domainId="default";
    protected String errorProcessId;
    protected String errorProcessVer;
    protected String errorProcessURL;
    protected Long  errorInstanceId;
    protected String fileName;
    protected String payload;
    protected String fileDate;
    protected String sourceSystem;
    protected String reference;
    protected String emailTo="team1@gmail.com";
    protected String emailCC;
    protected String errorPartnerLink;
    protected String subject="Runtime Error: ";
    protected String providerURL;
    protected String initialContext="weblogic.jndi.WLInitialContextFactory";
    protected String securityCredential;
    protected String securityPrinciple;
    protected String commonEHProcessName="CommonErrorHandlerProcess";
    protected String commonEHProcessVer="1.0";
    protected String commonEHURL;
    protected String errorPayload;
    protected String businessPayload;
    public Exception() {
        super();       
       
    }
   //Setter methods  
    public void setErrorCode  (String errorCode ){
        this.errorCode = errorCode;
    }
    public void setErrorMessage  (String errorMessage){
        this.errorMessage = errorMessage;
    }
    public void setErrorTime  (Date errorTime){
        this.errorTime = errorTime;
    }
    public void setDomainId  (String domainId){
        this.domainId = domainId;
    }
    public void setErrorProcessId  (String errorProcessId){
        this.errorProcessId = errorProcessId;
    }
    public void setErrorProcessVersion  (String errorProcessVersion){
        this.errorProcessVer = errorProcessVersion;
    }
    public void setErrorProcessURL  (String errorProcessURL){
        this.errorProcessURL = errorProcessURL;
    }
    public void setErrorInstanceId  (Long errorInstanceId){
        this.errorInstanceId = errorInstanceId;
    }
    public void setFileName  (String fileName){
        this.fileName = fileName;
    }
    public void setPayload  (String payload){
        this.payload = payload;
    }
    public void setFileDate  (String fileDate){
        this.fileDate = fileDate;
    }
    public void setSourceSystem  (String sourceSystem){
        this.sourceSystem = sourceSystem;
    }
    public void setReference  (String reference){
        this.reference = reference;
    }
    public void steEmailTo  (String emailTo){
        this.emailTo = emailTo;
    }
    public void setEmailCC  (String emailCC){
        this.emailCC = emailCC;
    }
    public void setErrorPartnerLink  (String errorPartnerLink){
        this.errorPartnerLink = errorPartnerLink;
    }
    public void setSubject  (String subject){
        this.subject = subject;
    }
    public void setProviderURL  (String providerURL){
      this.providerURL = providerURL;
    } 
    public void setInitalContext  (String initialContext){
       this.initialContext = initialContext;
    }
    public void setSecurityCredential (String securityCredential){
       this.securityCredential = securityCredential;
    }
    public void setSecurityPrinciple (String securityPrinciple){
       this.securityPrinciple = securityPrinciple;
    }
    public void setCommonEHProcessName (String commonEHProcessName){
       this.commonEHProcessName = commonEHProcessName;
    }
    public void setCommonEHProcessVer (String commonEHProcessVer){
       this.commonEHProcessVer = commonEHProcessVer;
    }
    public void setCommonEHURL (String commonEHURL){
       this.commonEHURL = commonEHURL;
    }
   
    public void setBusinessPayload (String businessPayload){
       this.businessPayload = businessPayload;
    }
   
    //Getter methods  
     public String getErrorCode  ( ){
        return  this.errorCode;
     }
     public String getErrorMessage  (){
         return this.errorMessage;
     }
     public Date getErrorTime  (){
         return this.errorTime ;
     }
     public String getDomainId  (){
        return this.domainId ;
     }
     public String getErrorProcessId  (){
        return this.errorProcessId ;
     }
     public String getErrorProcessVersion  (){
        return  this.errorProcessVer ;
     }
     public String getErrorProcessURL  (){
       return  this.errorProcessURL ;
     }
     public Long getErrorInstanceId  (){
       return  this.errorInstanceId ;
     }
     public String getFileName  (){
        return this.fileName ;
     }
     public String getPayload  (){
       return  this.payload ;
     }
     public String getFileDate  (){
       return  this.fileDate ;
     }
     public String getSourceSystem  (){
        return this.sourceSystem ;
     }
     public String getReference  (){
        return this.reference ;
     }
     public String getEmailTo  (){
         return this.emailTo ;
     }
     public String getEmailCC  (){
      return this.emailCC ;
     }
     public String getErrorPartnerLink  (){
      return this.errorPartnerLink ;
     }
    public String getSubject  (){
      return this.subject;
    }
    public String getProviderURL  (){
      return this.providerURL;
    } 
    public String getInitialContext  (){
      return this.initialContext;
    }
    public String getSecurityCredential (){
      return this.securityCredential;
    }
    public String getSecurityPrinciple (){
      return this.securityPrinciple;
    }
    public String getCommonEHProcessName (){
      return this.commonEHProcessName ;
    }
    public String getCommonEHProcessVer (){
      return this.commonEHProcessVer;
    }
    public String getCommonEHURL (){
       return this.commonEHURL;
    }
   
    public String getBusinessPayload (){
       return this.businessPayload;
    }
    public String toString(){      
   
        errorPayload =
        "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" +
        "
<BPELException xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
        "xsi:schemaLocation=\"http://www.example.net/BPELException CommonErrorHandlerProcessInput.xsd\"\n" +
        "                  xmlns=\"http://www.example.net/BPELException\">\n" +
        " 
<ErrorCode>"+getErrorCode()+"</ErrorCode>\n" +
        " 
<ErrorMessage>"+getErrorMessage()+"</ErrorMessage>\n" +
        " 
<ErrorTime>"+getErrorTime()+"</ErrorTime>\n" +
        " 
<DomainId>"+getDomainId()+"</DomainId>\n" +
        " 
<ProcessId>"+getErrorProcessId()+"</ProcessId>\n" +
        " 
<ProcessVersion>"+getErrorProcessVersion()+"</ProcessVersion>\n" +
        " 
<ProcessURL>"+getErrorProcessURL()+"</ProcessURL>\n" +
        " 
<InstanceId>"+getErrorInstanceId()+"</InstanceId>\n" +
        " 
<FileName>"+getFileName()+"</FileName>\n" +
        " 
<payload>"+getBusinessPayload()+"</payload>\n" +
        " 
<FileDate>"+getFileDate()+"</FileDate>\n" +
        " 
<SourceSystem>"+getSourceSystem()+"</SourceSystem>\n" +
        " 
<Reference>"+getReference()+"</Reference>+
        " 
<EmailTo>"+getEmailTo()+"</EmailTo>\n" +
        " 
<EmailCC>"+getEmailCC()+"</EmailCC>\n" +
        "
</BPELException>\n" ;
        return this.errorPayload;
    }
     
}  


Configuring Java class
  • Pack above classes into jar 
  • stop  WLS server
  • Place them in  $ORACLE_HOME/soa/modules/oracle.soa.ext_11.1.1
  • run ant from same location
  • Restart Oracle WebLogic Server
Now code is ready for testing.
In a nutshell what we are trying to implement is, whenever there is either remote or binding fault in HellowWorld1 composite, then email notification should be sent out to configured users and human intervention should be waiting for someone to log in and correct payload and resubmit.    

How to test
Create HelloWorld1 and HelloWorld2 composites.HelloWorld1 invokes HelloWorld2.
Place fault-policies.xml and fault-bindings.xml into HellowWorld1 project and deploy both.Now retire HellowWorld2.Initiate HellowWorld1 

Monday, March 19, 2012

Configuring SystemMBean RecoveryConfig

This article discusses about how to automate recovery of certain activities.
Below activities can be configured for recovery.
  • All activities (for example, wait activities and OnAlarm branches of pick activities) that have an associated expiration date and are scheduled with the SOA Infrastructure to be rescheduled
  • All activities that are not complete over a provided threshold time
  • All invoke and callback messages that are unresolved

Login to EM console,go to SOA Infrastructure Home=> SOA Administration > BPEL Properties.Now click More BPEL Configuration Properties.



We can see two types of scheduling for auto recovery.
  • RecurringScheduleConfig
  • StartupScheduleConfig 

Recurring Schedule is used to configure a repeated execution of recovery process periodically.It is time window based and  always better to execute this during off-peak hours.

Startup Schedule is used to make all faulted instances are automatically retried when the SOA server is restarted.

MaxMessageRaiseSize  denotes maximum no.of messages to be  retired in every retry attempt and other attributes are reminiscent.

Wednesday, March 14, 2012

Invoking SOA11g Composite Using Direct Binding Invocation API

This article talks about how to invoke a Oracle SOA 11g composite from java program using Java direct binding API.

By default when composite is created it is exposed as SOAP WS but we also have an option of exposing it as direct binding to clients.
Well, the first question that comes to our mind is why should we use 'Direct Binding'  instead default SOAP WS.
Answer is performance gain.This binding is especially useful when applied to commonly re-used  or utility like services, for example CommonExceptionHandler and CommonLoggerService.This is because these services are invoked from many other business services and if we expose this service as WS then there are chances of performance degrade.To overcome this we may choose direct binding.
Below are some characteristics of direct binding.
  • The direct binding enables Java clients to directly invoke composite services, bypassing the intermediate conversion to XML required with the web service binding
  •  Direct binding uses T3 protocol and uses RMI over EJB to communicate with target service.
Now let's see how can we achieve this.
Assume that we have created a process named-CommonStatusLogger which will be invoked from every other business service and this service logs execution status of business service

When it is exposed as direct binding, following code is generated in composite.xml

  <service name="Service" ui:wsdlLocation="CommonStatusLogger.wsdl">
    callbackInterface="http://xmlns.oracle.com/CommonStatusLogger#wsdl.interface(CSLCallback)"/>
    <binding.direct/>
  </service>

Please note  <binding.direct/>.

Assume  that we also created BookBusTicket composite Service and invoked CommonStatusLogger service, then below code is generated in BookBusTicket service 's composite.xml

. <reference name="CommonStatusLogger"
   ui:wsdlLocation="http://host:port/soa-infra/directWsdl/default/CommonStatusLogger/Service?resource=%2FCommonStatusLogger.wsdl">
   <interface.wsdl interface="http://xmlns.oracle.com/CommonStatusLogger#wsdl.interface(CSL)"
   callbackInterface="http://xmlns.oracle.com/CommonStatusLogger#wsdl.interface(CSLCallback)"/>
    <binding.direct address="soadirect:/default/CommonStatusLogger/Service"
     connection-factory="oracle.soa.api.JNDIDirectConnectionFactory"
      useLocalJNDIProvider="true">
      <property name="java.naming.provider.url">t3://host:port</property>

    </binding.direct>
  </reference>

Please concentrate on bold font data.
binding.direct address is actual address where it is accessible  using direct binding API
connection-factory  is connection factory java class using which java clients can create connections.

Below is the java client which invokes CommonStatusLogger service using Java API.

package com.beachbody.bpel.fault.handler;
import com.beachbody.bpel.fault.handler.Exception;//This class is available in implementing-java-fault-handling thread

import java.io.StringReader;
import java.util.Map;
import java.util.HashMap;
import oracle.soa.api.PayloadFactory;
import oracle.soa.api.XMLMessageFactory;
import oracle.soa.api.invocation.DirectConnection;
import oracle.soa.api.message.Message;
import oracle.soa.api.message.Payload;
import org.w3c.dom.Element;
import org.w3c.dom.Document;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import oracle.soa.api.JNDIDirectConnectionFactory;
import oracle.soa.api.invocation.DirectConnectionFactory;
import org.xml.sax.InputSource;


public class CommonStatusLoggerDirectBinding  {

    /**
     * @param errorData
     * @return
     */
    public String invokeCommonErrorStatusDirect(Exception errorData){     
        try {             
          
            /* The JNDIDirectConnectionFactory can be used to establish SOA instance
             connections for exchanging messages over the direct binding.*/
            DirectConnectionFactory dcFactory = JNDIDirectConnectionFactory.newInstance();
            // Connections are created based on the configuration, which is a map of standard
             naming properties, which will be used for the underlying connection lookup.
            Map properties = new HashMap();        
            String soaDirectURL = "soadirect:/"+errorData.getDomainId()+"/"+errorData.getCommonEHProcessName()+"/Service";
            DirectConnection conn =
                dcFactory.createConnection(soaDirectURL, properties);            

                    
            DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
            docBuilderFactory.setNamespaceAware(true);          
            DocumentBuilder builder = docBuilderFactory.newDocumentBuilder();
            Document doc =  builder.parse(new InputSource(new StringReader(errorData.toString())));
            Element  root = doc.getDocumentElement();          

            Map partData = new HashMap();
            // have to use payload see BPELProcess1RequestMessage
            partData.put("payload", root);

            Payload payload = PayloadFactory.createXMLPayload(partData);

            //Messages are created using the MessageFactory
            Message request = XMLMessageFactory.getInstance().createMessage();
            request.setPayload(payload);
          
            // for a request-reply service we need to use conn.request else use conn.post
             need to provide operation name so we need to use process
              Message response = conn.request("initiate", request);
            conn.post("initiate", request);      
        
            return "S";
      
        } catch (Exception e) {
            e.printStackTrace();
            return "E";
        }
   
    }
    public CommonStatusLoggerDirectBinding  () {
        super();   

    }
     public static void main(String[] args) {     

   CommonStatusLoggerDirectBinding  startRMIProcess = new CommonStatusLoggerDirectBinding();
    }

}      


There is also another way of doing i.e using LocatorFactory,  if we go by this approach then following chunk can be used for connection purpose and remaining part of code is same

Hashtable jndiProps = new Hashtable();
Locator locator = LocatorFactory.createLocator(jndiProps);
CompositeDN compositedn = new CompositeDN(domainName, compositename, version);
String serviceName = "Service";
return locator.createDirectConnection(compositedn, serviceName);

Please remember here Service is direct binding partnerlink name in exposed service lane.

Please note that errorData contains data to be passed to CommonStatusLogger and coming from other class otherwise you can pass static data in input XML

Note:Above two approaches works only if java client and called services are co located on same server.If Java client is remote client then add below properties to Hashtable object

jndiProps.put(Context.PROVIDER_URL, "t3://" + hostname + ':' + portname +
 "/soa-infra");
jndiProps.put(Context.INITIAL_CONTEXT_FACTORY,
 "weblogic.jndi.WLInitialContextFactory");
jndiProps.put(Context.SECURITY_PRINCIPAL,"weblogic"); 
jndiProps.put(Context.SECURITY_CREDENTIALS,"welcome1");
jndiProps.put("dedicated.connection","true");

If you want to make this class available on WLS server classpath then,we need to jar this class and copy to domain/lib folder and restart server.
To successfully  compile this program we need to add following jars/libraries to Jdev libraries and classpath
  • BPEL Runtime
  • Oracle.soa.fabric.jar

In next article, we will discuss how to integrate this class into java-fault policies