Using an XQuery transformation to map between the different data models of the services
Due to the fact that on the proxy service we use a different WSDL than the external service offered, we need to adapt the data models between these two interfaces when sending the request message as well as on the way back when returning the response message. There are different ways to achieve that, probably the most common one in OSB being the use of an XQuery script.
Getting ready
Make sure that you have the current state of the basic-osb-service
project available in Eclipse OEPE. We will start this recipe from there. If necessary, it can be imported from here: \chapter-1\getting-ready\operational-branch-proxy-service-created
.
How to do it...
First we will need to create the transformation for the request message to be passed to the external service, which has not many data elements to transform.
Create a new XQuery script by right-clicking on the
transformation
folder in theProject
folder and then select New | XQuery Transformation.Enter
TransformFindCustomerRequest
into the File name field and then click on Next.In the Available Source Types tree, select the source type for the transformation: FindCustomer from the CustomerManagement.wsdl.
Click on the Add button to add it to the Selected Source Types, as shown in the following screenshot:
Click on the Next button.
In the Available Target Types tree, select the target type for the transformation: RetrieveCustomerByCriteria from the CustomerService.wsdl.
Click on the Add button to move it to the Selected Target Types.
Click on the Finish button.
Click on Yes to confirm switching to the XQuery Transformation perspective.
The graphical XQuery transformation editor opens, with the source on the left and the target structure on the right. We can now start mapping source to target values. In the case of the FindCustomer request, the target side is a generic query operation with a list of criteria elements. In this recipe, we will only map the ID, assuming that at the moment only the ID value needs to be supported. To map it, follow the ensuing steps:
Right-click on the criteriaField node on the right side (target) and select Create Constant.
Enter
id
into the Constant Value field of the pop-up window.Click on the OK button.
The criteriaField is annotated with a little c, indicating that a constant is specified.
Select the criteriaValue on the right side and click on the Target Expression tab (make sure that the XQuery Transformation perspective is active, otherwise the Target Expression tab will not be available).
From the available XQuery Functions on the left, drag the string Type Conversion Functions to the expression editor. The expression will read xs:string($item*-var).
Drag the ID element from the Source type and replace the $item*-var parameter value within the parentheses:
Click on Apply on the left of the Target Expression tab window to accept the expression and a line for the mapping should be displayed. The small f on the criteriaValue node indicates the usage of an XQuery function:
Save the XQuery script
The transformation for the request of the findCustomer operation is now ready to be used. Before we will apply it in the Messagse Flow, let's create the transformation for the response message. Perform the following steps:
Repeat steps 1-10 with the following differences:
Name the XQuery TransformFindCustomerResponse
Select the RetrieveCustomerByCriteriaResponse element of the CustomerService WSDL as the source type of the transformation
Select the FindCustomerResponse element of the CustomerManagement WSDL as the target type of the transformation
Map the source to the target values in the XQuery Transformation editor as shown in the following screenshot. The
ID
value cannot be directly mapped, a type conversion using thexs:long
function is needed:Now with the two XQuery transformations in place, let's use them in the message flow.
Switch to the Oracle Service Bus perspective.
Open the CustomerManagement proxy service and click on the Message Flow tab.
Drag a Replace action from the Message Processing section of the Design palette into the Request Action of the Routing for the FindCustomer operatin:
Select the Replace action and click on the Properties tab to show the properties of the Replace.
Enter
body
into the In Variable field.Click on the <Expression> link.
In the Expression Editor pop-up, click on the XQuery Resources tab.
Click on Browse and select TransformFindCustomerRequest.xq from the
transformation
folder.Click on the OK button.
Drag the FindCustomer node on the right side and drop it onto the Binding Variables field. The value of the binding should read
$body/cus:FindCustomer
.Click on the OK button.
Select the radio button Replace node contents.
Save the changes.
We have added the transformation of the request message. Let's repeat the same steps for the response message:
Drag a Replace action from the Message Processing section of the Design Palette into the Response Action of the Routing for the FindCustomer operation.
Select the Replace action and click on the Properties tab to show the properties of the Replace.
Enter
body
into the In Variable field.Click on the Expression link.
In the Expression Editor pop-up click on the XQuery Resources tab.
Click on Browse and select TransformFindCustomerResponse.xq from the
transformation
folder.Click on OK.
Enter
$body/ext:RetrieveCustomerByCriteriaResponse
into the Binding Variables field. An error is shown because the namespace aliasext
is not defined. Click on OK.Select the radio button Replace node conents.
Click on the Namespaces tab on the left of the Properties window.
Click on Add.
Enter
ext
into the Prefix field and http://www.crm.org/CustomerService/ into the URI field.Click on OK.
Save the proxy service and close it.
Deploy the project to the OSB server by right-clicking on the server and select Publish.
Use soapUI to test the behavior of the service. The following screenshot shows the result of successfully executing a test containing the find result of the external service:
The request as well as the response message in the soapUI test window represents the format defined in the Customer Managemen WSDL.
How it works...
We have used two standalone XQuery scripts to define and execute the transformation of the request as well as the response message. XQuery is a very efficient way of executing such transformations.
We have used a
Replace action to do each of the two transformations. This allows doing the transformation and assignment to the body variable in one single action. The setting Replace node contents is important because it takes care of the wrapping of the information returned by the transformation inside a <soap-env:Body>
element.
The transformation could also be done with an
Assign action. But in that case two Assign actions are necessary, the first one doing the transformation into a temporary variable and a second one to wrap the result of the transformation within the <soap-env:Body>
element and assign it to the body variable.
Using the Replace action is not only the most efficient way of doing a transformation, it's also the easiest one to use. Therefore, we highly recommend using it if all you need is a transformation from one value to another.