Archive Page 12

Using Dynamic Routing in OSB

Dynamic Routing in OSB can be used when we want to determine the business service at runtime in the message flow. To store the information about the business services that can be used, we can use XQuery resource.

Consider a scenario where OSB has to route the incoming requests to 2 different services based on the CustomerType element value sent in the payload. So create a XQuery resource with the following contents. Observe that we are using the absolute path of business service in configuration as required by dynamic routing.

<Configuration>
<CustomerType value =’Privileged’>
<Service>DynamicRoute/BSSystem1</Service>
</CustomerType>

<CustomerType value =’Ordinary’>
<Service>DynamicRoute/BSSystem2</Service>
</CustomerType>
</Configuration>

Following is the XML schema that we use.

<xsd:schema targetNamespace=”http://xmlns.oracle.com/schema/Customer”
    xmlns:xsd=”http://www.w3.org/2001/XMLSchema” xmlns:ns1=”http://xmlns.oracle.com/schema/Customer”>

    <xsd:complexType name=”Customer”>
<xsd:sequence>
<xsd:element name=”CustomerId” type=”xsd:string” />
<xsd:element name=”FirstName” type=”xsd:string” />
<xsd:element name=”LastName” type=”xsd:string” />
<xsd:element name=”MiddleName” minOccurs=”0″ type=”xsd:string” />
<xsd:element name=”CustomerType” type=”xsd:string” />
<xsd:element name=”Email” minOccurs=”0″ type=”xsd:string” />
<xsd:element name=”Mobile” minOccurs=”0″ type=”xsd:string” />
</xsd:sequence>
</xsd:complexType>

    <xsd:complexType name=”StatusMsg”>
<xsd:sequence>
<xsd:element name=”CustomerId” type=”xsd:string” />
<xsd:element name=”Response” type=”xsd:string” />
<xsd:element name=”ErrorCode” type=”xsd:string” minOccurs=”0″/>
<xsd:element name=”ErrorMessage” type=”xsd:string” />
</xsd:sequence>
</xsd:complexType>

    <xsd:element name=”Customer” type=”ns1:Customer” />
<xsd:element name=”StatusMsg” type=”ns1:StatusMsg” />
</xsd:schema>

Following is the WSDL that we will use for the proxy service:

<wsdl:definitions name=”CustomerService”
targetNamespace=”http://xmlns.oracle.com/wsdl/CustomerService”         xmlns:wsdl=”http://schemas.xmlsoap.org/wsdl/”
    xmlns:ns1=”http://xmlns.oracle.com/schema/Customer” xmlns:xsd=”http://www.w3.org/2001/XMLSchema”
    xmlns:tns=”http://xmlns.oracle.com/wsdl/CustomerService” xmlns:soap=”http://schemas.xmlsoap.org/wsdl/soap/”>
<wsdl:types>
<xsd:schema>
<xsd:import namespace=”
http://xmlns.oracle.com/schema/Customer”
                schemaLocation=”Customer.xsd” />
</xsd:schema>
</wsdl:types>

    <wsdl:message name=”CustomerCreate”>
<wsdl:part name=”parameters” element=”ns1:Customer” />
</wsdl:message>
<wsdl:message name=”CustomerCreateResponse”>
<wsdl:part name=”parameters” element=”ns1:StatusMsg” />
</wsdl:message>

    <wsdl:portType name=”CustomerServicePort”>
<wsdl:operation name=”CustomerCreate”>
<wsdl:input message=”tns:CustomerCreate” />
<wsdl:output message=”tns:CustomerCreateResponse” />
</wsdl:operation>
</wsdl:portType>

    <wsdl:binding name=”CustomerServiceBinding” type=”tns:CustomerServicePort”>
<soap:binding style=”document”
transport=”
http://schemas.xmlsoap.org/soap/http” />

        <wsdl:operation name=”CustomerCreate”>
<soap:operation soapAction=”CustomerCreate” />
<wsdl:input>
<soap:body use=”literal” />
</wsdl:input>
<wsdl:output>
<soap:body use=”literal” />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
</wsdl:definitions>

Create the required resources a proxy service based on the above WSDL, 2 business services and a XQuery resource with the contents shown above.

image

Create the message flow as shown below.

image

The first assign activity loads the XQuery resource and stores the contents of the file in variable ‘varConfig’. The second assign activity stores the value of customer type element in the payload in ‘varType’ variable using the xpath expression $body/cus:Customer/CustomerType/text().

For the dynamic routing the expression should resolve to the following XML snippet. The attribute isProxy has to be set to ‘true’ if routing the request to proxy service or ‘false’ if routing the request to business service. Operation name is optional as business service might  not be WSDL service always.

<ctx:route>
<ctx:service isProxy=’false’>absolute path of business service</ctx:service>
<ctx:operation>operation name</ctx:operation>
</ctx:route>

So for our case use the XML contents as shown in the below screenshot along with the XPath expressions to get the required values.

image

Deploy the configuration jar and test it from test console to verify its working as expected.

The sample jar can be download from the following location.

OEPE versions in OSB

As we know that Weblogic and OEPE installation are pre-requisites for OSB11g installation. Oracle had started shipping Weblogic bundled with Coherence and OEPE. Using this Weblogics installer is the best way to get compatible OEPE for a particular release. However, these are not available for 64-bit machines and need to do manual installation JDK, Weblogic using generic Installer, compatible OEPE version along with your required version of OSB 11g.

So you need to better understand compatible versions of OEPE for a particular OSB 11g release. The following shows the compatibility matrix:

OSB Weblogic Server OEPE
11.1.1.6.0
11.1.1.7.0
10.3.6 11.1.1.8.0
11.1.1.5.0 10.3.5 11.1.1.7.2
11.1.1.4.0 10.3.4 11.1.1.6.1
11.1.1.3.0 10.3.3 11.1.1.5

These versions of Oracle Enterprise Pack for Eclipse are available here.

SOA-INFRA Issue

I have installed SOA Suite and OSB several times but never observed an issue with soa-infra. I used Oracle DB Enterprise Edition in all these installations.

Today i have tried with SOA Suite 11.1.1.4 installation with XE database as i was just preparing an environment for developers for their practice. But observed an issue with soa-infra in EM console which showing it as down. So went to deployments in weblogic admin console and verified the status of soa-infra application and found it in ‘Failed’ status. So the first thing i tried out was starting the soa-infra from deployments section in admin console. When i did this, i encountered the following error:

ORA-04063: package body "DEV_MDS.MDS_INTERNAL_SHREDDED" has errors ORA-06508: PL/SQL: could not find program unit being called: "DEV_MDS.MDS_INTERNAL_SHREDDED" ORA-06512: at line 1

Solution:

  • Do ‘grant execute on dbms_lob to public’ in sqlplus using sys login.
  • Recompile the package DEV_MDS.MDS_INTERNAL_SHREDDED

Restart the server and verify that soa-infra is in Active status now. If the issue is not resolved drop the schema and recreate using the RCU. But before recreating, make sure that following environment variable is set when using XE database.

set RCU_JDBC_TRIM_BLOCKS=TRUE

SOA Suite 11g R1 Developers Guide

Ever since i have seen this post by Antony Reynolds, i wanted to grab my copy of this book. But the price of the book in India kept me away for some time. Finally last week i am able to get my copy of it.

The first sight of the book perplexed me as i was expecting the book to be of size similar to Thomas Erls’ book ‘Web Service Contract Design & Versioning for SOA’. But the contents of the book made me realize that the size does not matter always.

The book is well organized into 3 parts. Part-I  introduces the SOA architecture SCA, developing BPEL composites, endpoint virtualization using OSB and using JCA Adapters, Human workflows, Business Rules, Business Events and Business Activity Monitoring (BAM) that are components of Oracle SOA Suite. Part-II introduces the business requirements of a fictitious company and proceed with the development of application using SOA architecture by making use of the components described in Part-I. Finally the book ends with chapters on deployment, testing and security which constitutes Part-III of the book.

The first thing i did was the search for the following 2 things as i wanted to confirm the best practices from what i know currently:

  • Scheduling the BPEL processes
  • Way to differentiate System and Business faults in OSB

The above things are covered in Chapter 16 and Chapter 14 respectively.

I am reading the chapters in no sequence and i found the chapters Designing Service Contract (Chapter 11), Error Handling (Chapter 14) and Message Interaction Patterns (Chapter 16) very interesting as of now.

Though my recommendation does not add any brownie points, i recommend this book to novice to learn the basics of SOA Suite11g and to experts to get the quick summary.

I want to finish it off asap before somebody steals the book Smile.

Coherence in OSB

In one of our proxy services, we call one service to get credentials with which we can proceed with next service calls in the message flow. As anybody can guess, the credentials might remain same for a period of time (though based on the reset policy).

So if we can reduce number of service calls by caching the service results will increase the performance of the service. I felt that i have realized this very late Smileonce i started searching for this feature in OSB as i find number of articles on the same.

Using Oracle Coherence is the way to cache service results and ‘Result Caching’ is the feature of business service through which OSB can leverage coherence functionality. Thought of putting all my findings in one post but after seeing this article on OTN, i don’t dare to do that.

I have just taken this simple scenario to make a point on using coherence in OSB. The context explained over here may not be the right candidate if we are not aware of the credential reset policy. Then the credentials stored in cache may not be the right ones always and need to clear the cache. So the context has to be clearly ascertained to use coherence.

Currently in the process of finding the way to use coherence in BPEL.

Custom XPath Functions in OSB

Wikipedia says “Extensibility is a system design principle where the implementation takes into consideration future growth.Extensions can be through the addition of new functionality or through modification of existing functionality”.

The extensibility is possible even in case of OSB and custom XPath functions is one of the ways to extend the out-of-the-box functionality provided with OSB. In this  post, we talk about the procedure to come up with the custom XPath functions. Though the example taken in this post (division of numbers)does not represent the real-world case but sufficient enough to stress the point.

During the IDE and server start up, OSB checks for custom functions in the path $OSB_HOME/config/xpath-functions.

Creating the custom XPath functions involves coming up with an xml file and the java code that does the required task. The xml file is going to be similar to the file osb-built-in.xml provided in above path that contains OSB functions. So let us create a xml file custom-func-demo.xml with the below contents and place it the folder mentioned above.

<?xml version="1.0" encoding="UTF-8"?>
<xpf:xpathFunctions xmlns:xpf="
http://www.bea.com/wli/sb/xpath/config">
    <xpf:category id="Custom Functions">
       <xpf:function>
        <xpf:name>DivideNumbers</xpf:name>
        <xpf:comment>Function used for division of numbers</xpf:comment>
        <xpf:namespaceURI>
http://www.oracle.com/custom/custom-functions</xpf:namespaceURI>
        <xpf:className>demo.DivideNumbers</xpf:className>
        <xpf:method>java.lang.Double divide(java.lang.Double,java.lang.Double)</xpf:method>
            <xpf:isDeterministic>true</xpf:isDeterministic>
            <xpf:scope>Pipeline</xpf:scope>
            <xpf:scope>SplitJoin</xpf:scope>
            </xpf:function>
        </xpf:category>
</xpf:xpathFunctions>

The above XML fragment shows the custom XPath function name (Divide Numbers), Class Name, Java Method and the namespace that should be used to access the function in the message flow. ‘isDeterministic’ specifies whether the function is deterministic or non-deterministic. Deterministic functions always provide the same results where as Non-Deterministic functions return the unique results.

Create a simple java class with the following code. Make sure that class name (including the package) and method signature matches with the above xml contents. Create a jar of this and place it in the above mentioned location so that IDE and server can detect the custom function.

package demo;

import java.lang.Double;

public class DivideNumbers {
    public static Double divide(Double a, Double b) {
        return a/b;
    }
  }

On restart of Eclipse IDE and OSB server, we should be able to see the custom XPath function that we just defined.

           Xpath1

           Xpath4

           Xpath2

            Xpath3
Use the custom XPath function and run the proxy service to see the expected results as shown below.

            Xpath5

Common Mistakes in OSB message flow

I see following are the few common errors that developer might come across during the initial stages of OSB learning.

1)

Failed to set the value of context variable "body". Value must be an instance of {http://schemas.xmlsoap.org/soap/envelope/}Body.

Failed to set the value of context variable "header". Value must be an instance of {http://schemas.xmlsoap.org/soap/envelope/}Header.

This error is because of, OSB always enclose the context variables $body and $header with <soap-env:Body> and <soap-env:Header> respectively. So when we are manipulating $header and $body we should make sure that these soap-env tags are not removed. For example, doing in the following way in an Assign activity can cause the above error as we are not maintaining <soap-env:Body> tag in $body variable.

            Expression: <Value>Sample Value</Value>

            Variable: body

And the correct usage in assign activity is like below:

             Expression:

           <soapenv:Body xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">                    <Value>Sample Value</Value>

            </soapenv:Body>
            Variable: body

When we use service call out, the variable given for ‘SOAP Request Header’ should always contain <soap-env:Header> element irrespective of the selection of either ‘Çonfigure SOAP Body’ or ‘Configure Payload Document’. Otherwise again the above header related error will come.

2) 

Invalid message: the SOAP Header value is not an XML instance

One of the scenarios that this error can come is, when we use the service call out and the variable given for ‘SOAP Request Header’ is null.

Fault Handling in OSB

As we know, service provider can send the error back to the consumer in the following ways:

  • As a normal response, by populating the fields like “ErrorNumber” and “ErrorMesssage”. Assuming that these fields are defined in the response message structure in WSDL.
  • As a SOAP fault

Typically when OSB is mediating between service consumer and service provider, we might have to transform this error response or fault response to the response structure defined in the proxy WSDL. So we need to understand on what message context variables can be used for this transformation.

As per WS-I BP, the service provider should send the HTTP response code as 200 when the error is being sent back as normal response and 500 should be sent when the error being sent back in form of the SOAP fault.

When HTTP response code 200 is received, OSB treats it as a normal response and $body will have the received response. And when response code 500 is received, the OSB runtime control goes  to the ‘Service Error Handler’ if present or to ‘System Error Handler’. That means OSB considers the fault response also as a normal response and populates $body, when response code is 200 is received for fault response.

And OSB populates different message context variables in case of fault response with 500 code depending on whether Routing or Service Callout are used to call the business service. When routing is used, the variable $body will have the fault response. When service callout is used, the variable $fault will have the fault response in ‘ReceivedFaultDetail’ structure.

For demonstrating the same, the following SOAP fault structure is used as a response in SOAP UI mock service.

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance" xmlns:xsd="http://www.w3.org/1999/XMLSchema">
   <SOAP-ENV:Body>
      <SOAP-ENV:Fault>
         <faultcode>SOAP-ENV:Client</faultcode>
         <faultstring>Failed to locate method (ValidateCreditCard) in class</faultstring>
         <detail>
              <ValidationError>
                   <ErrorCode>78970989</ErrorCode>
                   <ErrorMessage>Validation failed.Credit Card Expired.</ErrorMessage>
              </ValidationError>
     </detail>
      </SOAP-ENV:Fault>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Create 2 proxy services with routing and service callout as shown below.

Proxy with Routing

                      image

Proxy with Service Callout

                      image

The log activities in the error handler are used to log the contents of $body and $fault variable for demonstration purpose.

Create a business service by giving the mock service endpoint which returns a SOAP fault as shown below.

                      image

In case of routing, the following screenshot confirms that $body has the received fault response. So the expression fn:empty($body/soap-env:Fault) can be used to find out whether we have received the fault or not.

                     Routing

In case of service callout, the following screenshot confirms that $fault has the received fault response. So the expression fn:empty($fault/ctx:details/con1:ReceivedFaultDetail) can be used to find out whether we have received the fault or not. We can come up with similar kind of expressions for all other OSB faults that are described in the link.

                    Service Callout

In case where both service callout and routing are used in single proxy service, a combination of both of above expressions has to be used.

Also look at the note given here that talks about fault handling in OSB.

Namespace Issue

Today, for one of the tasks i need one sample WSDL so that i can create some mock service in SOAP UI. As usual wanted to leverage google search capabilities Smile for the same, instead of coming up with one on my own.

I have taken one of the WSDLs given in w3.org to my eclipse. I am surprised to see the errors given by eclipse for the WSDL. I made sure that the WSDL structure, namespace aliases etc. are given correctly.On careful examination of the inline XSD given in the WSDL, found the issue is with the namespace which is given as http://www.w3.org/1999/XMLSchema.

Modifying this namespace to http://www.w3.org/2001/XMLSchema resolved the error.

So the moral of the story is that some times blind copy does not give the intended time saving benefits as we expect.

Java Embedded Activity in BPEL

Today, it’s the first time that i worked with the Java Embedded Activity in BPEL 11g as i had a requirement of using coherence in the context of BPEL.

Came across one of the silly issues during this process so wanted to share the resolution of the same as i feel its the common mistake that can be done.

When i put the code in java embedded activity and rebuild the composite, i was getting the following error.

Error(23,34): Failed to compile bpel generated classes. failure to compile the generated BPEL classes for BPEL process "BPELProcess1" of composite "default/Project1!1.0"
The class path setting is incorrect.
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.

The issue is coming as the necessary import statements are missing. To resolve this issue, add the import statements in the following way in .bpel file(these are the classes that i used) before the listing of partner links.

<bpelx:exec import="com.tangosol.net.CacheFactory"/>
<bpelx:exec import="com.tangosol.net.NamedCache"/>


Pages

Enter your email address to subscribe to this blog and receive notifications of new posts by email.

Join 196 other subscribers

Enter your email address to follow this blog and receive notifications of new posts by email.