IBM Support

Overriding the IBM DataPower Gateway WSDL optimization conversion

White Papers


Abstract

IBM DataPower Gateway performs a WSDL conversion when it exposes the WSDL to their clients. However, some Java clients cannot retrieve more schemas, which DataPower creates for optimization purposes. In this article, you learn how to override this optimization by using XSL transformations and XSL dynamic routing.

Content

Introduction 

IBM DataPower Gateway Appliances (after called DataPower) help you to virtualize your web services to act as a gateway. This pattern gives you many advantages, such as:

  • Web services virtualization 
  • Attack protection 
  • Policy enforcement 

For this reason, it is common to see this pattern in the network infrastructure of the customers. 

Prerequisites and system requirements 

This article is written for IBM DataPower Gateway administrators and developers who have interoperability issues with web services consumers that require the schema to be embedded in the WSDL, instead of a reference to the XSD schema file. 

To build and execute the example in this article, you need:

  • An IBM DataPower Gateway Appliance (virtual or physical). 
  • An XML editor. You can also use your favorite editor. 

Sample files 

You can import the export package, provided with this article, from the Import configuration option of your DataPower Control Panel. You also need to modify the mappings.xml file to make the sample work properly with your services. No further downloads are required to complete the instructions in this article. 

Understanding the architecture

One of the typical scenarios where DataPower fits is shown in Figure 1. 

Figure 1. Basic scheme of the example
Basic scheme of the example

The web service itself is located in WebSphere Application Server (after called Application Server) and DataPower sits between Application Server and clients (typically the Demilitarized Zone - DMZ). When a client wants to consume a web service, it invokes to DataPower, which checks for security threats and URL rewrites, checks the scheme of the incoming message, and performs all the operations specified on its processing policy before it invokes the service in the local intranet. 

The most flexible way to expose web services when you work with DataPower is by using a Web Service Proxy. When you expose a web service by using the Web Service Proxy object, DataPower requires the Web Services Description Language (WSDL) file. Once the service is deployed in the Web Service Proxy, DataPower internally optimizes the WSDL file for its consumption. If a client invokes the address of the service deployed in DataPower (plus the WSDL), it serves an optimized version of the WSDL, as shown in the following xsd:import:  

  <wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" ...>           ...     <wsdl:types xmlns:xsd="http://www.w3.org/2001/XMLSchema">        <xsd:schema>           <xsd:import schemaLocation="TemperatureConverter.xsd1.xsd"              namespace="http://converter.com"/>           </xsd:schema>        </wsdl:types>           ...  </wsdl:definitions>

Sometimes, a legacy web service client might request the WSDL to the device. As mentioned before, DataPower serves the WSDL with internal references to XML schemas (also known as XSD), and the client cannot retrieve the XSD file. It needs a single WSDL file with every artifact embedded in it. 

Therefore, if the client cannot retrieve the schemas, you can configure a Multi-Protocol Gateway in DataPower to retrieve the internal references, compose a single WSDL file, and serve it to the client. This pattern is reflected in Figure 2. 

Figure 2. Internal objects involved in the example 
Internal objects involved in the example

Creating the Multi-Protocol Gateway in DataPower

  1. Once you are logged in to your domain in DataPower, you see the Control Panel page. Click the Multi-Protocol Gateway icon, and create a new one by clicking the Add button as shown in Figure 3. 
    Figure 3. Adding a Multi-Protocol Gateway
    Adding a new Multi-Protocol Gateway
  2. Write a name for the Multi-Protocol Gateway, such as "Rewrite_XSD_Imports". Configure it as a dynamic-backend gateway and set both the request and response type as XML.
  3. Add a Front Side Protocol Handler (typically HTTP), and remember to check the GET method under the "Allowed Methods and versions" section, as shown in Figure 4. 
    Figure 4. Creating an HTTP Front Side Handler
    Creating an HTTP Front Side Handler
  4. Under the Advanced tab, make sure that the "Process messages whose body is empty" is set to on. This parameter lets DataPower process the GET requests from the clients requesting the WSDL. 

Creating the Multi-Protocol Gateway Policy 

In this section, you create a policy with three rules in it: 

  1. The first rule is in charge of getting all the WSDL requests from the clients, getting the WSDL from the backend, transforming it adding the XSDs and giving it back to the client. 
  2. The second rule bypasses the SOAP request to the backend. 
  3. The third rule gets back the response from the backend server and serves it to the client. 

The policy looks similar to Figure 5. 

Figure 5. Policy overview of the Multi-Protocol GatewayPolicy overview of the Multi-Protocol Gateway

Rule 1: Both directions 

This rule is triggered when the consumer requests the WSDL (see Figure 6). It is detected by the presence of the "?WSDL" pattern ending the URL. 

Figure 6. Rule overview for the WSDL transformation
Rule overview for the WSDL transformation
  • Create a match action, which triggers this rule for every incoming request whose URL ends in "?WSDL". The easiest way to do this action is to configure the Match Regular Expression as (.*)[w|W][s|S][d|D][l|L]. Check the "Match with PCRE"  toggle to on under the Main tab of the Matching Rule. 
  • Add a Transform Action after the Match Action you created before, and select the wsdl-fetch.xsl stylesheet of this example. 

    This stylesheet gets the WSDL file from the backend. Since the Multi-Protocol Gateway you are creating in this sample can be used to modify the WSDLs of several Web Service Proxy services, the stylesheet loads a routing file, whose format is: URL of the service (deployed in the Multi-Protocol Gateway) and host of the service (where the service is located, typically the Web Service Proxy). An entry for this file would be: 

      <mapping source="http://9.172.176.70:5321/services/TemperatureConverter"   target="http://127.0.0.1:567"/>
  • After you get the host where the service is deployed and building a valid URL for the WSDL, the stylesheet performs a dp:url-open() call to obtain the WSDL. The code for the stylesheet is shown in Listing 1.

    Listing 1. wsdl-fetch.xsl file
      <?xml version="1.0" encoding="UTF-8"?>   <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"       xmlns:dp="http://www.datapower.com/extensions"       xmlns:regexp="http://exslt.org/regular-expressions"       xmlns:dpconfig="http://www.datapower.com/param/config"       extension-element-prefixes="dp dpconfig regexp"     version="1.0">          <xsl:param name="dpconfig:mapping-file" select="'off'"/>     <dp:param name="dpconfig:mapping-file" type="'dmFileToggle'" xmlns="">       <tab-override>basic</tab-override>       <display>Mapping file</display>       <description>Select the mapping file to convert the URL's       The default is local:///mappings.xml.</description>       <default>local:///mappings.xml</default>     </dp:param>    <xsl:template match="/">        <xsl:variable name="mappings" select="document($dpconfig:mapping-file)"/>        <xsl:variable name="host_to_find"           select="regexp:replace(                      dp:variable('var://service/URL-in'),                      '(.*)\?wsdl','i','$1')"/>        <xsl:variable name="host"           select="$mappings/mappings/mapping[@source=$host_to_find]/@target"/>        <dp:set-variable name="'var://context/wsdl-fetch/host_to_find'"           value="$host_to_find"/>        <dp:set-variable name="'var://context/wsdl-fetch/host'" value="$host"/>        <dp:set-variable name="'var://context/wsdl-fetch/wsdl-location'"           value="concat($host,dp:variable('var://service/URI'))"/>        <dp:url-open target="{           dp:variable('var://context/wsdl-fetch/wsdl-location')}"/>     </xsl:template>          </xsl:stylesheet>  

    The WSDL is the output of the stylesheet.

  • Add another Transform Action by selecting the schema-fetch.xsl stylesheet from the sample code.

    The schema-fetch.xsl stylesheet finds all the imports in the previously downloaded WSDL and replaces all of them with the document, which it is pointing to. To replace the import tags, the stylesheet builds, again, the URL of each schema and uses the dp:url-open() extension again to fetch them and place it into the WSDL file. The code for the schema-fetch.xsl stylesheet is shown in Listing 2.

    Listing 2. schema-fetch.xsl file
      <?xml version="1.0" encoding="UTF-8"?>   	<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"   	    xmlns:dp="http://www.datapower.com/extensions"   	    xmlns:regexp="http://exslt.org/regular-expressions"   	    extension-element-prefixes="dp regexp"   	    version="1.0">   	     	    <xsl:template match="/">   	        <xsl:apply-templates/>   	    </xsl:template>   	     	    <xsl:template match="/*[local-name()='definitions']   	            /*[local-name()='types']/*[local-name()='schema']">   	        <xsl:for-each select="*[local-name()='import']">   	              <xsl:variable name="myURI"   	                  select="regexp:replace(   	                      dp:variable('var://service/URI'),   	                      '(.*)/(.*)?wsdl','i','$1/')"/>   	              <xsl:variable name="location"   	                  select="concat(   	                      dp:variable('var://context/wsdl-fetch/host'),   	                      $myURI,@schemaLocation)"/>   	              <dp:url-open target="{$location}"/>   	        </xsl:for-each>   	    </xsl:template>   	     	      <!-- Copy everything else -->   	    <xsl:template match="@*">   	        <xsl:copy/>   	    </xsl:template>   	     	      <xsl:template match="*">   	        <xsl:copy>   	            <xsl:copy-of select="@*"/>   	            <xsl:apply-templates select="node()"/>   	        </xsl:copy>   	    </xsl:template>   	     	  </xsl:stylesheet>
  • After the second transformation, add a set-variable action and set the var://service/mpgw/skip-backside variable to "1". This action avoids the backside processing phase. 

Rule 2: Client-to-server direction

This rule handles the client SOAP requests and forwards it to the backend (see Figure 7).

Figure 7. Rule overview for the SOAP requests
Rule overview for the SOAP requests
  • Create a match-all action that gets all the SOAP requests and sends them to the backend.
  • Add a transform action after the match-all and select the wsdl-post.xsl stylesheet provided in the sample file. This stylesheet gets the routing information (as you previously did in the first rule) and forwards the SOAP request to the backend. The content for the wsdl-post.xsl stylesheet is shown in Listing 3. 
  • Listing 3. wsdl-post.xsl file 
  •   <?xml version="1.0" encoding="UTF-8"?>   	<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"   	    xmlns:dp="http://www.datapower.com/extensions"   	    extension-element-prefixes="dp"   	    version="1.0">   	    <xsl:template match="/">   	        <xsl:variable name="mappings" select="document('local:///mappings.xml')"/>   	        <xsl:variable name="host" select="$mappings/mappings/mapping[@source=                dp:variable('var://service/URL-in')]/@target"/>   	        <dp:set-variable name="'var://service/routing-url'" value="concat(                $host,dp:variable('var://service/URI'))"/>   	 	</xsl:template>  </xsl:stylesheet>  

Rule 3: Server-to-client direction 

This rule handles the SOAP response and serves it back to the consumer (see Figure 8).

Figure 8. Rule overview for the SOAP responses
Rule overview for the SOAP responses

Create a server-to-client rule just to get the SOAP responses back to the client.

The .zip file provided with this article contains the sample files you previously selected in the configuration of the Multi-Protocol Gateway. Extract them by using your favorite .zip file extraction tool. An export of the Multi-Protocol Gateway is also provided (Rewrite_XSD_Imports.zip), so you can import it by using the Import Configuration option in the DataPower Control Panel. The .zip file includes the following files:

  • mappings.xml
  • schema-fetch.xsl
  • wsdl-fetch.xsl
  • wsdl-post.xsl
  • Rewrite_XSD_Imports.zip
Sample files (sample-files.zip | 481KB)

Conclusion

In this article, you learned how to change services in IBM DataPower Gateway to modify the content of the WSDL files served by the Web Service Proxy object, or any other server that splits the WSDL file in several files. Splitting the files is good practice, but some clients are not able to get those files. You also learned how to route requests by using a routing file and the var://service/routing-url variable.

IBM DataPower Gateway Knowledge Center: A single web portal to all IBM DataPower Gateway documentations, with conceptual, task, and reference information on installing, configuring, and by using your IBM DataPower Gateway Appliance.
 

[{"Business Unit":{"code":"BU053","label":"Cloud & Data Platform"},"Product":{"code":"SS9H2Y","label":"IBM DataPower Gateway"},"Component":"","Platform":[{"code":"PF025","label":"Platform Independent"}],"Version":"","Edition":"","Line of Business":{"code":"LOB45","label":"Automation"}}]

Document Information

Modified date:
08 June 2021

UID

ibm11109505