Hi Everyone,
Today I will be describing how to create, deploy, and run test cases that automate the testing of SOA composite applications. You can also create test cases for testing BPEL process service components included in the SOA composite application. Test cases enable you to simulate the interaction between a SOA composite application and its web service partners before deployment in a production environment. This helps to ensure that a process interacts with web service partners as expected when it is ready for deployment to a production environment.
In this type of testing, wires, service binding components, service components (such as BPEL processes and Oracle Mediator service components), and reference binding components are tested.
Overview of Test Suites
Test suites consist of a logical collection of one or more test cases. Each test case contains a set of commands to perform as the test instance is executed. The execution of a test suite is known as a test run.
Before starting let me explain you two basic terms that will be used while creating test cases. These are
Assertions : You perform assertions to verify variable data or process flow. Assertions enable you to validate test data in an entire XML document as a process is executed. This is done by extracting a value and comparing it to an expected value.
Emulations: These are used to simulate the message data that your SOA composite application receives from web service partners.
Usecase:
I have created a sample SOA application having BPEL service exposed as web service and wired with DB adapter which is used to call a stored proceudre that I have created.The input for this interface is a string variable and its value would be passed to stored procedure as an input parameter by our BPEL process.In response stored procedure will return response based upon the input passed.Below is the list of input and output that would be returned by SP:
Input: 1 , Output: you entered one
Input: 2 , Output: you entered two
Input: 123(any random value) , Output: Default Output
I will be creating test case for first and last input only to show you guys how it works.
Step1: In project explorer,navigate to "testsuites" then right click and click on "Create Test Suite".
Step2: Give the name as "TestSuite1" and click ok.
Step3: Another window will open up prompting for test case name.Give it as Input1 and click OK.
Step4: You will under project explorer test suite is created and your composite will open in test mode.
Step5: Now, the input that would be passed to our interface, we will add.Right click on your exposes services partner link and click "Create Initiate Messages".
Step6: Initiate message window will pop up.Here either you can pass the input payload by loading from a file or manually.I will pass it manually.Click on generate sample button.It will generate sample input payload with dummy value.Since,we are testing for input 1,pass 1 in the input.
Step7: Now right click on wire between BPEL component and DB adapter in the external references lane and click "Create Wire actions".
Step8: Window will pop up with operations in the left pane and Asserts and Emulations tab on the right pane.Here we will pass input that is expected by our DB adapter.Under asserts tab,click on "+".
Step9: Assert Input --> Generate Sample. Again pass 1 in the input payload.
Step10: Similarly for asserting output,click on "+" again and add Assert ouput with correct value in the response that we are expecting from this reference.Please note assertions means the values that are expected by composite and emulation means emulating dummy response rather than calling the external web wervices/references in actual.Emulations for now leave it, I will explain it later on in this post.
Step11: Your test case will look like this.
Step12: Likewise,add one more test case with name as "RandomInput" to test the composite for scenarios in which random values are passed.
Step13: As we did for our first test case ,create initiate message with input as "123".
Step14: In this case we are expecting output as "Default Output".
Step15: Now we are good to go.Save all and deploy your composite.Open up your composite on EM and click on Unit test tab.Here you will see two tabs beneath "Unit Test" namely "Test Cases" and "Test Runs".You will see two test cases that we had created earlier.you can either execute both the test cases together or one by one.I will be executing them together by clicking on execute.
Step16: Window will pop up asking you to give a name to this test run.Enter "SampleTestRun" and OK.
Step17: You will be immediately shifted to "Test Runs" tab where you will see the status of your test cases.It will be showing as "RUNNING".Keep on clicking Refresh Test status after some time.
Step18: You will see that test cases has been executed successfully.
Step19: Click on input1.xml which is our first test case and click on the "XML" link.Window will pop up showing you the value that was passed to this test case and value that was expected.If both matches then test case passes.You will see 1 in both actual and expected payload.
Step20: Similarly check for output of our first test case again by clicking on second "XML" blue link and verify the outputs.
Step21: Likewise output for second test case.
Step22: Now how the test case behaves in case value expected and actual value does not match.Go back to JDev and open first test case and edit wire actions section where we had added assertions earlier both for input and output.Now what I will do is,simulate the output that stored procedure returns.Means when we will run this test case ,our DB adapter will not be invoked and in turn emulated output will be returned back by composite in the actual value section.Go to Emulate tab and click on Add.
Step23: Add emulate output and enter dummy data in the output paylaod.
Step24:Save and deploy.Test your this test case again.This time its state will be shown as "Failed" which means our test case did not pass.
Step25: Open up the xml and see the value in actual and expected value section is different.Hence,it failed.
In this way you can add number of test cases you want to your SOA composite application and before deploying them to production you can test your composites functionality whether they are behaving in expecting manner or not.For more information refer Oracle documentation HERE
Hope this post help you guys.
Happy Learning,
Cheers !!!
Oracle SOA Suite 11gR1 (11.1.1.6.0) includes new features.Some of them are new delivery and transaction properties that you can set when creating a BPEL process.These configuration properties have a significant impact on the behavior of a BPEL process. You can now set these properties as part of the BPEL component creation process within JDeveloper. The wizard presents these properties and sets the default values based on the context. For example, the oneWayDeliveryPolicy property only shows up for one way processes and the transaction property only shows up for synchronous processes.
Delivery: The possible values are:
async.persist: Messages into the system are saved in the delivery store before being picked up by the service engine.
async.cache: Messages into the system are saved in memory before being picked up by the service engine.
sync: The instance-initiating message is not temporarily saved in the delivery layer. The service engine uses the same thread to initiate the message.
Transaction: The possible values are:
requiresNew: A new transaction is created for the execution, and the existing transaction (if there is one) is suspended. This behavior is true for both request/response (initiating) environments and one-way, initiating environments in which the Delivery list value (oneWayDeliveryPolicy property) is set to sync
required: In request/response (initiating) environments, this setting joins a caller's transaction (if there is one) or creates a new transaction (if there is no transaction). In one-way, initiating environments in which the Delivery list value (oneWayDeliveryPolicy property) is set to sync, the invoke message is processed using the same thread in the same transaction.
For more information please refer this LINK.
Happy Learning,
Cheers !!!
Hi All,
Retrying and rolling back transactions that got failed while invocation is one of the major things that needs to be keep in mind while designing the solution for any interface.As it helps in preventing any data discrepancy that can be there between source and target systems,had there not been any rollback in case of failed transaction.
I will be demonstrating,how to retry and rollback failed transactions in SOA.To illustrate this use case I will be using one JMS queue from where our composite will consume the message and, after that it will insert data in 3 tables that I have created for this usecase.you will be requiring XA JNDIs both for Database and JMS Adapters.
Three tables have been created namely Customer,Order, and Invoice.Our SOA process will insert records in table in the same order.
On weblogic console,we need to set some properties for our jms queue for retry functionality.Just go to your jms queue and navigate to "Delivery Failure" tab for your queue.Set following parameters
- Redilvery Delay Override: 10000 (10 seconds) It is the interval after which rolledback messages will be retried.
- Redilvery Limit: 2 (Number of times failed message will be retried).
- Expiration Policy: Redirect (or Discard, if you want to discard the message after retry) Redirect will move the message to "Error Destination" if even after configured retry parameters message is failed.
- Error Destination: <Queue Name> Queue to which failed message will be moved after all retry attempts.
In the BPEL process, add catch or catch all handler for your composite to handle any faults that may occur.In the Catch All block ,explicitly throw a rollback fault using throw activity.It will rollback the complete transaction i.e. undo all the data inserted in any of the tables and then request message will be rolled back to the jms queue.
NOTE: Any fault thrown using throw activity that is not being caught will result in rollback of complete transaction.
Now,first we will test the happy path.Deploy your code to EM and test the interface.Records will be inserted into all the tables successfully.
To see how rollback works,I will intentionally change the DB jndi for Invoice adapter.To do that open jca file for your Invoice DB Adapter and give some random value in that.Save and redeploy the code.Now the interface will fail while inserting the data in Invoice table and flow will got to Catch All block,where transaction will be rollbacked.
To validate this,check the tables and no new records would have been inserted into the tables.
Since we have configured,retry parameters for our request queue, the rollbacked message will be retried again after 10 seconds.Message state will be changed to "delayed" which means it is being retried.
After all failed attempts the message will be redirected into the error destination that we have configured for our queue.
In this way, you can implement retry and rollback functionality in your interfaces.
Hope this helps you.
Happy Learning,
Cheers !!!
Hi guys,
Today I am gonna write about,how to use summation function in XSL and how to create a cariable and use it in your xsl. Actually,there was a requirement in our project,which was like adding some values of some fields in the input and based upon the sum we required to pass some value to the target system.So, to accomplish this we used sum function, that is available in xslt.
I will be demonstrating it taking one example.Suppose we have some fields that are coming in the input such as A,B,C and we need to add all these values and see whether its sum is greater than zero or less than zero.If the sum is greater than 0, we will pass say "pass" and if its other way around we will pass say "fail" to the target system.I have create a sample BPEL process for this usecase.Process is very simple: it is exposed as webservice and taking input from the client and after doing aforesaid transformation and logic will publish the message in jms Queue.I will just explain the XSL part.
Step1: In my transformation, first I will create a variable that I will be using to storing the sum of all the required nodes. So in your xsl on target node,right click and add variable "tempVar".
Step2: Drag and drop "Sum" function from Mathematical functions in the centre of xsl.
Step3: Now in the function add all the nodes that you want to add separated by "|".In this example I am adding surcharge,tax,vat,shipmentcharge nodes.
<xsl:variable name="tempVar"
select="sum((/imp1:employee/imp1:surcharge | (/imp1:employee/imp1:order/imp1:Tax | (/imp1:employee/imp1:order/imp1:VAT | /imp1:employee/imp1:order/imp1:shipmentCharge))))"/>
Step4: Based upon the sum we need to send value in the target XML.So in our case if its greater tha 0, We will send "Invocie" in typecode tag and "Credit MEmo" otherwise.To implement this add a choose when and otherwise condition.
Step5: It will check the value of "tempVar" and based on the result,value will be set in the target xml.
Step6: Now deploy and test your composite. First we will test for positive vsalue.I have passed values in all the field greater than 0.As per our logic value in Typecode tag is sent as "INVOICE".
Step7: To check the opposite scenario,pass values such that sum is less than 0.Values now passed is "Credit Memo".
In this way we can use the sum function and also you learned ,how to create a variable in xsl and use that in your XSL.
NOTE: There can be scenarios where values in some nodes can be empty.So you have to handle that as well,otherwise,you will get "NaN" in your result.Hence in order to handle blank nodes use below expresssion:
sum((/imp1:employee/imp1:surcharge[. != ""]
| (/imp1:employee/imp1:order/imp1:Tax[. != ""] |
(/imp1:employee/imp1:order/imp1:VAT[. != ""] |
/imp1:employee/imp1:order/imp1:shipmentCharge[. != ""]))))
Hope this post is useful to you guys.
Happy Learning,
Cheers !!!
The Oracle Database Adapter supports two high availability setups.
- Active-Active setup
- Active Passive setup
In an active-active setup, distributed polling techniques can be used for inbound Database Adapters to ensure that the same data is not retrieved more than once.
Singleton behavior within an active-passive setup allows a high performance multithreaded inbound Oracle Database Adapter instance running in an active-passive setup, to follow a fan out pattern and invoke multiple composite instances across a cluster.
The Oracle Database Adapter also supports the high availability feature when there is a database failure or restart. The DB adapter picks up again without any message loss.
Distributed Polling
Often in production environments,servers runs in clustered mode i.e more than one managed server running under one cluster.Generally if we don't implement distributed functionality then say for eg we have 5 severs in clustered environment.Then in clustered env in case of polling DB adapter it is quite possible that all 5 nodes try to poll the same record at same time,which will result in 5 concurrent instances with same data.Clearly,we dont want that at all.
When we select Distributed polling while configuring DB adapter, it automatically uses the syntax SELECT FOR UPDATE SKIP LOCKED that means the same row cannot be processed multiple times.
SingleTon Behavior
As metioned under distributed polling,there may be times where it is best to improve performance on a single node, and then optionally do fan-out to multiple nodes in a cluster. Relying on concurrency control features of the database such as locking can be great, but these are often designed more for preserving data integrity than for high performance scalability.
The JCA Binding Component supports active fail over of inbound Adapter Services.To enable this fail over feature for a given inbound adapter endpoint, you must add the singleton JCA service binding property in the composite.xml within the <binding.jca> element and set it to a value of true as shown below:
<binding.jca config="SchedulerPollDBAdapter_db.jca">
<property name="singleton">true</property>
</binding.jca>
Only one node of the cluster will poll for the record. If the active node goes down then other node of the cluster will active node and started polling for the record.
Hope this post is useful to you guys.
Happy Learning
Cheers !!!
Hi Guys,
Sometimes there are requirements where we receives request from consumer in opaque/binary format or we may have to interact with applications using binary format.To facilitate this requirement Java embedding activity is used in BPEL.I will be demonstrating how to convert string to binary format and vice verse.
For this use case I have already created a BPEL process that will receive string in string format.In the BPEL code I have added 2 java embedding activities one for encoding and one for decoding the data.
Firstly, I will encode the payload received in binary format using below code:
addAuditTrailEntry("Encoding started");
try {
oracle.xml.parser.v2.XMLElement input = (oracle.xml.parser.v2.XMLElement) getVariableData("inputVariable","payload","/client:process/client:input");
java.lang.String input_str = input.getTextContent();
addAuditTrailEntry("Input String = "+input_str);
oracle.soa.common.util.Base64Encoder encoder = new oracle.soa.common.util.Base64Encoder();
java.lang.String encoded = null;
encoded = encoder.encode(input_str);
addAuditTrailEntry("encoded string = "+encoded);
setVariableData("InputVar",encoded);
} catch (Exception e) {
addAuditTrailEntry("Exception: "+e.getMessage());
}
addAuditTrailEntry("Encoded ended");
Pass the input variable name in the input string and create one more variable of 64binary format that will store the encoded string.
Now, we will decode the string that we encoded in previous step using below code:
addAuditTrailEntry("decoding started");
String encodedString = (String)getVariableData("InputVar");
Base64Decoder Decoder = new Base64Decoder();
addAuditTrailEntry("encoded String = "+encodedString);
try
{
String decoded = Base64Decoder.decode(encodedString);
addAuditTrailEntry("decoded string = "+decoded);
setVariableData("decodedString",decoded);
}
catch(Exception e)
{
addAuditTrailEntry("Exception: "+e.getMessage());
}
Create one more variable of string type that will contain the decoded string.In this case we will pass the variable we created in previous step as input.Decoded string will be stored in variable we created for storing decoded string.
Now, we will test our composite to verify the changes we have made.String passed is encoded using 1st java embedding activity and decoded using second java embedding java activity.
Make sure you imported below mentioned classes in your BPEL source:
<bpelx:exec import="oracle.soa.common.util.Base64Encoder"/>
<bpelx:exec import="oracle.soa.common.util.Base64Decoder"/>
Otherwise your compilation will fail.
In this way you can achieve encoding and decoding functionality in BPEL.Hope this post is useful to you.
Happy Learning,
Cheers !!!