Friday, January 19, 2018

Replace Namespace with XSLT in OSB

Recently, I'm working on a project and the vendor changed their framework for implementing their web services. This change caused their web service cannot fully compatible with existing WSDLs and the second level element will not have a correct namespace as before.

Before the change, the request will like below.
<ns0:getRelatedContacts xmlns:ns0="http://ws.crm.victor.com" xmlns:ns1="http://lib.ws.victor.com">
    <ns0:contactRequest>
        <ns1:FAID>FAID_1</ns1:FAID>
        <ns1:subscriptionId>subscriptionId_1</ns1:subscriptionId>
    </ns0:contactRequest>
</ns0:getRelatedContacts>

After the vendor change, the request will like below. The elment contactRequest lost its namespace.
<ns0:getRelatedContacts xmlns:ns0="http://ws.crm.victor.com" xmlns:ns1="http://lib.ws.victor.com">
    <contactRequest>
        <ns1:FAID>FAID_1</ns1:FAID>
        <ns1:subscriptionId>subscriptionId_1</ns1:subscriptionId>
    </contactRequest>
</ns0:getRelatedContacts>

The response has the same issue and second level element will not have a namespace. Due to the vendor cried they might take too much effort to fix it (I don't think it is true. :)), our team has to provide a solution to fix and make the service behavior we exposed to clients same as before and hence we need to find out a way to fix the namespace issue.

Definitely, there isn't a out-box solution. We have to create some code by ourselves to resolve this specific issue.

For replacing namespace, it is pretty simple with XSLT and can be done by a element copy. The next issue is to find out the second level element in the request to remove the namespace and adding the namespace back in response.

Here are the code for removing namespace from request.
<xsl:stylesheet version="1.0"  xmlns:xsd="http://www.w3.org/2001/XMLSchema"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
   
   <xsl:template match="/">
    <xsl:apply-templates/>
  </xsl:template>
  
  <xsl:template match="*[count(ancestor::node())=2]">
    <xsl:element name="{local-name()}">
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates select='@*|node()'/>
    </xsl:element>
  </xsl:template>

  <xsl:template match='@*|node()'>
    <xsl:copy>
        <xsl:apply-templates select='@*|node()'/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

Here are the code for adding namespace back in response.
<xsl:stylesheet version="1.0"  xmlns:xsd="http://www.w3.org/2001/XMLSchema"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
      
   <xsl:template match="/">
    <xsl:apply-templates/>
  </xsl:template>
  
  <xsl:template match="*[count(ancestor::node())=2]">
    <xsl:element name="{local-name()}" namespace="{namespace-uri(parent::node())}">
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates select='@*|node()'/>
    </xsl:element>
  </xsl:template>

  <xsl:template match='@*|node()'>
    <xsl:copy>
        <xsl:apply-templates select='@*|node()'/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

The above codes were tested in OSB 11g and 12c. They worked as what I expected.

Thursday, June 26, 2014

Practise BPEL Process and XSLT Programming

How did you develope your BPEL processes and XML transformation? What is the best approach for development with BEPL and XSLT in Oracle SOA Suite? Should we put most effort on BPEL processes to manipulate the data or should we put more time on XSLT to transform the data? What is a good practice for BPEL + XSLT programming?

When I ask myself these questions, I couldn't give myself an truly answer. It is really difficult to have a clear standard for these programming. But I definitely have my own 2 standards in my daily work.

  1. For business orchestration, 100% sure we should use BPEL to make it works
  2. For data manipulate or transformation, I will prefer to use XSLT to transform them
But they are not always working. As, sometimes, the XSLT may not be able to complete what you want and you may have to leverage the BEPL or even the Embeded Java. 

Recently, I worked on a project and the product of vender is using UTC time to save the datetime. But client is using local time without timezone. In the BPEL processes, I have to convert the local time to UTC time. But it is not just timezone issue and I need to handle daylight saving too. In summer, the offset is 4hrs (Toronto), but it is 5hrs in winter. I looked for a solution and tried many times, but it didn't work. At the begining, I used the current time function in XSLT to get the offset. But when I test the dates which crosses over the daylight saving change day, it will not work. What should I do?

Later, I have to leverage the power of Java. Don't laugh at me, I know it is a little of ugly to introduce the embeded Java in BEPL process. But only several lines of Java code really make the time calculation working. 

I never advocate the purity of codes, but I would insist my these 2 standards to make the code clear and maintainable and keep the intrusive codes as less as possible. Just like many years ago, when I was using Hibernate, I used it to handle CRUD and small volume of data access and never refuse to use stored procedures to handle big volume of data for efficiency.

What I believed is we should use the right tool or approach to do the right thing.

Friday, March 07, 2014

SOA - Handle timeout in a synchronous BPEL processes with Correlation Sets



Recently, I worked on a project and need to handle webservice call time-out issue. In current solution, the developers used JMS Queue to handle the time-out issue. The flow can be described as the following steps.

  1. When our webservice gets a request from client, the message will be put in the request queue
  2. a MDB picks the message and initializes an webservice call to an scheduling system to make an appointment
  3. After the MDB gets the response, it puts the response message into response queue.
  4. The caller  process picks up the message and returns to client.
That the happy path, but sometimes you will need a long time to get the response back caused by the slow network or the busy scheduling system. As the client can't wait for too long and the socket connection has been closed when the response comes back. At this time, the response message will sit in the response queue. When it gets expired, it will be moved to an error queue. The Error handling MDB will initialize a call to the scheduling system to cancel the booked appointment.

Now, we prepared to move the application from WLI to SOA Suite and were asked to handle the same issue in SOA Suite. What I thought is there are 2 approaches to do it.

  1. Implement the exact same logic with BPEL and JMS Queue.
  2. Implement a much smarter process to return the response to client utilizing the BPEL correlation.

I did some research on the internet and didn't get a happy answer on how to implement second solution. But theoretically, I thought BPEL should be able to complete this job as it is statful and supports long run transaction. I didn't give up and kept to look for any sample I could find on the internet and books. Eventually, I found some helpful information from Oracle SOA Suite 11g Developers Cookbook and a blog on AMIS Technology Blog, which are listed in the references. Based on these pieces information, I began my adventure.

At the beginning, I just followed the book as the book mentioned the correlation implementation is different from SOA Suite 11.1.1.6 and didn't looked at the log in detail. I copied the schema and wsdl from the sample code of Oracle SOA Suite 11g Developers Cookbook, then modified them to add an response for the service.  But the code didn't work when I completed and it could not accept any further call with the OnMessage activity.

Later, I began to look at the blog line by line and tried to find useful information. Fortunately, it is really helpful and I found I need to add correlation on the response too. After that, it still didn't work. Then I added an reply before the invocation of third part webservice. Woo! What a magic it is. it worked eventually.

References:
Use BPEL Correlation Sets for repeated (synchronous) access to long running BPEL processes
Chapter 5 of Oracle SOA Suite 11g Developers Cookbook (P96)

SOA - DB connection issue in SOA env.

Today, I installed SOA Suite and OSB on a machine. Then I created a domain with OSB, SOA Suite and BAM support. When I started the weblogic service, I always got the follow error and the server could not be started.

The error is 
Insufficient data while reading from the network - expected a minimum of 6 bytes and received only 0 bytes.  The connection has been terminated.
    at org.apache.derby.client.am.SQLExceptionFactory40.getSQLException(Unknown Source)
    at org.apache.derby.client.am.SqlException.getSQLException(Unknown Source)
    at org.apache.derby.jdbc.ClientDriver.connect(Unknown Source)
    at java.sql.DriverManager.getConnection(DriverManager.java:322)
    at java.sql.DriverManager.getConnection(DriverManager.java:273)
    at jdbc.JDBCSample.main(JDBCSample.java:19).

Searched on the internet, but didn't get any useful info. But it looks like a connectionissue. Then I opened the config file wlsbjmsrpDataSource-jdbc.xml and found the follow funny configuration.

jdbc:derby://localhost:1521/XE;create=true;ServerName=localhost;databaseName=XE
org.apache.derby.jdbc.ClientDriver

The driver is used derby, but the database was pointed to Oracle XE. Really have no idea why got such a config. Whatever, I modified it to the follow and the server started properly.

jdbc:oracle:thin:@localhost:1521/XE
oracle.jdbc.xa.client.OracleXADataSource


Tuesday, October 29, 2013

SOA - No silver bullet in software development at all

With the emerge of a new technology, there always some people would tell the people that technology would solve the problem and make the development successful. But people found that is not true soon and got disappointed as the silver bullet they expected is not true at all.

When the Java appeared in our development life, the people praises it is a revolution as it has garbage collection and is Object-Oriented. Also, it makes the software runs anywhere by using JVM. Theoretically, Java can improve the re-usability and  readability of code. Later, I saw many many developers create giant classes and giant methods without any OO concept, and there is no re-usability and readability at all. I do agree that it is not for all of developers, but pretty a lot did, especially some developers who worked with C previously.

When the SOA was introduced, people felt they found another extreme weapon to solve the development issues and make the project much successful. But I cannot believe it. If the developers don't follow the best practices and related disciplines, nothing can get better but more difficult to trace the problem.

When I first began to learn SOA Suite on 2010, the trainer told me a lot of advantage of it and gave me wonderful picture of it. But I couldn't believe it completely. The SOA Suite allow you to build BPEL process by dragging and dropping and I supposed it should make the process much easy to understand and be clear.  It should bring agility too. Later, I see some developers are creating giant complicated BPEL processes. It is too big to look at it and too complicated to understand it. Some giant one really make me scared.

After so many years, I have to say there is no silver bullet in software development as the issue is created by people not the technologies. For Java, the developer should create proper classes and extract proper methods to put the logic in different places leveraging the advantages of OOP and design patters to make the code re-usable and readable. For BPEL, the developer should create multiple BPEL processes to make the processes as clear as possible and as unique as possible to make it understandable and re-usable.

I still strongly believe the software programming/development is still an Art and really need the people think more and do more.  Otherwise, the people just create another mess when they criticize the mess made by somebody else.

Wednesday, July 31, 2013

OSB-Error handling with Resume action to execute the process continously without throw the exception



In some scenarios, we want the process continuously executes the further steps and ignore the error. In Java code, it is pretty easy and what you need to do just uses a try..catch and then properly set the variables and not throw the exception again. In OSB, it has a little bit difference and a Resume action must be introduced to make the process resumed and executed continuously to handle the further steps.


Error Handler Actions
http://docs.oracle.com/cd/E13171_01/alsb/docs21/consolehelp/proxyerrors.html#1113851
When an error handler processes an error, it can finish with one of two actions:
Table 18-1 Error Handler Actions
Error Actions
Description
Reply
If you assign this action, an error response is immediately created for the proxy service client. All further Message Flow processing stops and a response message is sent based on the message-related context variables. In this instance, you can configure the error handler to send a simple reply to the proxy service or a more detailed reply stating that an error occurred.
The difference between HTTP reply with success and reply with failure is as follows:
  • Reply with success sends status code 200 and $body
  • Reply with failure status sends status code 500 and $body
Resume
When this action is included in a message flow, message flow processing continues as though no error has occurred. Processing continues after the node or stage in which the error handler is configured. You may need to configure the error handler with compensating logic to set the context variables and message state to correspond with the variable and message state expected by subsequent message flow logic. Configure the compensating logic prior to the Resume action.
If neither the Reply nor the Resume action is initiated, the error is rethrown. In this case, the error is pushed forward and handled by the next level error handler. Unless otherwise specified, the rethrow action is the default action of an error handler.

Thursday, June 20, 2013

OSB-Create an fault with customized error code and error message

When you developed in OSB, you may want to provide a customized error code instead of BEA-xxxxxxx when you catch a fault. By the follow steps, you can replace the error code in fault and reply a fault with your customized error code.

In error handler,
1. Replace the error code with the customized error code by xpath ./ctx:errorCode  in fault2. Replace reason with your customized error message by xpath ./ctx:reason in fault
3. Replace the node contents by xpath . in body with $fault
4. Put a Reply at the end of error handling and select the radio button With Failure

For more detail about error handling in OSB, you can refer the follow blog of Eric.

Oracle Service Bus 11g, handling SOAP Faults


Thursday, June 06, 2013

OSB-Parallel Programming with Static and Dynamic Split-Join

JAVA

In Java language, we can make one Thread to wait for another by using join method. 
private void startThreads(int nfOfThreads) {
  Thread[] threads = new Thread[nfOfThreads];
  //start the threads
  for (int i = 0; i < threads.length; i++) {
    threads[i] = new ThreadTestWithoutJoin.MyThread();
    threads[i].start();
  }
  //join the threads
  for (int i = 0; i < threads.length; i++) {
    try {
      threads[i].join();
    } catch (InterruptedException e) {}
  }
}

NOTE:
In the above code, there are two for-loops, the first to create and start each thread, and the second loop to join each thread. If each thread is joined right after start, the effect is these threads are executed sequentially, without the desired concurrency.
// The following is NOT concurrent:
private void threadTest(int numOfThreads) {
 Thread[] threads = new Thread[numOfThreads];
 for (int i = 0; i < threads.length; i++) {
     threads[i] = new foo.ThreadTest.MyThread();
     threads[i].start();
     try {
         threads[i].join();
     } catch (InterruptedException ignore) {
     }
 }
}
(Refer http://javahowto.blogspot.ca/2007/05/when-to-join-threads.html)

WLI

In WLI, Parallel node represents a point in a business process at which a number of activities are executed in parallel. By default, parallel nodes contain an AND join condition. In this case, the activities on all branches must complete before the flow of execution proceeds to the node following the parallel node. You can change the join condition to OR

NOTE:
Parallel branches of execution in a business process are logically parallel; physically the branches are executed serially by the business process engine. While one branch of execution is waiting for a response, another branch of execution in the parallel flow can progress.
(Refer http://docs.oracle.com/cd/E13214_01/wli/docs102/bpguide/bpguideParallelDesign.htmlhttp://docs.oracle.com/cd/E13214_01/wli/docs102/jpdtutorial/tutWLIProcessParallel.html)

OSB

In OSB, Split-Join feature lets you split a service payload, such as an order, into individual messages for concurrent processing. Concurrent processing, as opposed to sequential processing, greatly improves service performance. Split-Join achieves this task by splitting an input message payload into sub messages (split), routing them concurrently to their destinations, and aggregating the responses into one overall return message (join). This process of payload splitting and response aggregation is called a Split-Join pattern.we can create Split-Join flow for parallel programming. There are two types of Split-Join, one is static and another one is dynamic.

The Static Split-Join can be used to create a fixed number of message requests
The Dynamic Split-Join can be used to create a variable number of message requests.

Any webservice needs a WSDL, Split-Join flow is the same and the first thing we need to do is to create a WSDL. Every Split-Join is based upon a WSDL operation. When you first create a Split-Join, you will be asked to browse to the appropriate WSDL file and to select an operation as part of the creation process. The WSDL of Split-Join flow can be same as the proxy service which will invoke the flow or you can defined a totally different WSDL. The choice is really based on your requirement.

For dynamic Split-Join, please refer the follow blogs. As these blog is pretty detail, I won't write anything.
http://biemond.blogspot.ca/2008/11/split-join-in-oracle-service-bus.html
http://www.xenta.nl/blog/2011/07/03/oracle-service-bus-implementing-aggregator-pattern-by-use-of-split-join/
http://rohanlopes.blogspot.in/2011/10/implement-parallel-split-join-osb.html

For static Split-Join, I got few help from the internet. But it is pretty easy when you have done a dynamic one.
First, create a new Split Join based on the WSDL operation you want to use.  In the Split-Join editor, you can see following flow, which consists of a Start Node, a Receive, a Reply. By clicking the triangle icon beside of Start Node, you can see the Start Node contains both a Request Variable and a Response Variable that have been determined by the WSDL operation initially selected. You can change the variables' name same as what you did in dynamic Split-Join. The Receive Node receives the incoming request message, and the Reply Node generates a response message and sends it back to the client.
Debugging a proxy service
Second, add an Assign Node after the Receive Node to initialize the Response Variable in a form such that the later nodes can work on the data within it. This output message is relayed to the final Reply node in the Split-Join and, in turn, returned to the original client.
Third, add a Parallel Node. The Parallel Node contains two main branches at the beginning, you can add more by clicking on the plus icon. Each branch is composed of a number of actions, the sequence and general configuration being the same for both branches.
Debugging a proxy service

Forth, add an Invoke Service Node. On the properties tab, config the service and operation. Select the Input Variable to create a new request variable and then select the Output Variable to create response variable. The result will be stored in the output Variable. The service you reconfigured for each branch may be not the same based on your requirement.

Fifth, add an Assign/Copy/Insert/Replace before the Invoke Service Node to prepare the input variable for service invocation. As the service invoked may be different, the logic in the node is not the same.

Sixth, add an Assign/Copy/Insert/Replace after the Invoke Service node to put the data in the Output Variable to the response variable of flow.

When you done everything you need, you can follow the steps in dynamic Split-Join to generate a business service. Then you can invoke it and test it in a proxy service.

If you have the book The Definitive Guide to SOA, you can look at the chapter 7 Parallel Calls with Split-Join for help as there is more detail.
(Reference http://docs.oracle.com/cd/E13159_01/osb/docs10gr3/eclipsehelp/tasks.html#wp1150654)

When I opened the source code of flow in text editor, I found the flow is implemented with BPEL instead of genera OSB xml.