Monday, 29 August 2011

Convert A-Synchronous proccess to Synchronous proccess

IntroductionThis article how to convert an Asynchronous to a Synchronous BPEL process. Since BPEL determines whether a process is async or sync by just some small settings in the .bpel file (and some dependency in the wsdl) it is rather easy to convert from one to another.

When creating BPEL processes, three files are created by default:
  1. bpel.xml
  2. .bpel
  3. .wsdl
To determine whether a BPEL process is Asynchronous or Synchronous, it looks at the second file: YourBPELProcess.bpel. Generally, when creating a process based on the Asynchronous template, the .bpel file look like this:
<process
  name="BPELProcess1"
  targetNamespace="http://xmlns.oracle.com/BPELProcess1"
  xmlns="http://schemas.xmlsoap.org/ws/2003/03/business-process/"
  xmlns:client="http://xmlns.oracle.com/BPELProcess1"
  xmlns:ora="http://schemas.oracle.com/xpath/extension"
  xmlns:orcl="http://www.oracle.com
/XSL/Transform/java/oracle.tip.pc.services.functions.ExtFunc"
  xmlns:xp20="http://www.oracle.com
/XSL/Transform/java/oracle.tip.pc.services.functions.Xpath20"
  xmlns:ldap="http://schemas.oracle.com/xpath/extension/ldap"
  xmlns:bpelx="http://schemas.oracle.com/bpel/extension"
  xmlns:bpws="http://schemas.xmlsoap.org/ws/2003/03/business-process/">
<partnerLinks>
  <partnerLink
      name="client"
      partnerLinkType="client:BPELProcess1"
      myRole="BPELProcess1Provider"
      partnerRole="BPELProcess1Requester"/>
  </partnerLinks>
<variables>
  <variable
    name="inputVariable"
    messageType="client:BPELProcess1RequestMessage"/>
  <variable
    name="outputVariable"
    messageType="client:BPELProcess1ResponseMessage"/>
</variables>
<sequence name="main">
  <receive
    name="receiveInput"
    partnerLink="client"
    portType="client:BPELProcess1"
    operation="initiate"
    variable="inputVariable" createInstance="yes"/>
  <invoke
    name="callbackClient"
    partnerLink="client"
    portType="client:BPELProcess1Callback"
    operation="onResult"
    inputVariable="outputVariable"/>
  </sequence>
</process>

The differences between a synchronous and asynchronous process lie in the steps of invoke callback vs. reply difference to return the response. In a synchronous process, the way a reply message is handed back is through a reply. The asynchronous process invokes a callback method to hand back the reply message.
<process … namespace definitions etc … >
<partnerLinks>
<partnerLink name="client"
 partnerLinkType="client:BPELProcess3"
 myRole="BPELProcess3Provider"/>
</partnerLinks>
<variables>
<variable name="inputVariable"
          messageType="client:BPELProcess3RequestMessage"/>
<variable name="outputVariable"
          messageType="client:BPELProcess3ResponseMessage"/>
</variables>
<sequence name="main">
<receive name="receiveInput"
         partnerLink="client"
         portType="client:BPELProcess3"
         operation="process"
         variable="inputVariable"
          createInstance="yes"/>
<reply name="replyOutput"
       partnerLink="client"
       portType="client:BPELProcess3"
       operation="process"
       variable="outputVariable"/>
</sequence>
</process>
As shown in the .bpel xml examples, receive, invoke and reply refer to a portType and a partnerLink attribute. These are specified in the .wsdl and also show some differences.
<portType name="BPELProcess1">
<operation name="initiate">
<input message="client:BPELProcess1RequestMessage"/>
</operation>
</portType>
<portType name="BPELProcess1Callback">
<operation name="onResult">
<input message="client:BPELProcess1ResponseMessage"/>
</operation>
</portType>

<plnk:partnerLinkType name="BPELProcess1">
<plnk:role name="BPELProcess1Provider">
<plnk:portType name="client:BPELProcess1"/>
</plnk:role>
<plnk:role name="BPELProcess1Requester">
<plnk:portType name="client:BPELProcess1Callback"/>
</plnk:role>
An asynchronous process specifies two portTypes, each with its own variable. Also it specifies two partnerLinkTypes, because it uses the same client partnerlink to receive from and invoke to (the callback). A synchronous process only specifies one portType holding both the input aswell as the output variable. It requires just one definition of the client partnerlink, because it doesn’t need to be invoked separately. blok

There is also a difference in the operation names (ie. Initiate, onResult and process). Though these are just labels that are referred to, it is good practice to actually rename the to the labels as shown in the default generated code, when changing from async to sync (and vise versa). This makes the xml code better understandable later on.

Summary

In your Asynchronous BPEL process diagram:
  1. Remove the Invoke process step from the diagram
  2. Drag a Reply process step in that place
  3. Connect the Reply process step to the client partnerlink (on the left lane)
  4. In the Edit reply dialog change the name to replyOutput and click OK
  5. Ignore the yellow exclamation mark for now
Now go to the source view of the .bpel file (and auto indent xml):
  1. Within the sequence element find the receive and reply elements
  2. For both of them, set the operation attribute’s value to process
  3. To the reply element, add the attribute variable and assign as value the name of the output variable, by default this is outputVariable.
Open the .wsdl file in source view (and auto indent xml):
  1. Find the two portType definitions
  2. From the one with operation onResult and name Callback prefixed with your service name, copy the input element and paste it after the input element of the first portType (named your service name)
  3. Rename the element you just copy/pasted from input to output
  4. In the current portType, set the value for operation name to process
  5. Remove the element (including its child elements!) from which you copied the input element (the one that’s called Callback prefixed with the name of your process)
  6. Remove the partnerLink role element - plnk:role - (including its child elements!) that has a portType name equal to the earlier removed portType .
Now go back to your .bpel file and open it in diagram view. The yellow exclamation mark should now be gone. If not, open the Reply process step and click the Apply button. Recompile your project and deploy it.

SOA 11g: Configure DBAdapter

Establish a DBAdapter Deployment Plan Directory

* Create a directory on the host machine where the deployment plan for the DbDapter application can be saved.
* This only needs to be done once.
* Example:
mkdir /opt/oracle/Middleware/home_11gr1/Oracle_SOA1/soa/DBPlan

Acquire Change Lock

* Click Lock & Edit button in the Change Center pane.

Create a Data Source

* To create a Data Source to point to your database.
* Example:
- Name: myDS
- JNDI Name: jdbc/myDS

Create an Outbound Connection Pool

* Click soa_domain > Deployments in Domain Structure pane.
* Click DBadapter in Summary of Deployments pane.
* Click Configuration -> Outbound Connection Pools tab.
* Click New button.

* Select javax.resource.cci.ConnectionFactory and click Next.

* Enter
JNDI Name: eis/DB/myDB

* Click Finish.

Assign Data Source to Connection Pool

* Click Configuration tab -> Outbound Connection Pools tab.
* Expand javax.resource.cci.ConnectionFactory.
* Click the newly created outbound connection pool, e.g eis/DB/myDB.

* Click Properties tab and enter
xADataSourceName: jdbc/myDS
* Hit Enter key.
* Click Save button.

Redeploy DbAdapter

* Click soa_domain > Deployments in Domain Structure pane.
* Click thecheckbox to select DBAdapter.

* Click Update button.
* Select Redeploy this application using the following deployment files
* Check deployment plan file is correct:
- Deployment plan path: /opt/oracle/Middleware/home_11gr1/Oracle_SOA1/soa/DBPlan/Plan.xml

* Click Next.
* Click Finish.

Activate Changes

* Click Activate Changes button in the Change Center pane.

Tuesday, 16 August 2011

custom faults in SOA11g


In this post, I am going to discuss how custom faults can be created and handled in Oracle SOA Suite 11g.Faults in SOA suite can be broadly categorized into following categories:-
                                   
                                             System Faults
                                             Custom Faults
                                             Mediator Faults

So lets get started.First create a new SOA application and a new SOA project.Choose empty composite template.Next open the composite file and drag and drop a new BPEL process.Enter FaultThrower as the name,choose synchronous template and accept the default input and output.Make sure the "Expose as SOAP service" is checked. Hit Ok once your done.
                                                   


Your composite should look like the following image:-



Now we shall create a message on which our fault variable is going to be based on.I should mention here that fault variables in Oracle SOA Suite 11g must be WSDL message based.
To do that,first create a new XML Schema Document.I used the name Faults.xsd.You can choose any name you like.Following is the source for Faults.xsd:-


<?xml version="1.0" encoding="windows-1252" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns:tns="http://www.customfaults.org"
            targetNamespace="http://www.customfaults.org"
            elementFormDefault="qualified">
 
  <xsd:element name="MyBusinessFault" type="tns:MyBusinessFaultType"/>
 
  <xsd:complexType name="MyBusinessFaultType">
 
    <xsd:sequence>
      <xsd:element name="FaultCode" type="xsd:string"/>
      <xsd:element name="FaultDesciption" type="xsd:string"/>
    </xsd:sequence>
 
  </xsd:complexType>
 
 
</xsd:schema>

Next, open the FaultThrower.wsdl file.First import the schema Faults.xsd into your wsdl:

    <import namespace="http://www.customfaults.org" schemaLocation="xsd/Faults.xsd"/>



Next add a namespace declaration:-

                         xmlns:tns="http://www.customfaults.org"


Now add the following WSDL message:-

   <wsdl:message name="MyCustomFaultMessage">
    <wsdl:part name="businessFault" type="tns:MyBusinessFaultType"/>
  </wsdl:message>



Next, we are going to specify a fault in the operation section for our service.To do this, add the follwing line of code in the operation section:-

                  <wsdl:fault message="client:MyCustomFaultMessage" name="MyBusinessFault"/>


So we are done with WSDL file.Next open the FaultThrowerBPEL process by double clicking on it.Now, we shall create a fault variable based on our WSDL message type.To do this, click on the create new variable icon in the BPEL process as shown in the image below:-


The create new variable dialog opens.Click on the green plus icon to add a new variable.


Enter the name FaultVar(or any name you wish).Select Message Type radio button and click on the magnifying glass as shown in the image below:-


In the type chooser dialog, select the fault message that you created.


Hit Ok three times to complete the variable creation.In this step, I created a variable manually.In the subsequent steps, we are going to see how JDev can automatically create the fault variable based on our message type.Next drag and drop a throw activity onto your BPEL process , between the Receive and Reply activities.Double click on the throw activity.On the window that appears, click on the magnifying glass as shown in the image below to select the fault that you want to throw:-


Select the fault that you created.Take a moment to recall that the fault name that is being displayed i.e. MyBusinessFault was specified in the name attribute while creating the fault inside the WSDL file's operation section.
     <wsdl:fault message="client:MyCustomFaultMessage" name="MyBusinessFault"/>






Next drag an Assign activity onto the BPEL process just before the throw activity.The BPEL process should look like the following image:-




Double click on the Assign activity.Add a new copy operation.




Create a copy operation as shown in the following image.Hit Ok once you are done.


Create another copy operation as shown in the following image.Hit Ok twice to return to the BPEL process.


This completes the assign activity.Next add a catch branch by licking on the add catch branch icon on the BPEL process as shown in the following image:-


A catch branch is added to the BPEL process.Next, double click on the catch activity to specify the fault that we intend to catch.On the window that comes up, click on the magnifying glass as shown in the image below to choose the fault.


In the fault chooser dialog, select the fault that we created i.e. MyBusinessFault.Hit Ok once you are done.


Now, we could use the same fault variable that we created earlier but for now, we are going to create a new fault variable.To do that,click on the green plus icon as shown in the image below.


The variable creation dialog appears.Enter a name.To follow along, enter the name MyFaultVar.Notice that in the type section, JDev has automatically selected the fault message that we created.


Hit Ok once you are done.Now drag and drop a Reply activity under the catch branch.Your BPEL process should look like the following image:-



Now double click on the Reply activity.In the dialog that opens, click on the magnifying glass to select the partner link.


In the partner chooser dialog, select the faultthrower_client partner link.


Next, click on the magnifying glass to select the variable.


Select the newly created fault variable MyFaultVar.hit Ok once you are done.


Now click on the magnifying glass to choose the fault that we are returning.


In the fault chooser dialog, select the fault MyBusinessFault.Hit Ok twice to return to the BPEL process.




The reply activity is now configured to return a fault.This completes our BPEL process.You can now deploy and test the BPEL process.When tested, a fault is going to be returned by the process which is the custom fault that we created.

In fact, we can use BPEL throw activity to throw any custom fault that we like.For example,while throwing a fault, we can choose any arbitrary namespace URI and  local part.





 We can also catch the fault using a catch activity.In this case, the URI and local part must be same as the fult that was thrown.



We can use such throw activities in a similar way use break statements in C.However, if we want to associate a fault variable with the Throw activity, the fault variable must be a WSDL message based.Hope this helps.

Basic Fault Handling in SOA 11g

In this post, I am going to illustrate the basics of fault handling in Oracle SOA 11g.For the sake of illustration, I am going to create a a sample application.So , let's get started.

In Oracle SOA 11g, faults can be categorized broadly into two categories:- System Faults and Custom Faults.So, let us get started to see how it works.In this first example, we are going to see how faults are propagated.

First,open JDev and create a new SOA Application and a SOA project, select empty composite template.Now drag and drop a  BPEL process onto your composite application.Name it FaultHandlerBPEL and choose synchronous template;leave the default input and output and make sure the "Expose as SOAP service" check box is checked.


 Hit ok once you are done.In the FaultHandlerBPEL process, we are going to handle the faults.Drag another BPEL process.Name it FaultThrowerBPEL.Like before, choose synchronous template and accept the default input and output.However, do not expose this BPEL process .i.e. the check box "Expose as SOAP service" should be unchecked.


As the name implies, the FaultThrowerBPEL process throws a fault Now wire the FaultHandlerBPEL to the FaultThrowerBPEL process.Your composite should look like the following image:-



Now, double click on the FaultThrowerBPEL process to open the BPEL process editor.Now,drag a Throw activity between the receive and reply activity.Name the activity ThrowFault.






Now double click on the Throw activity.A window will pop up.Click on the magnifying glass as shown in the image below to select the fault.



In the fault chooser window, expand the System Faults node and select remoteFault.Hit ok once you are done.



This will bring you back to the previous window.Now click on the green plus sign to add a fault variable as shown in the image below:-


Accept the default name and scope in the variable creation window.Hit Ok twice to come back to the BPEL process.


So in the previous steps, what we have done is we have created a throw activity which throws a remoteFault.While throwing the fault, we have also specified a fault variable.Using the throw activity, we can throw system faults and custom faults.However, the custom faults are discussed later.So, if you are familiar with java, up to now we have written something like this:-

     throw new Exception();

Notice that, once we create a fault variable, a new WSDL file is added to our project.The name of the WSDL file is RuntimeFault.wsdl.The wsdl file is a simple one which contains a message on which the fault variable is based on.It is important to mention here that in SOA 11g, the fault variables must be WSDL message based,be that a custom fault variable or a system fault variable.

Now, drag and drop an Assign activity just before the Throw activity.Name it AssignFaultDetails.The BPEL file should look like the following image:-


Now double click on the assign activity.Add a copy operation.



Choose expression on the from side and enter the string '007'.On the to side,expand the FaultVar node and select the code  part.


Hit Ok once you are done.Now,add another copy operation.On the from side, select expression and enter the string 'My Fault Summary'.On the to side, expand the FaultVar node and select the summary part
.

Add another copy operation.Like before, on the from side select expression and enter the string 'My Fault Details'.On the two side, expand the FaultVar node and select detail node.Hit Ok twice to complete the Assign activity.

So the assign activity populates the fault variable with some dummy data before the fault is thrown. This completes our FaultThrowerBPEL process.

Next open the composite.xml and double click on the FaultHandlerBPEL to open the BPEL editor.Next, drag and drop an Invoke activity onto the BPEL process between the Receive and Reply activity.Double click on the invoke activity.Enter the name InvokeFaultThrower.Next click on the magnifying glass beside the Partner  Link as indicated in the following image:-





The partner link chooser dialog opens.Select the FaultThrowerBPEL.faultthrowerbpel_client partner link and hit ok.




Back in the invoke dialog, create input and output variables.Choose the default name.Your BPEL process should look like the following image.


Add an Assign activity before the invoke activity.Name it initialize variable.Create a copy operation as shown in the follwing image:-
Hit Ok twice to come back to the BPEL process.Add another activity after the Invoke activity and before the Reply activity.Call it IntializeOutput.Create a new copy operation as shown in the following image:-


Hit Ok twice to come back to the BPEL process.Now click on the validate icon on the upper left corner of the BPEL process as shown on the image below:-


All the warning signs from the BPEL process should disappear now.If you test the process now and invoke the FaultHandlerBPEL, when executing the invoke activity InvokeFaultThrower, a fault is going to be thrown.This is because the FaultThrowerBPEL is going to be invoked which is going to throw a remoteFault.As we do not have any catch or catchAll activity in the FaultThrowerBPEL, the fault is going to be propagated to the FaultHandlerBPEL.

Now add a catch all branch.To do this, click on the add catch all branch icon as indicated in the image below:-




A new catch all branch is going to be added to the BPEL process.Expand the catch all activity and drag and drop an Assign activity under the catchAll activity and name it PopulateOutput.The BPEL process should now look like the following image:-





Double click to open the Assign activity and add a copy operation.On the from side select, expression,open the expression builder and enter expression:-

concat(ora:getFaultName(),'::',ora:getFaultAsString())

On the to side, select the result element as shown in the image below:-



The function ora:getFaultName() returns the fault name i.e. remoteFault in this case.The function ora:getFaultAsString() returns the details of the fault which contains all the parts i.e. code, summary and detail.Next drag and drop a Reply activity under the catchAll branch just below the PopulateOutput Asign activity.Your BPEL process should look like the following image:-





Double click to open the Reply activity.Enter replyOutput as the name.Now select the partner link as before.In the partner link chooser, select the faulthandlerbpel_client partner link.Hit ok to comeback to the previous window.


Now click on the magnifying glass beside the Variable chooser as shown in the image below:-








In the variable chooser, choose the output variable.


Hit Ok twice to complete the Reply activity.In the previous steps, we created a catch all branch synonymous to java "catch(Exception e){}".Now,inside the catch all, we have implemented an Assign activity which update the output variable with the details of the fault and a Reply activity which replies to the calling process.

Now deploy and test the service from the EM console.A fault is going to be returned when you invoke the ErrorHandlerBPEL from the EM console.


Returning a fault from a synchronous BPEL process:-

Now we are going to see how we can return a fault from a synchronous BPEL process.To do this, open the FaultThrower BPEL process. Next add a catch branch by clicking on the add catch branch as indicated in the image below:-


Now double click on the catch branch that is created .Now we are going to choose the fault that we intend to catch which is, in this case, a remoteFault.Click on the magnifying glass icon as indicated in the image below to bring up the fault chooser window.



In the fault chooser window, select remoteFault.Hit Ok once you are done.



 Next click on the magnifying glass icon as indicated in the image below to select a fault variable.Here, we are going to reuse the same variable that we created while throwing the fault.Alternatively, you can create a new fault variable by clicking on the green plus icon.In this case, the fault variable is going to be automatically populated when the fault is caught.
.


Next, choose the FaultVar and hit Ok once you are done.Hit Ok again to complete the catch activity.So in java syntax, we have written something like this:-
                       catch(RemoteFault faultVar){}


Now drag and drop a Reply activity under the catch activity.Your BPEL process is going to look like the following image.



Next we are going to configure the reply activity to reply with a fault.Double click on the Reply activity.Enter ReplyFault as name.Choose the faultthrowerbpel_client partner link.Now, select the fault variable as the variable.Next click on the magnifying glass as indicated in the following image  to choose the fault that we intend to return.

In the fault chooser dialog, select remoteFault.Hit Ok once you are done.



The reply activity should look like as shown in the following image.


 Hit Ok to complete the reply activity.The BPEL process should look like the following image.


 Next,we have to configure the operation for the FaultThrower BPEL to indicate that he process can return a fault.To do this, open the FaultThrower.wsdl file and go to source.Notice that the RuntimeFault.wsdl is imported into this WSDL automatically.



Now, add a new fault inside the operation.The fault should be based on the message as defined in the RuntimeFault.wsdl.file.Make sure the namespace is declared.


This completes the BPEL process.Now deploy and test the web service.The behavior is going to be the same;this time though, the fault is caught by the FaultThrowerBPEL.Once caught, the FaultThrowerBPEL replies to the calling BPEL i,e, the FaultHandlerBPEL in this case with a remoteFault.This remoteFault is then caught by the catchAll activity inside the FaultHandlerBPEL.So in java syntax, we are doing something like this in the FaultThrowerBPEL:-


                                ....
                                catch(RemoteFault faultVar){
                                                throw new RemoteFault(faultVar);
                                }