Tuesday, March 06, 2012

Transaction in SOA 11g

Executive Summary

Oracle SOA Suite is a product which provides a complete functionality for implementing end to end scenario.
This paper focuses on the importance and applicability of one of the most important concepts of SOA i.e. Transactions-How the business behave, Does it go in a single thread or it is processed in multiple threads.
In an ideal scenario we expect that when ever we are making a transaction if there occurs any error in the middle of the process the whole process should roll back to the initial point from where it is started.Specially in case of monetary transaction we want that the whole transaction should be rolled back to the initial point.
In this paper we will see a demo scenario where in we will see what error occurs when the process runs in different transcations and how we can overcome them by making them run in a single transaction.Transactions are mainly considered in case of fault propagation.
Transactions in SOA Suite
A transaction enables an application to coordinate a group of messages for production and consumption, treating messages sent or received as an atomic unit.
When an application commits a transaction, all of the messages it received within the transaction are removed from the messaging system and the messages it sent within the transaction are actually delivered. If the application rolls back the transaction, the messages it received within the transaction are returned to the messaging system and messages it sent are discarded.
In the document we will see how transaction semantics behave in Oracle BPEL Process Manager.
Need for transaction in SOA Suite
Oracle BPEL Process Manager by default creates a new transaction on a request basis. That is, if a transaction exists, it is suspended, and a new transaction is created. Upon completion of the child (new) transaction, the master (suspended) transaction resumes.
However, if the request is asynchronous (that is, one-way), the transaction is either:
• Inherited for insertion into the dehydration store (table dlv_message).
• Enlisted transparently into the transaction (if one exists).
There is no message loss. Either the invocation message is inserted into the dehydration store for processing or the consumer is notified through a fault.
In release 10.1.3.x, there were several properties to set on the consuming process (that is, on the partner link) and the providing process. This enabled you to chain an execution into a single global transaction. On the consuming side, you set transaction=participate on the partner link binding in the bpel.xml file. On the providing side, you set transaction=participate in the section of bpel.xml.
In release 11g, you only must set a new transaction property on the BPEL component being called (known as the callee process). You add bpel.config.transaction into a BPEL process service component section in the composite.xml file (note the required prefix of bpel.config.). This property configures the transaction behavior for BPEL instances with initiating calls.

Additionally we will see how the global inbond parameter for inbound adapter in BPEL process manager affects the flow of process.

Problem definition
We will create a scenario first of all to understand what the problem is when the process do not executes in a single transaction.In this sample I am replicating this scenario by using following logic.

There is an inbound database adapater which is being polled.Upon arrival of data in the table the process is triggered and then within the process (business flow) some transformation happens as per the target system requirement and again this data is write to another table in target database.Once database is update in the next flow of business process a file is also write to the system file directory using a file adapter.

Now Let suppose there is a situation where in you have put a record in the source table and the flow started, transformation happened and then while trying to write the record in file system some issue happened(for simulation we will revoke the write privilege from the file location.).So ideally you will expect the process to roll back that is your data should not be written to target table and should go back to the source table.But if the process is in different transaction you will find that the process will throw an error at stage when it is trying to write a record in file system,The record from the source will be deleted and the target table will be updated.Obviously you don’t want this.We will see how this happens using different retry parameters at different adapter level to understand how the process behave.

High-level solution

We will make the process work in a single transaction; Additionally we will define a global inbound parameter which will ensure that the inbound adapter keeps on polling the record until the whole process works fine.

Solution details

The following section details out the setups required to recreate the problem scenario and then the solution steps.

Setups

SOA Suite 11.1.1.5
Oracle XE 11.2
RCU 11.1.1.5
Oracle WebLogic Server 10.3
Jdeveloper 11.1.1.5




Business flow
Steps to recreate the issue.
1. We will create two tables one for source and one for target.For demo purpose we will create a simple table with two columns.

Source Table:- create table source (name varchar(20), EmployeeId varchar(20));
Target Table:- create table target (EmpName varchar(20),Id varchar(20));



2>Creating Sub Process-Create a simple synchronous BPEL process which will take two input parameter from client and will update it in the target table of the database.My process will look something like this.



On top I have the composite and in bottom I have the BPEL process which is assigning the in put data to the adapter to insert in to the target database.Deploy this process to your application server to get a concrete wsdl url for the Sub-Process.

3. Creating the Connection pool and the data Source
Create a data-Source from Admin console.This will contain the details of the database you want to connect.




Create a new Outbound Connection Pool,This will provide a Jndi name to be associated with the data source using the jndi name in design time configuration.



4. Creating the Main Process.

In the main process we will create an inbound db adapter then using the partnerlink feature of BPEL We will call the SubProcess that we have already defined.We will then create a file Adapter to write the file to a file system.My Final process will look something like this.



Now with write privilege in the folder the process will complete successfully and we will get a completed scenario as shown below.



Now in order to create our issue we will revoke the write privilege from the folder location where file adapter is writing.This will result in a faulted instance as shown below.



But as you can see the first invoke has already updated the record and is completed successfully however the whole flow is not complete.This mean that our record is taken from the source table and is update in the target table but still our process is not complete.So if you will check the end system this result will come.


The expected behavior is if file is not writing the whole process should roll back to the initial point.That is the target should not be updated and the record should not be deleted from source.This happens because the Target database is getting updated in a separate transaction.

Recovery
In order to recover from this situation we need to make the process work in a single transaction so we will see how we can do that.
We will add the following property in the composite of our Sub process.

required

Now we need to redeploy the process to make these changes take effect.Now if you will test this process you will find that the target table is not updated but the record is deleted from the source. So now if you will check the records you will get the following result.


This time as you can see you can see that the target is not update but at the same time the record is deleted from the source table. This happens because we have designed our process as a asynchronous process which by default doesn’t retry for inbound adapter.So it just checked once and then faulted.So we need to make our process a synchronous process in order to make retry happens at inbound level.
As we know that in a synchronous process the input and output lies in the same operation.We will make a change in our inbound WSDL file and will add one more output tag so initially my WSDL was having following entry.






I will add one more output message type in the operation to make it a synchronous process.So now my WSDL will have following entry








Further we need to change our process also as this is now a synchronous process ,hence I will include a reply activity at the end of my process and will send a reply to client.So My new process with the changes will appear like this.






Now further we need to take in to consideration few things.

Following property is by default provided for the inbound dbadapter.

2147483647
1
2
120

So by default the inbound adapter will retry for 2147483647 number of times.Please note that this value is the default value generated by the wizard when we created the adapter.This practically means that adapter will try for an infinite number of times.

Now we will test our process again.This time you will find that neither the target table is updated nor the record is deleted from the source table.This happened because the process is in a single transaction now so every time it will start from polling the database as per the polling interval and go till the last state to verify if transaction can reach up to the last point.If if will find that there is a problem at any point it will not commit and the process will roll back to initial point i.e. our record will not be deleted from the source table which is the functionality we wanted to achieve.So our record will show the following values.



In case when retry parameters are not provided the BPEL Engine takes this value from the server configuration which is again set to infinite by default.

This value is called as GlobalInboundJcaRetryCount

You can set this value from your em console in case if you don’t want to use the retry feature in your composite.
You can set if rom following location in your em console
Go to SOA-Infra
Administration->System Mbean Browser
Here go to oracle.as.soainfra.config
your server then AdapterConfig and then adapter
Now on the right hand side you will find a property called as
GlobalInboundJcaRetryCount
You can set this value to -1
The diagram below shows the location and the definition for the parameter.












Results
When the Main process and SubProcess are in same transaction it will force the process to run in a single thread resulting in a rollback of process to initial point if any error occurs in between.

Further Scope

Transactions are mainly considered in the case of fault propagation we can further verify the following scenario using the same process.
Main Process Calls SubProcess That Has bpel.config.transaction Set to requiresNew
If The SubProcess Then The SubProcess Transaction... And The Main Process
Replies with a fault (that is, it uses ). Is saved. Gets the fault and can catch it.
Throws a fault that is not handled (that is, it uses ). Is rolled back. Gets the fault and can catch it.
Replies back with a fault (FaultOne), and then throws a fault (FaultTwo). Is rolled back. Gets FaultTwo.
Throws a bpelx:rollback fault (that is, it uses ). Is rolled back. Gets a remote fault.






MainProcess Calls SubProcess That Has bpel.config.transaction Set to required
If The SubProcess Then The MainProcess
Replies with a fault (that is, it uses ). Gets the fault and can catch it. The BPELCaller owns the transaction. Therefore, if it catches it, the transaction is committed. If the BPELCaller does not handle it, a global rollback occurs.
Throws a fault (that is, it uses ). Gets the fault and can catch it.
Replies back with a fault (FaultOne), and then throws a fault (FaultTwo). Gets FaultTwo.
Throws (that is, it uses ) a bpelx:rollback fault. Gets its transaction rolled back; there is no way to catch it. This fault cannot be handled.

Behavior of bpel.config.transaction parameter for a Process


For With bpel.config.transaction Set to required... With bpel.config.transaction Set to requiresNew...
Request/response (initiating) invocations The caller's transaction is joined (if there is one) or a new transaction is created (if there is not one). A new transaction is always created and an existing transaction (if there is one) is suspended.
One-way initiating invocations in which bpel.config.oneWayDeliveryPolicy is set to sync. Invoked messages are processed using the same thread in the same transaction. A new transaction is always created and an existing transaction (if there is one) is suspended.








¬¬¬¬¬


The transaction concept is also applicable to mediator in SOA Suite.
In Inbound Scenario the Mediator either participates in existing transaction or if a transaction is not present it will start the new transaction.In general when a mediator is invoked via binding.ws it will create a new transaction and in other case it will join the existing transaction.
In case of sync routing rules, they will be all executed in the same transaction, and if an error occurs, a rollback will be issued.
Note: in this case even a fault policy that is configured against a mediator fault will NOT trigger.
In case of async routing rules, each rule will be executed in a new transaction, and if errors occur, a rollback will happen, and a fault policy can be configured to react to it.

Business benefits
Ensure that the Process complete then only status is changed,If an error occurs in between the process rollback to the initial point.No transaction is lost.No need to resubmit the record.
Drawbacks
If you set the retry parameter to infinite this will cause an un-necessary logging so one should design the retry parameter as per the requirement of the project.
Conclusion
Data will not be lost and user will not require resubmitting the data. This concept is very important especially when you are doing a monetary transaction through internet.



Reproduce issue in local Machine
1>Run the scripts to create the required table.
2>Import the two project in to jdeveloper.
2>Create the data-sources required for interaction with database.
4>Change the folder location where data has to write.
5>Deploy the process and test it.
(You can check the process by removing the bpel.config.transaction parameter from Subprocess and redeploying to notice the changes yourself.)

1 comment:

Anonymous said...

Hi,

Thanks for sharing!
The pictures are not showing though.
Do you have an example of transaction rollback in asychronous process?

Thank you.

Dana