Jumpstart for Oracle Service Bus Development: Tutorial #3

Tutorial 3: Data Enrichment
by Ronald van Luttikhuizen and Eric Elzinga
Published October 2009

Architect: SOA

In this tutorial we will combine the OSB Customer Service from the first tutorial and the OrderWebService to create a new composite service. The service is used when customers purchase something from Foo Inc.'s website. This way customers do not need to supply their personal information every time they make an online purchase. The information is obtained automatically using the Customer Service.

Goal

Getting to know the more advanced routing and transformation capabilities of OSB. Especially data-enrichment according to the VETO-pattern (Validate, Enrich, Transform, and Operate) using service callouts and variables. VETO is particularly difficult to achieve in Oracle ESB due to its absence of temporary variables.

Let's begin by creating a new project.

Oracle Service Bus Project

  1. Create a new Oracle Service Bus Project and name it "WAAI_Case3_Order_Service". Create the following folders in the project: business, business/wsdl, proxy, proxy/wsdl, and xquery. These folders will contain the various OSB artifacts.

    Figure 1: Oracle Workshop after creating the project and folder structure

Business Services

Next step is to define the Business Service for the OrderWebService that will be used in this project.

  1. Create a new Business Service based on the OrderWebService that was used in the second tutorial. Perform the following steps to retrieve its WSDL and XSD's:
    1. Use Oracle WebLogic Administration Console to retrieve the WSDL and accompanying XSD of the OrderWebService as outlined in the first tutorial. Place these files in the business/wsdl folder.

      Figure 2: OSB project after adding the WSDL's and XSD's

    2. Create a Business Service by right-clicking the business folder and selecting New → Business Service . Enter "OrderBS" as name. The "General Configuration" dialog opens. Select "WSDL Web Service" as "Service Type", browse to the OrderWebService WSDL in the business/wsdl folder that you imported previously, and select "OrderWebServicePort (port)".

      Figure 3: OSB project after creating the Business Services

Proxy Service

We will now create a new Proxy Service named "OrderPS". This service looks like the OrderWebService but requires less input parameters. The customer data required by the OrderBS -first name and last name- is gathered using a Service Callout to the Customer Proxy Service.

  1. Copy the following files from the WAAI_Case3_Order_Service/proxy/wsdl folder in the resources archive to the proxy/wsdl folder of the OSB project:
    1. OrderService.wsdl
    2. OrderService.xsd

    These files describe the Order Proxy Service including its request and response payload.

  2. Create a new Proxy Service by right-clicking the proxy folder and selecting New → Proxy Service . Enter "OrderPS" as "File name". Click "Finish". This will open the "General Configuration" dialog of the Proxy Service. Select "WSDL Web Service" as "Service Type", browse to the newly added OrderService.wsdl and select its port.

Figure 4: OSB project after adding the Proxy Service

You have now defined the starting point and endpoints of this OSB project. It's time to add the routing and transformation logic.

Routing and Transformation

We'll now start designing a somewhat more complex Message Flow involving data enrichment using a Service Callout.

The Proxy Service exposes the "PlaceOrder" operation. The input contains a "customerId" that is used to retrieve customer details via an invocation to the Customer Proxy Service. The original input will be enriched with the returned customer data. The enriched data is then used to invoke the "placeOrder" operation of the Order Business Service. This operation places the order and returns its status. The status is then routed as output of the OSB Order Service.

Figure 5: Message Flow, minus routing and transformation logic

We will first create a so-called Pipeline Pair. A Pipeline Pair node combines a single request pipeline and a single response pipeline in one top-level element. A Pipeline Pair node can have only one direct descendant in the Message Flow. During request processing, only the request pipeline is executed when Oracle Service Bus processes a Pipeline Pair node. The execution path is reversed when Oracle Service Bus processes the response pipeline.

  1. Open the Message Flow of the Order Proxy Service. Right-click the "OrderPS" icon and select Insert Into → Pipeline Pair .

    Figure 6: Adding a Pipeline Pair activity

We are now going to complete the request and response flow of the Pipeline Pair among others using stages. A stage is a container of related activities to manipulate messages passing through the pipeline.

  1. Right-click the Request Pipeline of the Pipeline Pair and select Insert Into → Stage . Enter "AssignVariables" as name. Right-click the Stage flow and select Insert Into → Message Processing → Assign . We will extract the customer ID from the input and store it using a temporary variable named "customerId".
    1. Open the XQuery/XSLT Expression Editor, select body → $body - PlaceOrder (request) → PlaceOrderRequest → Order →customerId from the "Variables Structure", and drag it into the editor. This will create the following XQuery expression: "$body/ord:PlaceOrderRequest/ord:Order/ord:customerId"

      Change this expression to: " $ord:PlaceOrderRequest/ord:Order/ord:customerId /text()" — since we are only interested in the node contents and not the element itself.

    2. Enter "customerId" as "Variable".

    The Message Flow now looks like this:

    Figure 7: Adding an Assign activity to the Message Flow

The next step is to define a Service Callout to the "GetCustomerById" operation of the CustomerProxyService to gather the required customer information. A Service Callout is used to configure a synchronous (blocking) callout to an Oracle Service Bus-registered Proxy or Business Service. When Oracle Service Bus makes a call to a service via a Service Callout action, the content of the message is constructed using the values of variables in the message context.

  1. Right-click the "AssignVariables" activity and select Insert After ? Stage. Enter "GetCustomerDetails" as name. Right-click the newly created Stage and select Insert Into → Communication → Service Callout . In the Service Callout properties window browse to the Customer Proxy Service from the first tutorial and select "CustomerPS" as "Service". After selecting the service the following properties need to be configured:
    1. Select "GetCustomerById" as "Invocation"
    2. Select "Configure Payload Body" option
    3. Enter "getCustomerByIdRequestVariable" as "Request Variable"
    4. Enter "getCustomerByIdResponseVariable" as "Response Variable"

    The header fields are left empty since there is no need to add specific processing instructions such as WS-Security information.

    Figure 8: Defining a Service Callout to the Customer Business Service

Next step is to assign the correct value to the "getCustomerByIdRequestVariable" variable that is used to invoke the Customer Business Service.

  1. Right-click the Stage "GetCustomerDetails" and select Insert Into → Message Processing → Assign . Enter "getCustomerByIdRequestVariable" as "Variable"; this is the variable that is used as request body for the Service Callout. Click "Expression" and enter the following contents:
    <cus:GetCustomerByIdRequest xmlns:cus="http://www.waai.nl/cdm/customer">
    <cus:id>{$customerId}</cus:id>
    </cus:GetCustomerByIdRequest>

    The expression evaluates to a request payload that contains the customer ID we previously extracted from the request.

    Figure 9: Defining the request message for the Customer Proxy Service

Next we need to extract the customer detail information that is returned by the Customer Proxy Service so it can be used to invoke the Order Business Service.

  1. Right-click the Service Call activity and select Insert After → Message Processing → Assign . Extract the customer's last name by providing the following properties:
    1. Enter " $getCustomerByIdResponseVariable/cust:Customer/cust:lastName/text()" as "Expression"
    2. Enter "lastName" as "Variable"

    Create another Assign activity to extract the customer's first name by providing the following properties:

    1. Enter " $getCustomerByIdResponseVariable/cust:Customer/cust:firstName/text()" as "Expression"
    2. Enter "firstName" as "Variable"

    Add the "cust" prefix and its namespace — "http://www.waai.nl/cdm/customer" (as used in the Assign expressions) — to the list of namespaces. See the first tutorial if you need help with this.

    Figure 10: Message Flow after adding the Assign activities

We now have all required information to invoke the "placeOrder" operation of the Order Business Service. Next step is to create the request payload for the Business Service.

  1. Right-click the Pipeline Pair and select Insert After → Route . Enter "Place Order" as "Name". Right-click the newly created Route activity and select Insert Into → Communication → Routing . Browse to the "Order Business Service" in the Routing properties window and select "OrderBS". Select "placeOrder" in the "Invoking" dropdown list.

    Figure 11: Message Flow after adding the Route and Routing activities

The next step is to create a valid request document for the "placeOrder" operation of the Order Business Service.

  1. Create a Replace activity by right-clicking the Request Action flow and selecting Insert Into → Message Processing → Replace . Use the following settings to create a valid request payload:
    1. Enter "." as "XPath"
    2. Enter "body" as "In Variable"
    3. Select the "Replace node contents" option
    4. Click "Expression" and enter the following expression:
    <ordSrv:placeOrder xmlns:ordSrv="http://www.waai.nl/order/service">
    <order:order xmlns:order="http://www.waai.nl/order">
    <customerFirstName>{$firstName}</customerFirstName>
    <customerId>{$body/ord:PlaceOrderRequest/ord:Order/ord:customerId/text()}</customerId>
    <customerLastName>{$lastName}</customerLastName>
    <orderId>{$body/ord:PlaceOrderRequest/ord:Order/ord:orderId/text()}</orderId>
    <orderName>{$body/ord:PlaceOrderRequest/ord:Order/ord:orderName/text()}</orderName>
    <orderPrice>{$body/ord:PlaceOrderRequest/ord:Order/ord:orderPrice/text()}</orderPrice>
    </order:order>
    </ordSrv:placeOrder>

    This is where the actual data enrichment occurs. The expression is composed of the original request parameters of the Order Proxy Service -e.g. the order name- and of the retrieved customer data using the Customer Proxy Service; the customer's first and last name.

    Figure 12: Defining an expression in the XQuery/XSLT Expression Editor to construct the Proxy Service's request

    Make sure to add the "ord" namespace prefix and its URI "http://www.waai.nl/cdm/order".

This concludes the request flow of the OSB project. We now need to construct the response flow. This is much simpler and involves extracting the response of the "placeOrder" operation and using it to construct the response of the Order Proxy Service.

  1. Right-click the Reponse Action of the Routing activity and select I nsert Into → Message Processing → Assign to add an Assign activity. Enter "placeOrderResponse" as "Variable" in the Assign properties window. Click "Expression". This will open the XQuery/XSLT Expression Editor. Enter " $body/ordSrv:placeOrderResponse/return/text()" as expression. Click "OK" to close the editor. Make sure to add a namespace with prefix "ordSrv" and URI "http://www.waai.nl/order/service".

    Figure 13: Defining an expression in the XQuery/XSLT Expression Editor to retrieve the Proxy Service's response

  2. 13. Right-click the newly created Assign activity and select Insert After ? Message Processing ? Replace to add a Replace activity. Use the following settings to create a valid request payload:

    1. Enter "." as "XPath"
    2. Enter "body" as "In Variable"
    3. Select the "Replace node contents" option
    4. Click "Expression" and enter the following expression:
      <order:PlaceOrderResponse xmlns:order="http://www.waai.nl/cdm/order">
      <order:return>Returned status: {$placeOrderResponse}</order:return>
      </order:PlaceOrderResponse>
    This will result in the following response message: "Return status: " postfixed by the status returned by the Order Business Service.

    Figure 14: Defining the response payload of the Order Proxy Service

This completes the entire routing and transformation flow. We are now ready to test the OSB project!

Deployment and Testing

Deploy the OSB project to WebLogic Server as outlined before and open Oracle Service Bus Console. Click "Project Explorer", expand the "WAAI_Case3_Order_Service" project, and browse to the "proxy" folder. Use the "Launch Test Console" icon to test the OSB project.

Figure 15: Launching Test Console in OSB Service Bus Console

Enter some valid request parameters in the new "Proxy Service Testing" dialog and click "Execute".

Figure 16: Entering a request document to test the Order Proxy Service

The test should return a valid response document indicating the status of the new order to be "OK".

Figure 17: Response document of the Order Proxy Service

Lessons Learned

You have used some of the more advanced routing and transformation capabilities of OSB in this tutorial, resulting in the creation of a VETO-pattern (Validate, Enrich, Transform, and Operate). This third and last tutorial concludes the hands-on part of this article. You are now ready to dive into OSB and get to know all its features!

Summary

Oracle Service Bus is the strategic Service Bus product for Oracle. The tutorials in this article demonstrate the capabilities of Oracle Service Bus, in particular the functionality that isn't included in Oracle ESB. The most important differences that are highlighted in the tutorials are the support for data-enrichment using temporary variables, the different adapter offering, and other types of routing and transformation.

Read more about Oracle's go-forward strategy for the Service Bus product in its Statement of Direction (SOD).

Additional Information and References

Read more about Oracle Service Bus (OSB) on OTN.

Ronald van Luttikhuizen is an Oracle ACE and architect at Approach Alliance, a Netherlands-based information and communications technology consultancy focusing on SOA and BI. ( Visit Ronald's blog)

Eric Elzinga is an Oracle integration consultant at IT-eye. a Netherlands-based specialist in Architected Integration. ( Visit Eric's blog)

.