Powered By Blogger

Wednesday, September 19, 2012

Configuring Jdeveloper 11g to work with SSL

Many times we come across situations where we need to create connection to SSL enabled weblogic server and deploy the code. Here I would like to show steps I have followed to setup Jdev for SSL.

  • Get the server certificate preferably in '.cer' extension.If you have certificate installed in your browser then you can simply export it(Tools->Internet Options->Content then certificates)
  • Copy certificate into any local folder, assume that D:\certificates
  • Open DOS prompt and import certificate into Jdev certificate trust store
DOS:\>keytool -import -alias democert  -file D:\Certificates\<certificatefile.cer> -keystore D:\Oracle\Middleware\wlserver_10.3\server\lib\DemoTrust.jks -storepass DemoTrustKeyStorePassPhrase


Parameters explanation
democert is some alias name I have given to my certificate
DemoTrustKeyStorePassPhrase is default key store password
D:\Oracle\Middleware\wlserver_10.3 is my Integrated WLS home that comes with Jdev
DemoTrust.jks is default certificate store comes with WLS(Weblogic server)

  • List certificate in store
Open DOS and run below command
D:\Oracle\Middleware\jdk160_29\bin>keytool -list -keystore   D:\Oracle\Middleware\ wlserver_10.3\ server\lib\DemoTrust.jks
Cross check output returned by above command has your certificate
If it doesn't list your certificate then import was not successful and you need to make sure import happens successfully

We need to import same certificate in below keystore also

JDK_HOME\bin>keytool -import -alias  <alias name> -file < certificate file path > -trustcacerts -keystore JDK_HOME\jre\lib\security\cacerts

Default pwd will be changeit

Restart Jdev and try to create connection to Jdev Note: When you create WLS connection in Jdev please choose 'Always use SSL' and enter SSL Port

If you still see issues with creating connection then please follow steps mentioned at
Oracle support document-ID 1338707.1

Document says-
We need to clean profile and preferences then re create connection again by the following steps:

  • Close Jdeveloper
  • Navigate to following path-C:\Documents and Settings\\Application Data\JDeveloper\system11.1.1. x.x.x.x.x
Note : Here x.x.x.x.x is some numbers
If you dont find above path then try to search for folder with name starting with 'system11.1.1'
  • Rename this directory to any other name
  • Restart Jdeveloper
  • Try to create connection
Now we will have a jdev thats totally clean with preferences set to default values

Monday, August 27, 2012

java.io.IOException: oracle.mds.exception.MDSException: MDS-00054

Often we use MDS to persist shared SOA11g artifacts like WSDLs and XSDs .
When we use MDS and to work with jdev during design time, we need to configure a MDS configuration file at \.adf\META-INF\adf-config.xml
By default, adf-config.xml is configured with file based persistent.If we are using database based store then we need provide database details in the file otherwise you will see the error mentioned in the subject.This error happens on all partner links which are using database persisted MDS based urls.
adf-config.xml contains metadata store usage configurations.
check above sample file picture


Above MDS configuration file explains Jdev SOA application is using two MDS stores
1.File based
 2.Data base based store
Highlighted portion is the one which is added extra to configure database based persistent. To load all database based persisted WSDLs and XSDs from MDS we need to configure highlighted portion in adf-config.xml.    

Sunday, June 17, 2012

Oracle 11g Human Workflow Mapped Attributes


Oracle BPM Worklist included a feature known as flex fields. Starting with Release 11g R1 (11.1.1.4), flex fields are now known as mapped attributes.

These attributes are used to display application /use-case specific data in workflow task list page.Indeed these attributes are stored as dehydration store data bases columns.

Steps to create mapped attributes.
1.       Declare and Populate data to task payload parameter attributes
2.       Specify a label for the mapped attribute.
3.       Map the payload attribute containing the data to the label.

1.Declare and Populate data to task payload attribute

  • Open Human task meta data (.task) file
  • Go to Data area
  • Add a parameter which is of standard simple XML type
  • Assign  required value to it in the process flow. 
  • After completing remaining task meta data configuration, deploy to server 

Below screen-1 shows a simple XML string task parameter-'mapAttr' being added to task


  Above assigned value is going to be displayed in task list  with the label we will provide now

2.Specifying a label for the mapped attribute 

  •        Login to Work list application
  •        Click on Administration
Note: The user who login and performs mapping attributes must have one of below application roles


BPMWorkflowCustomize: Grant this role to business users who must perform mapped attributes (formally flex field) mapping to public mapped attributes. This role is also granted the workflow.mapping.publicFlexField permission.
BPMWorkflowAdmin: Grant this role to users who must perform any workflow administrative action. This includes actions such as searching and acting on any task in the system, creating and modifying user and group rules, performing application customization, and so on. This role is granted the BPMWorkflowCustomize role
  •        Click on either Public Flex Fields or Protected Flex  Fields  Mapping  and select  Browse all mappings radio button


      Public flex field - Attributes mapped to specific task at run time. These mappings can be changed at any time, and must be re-created when a task component is redeployed.
       Protected flex field - mappings between a task component and protected flex field attributes defined at design time from Jdev. They cannot be changed at run time, and are deployed along with the task component
  •        Click Add icon to create labels for required mapped attributes
 Below screen-2 shows a label- 'SPANumber' of type TextAttribute being created
Note: A given mapped attribute may have multiple labels associated with it. This attribute label is what is displayed to users when displaying lists of attributes for a specific task in Oracle BPM Worklist. You can use each label associated with same mapped attribute in different tasks for different purposes from different SOA applications.

3.Map the payload parameter attribute containing the data to the label

3.1 For Public flex field label:

  In this step we create mapping between task payload parameter defined in step-1 and the attribute labels created in step-2

  For example, the payload field customerIdentifier can be mapped to the attribute label SPANumber. Different task types can share the same attribute label. This allows payload attributes from different task types that have the same semantic meaning to be mapped to the same attribute label
  • .       Go to Administration page
  • .       Select Edit mappings by task type radio button. Please note that this option is enabled only for Public Flex Fields. If it is Protected Flex Fields then we should do it from Jdeveloper.
  • .       Select required human task then click ok
  • .       Now  we need to map map payload attributes created in step-1 to label created in step-2

In below screen-3 I have mapped a payload parameter 'mapAttr'  to a label 'SPANumber'
 
3.2 For  Protected Flex Fields label:

  •     Open  human task meta data(.task ) file
  •     Add Mapped attributes. This will connect to SOA server and fetch all defined protected flex attributes(defined in step-2) which are not mapped to this task.
  •     Provide value to chosen attribute. After completing above steps then your Mapped attributes contain your mapping and goes as part of deployment.
 Check screen-1, we have added two mapped attributes for protected flex fields and populated with values.

 Now create  work queue from BPM worklist to display all required custom fields

Restrictions:

1. Only payload fields that are top-level and simple XML types can be mapped. Complex attributes or simple types nested inside a complex attribute cannot be promoted. So  It is important to define the payload for a task in the Human Task Editor, keeping in mind which attributes from the payload may must promoted to a mapped attribute
2. A mapped attribute (and thus a label) can be used only once per task type.
3. Data type conversion is not supported for the number or date data types. For example, you may not map a payload attribute of type string to a label of type number.

Another alternative way is
Couple of mapped attributes are included in the WorkflowTask.xsd file and are available out of box for your use without restrictions.
They are available under task/ customAttributes
1.Map data to be displayed in task lit to CustmAttributes.

below screen shows static value-'Attr1' is mapped to CustomAttributeString1

2.Go to Edit User Preferences from Worklist Views pane
3.Select the required custom attribute from Available columns and move it to Selected columns
4.Click Ok
Now task list page will display custom attributes with mapped data

 

Wednesday, May 30, 2012

The RL function getFactByType found more than one instance of the fact type

In this article we discuss one of rules invocation error we encounter frequently during development.
The error mentioned in post title generally comes because of rules data modeling mistake.

Following are some rules data modeling mistakes we may do
  • Assuming rule firing order, but rules execution order is not predefined by OBR engine
  • Asserting multiple facts of same type 
In OBR, before decision function is about to return, it will check for a fact in the working memory whose type matches the type defined as the output of the decision function. If it finds multiple facts that match the type,then it doesn't know which fact to select and  it will throw an above mentioned exception.
Here magic is input and output facts are matched based on their types but not on names.

Best and bit tedious way to resolve the error is, go back and re visit all your rule actions and make sure your code is not asserting same fact repeatedly and unnecessarly.
Most of asserts can be replaced by modify  which will modify same fact instance.

Second solution would be go to decision function Outputs section and mark  List option.What we are saying is duplicates are allowed and it returns all matching type output facts. It is our BPEL code responsibility to check and use appropriate fact in decision making process.


Thursday, May 17, 2012

ORABPEL-01005 Failed to compile bpel generated classes.The class path setting is incorrect.

This thread  discuss about one issue we got when we deploy SOA 11g BPEL composite from Jdev11g.
build in Jdev  succeeds but deployment on to server is filing.That means Jdev can compile the generated Java classes but server couldn't compile same classes.

When  I mention Java classes that doesn't mean my SOA composite has some dependency on Java classes or BPEL is carrying Jar files in its Libraray and classpath.It means Java classes generated by engine which are representation of our composite and its components.XML representation is converted back to Java and executed on server during run time.

Error in Jdev when we deploy


---->response code=500, error:There was an error deploying the composite on AdminServer: Error occurred during deployoment of component: OrderImport to service engine: implementation.bpel, for composite: OrderProcess: ORABPEL-01005

[deployComposite]

[deployComposite] Failed to compile bpel generated classes.

[deployComposite] failure to compile the generated BPEL classes for BPEL process "OrderproProcess" of composite "default/OrderproProcess!1.0*soa_4556-23d3-4bd3561-97e7a1b14e52"

[deployComposite] The class path setting is incorrect.

[deployComposite] Ensure that the class path is set correctly. If this happens on the server side, verify that the custom classes or jars which this BPEL process is depending on are deployed correctly. Also verify that the run time is using the same release/version.

[deployComposite] .

for example I can see error in Adminserver.out  log file
/oracle/domains/soa_domain/servers/AdminServer/dc/soa_968d12a9-7b6d-4ccb-84fa-97d870246c8e/SCA-INF/bpel/OrderProcess/src/orabpel/OrderproProcess/BPEL_BIN.java:253: illegal escape character
When I open above mentioned java file on server at specified location, I can see

__pa.setNSPrefix("tns", "http:\/\/xmlns.oracle.com\/bpel\/workflow\/taskService");


Solution

The reason for above error is, we have added certain third-party jars to server PRE-CLASS PATH in SetSOADomain.sh file, especially we have added them in first line of CLASS-PATH.
The jar file has incompatibe classes for commons-lang which is causing this issue.

Now we have added them at the last place in class path and that resolved this issue.

Tuesday, April 17, 2012

org.xml.sax.SAXException: Bad types

This article talks about one of the important SAX exceptions we encounter while building/invoking SOAP web services.
To understand why this error happens in the first place,the person has to have knowledge about WSDL binding styles.Please refer to any online documents to understand WSDL binding styles.

May be there are many reasons why we see this error, but I am going to discuss here one of the main causes that brings this error.
rpc/encoded style web service invocation is one of the reasons for this error.

Let's see what is the significance of RPC style web services.

Sample rpc/encoded style WSDL:

<message name="SumMethodReqMsg">
    <part name="x" type="xsd:int"/>
    <part name="y" type="xsd:float"/>

</message>

<message name="ResultRespMsg">

     <part name="result" type="xsd:float"/>

</message>

<portType name="Port">

    <operation name="sumMethod">

        <input message="SumMethodReqMsg"/>

        <output message="ResultRespMsg"/>

    </operation>

</portType>

<binding .../> 

rpc/literal WSDL to SOAP request message translation:
Below  format is  how message looks like on the wire.
<soap:envelope>
    <soap:body>
        <sumMethod>
            <x xsi:type="xsd:int">2</x>
            <y xsi:type="xsd:float">7.0</y>
        </sumMethod>
    </soap:body>
</soap:envelope>

If you clearly observe above, there is something different form how document/literal style service  composes SOAP message.

Well, here are the differences.
  • Here operation name appears in the message,this is not true for document/literal style web service.
  • The type encoding info (such as "xsi:type="xsd:int" and "xsi:type="xsd:float").We can not see this information on  document/literal web services.
Here catch is, when we pass on input request to rpc/literal service, we tend to ignore declarations like "xsi:type="xsd:int" and "xsi:type="xsd:float" on input elements.

but above type information is mandatory for rpc style web service invocations.
Put a transform activity before invoke and make sure above type formation is passed on to service as part of request.

If issue still persists,then pass below name space nodes also.

xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

Now request becomes

<soap:envelope>
    <soap:body>
        <sumMethod>
            <x xsi:type="xsd:int"xmlns:xsd="http://www.w3.org/2001/XMLSchema"   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">2</x>
            <y xsi:type="xsd:float"xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">7.0</y>
        </sumMethod>
    </soap:body>
</soap:envelope>

Now I hope issue will be resolved.

Monday, April 16, 2012

Error deploying the composite ORABPEL-01010 Process Generation Failed.- deploy.lock (No such file or directory)

I have come across above said exception while I was deploying SOA 11.1.1.5 composite to Weblogic through Jdeveloper.

When I analyzed the issue what I understood  was, this error must be something to do with environment.
The probable reasons are listed down from most relevant to least.

Deployment utility has to create some temporary files  during deployment and for that we need sufficient space on server.These temporary files will be deleted later by same utility.
  • Disk space issue
  • OS file descriptor issue
Disk space issue:
  1. Check your server mounted disk space using df command for Unix/Linux OS(For windows use different method)
  2. If you find less space then add more space or clean up unnecessary files like logs
  3. Now try deployment again(server restart not necessary)
OS file descriptor issue :
  1. Check maximum number of files allowed to be open using ulimit -n command
  2. If required, increase it.This depends upon type of shell we use.
You may use sysctl
 or
other ways:
In tcsh
limit descriptors 65535

In bash
ulimit -n 65535
Please talk to your admin to perform this activity.

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 

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>