WebSphere ESB endpoint selection based on the WebSphere Service Registry and Repository Governance Enablement Profile

This article shows how to create a WebSphere ESB mediation flow that selects endpoints based on the WebSphere Service Registry and Repository Governance Enablement Profile.

David Bell (david.bell@uk.ibm.com), Integration Test Technical Lead, WebSphere Service Registry and Repository, IBM

David Bell is the Integration Test Technical Lead on the WebSphere Service Registry and Repository team, responsible for cross-product testing. You can contact David at david.bell@uk.ibm.com.



Michael Ellis (msellis@ca.ibm.com), Solution Architect, IBM Software Services for WebSphere, IBM

Michael Ellis is a Solution Architect for IBM Software Services for WebSphere in Ottawa, Canada. He specializes in Web services, SOA architecture, and SOA governance, and helps IBM customers develop SOA reference architectures and implement solutions based on them. He is currently the Consulting Practice Lead for WebSphere Service Registry and Repository worldwide.You can contact Michael at msellis@ca.ibm.com.


developerWorks Contributing author
        level

Brian Hulse (brian_hulse@uk.ibm.com), Senior Software Engineer, WebSphere Service Registry and Repository, IBM

Brian Hulse was a Senior Software Engineer on the WebSphere Enterprise Service Bus team, and is now doing a similar job on the WebSphere Service Registry and Repository team. He has worked in software development at the IBM Hursley Lab in the UK for over 20 years, the last seven of which have been in the SOA arena. You can contact Brian at brian_hulse@uk.ibm.com.



James Magowan (magowan@uk.ibm.com), Senior IT Specialist, WebSphere Service Registry and Repository, IBM

James MagowanJames Magowan is a Senior IT Specialist on the WebSphere Service Registry and Repository team. He started working on the product during its first release, and is one of the senior developers on the team. He works with product architects on future product directions, and is responsible for promotion and upgrade. You can contact James at magowan@uk.ibm.com.



11 August 2010

Also available in Chinese

Introduction

IBM® WebSphere® Enterprise Service Bus V7.0 (hereafter called WebSphere ESB) gives you multiple ways to select dynamic endpoints within a mediation flow, using SOAP Action/PortType and information stored in WebSphere Service Registry and Repository. Any endpoints you select can be checked against a Service Level Agreement (SLA) in WebSphere Service Registry and Repository. But what you cannot do out of the box, and what this article shows you how to do, is to select endpoints based on Governance Enablement Profile (GEP) objects in WebSphere Service Registry and Repository. The article shows you how to create a service gateway mediation flow that enables endpoint selection based on an active SLA between a particular consumer and an agreed endpoint.

To benefit from this article, you should have some knowledge of WebSphere ESB mediation flows and the WebSphere Service Registry and Repository GEP. This article uses of WebSphere ESB V7.0 and WebSphere Service Registry and Repository V7.0.

If you use WebSphere ESB to integrate your enterprise and WebSphere Service Registry and Repository to model your business using its Governance Enablement Profile (GEP), you will probably want to select dynamic endpoints based on a number of factors modeled in that profile. For example:

  • Whether the Consumer of the endpoint has a valid SLA for the endpoint
  • Whether the particular SLA is active
  • Whether the endpoint is online
  • Whether the endpoint has a desired classification, such as Production or Development

These factors imply a view of your enterprise that more business-centric than IT-centric view. For example, the GEP has a number of key objects, as shown in Figure 1.

  • A Consumer wants to use a particular Service.
  • This relationship is described by the dependency between a Consumer Version and a Service Version.
  • More specifically, this relationship is described by an operational dependency between a Service Level Agreement and a Service Level Definition.
Figure 1. Governance Enablement Profile objects
Governance Enablement Profile objects

Looking at the overall scenario, the consumer makes a request via a specific WebSphere ESB mediation that is acting as a service gateway for all requests requiring validation via the WebSphere Service Registry and Repository GEP. The mediation consults the registry to check on the interrelationships shown, and some of the objects must be in the correct states and have the correct classifications for the endpoint selection to be successful. If all of these checks pass, the mediation knows the final target for the consumer, and routes the request accordingly. How to create this is what the rest of this article is about.

Figure 2. GEP service gateway mediation
GEP service gateway mediation

Strategy

The solution has three basic parts:

Table 1. Solution elements
ElementDescriptionUsage
Service gateway mediationFeatures a custom mediation primitive to contain the Java code described below. This code extracts information relevant to an endpoint lookup, calls WebSphere Service Registry and Repository to extract the target address of a suitable endpoint, and load that into the WebSphere ESB Service Message Object (SMO) so that WebSphere ESB can dynamically route the request.Installed as a WebSphere ESB mediation flow
Named querySince WebSphere Service Registry and Repository's GEP is customizable, it is unwise to have any knowledge of its structure inside the mediation itself. Therefore you should use the WebSphere Service Registry and Repository named query capability, which enables a predefined set of parameters to be passed to a pre-constructed query on WebSphere Service Registry and Repository itself.Installed as a named query on WebSphere Service Registry and Repository
HandlerThe custom mediation requires certain parameters to call the named query relating to the GEP being queried. However, these may not be architected as part of the incoming request message. In fact, in the case of a service gateway pattern, this is very unlikely as it could service many different request types. You can use many patterns of behaviour to overcome this -- this example insert this metadata into a SOAP header, leaving the request message body intact. Consequently, the handler must be activated by the consumer -- this example uses a JAX-RPC handler.Packaged as part of the service consumer
Figure 3. Elements for endpoint selection
Elements for endpoint selection

Named query

Since this is a service gateway pattern, any type of endpoint can be requested. Here is an example that represents the relationship between the key object types in the GEP:

Figure 4. Temperature converter
Temperature converter

This example has two endpoints for the same provider of the temperature converter service, where the internal endpoint is proxied by a gateway mediation whose endpoint is the exposed endpoint.

Figure 5. Temperature converter states
Temperature converter states

As stated earlier, the named query looks for those endpoints that have an active SLA in play for the particular consumer, and checks that the endpoints conform to some required classifications, which in this example could be PRODUCTION and INTERNAL. Additionally, the endpoint is required to be ONLINE. The named query gathers three pieces of information in order to perform this lookup:

Table 2. Query Parameters
ParameterDescription
Consumer identifierA a unique identifier that typifies the consumer; it is a field in the Consumer Version.
Context identifierA unique identifier that typifies the interactions in this relationship; it is a field in the Service Level Agreement.
Endpoint classificationAn additional search constraint associated with the endpoint; it is a classification of the Service Endpoint.

How these identifiers are used and defined is specific to your own installation, but an understanding of how these are used in this named query should inform your naming strategy. You can add additional search criteria if needed for your installation. The WebSphere Service Registry and Repository query is activated in the named query using these parameters:

Figure 6. WebSphere Service Registry and Repository query
WebSphere Service Registry and Repository query
  • %1 -- Consumer identifier
  • %2 -- Context identifier
  • %3 -- Endpoint classification

This query needs to be wrapped in some XML before it can be imported into WebSphere Service Registry and Repository as a named query:

Listing 1. Named Query
<?xml version="1.0" encoding="UTF-8"?>
<query xmlns="http://www.ibm.com/xmlns/prod/serviceregistry/7/0/NamedQueryConfiguration"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation=
  "http://www.ibm.com/xmlns/prod/serviceregistry/7/0/NamedQueryConfiguration 
    ../../schemas/NamedQueryConfiguration.xsd" 
  type="graphQuery">
      <xpath></xpath>
      <depth>0</depth>
</query>

The actual query string needs to be placed inside of the xpath tags. The query depth for our named query SLAEndpontLookup is set to 0, which means that the endpoints are returned with just properties and classifications -- no relationships are populated. This example is concerned only with the endpointAddress, so a query depth of 0 improves performance. Other scenarios may require a non-zero query depth. Save the updated named query file as SLAEndpointLookup.xml and then import it into WebSphere Service Registry and Repository:

  • Change to the Configuration perspective on the WebSphere Service Registry and Repository console.
  • Select Named Queries from the Active Profile menu item.
  • Click Load Named Query Configuration to load the SLAEndpointLookup.xml file, supplying SLAEndpointLookup as the name of the query.
Figure 7. Loading the named query
Loading the named query

The named query described here assumes that the GEP supplied with WebSphere Service Registry and Repository has not been customized in any way. If the GEP has been customized, you will need to modify the query accordingly.

Mediation

The next part of the solution is the WebSphere ESB mediation, which you create using WebSphere Integration Developer.

Service gateway pattern

  1. From the Business Integration perspective select the Open Patterns Explorer and then create a new instance of a Dynamic Service Gateway:
    Figure 8. Dynamic Service Gateway
    Dynamic Service Gateway
  2. In the Configure Pattern Parameters window, for the Routing Option select Write my own logic; for all other values accept the defaults:
    Figure 9. Service Gateway Configuration
    Service Gateway Configuration
  3. This step creates a service gateway mediation flow with a single custom mediation primitive to contain the routing logic:
    Figure 10. Mediation Flow
    Mediation Flow

Update the build path

Add calls to WebSphere Service Registry and Repository in the routing custom mediation primitive using the WebSphere ESB proxy interface. There is a known bug in the build configuration, so you need to add an extra JAR file into the build path for the gateway project. The proxy interface was first available in WebSphere ESB V7.0, and as of WebSphere ESB V7.0.0.2 the bug still exists. A fix should be available in a future release, so consult the documentation if your current release is later than V7.0.0.2 to see if this step is needed.

  1. Right click on the gateway project and select Properties.
  2. Select Java Build Path => Libraries.
  3. Select Add External JARs.
  4. Locate the plugins directory for your WebSphere Process Server/WebSphere ESB installation and select com.ibm.sibx.runtime_6.1.0.jar.

Before updating the Java code in the custom mediation primitive:

  • Change the terminals of the custom mediation primitive
  • Add in user properties for the custom mediation primitive

Modify the custom mediation

  1. Open the custom mediation primitive and select the Properties tab and then the Properties section. Add in a new user property called registryName.
  2. Select the Promotable Properties section and promote this property, which lets you control the registry being used via administration control. To add in a WebSphere Service Registry and Repository definition for this interaction, see the the WebSphere ESB information center. In this example, the name of the registry definition is left blank, so WebSphere ESB uses the default definition:
    Figure 11. User Properties
    User Properties
  3. Now select the Terminal section and change name of the first out terminal to found. Next, add in a new out terminal called notFound:
    Figure 12. Terminals
    Terminals
  4. The notFound terminal is used when no matching is SLA found; the fault conditions for the flow should match your local installation policies for fault handling, but for this example, simply wire the notFound terminal to the Input Response, and the fail terminal to the Input Fault:
    Figure 13. Updated Mediation Flow
    Updated Mediation Flow

Adding the Java code

  1. Select the Java Imports section and add in the following code:
    Listing 2. Java Imports
    import com.ibm.wsspi.sibx.mediation.wsrr.client.ServiceRegistryProxy;
    import com.ibm.wsspi.sibx.mediation.wsrr.client.ServiceRegistryProxyFactory;
    import com.ibm.wsspi.sibx.mediation.wsrr.client.data.ServiceRegistryDataGraphList;
    import com.ibm.wsspi.sibx.mediation.wsrr.client.
        exception.ServiceRegistryProxyException;
    import com.ibm.wsspi.sibx.mediation.wsrr.client.jaxrpc.types.DataGraphType;
    import com.ibm.wsspi.sibx.mediation.wsrr.client.jaxrpc.BaseObject;
    import java.util.List;
  2. Now select the Details section and add in the following code:
    Listing 3. Custom Mediation java code
    String namedQuery = "SLAEndpointLookup"; 
    String consumerID = "";
    String contextID = "";
    String endpointClassification = "";
    if (smo.get("/headers/SOAPHeader[name='GEPGatewayHeader']/value/consumerID")!=null) {
      consumerID = smo.getString(
        "/headers/SOAPHeader[name='GEPGatewayHeader']/value/consumerID");
    }
    if (smo.get("/headers/SOAPHeader[name='GEPGatewayHeader']/value/contextID")!=null) {
      contextID = smo.getString(
        "/headers/SOAPHeader[name='GEPGatewayHeader']/value/contextID");
    }
    if (smo.get("/headers/SOAPHeader[name=
          'GEPGatewayHeader']/value/endpointClassification")!=null) {  
      endpointClassification = smo.getString(
        "/headers/SOAPHeader[name='GEPGatewayHeader']/value/endpointClassification");
    }  
    boolean isFound = false; 
    try { 
      ServiceRegistryProxy srProxy = null; 
      if ((registryName == null) || (registryName == "")) {
        srProxy = 
        ServiceRegistryProxyFactory.getInstance().getDefaultServiceRegistryProxy();
      } else {   
        srProxy = 
        ServiceRegistryProxyFactory.getInstance().getServiceRegistryProxy(registryName);
      }    
      String params[] = new String[3];
      params[0] = consumerID;
      params[1] = contextID;
      params[2] = endpointClassification;
      ServiceRegistryDataGraphList srList = srProxy.namedQuery(namedQuery, params);
      if (srList.getDataGraphs() != null) {
        isFound = true;    
        List<DataGraphType> dgList = srList.getDataGraphs();  
        if (dgList.size() > 0) {
          DataGraphType dg = dgList.get(0);    
          BaseObject[] topLevelObjects = dg.getWSRR().getArtefacts();    
          if (topLevelObjects.length > 0) {
            BaseObject base = topLevelObjects[0];
            // The name of the CapabilityVersion is the endpoint we need
            String endpointAddress = base.getName();
            smo.setString("headers/SMOHeader/Target/address", endpointAddress);        
            isFound = true;
          }     
        }
      } 
    } catch(ServiceRegistryProxyException e) {
          e.printStackTrace();
    }
    if (isFound) { 
      found.fire(smo);
    } else {
      notFound.fire(smo);
    }

The code performs the following functions:

  1. Extracts the three parameters for the named query from specific locations in the SOAP Header. This information can be transmitted and extracted in whatever method suits your enterprise; in this example, the location matches what is set up with the Handler described in the next section.
  2. Uses these three parameters to call the named query SLAEndpointLookup. These are loaded into the call in the same order as that expected by the named query you have already loaded into WebSphere Service Registry and Repository. The name of the query is the same as the one loaded into WebSphere Service Registry and Repository in the previous section.
  3. Checks the return from the named query. If an object is returned, it assumes it is a service endpoint whose name is the target endpoint required.
  4. If the target has been found, it is loaded into the correct part of the SMO to activate the dynamic routing, and the found terminal is fired.
  5. If the named query does not return an object, the notFound terminal is fired.

Adding the schema for the SOAP headers

  1. In order for the service gateway to parse the headers in the request message, the schema for those headers must be available at runtime, and you must define the business object. Under the gateway project in the Business Perspective, select the Data Types section, then right-click and select New => Business Object. You must create a new business object with the correct namespace and parameters to represent the SOAP header:
    Figure 14. SOAP header business object
    SOAP header business object

The mediation flow is now complete and can be deployed onto a runtime WebSphere Process Server or WebSphere ESB system.

Handler

The final part of the picture is the piece of code that adds in the SOAP header at the client/consumer site. In this example, it is implemented as a JAX-RPC handler, but as stated earlier, it can be done in whatever way suits your enterprise installation.

Listing 4. JAX-RPC handler
package com.ibm.sample;

import javax.xml.namespace.QName;
import javax.xml.rpc.handler.GenericHandler;
import javax.xml.rpc.handler.HandlerInfo;
import javax.xml.rpc.handler.MessageContext;
import javax.xml.rpc.handler.soap.SOAPMessageContext;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPFactory;
import javax.xml.soap.SOAPHeader;

public class GEPGatewayRPCHandler extends GenericHandler {
  public static final String PROP_CONSUMER_ID = 
     "com.ibm.wsrr.ws.client.jaxrpc.consumerid";
  public static final String PROP_CONTEXT_ID = 
     "com.ibm.wsrr.ws.client.jaxrpc.contextid";
  public static final String PROP_ENDPOINT_CLASSIFICATION = 
     "com.ibm.wsrr.ws.client.jaxrpc.endpointclassification";

  private String consumerID;
  private String contextID;
  private String endpointClassification;

  public void init(HandlerInfo hi) {
    consumerID = 
      (String)hi.getHandlerConfig().get(PROP_CONSUMER_ID);
    contextID = 
      (String)hi.getHandlerConfig().get(PROP_CONTEXT_ID);
    endpointClassification = 
      (String)hi.getHandlerConfig().get(PROP_ENDPOINT_CLASSIFICATION);
  }

  public boolean handleRequest(MessageContext messagecontext) {
    try {
      if (messagecontext instanceof SOAPMessageContext) {
        SOAPMessageContext smc = (SOAPMessageContext)messagecontext;
        SOAPBody body = smc.getMessage().getSOAPBody();
        SOAPEnvelope envelope = smc.getMessage().getSOAPPart().getEnvelope(); 
        SOAPHeader header = envelope.getHeader(); 
        SOAPFactory sFactory = SOAPFactory.newInstance();

        SOAPElement headerElement = 
          sFactory.createElement("GEPGatewayHeader", 
            "gep", 
            "http://com.ibm.sample.gepgateway");	

        SOAPElement contextElement = 
          sFactory.createElement("contextID", 
            "gep", 
            "http://com.ibm.sample.gepgateway");
        contextElement.addTextNode(contextID);
        headerElement.addChildElement(contextElement); 
        
        SOAPElement consumerElement = 
          sFactory.createElement("consumerID",
            "gep", 
            "http://com.ibm.sample.gepgateway");
        consumerElement.addTextNode(consumerID);
        headerElement.addChildElement(consumerElement);
        
        SOAPElement endpointClassificationElement = 
          sFactory.createElement("endpointClassification",
            "gep", 
            "http://com.ibm.sample.gepgateway");
endpointClassificationElement.addTextNode(endpointClassification);
headerElement.addChildElement(endpointClassificationElement);

header.addChildElement(headerElement); 
}
    } catch (SOAPException soapEx) {
      throw new RuntimeException(soapEx.toString());
    }
    return true;
  }
}

The code performs the following functions:

  1. Initialises the handler with the values for the three parameters to be used in the named query called from the mediation. In a JAX-RPC handler, these are supplied as part of the deployment file, and can be tied specifically to the particular client/consumer. The XML for this example is shown below.
  2. Creates an element in the SOAP Header that represents the business object defined previously in the mediation flow. The namespace and name should match the previously defined business object, which in this case are http://com.ibm.sample.gepgateway and GEPGatewayHeader.
  3. Populates this element with three text elements containing the three named parameters: consumerID, contextID, and endpointClassification.
Listing 5. JAX-RPC Handler configuration
<handler>
  <display-name>GEPGatewayHandler</display-name>
  <handler-name>GEPGatewayHandler</handler-name>
  <handler-class>com.ibm.sample.GEPGatewayHandler</handler-class>
  <init-param>
    <param-name>com.ibm.wsrr.ws.client.jaxrpc.consumerid</param-name>
    <param-value>MyConsumerID</param-value>
  </init-param>
  <init-param>
    <param-name>com.ibm.wsrr.ws.client.jaxrpc.contextid</param-name>
    <param-value>MyContextID</param-value>
  </init-param>
  <init-param>
    <param-name>com.ibm.wsrr.ws.client.jaxrpc.endpointclassification</param-name>
    <param-value>MyEndpointClassification</param-value>
  </init-param>
</handler>

The three major elements are now in play: the handler at the client/consumer site, which populates a SOAP Header, so that when the request message arrives at the WebSphere ESB service gateway, the parameters can be extracted by the routing mediation primitive, and used to call a named query on WebSphere Service Registry and Repository to extract the relevant service endpoint and enable WebSphere ESB to dynamically route to that endpoint. Looking at a WebSphere ESB trace with this configuration in play, you can see the SOAP Header that will be interpreted by the custom mediation code:

Listing 6. SOAP header in WebSphere ESB trace
<SOAPHeader>
  <nameSpace>http://com.ibm.sample.gepgateway</nameSpace>
  <name>GEPGatewayHeader</name>
  <prefix>gep</prefix>
  <value xsi:type="com:GEPGatewayHeader">
    <consumerID>MyConsumerID</consumerID>
    <contextID>MyContextID</contextID>
    <endpointClassification>MyEndpointClassificationID</endpointClassification>
  </value>
</SOAPHeader>

Conclusion

This article has shown you how to create a service gateway in WebSphere ESB that extracts an endpoint to dynamically route to based on a query of GEP objects in WebSphere Service Registry and Repository. The solution consists of three major elements:

  • A WebSphere Service Registry and Repository named query
  • A WebSphere ESB custom mediation
  • A JAX-RPC handler

The article used a simple temperature conversion Web service accessed via the WebSphere ESB service gateway, and showed how the SOAP header was populated, and then interpreted by a WebSphere ESB custom mediation so that WebSphere ESB could route to the correct endpoint for that service, based on pre-selected GEP criteria.

Resources

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into WebSphere on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=WebSphere
ArticleID=507183
ArticleTitle=WebSphere ESB endpoint selection based on the WebSphere Service Registry and Repository Governance Enablement Profile
publish-date=08112010