Contents


Integrating IBM Integration Bus with WebSphere Service Registry and Repository

Part 8: SLA checking using the HTTPRequest node

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.

When a service is offered for reuse within an organization, the provider of the service typically provides a number of artifacts that consumers of the service can use to implement client applications or services. These artifacts usually include one or more WSDL or XML schema documents. While these artifacts provide the information required by the developers of a service consumer, they do not provide any information regarding the non-functional, or quality of service (QoS), characteristics that the service consumer can expect from the service.

The Governance Enablement Profile (GEP) provided with IBM WebSphere Service Registry and Repository (hereafter called WSRR) is a complete WSRR configuration profile that contains all of the business models, life cycles, ontologies, and governance policies, that you need to quickly get up and running with Service Oriented Architecture (SOA) governance. It enables a service provider to capture the QoS characteristics for a service using Service Level Definitions (SLDs). It also enables the agreements that exist between service providers and service consumers to be represented using Service Level Agreements (SLAs).

This article describes a sample message flow that enforces SLAs defined in WSRR at runtime, to ensure that the service consumer is authorised to invoke the target service. While it achieves the same results as the message flow described in part 5 of this series, Performing SLA checks at runtime and registry lookup scenarios, the message flow described in this article is implemented very differently. It uses of an HTTP Request node to invoke the WSRR REST API to retrieve the required metadata.

SLA Check Business Scenario

The sample flow that is described within this article focuses on the SLA checking scenario that was described in part 1 of this series, Scenarios and Configuration, as follows:

  • Business Problem

    You have several services deployed in your SOA and they are all registered in WSRR. You have not, however, registered the consumers of those services in WSRR. As a consequence you do not know which service consumers might be invoking each service at any given point in time. You want to ensure that all of the service consumers in your SOA are registered in WSRR and that only consumers who are authorized to invoke a target service are allowed to do so.

  • Solution

    WSRR allows you to register the service consumers in your SOA, as well as service providers. It also enables the agreements, or contracts, that exist between service providers and service consumers to be represented using Service Level Agreements (SLAs). A message flow can retrieve this information from WSRR dynamically at runtime and use it to determine whether a service consumer is authorized to invoke a target service. If the service consumer is authorized to invoke the target service it can forward the request on to the agreed endpoint. If the service consumer is not authorized to invoke the target service a suitable error can be returned.

  • Benefits

    This approach allows you to control which service consumers are invoking the actual back end services, enabling you to enforce a level of runtime governance in your SOA. An added benefit is that, after the service consumers and providers are registered in WSRR, you can visualize these relationships in the Service Registry Dashboard user interface and use it to assess the impact of any changes that you are planning to make to your service.

Modeling Service Providers and Consumers

The business models contained within the GEP define all of the object types that you need to represent service providers, service consumers, and the agreements between them. For more information on how these concepts are modeled, see the "Modeling Service Providers" and "Modeling Service Consumers" sections in Part 5. Familiarize yourself with these concepts so that you can fully understand the implementation of this message flow.

HTTP Request Node Overview

IBM Integration Toolkit provides support for interacting with REST services by providing the HTTP Request node. This node allows you to use all or part of the input message as the request that is sent to the service. It can also be used to create an output message based on the input message, augmented by the contents of the service response, before propagating the message to subsequent nodes in the flow.

The node can be configured to construct either an HTTP or HTTPS request from the specified parts of the input message and send this request to the target service. It can then parse the response from the service and inject the content into the output tree for propagation to other nodes in the flow.

Node Terminals

The terminals for the HTTP Request node are shown in the following figure.

HTTP Request node terminals
HTTP Request node terminals

The terminals are described in the following table.

Terminals on the HTTP Request node
TerminalDescription
InThe input terminal that accepts a message for processing by the node.
FailureThe output terminal to which the message is routed if a failure is detected during processing in the node.
OutThe output terminal to which the message is routed if it represents successful completion of the service request, and if further processing is required within this message flow.
ErrorThe output terminal to which messages that include an HTTP status code that is not in the range 200 through 299, including redirection codes (3xx) if you have not set the property Follow HTTP(s) redirection property, is routed.

Node properties

The HTTP Request node provides an extensive set of properties that can be configured using the Properties editor in IBM Integration Toolkit. Many of these properties have not been modified by the message flow described in this article. For brevity, only the properties of the HTTP Request node that have been modified by the message flow are described in the following table.

HTTP Request Node Properties
PropertyEditor TabDescription
Web Service URLBasicThe URL for the target service. This must be specified in the form http://hostname[:port]/[path] where:
  • http://hostname must be specified.
  • port has a default of 80. If you specify a value, you must include the : before the port number.
  • path has a default of /. If you specify a value, you must include the / before the path.

The value of the Web Service URL property can be specified programmatically using a compute node earlier in the message flow to insert elements into the input message or the local environment tree. A value specified programmatically overrides the value specified on the node. The locations that can be used to override the value specified on the node are:

  • X-Original-HTTP-URL in the HTTP Request header in the input message.
  • Destination.HTTP.RequestURL in the local environment tree.

The locations shown are listed in order of priority. That is, if a value is specified for the X-Original-HTTP-URL field, this overrides any value specified in the Destination.HTTP.RequestURL field.

If the specified URL starts with http://, the request node makes an HTTP request to the specified URL. If the specified URL starts with https://, the request node makes an HTTP over SSL (HTTPS) request to the specified URL, using the parameters that are specified on the SSL tab for the node.

HTTP methodHTTP SettingsThe HTTP method that the node will use when making requests. Valid values are POST, GET, PUT, DELETE, and HEAD. By default, the HTTP Request node uses the HTTP POST method when it connects to the remote web server.
HTTP VersionHTTP SettingsSpecifies the HTTP version that the node will use when making requests. Valid values are 1.0 and 1.1.
Use CompressionHTTP SettingsThis property controls whether the content of the HTTP request is compressed. Valid values are none, gzip, zlib (deflate), and deflate. If the request is compressed, the Content-Encoding header is set to indicate that the content is compressed.
ProtocolSSL

This property specifies the protocol to use when making an HTTPS request. Both ends of an SSL connection must agree on the protocol to use. Therefore, the selected protocol must be one that the remote server can accept. The following options are available:

  • SSL. This option is the default. This option tries to connect using the SSLv3 protocol first, but enables the handshake to fall back to the SSLv2 protocol where the SSLv2 protocol is supported by the underlying JSSE provider.
  • SSLv3. This option tries to connect with the SSLv3 protocol only. Fallback to SSLv2 is not possible.
  • TLS. This option tries to connect with the TLS protocol only. Fallback to SSLv3 or SSLv2 is not possible.
Message DomainResponse Message Parsing

Specifies the name of the parser that will be used to parse the response. If the field is blank then the default is BLOB. The following options are available:

  • DFDL
  • XMLNSC
  • JSON
  • BLOB
  • MIME
  • MRM
  • XMLNS
Replace input message with web-service responseAdvancedIf you select this check box, the web service response message is used as the output message for the node, replacing the original input message. If you clear this check box, you must specify a value for the Response message location in tree property.
Response message location in treeAdvancedSpecifies the location in which the parsed elements from the web service response bit stream are stored. This property takes the form of an ESQL field reference.
Accept compressed responses by defaultAdvancedThis property indicates whether the request node handles compressed responses by default. If the request header does not contain an Accept-Encoding header and this option is selected, the node sets the Accept-Encoding header to "gzip, deflate", and any compressed response that is received is decompressed by the node.

Accessing a secure service

If the service being accessed by the HTTP Request node requires the client to authenticate, a security profile must be associated with the node that allows credentials to be propagated to the target service. IBM Integration Bus provides a profile that is pre-configured to allow credential propagation and is specifically intended for use by request nodes. It is called the Default Propagation security profile. To configure this security profile on a node in a message flow you must use Broker Archive Editor in the IBM Integration Toolkit. This security profile has already been configured on all of the HTTP Request nodes contained within the sample flows provided with this article series. To verify this, perform the following steps:

  1. Open IBM Integration Toolkit.
  2. Open the Integration Development perspective.
  3. In the Application Development view, expand BARs and double click on WSRRIntegrationDemos.bar, as shown below:
    Opening the BAR file
    Opening the BAR file
    Opening the BAR file
  4. The file will be opened in the Broker Archive Editor. Select the Manage tab at the bottom of the editor.
  5. Expand WSRRIntegrationDemos => HTTPNode_SLACheck_GlobalCache.msgflow -> HTTPNode_SLACheck_GlobalCache.
  6. From the list of nodes in the flow select WSRR REST Query , as shown below:
    Selecting the node
    Selecting the node
    Selecting the node
  7. The properties for the node will be displayed in the Properties editor. The Security Profile property is towards the bottom of the list of properties on the Configure tab, as shown below:
    Security Profile property
    Security Profile property
    Security Profile property

IBM Integration Bus global cache

One of the benefits of using the Endpoint Lookup and Registry Lookup nodes to interact with WSRR is that IBM Integration Bus provides a cache for these nodes that is used to store the metadata that is retrieved for a configurable period of time. This cache was described in detail in Part 7: Configuring the WSRR Cache in IBM Integration Bus. However, because the message flow described in this article is not making use of the WSRR nodes, another caching mechanism must to be used to ensure that the performance of the flow is not impacted by querying WSRR for every request that is processed.

Fortunately, IBM Integration Bus provides another caching mechanism that the message flow can use to store the metadata retrieved from WSRR. The Global Cache was first introduced into WMB V8.0.0.1 and was enhanced in IBM Integration Bus V9. The global cache is implemented using embedded WebSphere eXtreme Scale (WebSphere XS) technology. By hosting WebSphere XS components, the JVMs embedded within IBM Integration Bus execution groups can collaborate to provide a cache.

By default, the global cache is turned off, and the cache policy is set to disabled. To use the global cache, a suitable cache policy must be specified at the broker- level. The global cache has a default single-broker topology that can be used immediately without any configuration.

Interacting with the Global Cache

IBM Integration Bus provides the MbGlobalMap object to enable message flows to access the Global Cache. This is a Java object and so must be used within a Java Compute node within your flows. This object handles client connectivity to the global cache, and provides a number of methods for working with maps in the cache. The methods available are similar to those you would find on regular Java maps. Individual MbGlobalMap objects are created by using a static getter on the MbGlobalMap class, which acts as a factory mechanism. You can create MbGlobalMap objects anonymously (which uses a predefined default map name under the covers in WebSphere XS), or with a map name of your choice. The code shown in the following listing shows an MbGlobalMap object being created with a name of WSRREndpointCache.

Enabling the Global Cache
MbGlobalMap endpointCache = MbGlobalMap.getGlobalMap("WSRREndpointCache");

Removing data from the Global Cache

When you get an MbGlobalMap object, you can also specify how long the data remains in the global cache before it is removed automatically. This time is known as the time to live and is counted from when that map entry is last updated. The value applies to all cache entries that are created by using that MbGlobalMap object in that instance of the message flow. By default, the time to live is set to zero so that the data is never removed. To set a specific time to live, you need to create a session policy, which you can reference from the MbGlobalMap object. The code in the following listing shows how to create an MbGlobalMap object with a time to live session policy of 30 seconds.

Enabling the Global Cache
MbGlobalMapSessionPolicy sessionPolicy = new MbGlobalMapSessionPolicy(30);
MbGlobalMap endpointCache = MbGlobalMap.getGlobalMap("WSRREndpointCache", sessionPolicy);

WSRR Named Queries

Named queries in WSRR provide a powerful mechanism that allow you create pre-defined queries that can be invoked using any of the WSRR APIs. They are defined in configuration files that are maintained as part of a WSRR configuration profile. They can therefore be created, modified, and deleted by a WSRR administrator using the WSRR Studio tooling provided with WSRR, the Web UI or administration scripts.

When defining a named query, the name that you specify for the configuration file is used to identify the query. This is the name that is used by a WSRR client to specify the named query that they want to invoke. The content of the named query configuration file defines:

  • The type of the query, which is either propertyQuery or graphQuery.
  • The XPath expression that will be executed against WSRR when the query is invoked. This XPath expression can include definitions of parameters that a client must pass when invoking the named query. The parameters are substituted at run time on the server before the query is executed.
  • The depth of the query, if the type specified is graphQuery. This must be 0, 1 or -1.
  • The list of properties to return, if the type specified is property

The true power of a named query is that encapsulates all of the information that is required in the configuration file. The WSRR client only needs to know the name of the named query that they want to invoke and what parameters they need to pass. The complexities of the underlying model, and the XPath expression used to query against the model, are hidden from the WSRR client. Named queries also provide a level of protection against changes to the model because it allows the XPath expression in the configuration file to be modified to reflect the changes without impacting the client.

The SLAEndpointLookup Named Query

The SLAEndpointLookup named query was introduced into the GEP in version 7.5 of WSRR. It defines an XPath expression that performs all of the checks that are required to ensure that a service consumer is authorized to invoke a target service. Recall that in the section SLA Check node in Part 5, all of these checks needed to be performed programmatically in a Java Compute node. The SLAEndpointLookup named query can capture all these checks in a single XPath expression because it is free to define a complex expression that traverses multiple objects and applies predicates at various stages in the query. Neither the Endpoint Lookup or Registry Lookup nodes in IBM Integration Bus allow you to control the XPath expressions that are generated.

As mentioned above, the XPath expression for the SLAEndpointLookup named query is complex and it is not described in detail here. But again, this is the benefit of using named queries in WSRR. A WSRR client does not need to understand the complexity of the named query configuration. It just needs to understand the parameters that it needs to pass and the results that should be returned. In the case of the SLAEndpointLookup, the parameters that are required are:

  1. The consumer identifier for the service consumer
  2. The context identifier for the SLA
  3. The OWL URI of the environment classification for the endpoint

The objects that are returned are the service endpoints defined on the SLD of the target service provider.

WSRR REST API

WSRR provides a number of APIs that can be used to interact with the service metadata artifacts registered with the product, as follows:

  • Enterprise JavaBean (EJB) API
  • Web Service API
  • REST API

All of these APIs support publishing (creating and updating) service artifacts and the metadata that is associated with those artifacts, retrieving service metadata artifacts, deleting the artifacts and their metadata, and querying the content of WSRR. Basic create, retrieve, update, and delete operations, as well as governance operations and a flexible query facility based on XPath, are provided through these APIs.

The WSRR REST API allows for lightweight clients, that do not have support for EJB and web services, to perform actions on content and metadata by using HTTP requests. WSRR clients are also able to use the REST API to invoke named queries that have been configured within WSRR. For example, the URL shown in the following listing can be pasted into a web browser to invoke the SLAEndpointLookup named query, passing the three required parameters as URL query parameters. Parameters are split over multiple lines for clarity and that the OWL URI for the p3 parameter would need to be URL encoded.

Example named query URL
https://localhost:9443/WSRR/8.0/Metadata/XML/Query/SLAEndpointLookup?
  p1=CalculatorApplication&
  p2=CTX_1&
  p3=http://www.ibm.com/xmlns/prod/serviceregistry/6/1/GovernanceProfileTaxonomy#Staging

Message Flow Description

The SLA check message flow (as shown in the following figure) uses the consumer identifier and context identifier specified in the service request to determine whether the service consumer is authorized to invoke the target service. To do this it invokes the SLAEndpointLookup named query to retrieve the list of endpoints that the service consumer is authorized to use to invoke the service. If one or more endpoints are returned, it selects the first endpoint and forwards the request on to it. If no endpoints are returned, it responds to the client with a suitable error. The sections below describe each of the nodes in this message flow in detail, along with any settings or code used by each node to perform the SLA checking.

The SLA Check Message Flow
The SLA Check Message Flow
The SLA Check Message Flow

Service Request node

The flow starts with the Service Request SOAP Input node. The important point to note about this node is that it 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 the following figure. 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 after the WSDL file is 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/slacheck5. 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 SLA check flow using the out terminal.

Exposed WSDL Interface
Exposed WSDL Interface
Exposed WSDL Interface

Check SOAP Headers node

The Check SOAP Headers node is an instance of a Java Compute node. This node processes the service requests that are passed to it by the Service Request node, extracting the consumer identifier and context identifier properties from the SOAP header. It then checks whether the values extracted are valid. The code in the following listing shows these tasks being performed.

Extracting the consumer identifier and context identifier
MbMessage inMessage = inAssembly.getMessage();
MbElement rootElement = inMessage.getRootElement();

MbElement consumerIdElement =
    rootElement.getFirstElementByPath("/SOAP/Header/MathHeader/consumerID");

MbElement contextIdElement =
    rootElement.getFirstElementByPath("/SOAP/Header/MathHeader/contextID");
    
if (  consumerIdElement != null && consumerIdElement.getValue() != null
   && contextIdElement != null &&contextIdElement.getValue() != null)
   {
        ...
}

If a valid value for either of these identifiers has not been specified in the service request, the Check SOAP Headers node generates a SOAP fault and passes the message to the failure terminal. This terminal is wired directly to the SOAP Reply node, which passes the SOAP fault back to the client. This check is important and is performed at the very beginning of the message flow because the flow needs to be able to identify both the service consumer and the relevant SLA that applies to the service request.

When this initial check is passed, the Check SOAP Headers node passes the message to the out terminal, which is wired to the Check WSRR Cache node.

Check WSRR Cache node

The Check WSRR Cache node is another instance of a Java Compute node. As its name suggests, this node checks the cache of endpoints that is being maintained in the IBM Integration Bus global cache to see if any endpoints for this combination of consumer identifier and context identifier have been retrieved before. Because both the consumer identifier and context identifier should be unique, the key into the cache is generated by simply concatenating the two values. The following listing shows these tasks being performed.

Checking the IBM Integration Bus global cache
WSRRCache wsrrCache = WSRRCache.getInstance();
            
String consumerId = getConsumerId(inAssembly);
String contextId = getContextId(inAssembly);
String cacheId = consumerId + contextId;
String addressUrl = wsrrCache.getEndpoint(cacheId);

if (addressUrl != null && !addressUrl.isEmpty()) {
    ...
} else {
    ...
}

A utility class, WSRRCache, is used to maintain the cache of endpoints in the IBM Integration Bus global cache. The following listing shows how the cache is accessed to attempt to retrieve the endpoint. It is also important to note that the time to live policy for entries in the cache is 30 seconds.

Checking the IBM Integration Bus global cache
MbGlobalMapSessionPolicy sessionPolicy = new MbGlobalMapSessionPolicy(30);
endpointCache = MbGlobalMap.getGlobalMap("WSRREndpointCache", sessionPolicy);
...
public String getEndpoint(String cacheId) {
    String endpoint = null;
        
    try {
        endpoint = (String)endpointCache.get(cacheId);
    } catch (MbException e) {
        e.printStackTrace();
    }

    return endpoint;
}

If an endpoint with the specified id was found in the cache, the message flow simply forwards the service request onto the target service without performing any queries against WSRR. To do this, the SLA check message flow uses a SOAP Request node called Forward Request. To programmatically override the Web Service URL that has been configured on the Forward Request node, the Check WSRR Cache node needs to insert the endpoint address into the Destination.SOAP.Request.Transport.HTTP.WebServiceURL field of the local environment tree. The following listing shows the code required to perform this task. The Check WSRR Cache node then passes the message to the out terminal, which is wired to the Forward Request node.

Programmatically specifying the web service URL
MbMessage environment = new MbMessage(inAssembly.getLocalEnvironment());
MbElement environmentRoot = environment.getRootElement();

environmentRoot.evaluateXPath(
    "?Destination/?SOAP/?Request/?Transport/?HTTP/?WebServiceURL[set-value('"
    + addressUrl + "')]");

outAssembly = new MbMessageAssembly( inAssembly
                                   , environment
                                   , inAssembly.getExceptionList()
                                   , inAssembly.getMessage()
                                   );
outTerminal = getOutputTerminal("out");

If no endpoint with the specified id was found in the cache, the message flow needs to invoke the SLAEndpointLookup named query in WSRR, passing the consumer identifier and context identifier as parameters, along with the OWL URI of the environment for the target endpoint. To do this, it must construct the URL that will be used to invoke the named query and insert it into the Destination.HTTP.RequestURL field of the local environment tree. It determines the scheme, host and port to use for the URL by programmatically querying the endpointAddress property from the DefaultWSRR configurable service object in IBM Integration Bus and extracting the values. This task is performed by the WSRRConfigurationUtils utility class. It must also insert the parameters for the SLAEndpointLookup named query in to the relevant fields of the local environment tree. The following listing shows the required code to perform these tasks.

Programmatically specifying the REST URL
private static final String NAMED_QUERY_SLAENDPOINTLOOKUP =
    "/WSRR/8.0/Metadata/XML/Query/SLAEndpointLookup";
private static final String OWL_URL_STAGING =
    "http://www.ibm.com/xmlns/prod/serviceregistry/6/1/GovernanceProfileTaxonomy#Staging";
        
WSRRConfigurationUtils wsrrConfig = WSRRConfigurationUtils.getInstance(); 

URI wsrrUrl = new URI( wsrrConfig.getScheme()
                     , null
                     , wsrrConfig.getWsrrHost()
                     , wsrrConfig.getWsrrPort()
                     , NAMED_QUERY_SLAENDPOINTLOOKUP
                     , null
                     , null);
environmentRoot.evaluateXPath("?Destination/?HTTP/?RequestURL[set-value('"
    + wsrrUrl.toString() + "')]");
                
environmentRoot.evaluateXPath("?Destination/?HTTP/?QueryString/?p1[set-value('"
    + getConsumerId(inAssembly) + "')]");
environmentRoot.evaluateXPath("?Destination/?HTTP/?QueryString/?p2[set-value('"
    + getContextId(inAssembly) + "')]");
environmentRoot.evaluateXPath("?Destination/?HTTP/?QueryString/?p3[set-value('"
    + OWL_URL_STAGING + "')]");

Before the Check WSRR Cache node can forward the request onto an HTTP Request node, it needs to perform several other tasks.

  1. The downstream HTTP Request node has been configured to place the response message in a specific location in the local environment tree. The Check WSRR Cache node needs to create the parent entry in the local environment tree.
  2. The HTTP Request node does not use the configuration on the BrokerRegistry object to determine which keystore and truststore to use when sending the HTTP request. The location of the keystore and truststore, along with their passwords, must be configured programmatically in the local environment before the HTTP Request node is invoked in the flow. The WSRRConfigurationUtils utility class is used to retrieve this information from a user defined configurable service called WSRRREST.
  3. The credentials that need to be propagated by the HTTP Request node to WSRR when invoking the REST API need to be defined programmatically on the output message. Again, the WSRRConfigurationUtils utility class is used to retrieve this information.

The following listing shows the code required to perform these tasks. The Check WSRR Cache node then passes the message to the alternate terminal, which is wired to the WSRR REST Query node.

Configuring additional properties
// Create a folder in the local environment to hold the response from the REST query
environmentRoot.createElementAsLastChild(MbXMLNSC.PARSER_NAME);

// Specify the location of the keystore and truststore used by the HTTP Request node
environmentRoot.evaluateXPath("?Destination/?HTTP/?KeystoreFile[set-value('"
    + wsrrConfig.getKeystoreFile() + "')]");
environmentRoot.evaluateXPath("?Destination/?HTTP/?KeystorePassword[set-value('"
    + wsrrConfig.getKeystorePassword() + "')]");
environmentRoot.evaluateXPath("?Destination/?HTTP/?TruststoreFile[set-value('"
    + wsrrConfig.getTruststoreFile() + "')]");
environmentRoot.evaluateXPath("?Destination/?HTTP/?TruststorePassword[set-value('"
    + wsrrConfig.getKeystorePassword() + "')]");

// Create the message assembly to return
MbMessage outMessage = new MbMessage(inMessage);
MbElement rootElement = outMessage.getRootElement();
rootElement.evaluateXPath("?Properties/?IdentitySourceType[set-value("
    + "'usernameAndPassword')]");
rootElement.evaluateXPath("?Properties/?IdentitySourceToken[set-value('"
    + wsrrConfig.getUserId() + "')]");
rootElement.evaluateXPath("?Properties/?IdentitySourcePassword[set-value('"
    + wsrrConfig.getPassword() + "')]");
outAssembly = new MbMessageAssembly( inAssembly
                                   , environment
                                   , inAssembly.getExceptionList()
                                   , outMessage
                                   );
outTerminal = getOutputTerminal("alternate");

WSRR REST Query node

The WSRR REST Query node is instance of an HTTP Request node. Its behaviour is determined by a combination of the entries that were programmatically created by the previous node and the properties defined on the node itself. The following table shows the values of the properties that are specified on the WSRR REST Query node.

WSRR REST Query Node Properties
PropertyValue
HTTP methodGET
HTTP Version1.1
Use Compressiongzip
ProtocolSSL
Message DomainXMLNSC
Replace input message with web-service responseUnchecked
Response message location in treeInputLocalEnvironment.XMLNSC.WSRR.REST.Response
Accept compressed responses by defaultChecked

The WSRR REST Query node will invoke the SLAEndpointLookup named query in WSRR and write the results to the location configured on the node. The out terminal is wired to the Cache REST Results node.

Cache REST Results node

The Cache REST Results node processes the results returned by the WSRR REST Query node. It attempts to extract the list of endpoints returned by the query from the local environment tree and checks to see if any endpoints were returned. The following listing shows the code required to perform this task. If no endpoints were returned, the node generates a SOAP fault and passes the message to the failure terminal. This terminal is wired directly to the SOAP Reply node, which passes the SOAP fault back to the client.

Checking the REST results
MbElement rootElement = inAssembly.getLocalEnvironment().getRootElement();
MbElement wsrrElement = rootElement.getFirstElementByPath("XMLNSC/WSRR");
List<MbElement> availableEndpoints =
    (List <MbElement>)wsrrElement.evaluateXPath("REST/Response/resources/resource");

if (availableEndpoints != null && !availableEndpoints.isEmpty()) {
    ...
} else {
    ...
}

If the results from the REST query against WSRR returned some endpoints, the Cache REST Results node simply selects the first one and caches it in the IBM Integration Bus global cache, generating the key by concatenating the consumer identifier and context identifier. After the endpoint is stored in the cache, Cache REST Results node forwards the service request onto the target service by setting the relevant value in the local environment tree and propagating the message to the Forward Request node. The following listing shows the code required to perform this task.

Caching the endpoint
MbElement endpoint = availableEndpoints.get(0);
String addressUrl = (String)endpoint.evaluateXPath(
    "string(properties/property[@name='name']/attribute::value)");      

if (addressUrl != null) {

    // Cache the results
    String consumerId = getConsumerId(inAssembly);
    String contextId = getContextId(inAssembly);
    String cacheId = consumerId + contextId;
    wsrrCache.addEndpoint(cacheId, addressUrl);
                    
    MbMessage environment = new MbMessage(inAssembly.getLocalEnvironment());
    MbElement environmentRoot = environment.getRootElement();
                    
    environmentRoot.evaluateXPath(
        "?Destination/?SOAP/?Request/?Transport/?HTTP/?WebServiceURL[set-value('"
        + addressUrl + "')]");

    // Create the message assembly to return
    outAssembly = new MbMessageAssembly( inAssembly
                                       , environment
                                       , inAssembly.getExceptionList()
                                       , inAssembly.getMessage()
                                       );
    outputTerminal = getOutputTerminal("out");
}

Forward Request and SOAP Reply nodes

The Forward Request node is responsible for calling the target service, in this case Version 1.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 programmatically overwritten at runtime by the Java Compute nodes in the flow. 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 Forward Request node is wired directly to the SOAP Reply node using all its terminals; out, fault and failure.

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 response from the actual target service. If an error occurs, the response will be a SOAP fault that was generated by one of the Java Compute nodes in the flow, or by the target service itself.

Additional Configuration

Before testing the SLA check message flow some additional configuration steps need to be performed. These are described in the sections that follow:

Enabling the IBM Integration Bus Global Cache

The message flow described in this requires the global cache to be enabled to work correctly. To enable the global cache on the broker instance that the flow is deployed to, use the mqsichangeproperties command, as shown in the following listing. Restart the broker for the changes to take effect.

Enabling the Global Cache
mqsichangeproperties <BROKER_NAME>
                     -b cachemanager
                     -o CacheManager
                     -n policy
                     -v default

Where:

  • <BROKER_NAME> is the name of the broker (Integration Node).

Creating the WSRRREST configurable service

Various properties need to be specified programmatically for the HTTP Request. The values for these properties could have been hard coded into the flow. A better solution is to create a user defined configurable service in IBM Integration Bus and retrieve the properties dynamically at run time. This is the approach taken within this message flow. To create the configurable service, use the mqsicreateconfigurableservice command as shown in the following listing:

Creating the WSRRREST configurable service
mqsicreateconfigurableservice
<BROKER_NAME> -c UserDefined -o WSRRREST

Where:

  • <BROKER_NAME> is the name of the broker (Integration Node).

To create the required properties on the WSRRREST configurable service you need to use the mqsichangeproperties command as shown below:

Creating the required properties
mqsichangeproperties <BROKER_NAME>
                    -c UserDefined
                    -o WSRRREST
                    -n keystoreFile
                    -v <KEY_STORE_FILE>

Where:

  • <BROKER_NAME> is the name of the broker (Integration Node).
  • <KEY_STORE_FILE> is the full path to key store file. For the purposes of configuring this message flow, you can actually use the trust store that was created in Part 1: Scenarios and configuration as both the keystore and truststore.

Repeat this process to create the following properties on the WSRRREST configurable service:

WSRRREST Configurable Service Properties
Property NameValue
keystorePasswordThe password for the key store.
truststoreFileThe full path to the trust store file.
truststorePasswordThe password for the trust store.
userIdThe id of a user who is authorized to access the required artefacts in WSRR.
userPasswordThe password for this user.

You should restart the broker (Integration Node) at this point to ensure that all of your changes take effect.

Testing the Message Flow

The next section shows you how to use the Calculator application to verify that the SLA Check flow is working correctly.

Basic Test

  1. Make sure that your IBM Integration Bus execution group is running, with the HTTPNode_SLACheck_GlobalCache flow deployed and started.
  2. Start the calculator application, as described in "Running the Calculator Application" in Part 1.
  3. Enter the host name 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/slacheck5. This is the endpoint for the HTTPNode_SLACheck_GlobalCache flow.
  5. Set the Consumer ID to CalculatorApplication. This is the consumer identifier that has been specified on the Application Version in WSRR that represents the Calculator application.
  6. Set the Context ID to CTX_1. This is the context identifier that has been specified on the SLA that represents the consumption agreement between the Calculator application and the Math Service.
  7. Enter the calculation you wish to perform using the number fields and the operator drop-down menu. The Calculator application should look similar to this when you have entered all of the information:
    The Calculator Application set up to use the SLA check message flow
    The Calculator Application set up to use the SLA check message flow
    The Calculator Application set up to use the SLA check message flow
  8. Click = (the equals button). The Calculator application will send a service request to the SLA check message flow, which will route the request to the actual Math Service. The result is ultimately returned to the Calculator application and is then displayed.

If you receive 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 path for the flow ( /MathServer/services/MathServer/slacheck5).
  3. You have specified the correct consumer identifier (CalculatorApplication).
  4. You have specified the correct context identifier (CTX_1).

Advanced Tests

To verify that the checks performed by the message flow are working correctly, you need to modify the state of the relevant objects in WSRR and then test the effect on the behaviour of the flow. The sections that follow describe the how to perform these tests.

Deactivating and reactivating the SLA

  1. Start the Calculator application and perform a calculation to check that the message flow is working correctly.
  2. In a Web browser, log on to the Service Registry Dashboard for your WSRR instance.
  3. Change to the SOA Governance view and then select the Overview page.
  4. Select SLA - CalculatorApplication 1.0 to MathService 1.0 in the Collection widget, as shown below:
    The SOA Governance View
    The SOA Governance View
    The SOA Governance View
  5. You will be taken to the Browse page, which will display the details of the SLA - CalculatorApplication 1.0 to MathService 1.0 service level agreement in the Detail widget. This is a representation of the consumption agreement between the Calculator application and the Math Service in WSRR. Select Action => Deactivate SLA, as shown below:
    Deactivating the SLA
    Deactivating the SLA
    Deactivating the SLA
  6. When the operation is completed, an Operation Successful dialog is displayed. Click OK. The governance state of the SLA has changed to SLA Inactive.
  7. Go to the Calculator application, and try to perform another calculation. The message Error: Unable to invoke math service. is displayed at the bottom of the application.
  8. Back in the Service Registry Dashboard, reactivate the SLA by selecting Action => Activate SLA. Click OK after the operation is completed. The SLA now has a governance state of SLA Active.
  9. Go to the Calculator applcation, and try to perform another calculation. This time the operation succeeds.

Taking the endpoints offline

  1. Start the Calculator application and perform a calculation to check that the message flow is working correctly.
  2. In a Web browser, log on the the Service Registry Dashboard for your WSRR instance.
  3. Change to the SOA Governance view and then select the Overview page.
  4. Select the MathService in the Approved Business Capabilities collection.
  5. You will taken to the Browse page, which will display the details of the MathService business service in the Detail widget. This is a business representation of the Math Service in WSRR. In this widget, under Versions , select MathService ‪(1.0).
  6. The Detail widget will be updated to display the details of the MathService (1.0) service version. This is a representation of an implementation of the Math Service in WSRR, specifically version 1.0. In the Detail widget, under Service Level Definitions select SLD - MathService v1.0.
  7. The Detail widget will be updated to display the details of the SLD - MathService v1.0 SLD. In the Detail widget, under Available Endpoints select http://localhost:7800/MathServer1/services/MathServer ‪(1.0). Note that the port number for your endpoint may be different if your IBM Integration Bus instance is not using the default port to listen for HTTP requests.
  8. The Detail widget will be updated to display the details of the http://localhost:7800/MathServer1/services/MathServer ‪(1.0) endpoint. Select Action => Revoke from use.
  9. Click OK after the operation is completed. The endpoint now has a governance state of Offline. Both of the endpoints for the version 1.0 of the Math Service should now be Offline.
  10. Go to the Calculator application, and try to perform another calculation. The message Error: Unable to invoke math service. is displayed at the bottom of the application.
  11. Back in the Service Registry Dashboard, switch the http://localhost:7800/MathServer1/services/MathServer ‪(1.0) endpoint back online by selecting Action => Approve For Use. Click OK after the operation is completed. The endpoint now has a governance state of Online.
  12. Go to the Calculator application, and try to perform another calculation. This time the operation succeeds.

Conclusion

This article described an example message flow that enforces SLAs defined in WSRR at runtime. The message flow uses the HTTP Request node to execute the SLAEndpointLookup named query usng the WSRR REST API. This named query verifies that the service consumer is authorized to invoke the target service by checking that it has an active SLA with the service provider. It then returns any online endpoints for the target service that are registered in WSRR.

An alternative solution to this business problem is presented in Part 5: Performing SLA checks at runtime . That solution makes use of the Registry Lookup node to retrieve the metadata for the service consumer from WSRR. Here are the benefits of using the HTTP Request node:

  • You have complete control over the XPath expressions that are used to query WSRR. This allows you to define complex XPath expressions that can traverse multiple relationships and apply predicates at various stages in the query. As a result, you would typically need to implement less code in the message flow to process the results. Neither the Endpoint Lookup or Registry Lookup nodes in IBM Integration Bus allow you to control the XPath expressions that are generated.
  • You have complete control over the type of query that is performed against WSRR. Both the Endpoint Lookup or Registry Lookup nodes in IBM Integration Bus perform Graph Queries against WSRR, which can potentially return a large amount of data and do not perform as well as Property Queries on the WSRR server. Using a Property Query allows you to retrieve just those properties that are required to perform your client side processing and is more performant.
  • You can use the WSRR REST API to invoke named queries in WSRR. This removes the need for the client to understand the structure of the data being queried in WSRR. The client simply needs to know the name of the named query, what parameters to pass and what type of objects are returned.

Of course, there are some drawbacks to using the HTTP Request node:

  • The HTTP Request node does not make use of the WSRR Cache in IBM Integration Bus, so you need to implement code to manually handle any caching that is required.
  • Because most of the validation is performed in the actual XPath expression defined in the named query, the message flow cannot be precise about why it is rejecting an request. It simply knows that the named query did not return any results, but it does not know the exact reason.

Acknowledgements

The author would like to thank 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 would also like to thank Anna Maciejkowicz for her help with reviewing this article.


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=970932
ArticleTitle=Integrating IBM Integration Bus with WebSphere Service Registry and Repository: Part 8: SLA checking using the HTTPRequest node
publish-date=04302014