Contents


Integrating IBM Integration Bus with WebSphere Service Registry and Repository

Part 4: Service transformation and registry lookup scenarios

Comments

Content series:

This content is part # of # in the series: Integrating IBM Integration Bus with WebSphere Service Registry and Repository

Stay tuned for additional content in this series.

This content is part of the series:Integrating IBM Integration Bus with WebSphere Service Registry and Repository

Stay tuned for additional content in this series.

Transformation and enrichment of in-flight messages is an important capability of IBM Integration Bus, and enables business integration without any additional logic in the applications themselves. Messages can be transformed between applications that use different formats, suh as transforming a custom format in a legacy system to XML messages that you can use with a web service. These transformations enable business information to be distributed to applications that handle completely different message formats, without reuiring any modification of the applications themselves.

Messages can also be transformed and enriched by integration with multiple sources of data such as databases, applications, and files. This allows for any type of data manipulation including logging, updating, and merging. For the messages that flow through the broker, business information can be stored in databases or can be extracted from databases and files and added to the message for processing in the target applications.

IBM Integration Bus provides a number of nodes that can be used to transform the format of messages within a flow:

  • .NET Compute node
  • Mapping node
  • XSL Transform node
  • Compute node
  • Java Compute node
  • PHP node

These nodes are provided with IBM Integration Toolkit and can be found in the Transformation folder of the message flow node palette. Each of the nodes provided makes use of a different technology to perform the transformation.

This article describes a sample message flow that uses the Registry Lookup node to dynamically retrieve XSL transformations that have been stored in WSRR and apply them to messages using the XSL Transform node.

Service Transformation Business Scenario

There are many scenarios in which the ability to transform a message from one format to another could be useful. The sample flow that is described within this article focuses on the service transformation scenario that was described in Part 1: Scenarios and Configuration, as follows:

  • Business problem

    A new version of a service has been implemented that is not backwards compatible with previous versions. You want to take the older versions of the service offline to free up resources, but you do not want to break the consumers of those versions or force them to update their implementations.

  • Solution

    All of the versions of the service can be registered in WSRR and additional metadata can be associated with each service. For example, in the scenario described above, you might define XSL transformations that can convert service requests for older versions of the service to the format required by the latest version (and the reverse transformations for the service responses). These XSL transformations can be loaded into WSRR and associated with the relevant services. They can then be retrieved by a message flow at runtime and applied to the messages flowing across the ESB.

  • Benefits

    This approach enables you to transparently route service requests intended for earlier versions of a service to a later version of the service. This allows you take the earlier versions of the service offline, freeing up the resources that they would otherwise consume. It also allows you to store the XSL transformations in WSRR and retrieve them dynamically at runtime, avoiding the need to build and redeploy the message flow if they change.

Modifications to the Math Service

The Business problem above states that a new version of a service has been implemented that is not backwards compatible with previous versions. To demonstrate this problem, the sample flows that accompany the articles in this series include two versions of the Math Service. The flows that implement each version are:

  • MathService.msgflow
  • MathServiceV2.msgflow

When implementing a new version of a web service that is not backwards compatible with previous versions, it is recommended that you modify the namespace for the new version. The reason for this is that it guarantees that runtimes can distinguish between different versions of the message because the namespace is reflected in the wire format of the service request and response messages. This recommendation has been followed with the different versions of the Math Service. The namespace for Version 1 of the Math Service is http://math.pot.ibm.com. The namespace for Version 2 of the Math Service is http://math.pot.ibm.com/V2.

To make it even easier to distinguish between requests and reponses for the two different versions of the Math Service, the interface for Version 2 has also been modified to require that an additional dummyElement element is included in every request and response message. See the following example of a service request for Version 2 of the Math Service:

Example Math Service V2 Request
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
                     xmlns:math="http://math.pot.ibm.com/V2">
  <soapenv:Header>
    <math:MathHeader>
      <consumerID>CalculatorApplication</consumerID>
      <contextID>CTX_1</contextID>
    </math:MathHeader>
   </soapenv:Header>
   <soapenv:Body>
      <math:add>
         <augend>1</augend>
         <addend>1</addend>
         <dummyElement/>
      </math:add>
   </soapenv:Body>
</soapenv:Envelope>

See the following example of a service response for Version 2 of the Math Service:

Example Math Service V2 Response
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                  xmlns:math="http://math.pot.ibm.com/V2">
  <soapenv:Body>
    <math:addResponse>
      <addReturn>2</addReturn>
      <dummyElement/>
    </math:addResponse>
  </soapenv:Body>
</soapenv:Envelope>

In both cases above, the relevant changes that have been made to the Version 2 request and response messages are shown in bold.

You can use the Calculator application to prove that Version 2 of the Math Service will not accept requests from a Version 1 client. The path to the Version 2 endpoint is /MathServer/services/MathServer/V2. If you attempt to invoke Version 2 of the Math Service using the Calculator application, you should see an error response, as shown in the following figure:

Invoking Math Service V2 with the Calculator Application
Invoking Math Service V2 with the Calculator Application
Invoking Math Service V2 with the Calculator Application

Transforming the Service Requests and Responses

The proposed solution to the Business problem described above is to make use of an XSL transformation to convert service requests for Version 1 of the Math Service to the format required by Version 2 (and the reverse transformation for the service response).

XSL transformation (XSLT) is a standards-based technology that transforms XML documents. Transformation rules for the input XML documents are described in a programming language known as Extensible Stylesheet Language (XSL), which is itself in XML. The XSL transformation rules are defined in a document called a stylesheet.

Because the modifications that have been made to Version 2 of the Math Service are simple, the XSL transformations that are required to transform the relevant service requests and responses are relatively trivial. The following example shows an XSL transform that can be used to convert a request for Version 1 of the Math Service into a request for Version 2. The XSL transform performs two main tasks:

  1. The template that handles the SOAP envelope simply outputs a new SOAP envelope but substitutes the namespace for Version 1 of the service with the namespace for Version 2. It also copies across the values for the consumerID and contextID elements from the SOAP header, if any. It then applies the appropriate template that matches that SOAP body.
  2. The template that handles the SOAP body simply outputs a new SOAP body but substitutes the namespace for Version 1 of the service with the namespace for Version 2. It also copies across the values for the operation specific elements that were specified in the original request and injects the additional dummyElement element. Obviously, only one of the templates for a specific operation will be matched for each request.
Math Service Request XSL Transform
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                xmlns:mathV1="http://math.pot.ibm.com"
                xmlns:mathV2="http://math.pot.ibm.com/V2"
                exclude-result-prefixes="mathV1"
                id="requestTransform"
                version="1.0">

    <!-- =============================================================== -->
    <!-- Template to handle the SOAP Envelope.                           -->
    <!-- =============================================================== -->
    <xsl:template match="/soapenv:Envelope">
        <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
            <soapenv:Header>
                <mathV2:MathHeader>
                    <consumerID><xsl:value-of select="//consumerID/text()"/></consumerID>
                    <contextID><xsl:value-of select="//contextID/text()"/></contextID>
                </mathV2:MathHeader>
            </soapenv:Header>
            <soapenv:Body>
                <xsl:apply-templates select="soapenv:Body"/>
            </soapenv:Body>
        </soapenv:Envelope>    
    </xsl:template>

    <!-- =============================================================== -->
    <!-- Template to handle the add operation                            -->
    <!-- =============================================================== -->
    <xsl:template match="mathV1:add">
        <mathV2:add>
            <augend><xsl:value-of select="augend/text()"/></augend>
            <addend><xsl:value-of select="addend/text()"/></addend>
            <dummyElement/>
        </mathV2:add>
    </xsl:template>

    <!-- =============================================================== -->
    <!-- Template to handle the subtract operation                       -->
    <!-- =============================================================== -->
    <xsl:template match="mathV1:subtract">
        <mathV2:subtract>
            <minuend><xsl:value-of select="minuend/text()"/></minuend>
            <subtrahend><xsl:value-of select="subtrahend/text()"/></subtrahend>
            <dummyElement/>
        </mathV2:subtract>
    </xsl:template>

    <!-- =============================================================== -->
    <!-- Template to handle the multiply operation                       -->
    <!-- =============================================================== -->
    <xsl:template match="mathV1:multiply">
        <mathV2:multiply>
            <multiplicand><xsl:value-of select="multiplicand/text()"/></multiplicand>
            <multiplier><xsl:value-of select="multiplier/text()"/></multiplier>
            <dummyElement/>
        </mathV2:multiply>
    </xsl:template>

    <!-- =============================================================== -->
    <!-- Template to handle the divide operation                         -->
    <!-- =============================================================== -->
    <xsl:template match="mathV1:divide">
        <mathV2:divide>
            <dividend><xsl:value-of select="dividend/text()"/></dividend>
            <divisor><xsl:value-of select="divisor/text()"/></divisor>
            <dummyElement/>
        </mathV2:divide>
    </xsl:template>

</xsl:stylesheet>

The following example shows an XSL transform that can be used to convert a response for Version 2 of the Math Service into a response for Version 1. Again, the XSL transform performs two main tasks:

  1. The template that handles the SOAP envelope simply outputs a new SOAP envelope but substitutes the namespace for Version 2 of the service with the namespace for Version 1. It then applies the appropriate template that matches that SOAP body.
  2. The template that handles the SOAP body simply outputs a new SOAP body but substitutes the namespace for Version 2 of the service with the namespace for Version 1. It also copies across the operation specific return value that was included in the original response and ignores the dummyElement element. Obviously, only one of the templates for a specific operation will be matched for each response.
Math Service Response XSL Transform
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                xmlns:mathV1="http://math.pot.ibm.com"
                xmlns:mathV2="http://math.pot.ibm.com/V2"
                exclude-result-prefixes="mathV2"
                id="responseTransform"
                version="1.0">

    <!-- =============================================================== -->
    <!-- Template to handle the SOAP Envelope.                           -->
    <!-- =============================================================== -->
    <xsl:template match="/soapenv:Envelope">
        <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
            <soapenv:Body>
                <xsl:apply-templates select="soapenv:Body"/>
            </soapenv:Body>
        </soapenv:Envelope>
    </xsl:template>

    <!-- =============================================================== -->
    <!-- Template to handle the add response                             -->
    <!-- =============================================================== -->
    <xsl:template match="mathV2:addResponse">
        <mathV1:addResponse>
            <addReturn><xsl:value-of select="addReturn/text()"/></addReturn>
        </mathV1:addResponse>
    </xsl:template>

    <!-- =============================================================== -->
    <!-- Template to handle the subtract response                        -->
    <!-- =============================================================== -->
    <xsl:template match="mathV2:subtractResponse">
        <mathV1:subtractResponse>
            <subtractReturn>
                <xsl:value-of select="subtractReturn/text()"/>
            </subtractReturn>
        </mathV1:subtractResponse>
    </xsl:template>

    <!-- =============================================================== -->
    <!-- Template to handle the multiply response                        -->
    <!-- =============================================================== -->
    <xsl:template match="mathV2:multiplyResponse">
        <mathV1:multiplyResponse>
            <multiplyReturn>
                <xsl:value-of select="multiplyReturn/text()"/>
            </multiplyReturn>
        </mathV1:multiplyResponse>
    </xsl:template>

    <!-- =============================================================== -->
    <!-- Template to handle the divide response                          -->
    <!-- =============================================================== -->
    <xsl:template match="mathV2:divideResponse">
        <mathV1:divideResponse>
            <divideReturn><xsl:value-of select="divideReturn/text()"/></divideReturn>
        </mathV1:divideResponse>
    </xsl:template>

</xsl:stylesheet>

Registering the XSL Transforms in WSRR

In order for a message flow to be able to dynamically retrieve the XSL transforms at runtime, they need to be loaded into WSRR and associated with the relevant service. The way in which the XSL transforms are associated with the relevant service can vary depending on your requirements. For example, if you need to apply a transform on every operation of a service, the simplest approach would be to define a single XSL transform for all service requests and add it as a target of a relationship on the Service Version in WSRR. This approach describes the current scenario because the request messages for every operation on Version 2 of the service require an additional dummyElement element to be included.

Alternatively, if only a small number of operations have changed in the new version of the service, you could define an XSL transform for each of the updated operations and associate each XSLT with the relevant Service Operation in WSRR. The message flow could then decide at runtime whether it needs to transform a given service request based on whether a transform is associated with the relevant Service Operation in WSRR.

These are just two examples of how you could associate the XSL transforms with the relevant service in WSRR. Because WSRR allows you to customize the business models that are used by the product, the options that you have when deciding how to model the association are extensive. It is recommended, however, that you do model the association so that the mechanism that is used is well structured and predictable. This ensures that common code can be used by your message flows to retrieve the XSL transforms from WSRR.

Other things that you might also want to consider are:

  • Defining a custom Classification System that can be used to classify your XSL transforms. For example, you might want to be able to classify an XSL transform as applying to service requests rather than service responses.
  • Defining a custom Lifecycle that could be applied to XSL transforms so that you could identify what state a given XSL transform is in. For example, you might want to only apply an XSL transform that is in an Approved state.

Having said this, a full description of how to modify the business models, classification systems and life cycles in WSRR is outside of the scope of this article. For more information on these topics, see Modelling business models, classifications and life cycles link or the Customising WebSphere Service Registry and Repository with Studio and Business Space, Part 1: Creating business models, life cycles, and classifications link in the Related topics section.

To keep the scenario simple, the test data that is provided with the articles in this series includes the XSL transforms that are described in above. They are registered in WSRR as XML Document objects with the following names:

  • MathService_Request_v1.0_To_V2.0_Transform.xsl
  • MathService_Respone_v2.0_To_V1.0_Transform.xsl

Two custom relationships have also been added to Version 1.0 of the Math Service and the relevant XML Document has been added as a target of each relationship. Because, for reasons of simplicity, custom relationships have been used in the test data, they only exist on the object in question. That is, these relationships do not exist on every Service Version in WSRR. The names of the custom relationships that have been defined are as follows:

  • requestTransform
  • responseTransform

The following example shows a high-level view of these relationships in the test data.

XSL Transforms Associated with MathService v1.0
XSL Transforms Associated with MathService v1.0
XSL Transforms Associated with MathService v1.0

XSL Transform Node Overview

IBM Integration Toolkit provides explicit support for XSL transformations by providing the XSL Transform node. This node makes use of the the Xalan-Java transformation engine as the underlying transformation engine. As discussed previously, this node can be found in the Transformation folder of the message flow node palette. The sections that follow describe this node in more detail.

Node Terminals

The terminals for the XSL Transform node are shown in . The terminals are described in .

XSL Transform node terminals
XSLTransform node terminals
Terminals on the XSL Transform node
TerminalDescription
InThe input terminal that accepts the message for processing by the node.
FailureThe output terminal to which the original message is routed if an error is detected during transformation.
OutThe output terminal to which the successfully transformed message is routed.

Deployed and non-deployed style sheets

IBM Integration Bus categorizes the stylesheets that you can use with the XSL Transform node depending on whether or not they are managed by IBM Integration Bus. These categories are described in the following list:

  • Deployed stylesheets

    Deployed stylesheets are stylesheets that you import into a broker archive (BAR) file and deploy to target systems. Deployed stylesheets are managed by the broker.

  • Non-deployed stylesheets

    Non-deployed stylesheets are stylesheets that you store in a location where the XSL Transform node can access them. Non-deployed stylesheets are not managed by the broker.

The sample flow described by this article retrieves the stylesheets from WSRR using a Registry Lookup node. These stylesheets are, therefore, not managed by IBM Integration Bus and are considered to be non-deployed stylesheets.

Specifying the Location of the Stylesheet

The XSL Transform node allows you to specify the location of the stylesheet that it will use in three ways:

  • Node properties

    Specify the stylesheet to use by setting the value of the Stylesheet name property using the Properties editor in IBM Integration Toolkit.

  • Local environment variable

    The value of the Stylesheet name property on the XSL Transform node can be specified programmatically. This is achieved by inserting an XSL.StyleSheetName element with a suitable value into the local environment tree that is associated with the current message. You must set this value in a node that precedes the XSL Transform node.

  • Embedded in the input message

    You can embed either the name or the entire contents of a stylesheet in an input message. To do this, you need to include the stylesheet in a sub-element of your input XML message body and assign an identity to it using an XML id attribute. You can then refer to the stylesheet using its id from within an xml-stylesheet processing instruction, as shown below:

    >Embedding a stylesheet in an XML document
    <?xml version="1.0"?>
    <?xml-stylesheet type="text/xml" href="#styleSheetId" ?>
    <docRoot>
        <docData>
            ...
        </docData>
        <xsl:stylesheet id="styleSheetId" version="1.0"
          xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
            <xsl:template match="xsl:stylesheet"/>
            <xsl:template match="/">
                <xsl:copy-of select="/"/>
            </xsl:template>
        </xsl:stylesheet>
    </docRoot>

Typically, the value of the Stylesheet name property on the XSL Transform node refers to a stylesheet that is managed by IBM Integration Bus which, as described above, is known as a deployed stylesheet. Because the sample flow makes use of non-deployed stylesheets, it needs to embed these stylesheets into the input message to make them available to the XSL Transform node.

Message Flow Description

The service transformation message flow accepts Math Service v1.0 requests. It then retrieves the appropriate XSL transforms from WSRR and dynamically inserts them into the message so that they can be used by an XSL Transform node to convert the message into a Math Service v2.0 request. The endpoint for the Math Service v2.0 is then retrieved from WSRR using an Endpoint Lookup node and the transformed message is forwarded to this endpoint. The message flow then uses another XSL transform node to transform the response back to a Math Service v1.0 response, before returning it to the client.

RegistryLookup_XSLTransform Message Flow
RegistryLookup_XSLTransform Message Flow
RegistryLookup_XSLTransform Message Flow

Service Request node

The flow starts with the Service Request SOAP Input node. This node is configured to expose the interface for the Math Service. This is specified on the Basic tab of the Properties editor for the node, as shown in . You can see that the MathServerServiceDummyEndpoint.wsdl has been specified in the WSDL file name field. The other basic properties for the node are automatically filled in once the WSDL file has been selected. When configured to expose a specific WSDL interface, the SOAP Input node will validate any service requests that it receives to ensure that they comply with the definition of the service contained in the WSDL. This node is also configured to use the HTTP transport with a URL suffix of /MathServer/Services/MathServer/xslt. This is the value that consumers will need to use when invoking the service exposed by this flow. The Service Request node is connected to the next node in the service transformation flow using the out terminal.

Exposed WSDL Interface
Exposed WSDL Interface
Exposed WSDL Interface

Registry Lookup node

The Registry Lookup node queries WSRR to retrieve the Service Version that represents version 1.0 of the Math Service. The properties that are used to query WSRR are specified as follows:

Registry Lookup node properties
Property nameValue
NameMathService
Namespacehttp://math.pot.ibm.com
Version1.0
Match PolicyOne
Depth PolicyReturn matched plus immediate related entities (Depth = 1)

The Name, Namespace and Version properties specified should ensure that only a single object matches the query generated by the node. The Depth Policy specified will retrieve all of the objects that are immediately related to this object. This includes the XSL stylesheets that the Math Service is associated with using the requestTransform and responseTransform custom relationships.

Registry Lookup node
Registry Lookup node

The Registry Lookup node inserts representations of all the returned objects into the ServiceRegistry entry in the local environment tree, where they can be accessed by nodes later in the flow. The node then passes the message to the out terminal.

If the query performed by the Registry Lookup node returns no results, the node passes the message to the NoMatch terminal. This terminal is wired to the No Match Faultnode.

Prepare Request Transform and Transform Request nodes

The Prepare Request Transform node is an instance of a Java Compute node. It extracts the XSL transform for the request message from the query results retrieved from WSRR by the Registry Lookup node. It then inserts this XSL transform into a copy of the original service request.

Prepare Request Transform and Transform Request nodes
Prepare Request Transform and Transform Request nodes
Prepare Request Transform and Transform Request nodes

The Prepare Request Transform node attempts to extract the XSL transform for the request message from the local environment tree. To do this, it attempts to traverse the requestTransform custom relationship on the returned object and retrieves the value of the content attribute on the target entity. If it finds a valid XSL transform, it creates a new message to pass to the Transform Request node, embedding the XSL transform in the new message along with the content of the original service request, as described in . If no valid XSL transform is found a SOAP fault is generated with a suitable error message and this is passed to the failure terminal. The code in the following example shows these tasks being performed.

Extracting the Request Transform
MbElement envRoot = inAssembly.getLocalEnvironment().getRootElement();
MbElement serviceRegistry = envRoot.getFirstElementByPath("/ServiceRegistry");

String xslContent = (String)serviceRegistry.evaluateXPath(
    "string(Entity/userDefinedRelationships[@name='responseTransform']/"
    + "targetEntities/Entity/attribute::content)");

if (xslContent != null && !xslContent.isEmpty()) {
    outAssembly = MessageUtils.createXSLTranformMessage( inAssembly
                                                       , "responseTransform"
                                                       , xslContent
                                                       );
    outputTerminal = getOutputTerminal("out");
} else {
    outAssembly = MessageUtils.createSOAPFault(inAssembly,
        "ERROR_XSLT_001",
        "It is not possible to process the request.",
        "An XSLT stylesheet for the request message was not associated with the Service" 
        + "Version in WSRR.");
        
    outputTerminal = getOutputTerminal("failure");
}

The task of copying the original service request and embedding the XSL transform is performed by the createXSLTranformMessage static method on the MessageUtils class. This cannot be done by simply copying the input message because some of the structure of the original XML was lost when it was parsed by the Service Request node. Instead, the createXSLTranformMessage method needs to create an empty message and copy the relevant sections of the input message across. It also inserts an xml-stylesheet processing instruction and the actual content of the XSL transform in the appropriate locations in the new message. The following code shows these tasks being performed.

Embedding the Request Transform in the Message
MbMessageAssembly outAssembly = null;

// Create an empty message, copying the headers from the original message over
MbMessage inMessage = inAssembly.getMessage();
MbMessage outMessage = new MbMessage();
MessageUtils.copyMessageHeaders(inMessage, outMessage);
        
// Create the XMLNSC parser at the root of the new messasge
MbElement msgRoot = outMessage.getRootElement();
MbElement xmlnscElement = msgRoot.createElementAsLastChild(MbXMLNSC.PARSER_NAME);
        
// Create the processing instruction for the stylesheet
xmlnscElement.createElementAsLastChild(MbXMLNSC.PROCESSING_INSTRUCTION
                                      ,"xml-stylesheet"
                                      ,"type=\"text/xml\" href=\"#" + transformId + "\"");

// Create the SOAP envelope element
MbElement soapEnvElement = xmlnscElement.createElementAsLastChild( MbXMLNSC.FOLDER
                                                                 , "Envelope"
                                                                 , null);
soapEnvElement.setNamespace(NAMESPACE_SOAP_ENV);

// Add the actual stylesheet into the message, stripping off the XML prolog.  
xslContent = xslContent.substring(XML_PROLOG.length());
soapEnvElement.createElementAsLastChildFromBitstream(
    xslContent.getBytes(), "", null, null, null, 0, 1208, 0);
        
// Copy the SOAP header element into the new message
MbElement originalSOAPHeader =
    inMessage.getRootElement().getFirstElementByPath("SOAP/Header");
MbElement newSOAPHeader = soapEnvElement.createElementAsLastChild( MbXMLNSC.FOLDER
                                                                 , "Header"
                                                                 , null);
newSOAPHeader.setNamespace(NAMESPACE_SOAP_ENV);
newSOAPHeader.copyElementTree(originalSOAPHeader);

// Copy the SOAP body element into the new message
MbElement originalSOAPBody =
    inMessage.getRootElement().getFirstElementByPath("SOAP/Body");
MbElement newSOAPBody = soapEnvElement.createElementAsLastChild( MbXMLNSC.FOLDER
                                                               , "Body"
                                                               , null);
newSOAPBody.setNamespace(NAMESPACE_SOAP_ENV);
newSOAPBody.copyElementTree(originalSOAPBody);

// Construct the output assembly
outAssembly = new MbMessageAssembly( inAssembly
                                   , inAssembly.getLocalEnvironment()
                                   , inAssembly.getExceptionList()
                                   , outMessage
                                   );
return outAssembly;

The Transform Request node is an instance of a XSL Transform node. Because the XSL transform is passed into the node as part of the message, no value has been specified for the Stylesheet name property on the node. XMLNSC has been specified as the value of the Message domain property on the Output Message Parsing tab. The node will apply the embedded XSL transform to the input message and pass the transformed message to the out terminal.

Endpoint Lookup and Forward Request nodes

The Endpoint Lookup node queries WSRR to retrieve the endpoint for version 2.0 of the Math Service. The properties that are used to query WSRR are specified as follows:

Endpoint Lookup node properties
Property nameValue
PortType NameMathServerPortType_V2
PortType Namespacehttp://math.pot.ibm.com/V2
PortType Version2.0
Classificationhttp://www.ibm.com/xmlns/prod/serviceregistry/lifecycle/v6r3/LifecycleDefinition#Online
Match PolicyOne

A a Match Policy of One has been specified on the node. This allows the node to be wired directly to a SOAP Request node, in this case the Forward Request node.

If the query performed by the Endpoint Lookup node returns no results, the node passes the message to the NoMatch terminal. This terminal is wired to the No Match Fault node.

Endpoint Lookup and Forward Request nodes
Endpoint Lookup and Forward Request nodes

The Forward Request node is responsible for calling the target service, in this case Version 2.0 of the Math Service. You must specify a value for the Web Service URL property on this node when defining the flow, even though this will be overwritten at runtime by the Endpoint Lookup node. As a result, a dummy value of http://tempuri.org/MathServer/services/MathServer has been specified for this property. Another important point to note is that the Operation mode for the node must be set to Invoke a generic web service. This is specified on the Basic tab of the Properties editor for the node. It enables the flow to proxy requests for any of the operations defined on the Math Service rather than being forced to proxy an individual operation. The out terminal of the Forward Request node is wired to the Prepare Response Transform node.

Prepare Response Transform and Transform Response nodes

The Prepare Response Transform node is an instance of a Java Compute node. It extracts the XSL transform for the response message from the query results retrieved from WSRR by the Registry Lookup node. It then inserts this XSL transform into a copy of the response message generated by invoking version 2.0 of the Math Service.

Prepare Response Transform and Transform Response nodes
Prepare Response Transform and Transform Response nodes
Prepare Response Transform and Transform Response nodes

The code for the Prepare Response Transform node is very similar to that used by the Prepare Request Transform node. The main difference is that it extracts the XSL transform for the response message by traversing the responseTransform custom relationship. If it finds a valid XSL transform, it creates a new message to pass to the Transform Response node, embedding the XSL transform in the new message along with the content of the response message from version 2.0 of the Math Service. If no valid XSL transform is found a SOAP fault is generated with a sutiable error message and this is passed to the failure terminal.

The Transform Response node is an instance of a XSL Transform node. Because the XSL transform is passed into the node as part of the message, no value has been specified for the Stylesheet name property on the node. XMLNSC has been specified as the value of the Message domain property on the Output Message Parsing tab. The node will apply the embedded XSL transform to the input message and pass the transformed message to the out terminal.

SOAP Reply node

The SOAP Reply node, as its name suggests, simply passes a SOAP response back to the service consumer. In a successful pass through the flow, the response returned will be the transformed response generated by the Transform Response node. If an error occurs, the response will be a SOAP fault that was generated by one of the Java Compute nodes in the flow, by the target service itself or one of the XSL Transform nodes.

No Match Fault node

When an error occurs in either of the Java Compute nodes, the nodes programmatically generate an appropriate SOAP fault and pass this to their failure terminals. These are wired directly to the SOAP Reply node. However, when the queries performed by the Registry Lookup or Endpoint Lookup nodes do not return any results, they do not automatically generate a SOAP fault. To do this, the NoMatch terminal for these nodes are wired to the No Match Fault Java Compute node. This node programmatically generates a SOAP fault which is returned to the service consumer using the SOAP Reply node.

Testing the Message Flow

  1. Make sure that your IBM Integration Bus execution group is running, with the RegistryLookup_XSLTransform flow deployed and started.
  2. Start the calculator application, as described in Running the Calculator in Part 1.
  3. Specify suitable hostname and port number values for the server that is running IBM Integration Bus. For example, if you are running IBM Integration Bus on the same machine as the Calculator application and are using the default port these values would be localhost and 7800.
  4. Modify the path for the service, setting its value to /MathServer/services/MathServer/xslt. This is the endpoint for the RegistryLookup_XSLTransform flow.
  5. Specify some values and a suitable operator (+, -, /, *) in the drop-down, then press the = button.
  6. The Calculator application will send a service request to the service transformation message flow, which will transform the request and route it to version 2.0 of the Math Service. It will then transform the response and return it to the Calculator application, which displays it. The Calculator application should look similar to this:
    The calculator application, set up to use the XSLT message flow
    The calculator application, set up to use the XSLT message flow
    The calculator application, set up to use the XSLT message flow

If you recieve an error from the application, check the following:

  1. You have performed all of the configuration steps described in Part 1: Scenarios and configuration.
  2. You have specified the correct hostname.
  3. You have specified the correct port number.
  4. You have specified the correct path for the flow.

Conclusion

This article described an example message flow that uses XSLT stylesheets to transform the request and response messages for a service at runtime in IBM Integration Bus. The flow enables the service requests from a verion 1.0 client of a service to be transformed and routed to an endpoint for version 2.0 of the service. It also transforms the responses from version 2.0 of the service and returns them to the version 1.0 client. This allows the client to continue to operate even if version 1.0 of the service is taken offline.

The sample message flow is a simple one, but the concepts used here can be adapted for use in your own message flows.

Acknowledgements

The author thanks the following people for all of their help with the development of the sample messages flows in this series:

  • John Hosie
  • Ben Thompson
  • Matt Golby-Kirk
  • Trevor Dolby
  • Andreas Martens
  • Graham Haxby
  • Andrew Coleman
  • John Reeve

The author also thanks the following people for their help with reviewing this article:

  • David Seager
  • Arnauld Desprets
  • Anna Maciejkowicz

Downloadable resources


Related topics


Comments

Sign in or register to add and subscribe to comments.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Middleware
ArticleID=970150
ArticleTitle=Integrating IBM Integration Bus with WebSphere Service Registry and Repository: Part 4: Service transformation and registry lookup scenarios
publish-date=04302014