+

Search Tips   |   Advanced Search

Set the JAX-RPC Web services client cache


The JAX-RPC Web services client cache is provided as a "Java API for XML-Based Remote Procedure Calls (JAX-RPC)" handler on the application server. The JAX-RPC Web services client cache is a part of the dynamic cache service used to increase the performance of Web services clients by caching responses from remote Web services. Set the JAX-RPC Web services client cache can improve the performance of the appserver by caching the responses from remote Web services for a specified amount of time.

The dynamic cache service is enabled by default. We can configure the default cache instance in the admin console. See Use the dynamic cache service for more information. Before attempting to configure the Web services client cache, understand how to create basic cache policies. See Set cacheable objects with the cachespec.xml file for more information.

Enable the Web services client cache is an option to improve the performance of the system by using the dynamic cache service to save responses from remote Web services for a specified amount of time. With WAS Version 6.1, Web services caching is enabled by enabling only the dynamic cache service. With WAS V7.0, you enable the Web service caching by enabling the dynamic cache service and servlet caching. After a response is returned from a remote Web service, the response is saved in the client cache on the appserver. Any identical requests that are made to the same remote Web service are then responded to from the cache for a specified period of time. The Web services client cache relies primarily on time-based invalidations because the target web service can be outside of the enterprise network and unaware of the client caching. Therefore, we can specify the amount of time in the cache and the rules to build cache entry IDs in the cache in the client application.

The Web services client cache is provided as a Java API for XML-Based Remote Procedure Calls (JAX-RPC) handler on the appserver. This JAX-RPC cache handler intercepts the SOAP requests that flow through it from application clients. It then identifies a cache policy based on the target Web service. After a policy is found, all the cache ID rules are evaluated one by one until a valid rule is detected.

 

  1. Locate the WSDL file for the remote service. Portions of the WSDL file contain information that you will use in writing the cache policy.

    See about WSDL files, see WSDL. Following is an example of portions of a WSDL file that contains values that are used for the purpose of demonstration.

    <definitions targetNamespace="http://TradeSample.com/"
        
        xmlns:tns="http://TradeSample.com/"
        
        xmlns="http://schemas.xmlsoap.org/wsdl/"
        
        xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
        
        xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <message name="getQuoteRequest">
        <part name="symbol" type="xsd:string"/>
      </message>
    .....
    .....
    <binding name="SoapBinding" type="tns:GetQuote">
      <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
        <operation name="getQuote">
          <soap:operation soapAction=""/>
          <input name="getQuoteRequest">
            <soap:body namespace="http://TradeSample.com/" 
            use="encoded"
          encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
          </input>
          ......
          </operation>
    </binding>
    <service name="GetQuoteService">
      <port binding="tns:SoapBinding" name="SoapPort">
        <soap:address location="http://TradeSample.com:9082/service/getquote"/>
      </port>
    </service>
    </definitions>
    
    The highlighted text indicates values that are used in writing the cache policy.

  2. Choose how you plan to generate the cache id for the Web services client caching. We can build the cache id rules by using one of four options:

    • By calculating a hash of the SOAPEnvelope

    • By using SOAPHeader entries

    • By using operation and part parameters

    • By using custom Java code to build the cache id from input SOAP message content

    Using SOAPHeader entries is the best option if we can include information for building cache keys as part of the SOAP header. This method creates easy to read cache keys and can be built without parsing the SOAP body. Use custom Java code to generate a specific cache id based on the SOAP message. If we cannot include the header information, we can calculate the hash of the SOAPEnvelope for performance or parse the SOAP Body for user-friendly cache keys.

  3. Develop the cache policy.

    All Web services client cache policies must have the class JAXRPCClient. The name element in each cache entry is the target endpoint location that is defined in the WSDL file. We can find this address in the WSDL file by finding the <soap:address location=".."/> tag located in the port element. In the WSDL file for this sample, the address is http://TradeSample.com:9082/service/getquote. Develop the rest of the cache policy by using one of the following options:

    • Calculate a hash of the SOAPEnvelope to identify the request

      <cache>
        <cache-entry>
          <class>JAXRPCClient</class>
          <name>http://TradeSample.com:9082/service/getquote</name>
          <cache-id>
            <component id="hash" type="SOAPEnvelope"/>
            <timeout>60</timeout>
          </cache-id>
        </cache-entry>
      </cache>
      

      Note the component attributes to create a cache id based on a hash calculation of the SOAPEnvelope. The cache id for this sample is generated as http://TradeSample.com:9082/service/getquote:Hash=xxxHashSoapEnvelope.

    • Use the SoapHeader to identify the request

      <cache>
        <cache-entry>
          <class>JAXRPCClient</class>
          <name>http://TradeSample.com:9082/service/getquote</name>
          <cache-id>
            <component id="urn:stock:getQuote" type="SOAPHeaderEntry"/>
          </cache-id>
        </cache-entry>
      </cache>
      

      This cache id is built by using special information in the SOAP header to identify requests for entries in the cache. Specify the type as SOAPHeaderEntry and the id as the operation name located in the binding element in the WSDL file. The cache id for this sample is generated as http://TradeSample.com:9082/service/getquote:urn:stock:getQuote=IBM.

      An example of a SOAP request generated by the client using SOAP Header: Note that the soapenv:actor attribute must contain com.ibm.websphere.cache.

      POST /wsgwsoap1/soaprpcrouther HTTP/1.1 SOAPAction: "" Context-Type: text/xml; charset=utf-8 User-Agent: Java /1.4.1 Host: localhost Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2 Connection: keep-alive Content-Length: 645
      
      <?xml version="1.0" encoding="UTF-8"?>
      <soapenv:Envelope 
      
          xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
        
          xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
        
          xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <soapenv:Header>
        <getQuote soapenv:actor="com.ibm.websphere.cache" 
          xmlns="urn:stock">IBM</getQuote>
      </soapenv:Header>
      <soapenv:Body soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding">
        <getQuote 
          xmlns="urn:ibmwsgw#GetQuoteSample">
          <symbol 
          xsi:type="xsd:string">IBM</symbol>
        </getQuote>
      </soapenv:Body>
      </soapenv:Envelope>
      

    • Use operation and part to identify the request

      <cache>
        <cache-entry>
          <class>JAXRPCClient</class>
          <name>http://TradeSample.com:9082/service/getquote</name>
          <cache-id>
            <component id="" type="operation">
              <value>http://TradeSample.com/:getQuote</value>
            </component>
            <component id="symbol" type="part"/>
          </cache-id>
        </cache-entry>
      </cache>
      

      This example uses operation and request parameters. The operation can be a method name in the WSDL file located in the binding element or a method name in the Document/Literal Invocation (DII). If the namespace of the operation is defined, the value is formatted as namespaceOfOperation:nameOfOperation. The part type can be defined in the message element of the WSDL file, as a request parameter, or as a request parameter of the DII invocation. Its id attribute is the part or parameter name, and the value is the part or parameter value. The cache id generated from using operation and request parameters is http://TradeSample.com:9082/service/getquote:operation=http://TradeSample.com/:getQuote/symbol=IBM.

      An example of the SOAP request generated by the client using operation and part:

      POST /wsgwsoap1/soaprpcrouter HTTP/1.1 SOAPAction:"" Content-Type: text/xml/charset=utf-8 User-Agent: Java /1.4.1 Host: localhost Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2 Connection: keep-alive Current-Length: 645
      
      <?xml version="1.0" encoding="UTF-8"?>
      <soapenv:Envelope
      
          xmlns: soapenv="http://schemas.xmlsoap.org/soap/envelope/"
        
          xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
        
          xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <soapenv:Body
        soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
        <getQuote 
          xmlns="urn:ibmwsgw#GetQuoteSample">
          <symbol 
          xsi:type="xsd:string">IBM</symbol>
        </getQuote>
      </soapenv:Body>
      </soapenv:Envelope>
      

    • Use custom Java code to build the cache id from input SOAP message content

      If we use custom Java code to build the cache id, create an ID generator Java class that implements the IdGenerator interface defined in the com.ibm.websphere.cache.webservices.IdGenerator package and add a reference to the class you create in the cachespec.xml file by using the idgenerator tag.

      We can also implement the com.ibm.websphere.cache.webservices.MetaDataGenerator package to assign cache metadata such as timeout, priority, and dependency ids to cache entries using the metadatagenerator tag.

      Implement the com.ibm.websphere.cache.webservices.InvalidationGenerator interface and use the invalidationgenerator tag in the cachespec.xml file to generate cache ids and to invalidate entries in the cache. The id generated by the invalidation generator can be a cache id or a dependency id.

      For example, if we develop an ID generator class named SampleIdGeneratorImpl, a metadata generator class named SampleMetaDataGeneratorImpl, and an invalidation generator class named SampleInvalidationGeneratorImpl, the cachespec.xml file might contain the following:

      <cache-entry>
        <class>JAXRPCClient</class>
        <name>http://TradeSample.com:9082/service/getquote</name>
        <cache-id>
          <idgenerator>com.mycompany.SampleIdGeneratorImpl</idgenerator>
          <metadatagenerator>
             com.mycompany.SampleMetaDataAndInvalidationGeneratorImpl
          </metadatagenerator>
          <timeout>60</timeout>
        </cache-id>
        <invalidation>http://TradeSample.com:9082/service/GetQuote
          <invalidationgenerator>
             com.mycompany.SampleMetaDataAndInvalidationGeneratorImpl
          </invalidationgenerator>
        </invalidation>
      </cache-entry>
      
      The SampleIdGeneratorImpl class is a custom Java class that implements the com.websphere.cache.webservices.IdGenerator interface. The SampleIdGeneratorImpl class contains the getID method:

      String getId(javax.xml.rpc.handler.soap.SOAPMessageContext messageContext)
      

      The following is an example of the SampleIdGeneratorImpl.java class.

      public class SampleIdGeneratorImpl implements IdGenerator {
      
      //The SampleIdGenerator class builds cache keys using SOAP header entries
          public String getId(javax.xml.rpc.handler.soap.SOAPMessageContext 
            messageContext) {
            ....
            
      // retrieve SOAP header entries from SOAPMessage
            SOAPHeader sh = soapEnvelope.getHeader();
             if (sh != null) {
              Iterator it = sh.examineHeaderElements("com.mycompany.actor");
              while (it.hasNext()) {
                 SOAPHeaderElement element =
                          (SOAPHeaderElement)it.next();
                Name name = element.getElementName();
                String headerEntryName = name.getLocalName();
                if (headerEntryName.equals("getQuote")){
                  String sNamespace = element.getNamespaceURI("");
                  if (sNamespace != null && !sNamespace.equals("")) {
                      headerEntryName = sNamespace + ":" + headerEntryName;
                    String quotes = element.getValue();
                  }
                  ...
                  ...
                  
      // create a method "parseAndSort" to parse and sort quotes
                  
      // By parsing and sorting quotes, you avoid duplicate cache 
                  
      // entries.
                  
      // quotes e.g. IBM,CSCO,MSFT,INTC
                  
      // to return a cache key "urn:stock:getQuote=CSCO,IBM,INTC,MSFT"
                  String sortQuotes = parseAndSort(quotes); 
                  cacheKey = headerEntryName + "=" + sortQuotes;
                 }
              }
          return cacheKey;
          }
        }
      
      

      The cache id for this sample is generated as http://TradeSample.com:9082/service/getquote:urn:stock:symbol=CSCO,IBM,INTC,MSFT.

      The SampleMetaDataAndInvalidationGeneratorImpl class is a custom Java class that implements the com.websphere.cache.webservices.MetaDataGenerator interface and the com.websphere.cache.webservices.InvalidationGenerator interface. The SampleMetaDataAndInvalidationGeneratorImpl class contains the setMetaData method and the getInvalidationIds method. We can also set up two smaller classes instead of this one large class. For example, create one class for the metadata generator and a different class for the invalidation generator.

      The following are method prototypes for the setMetaData method and the getInvalidationIds method:

      void setMetaData (javax.xml.rpc.handler.soap.SOAPMessageContext messageContext, 
        com.ibm.websphere.cache.webservices.JAXRPCEntryInfo entryInfo) String[] getInvalidationIds (javax.xml.rpc.handler.soap.SOAPMessageContext messageContext)
      

      An example of the SampleMetaDataAndInvalidationGeneratorImpl.java class follows:

      public class SampleMetaDataAndInvalidationGeneratorImpl implements 
        MetaDataGenerator, InvalidationGenerator {
          
      //assigns time limit, and priority metadata
          public void setMetadata(javax.xml.rpc.handler.soap.SOAPMessageContext messageContext, 
        com.ibm.websphere.cache.webservices.JAXRPCEntryInfo entryInfo) {
            ....
                      
          
      // retrieve SOAP header entries from SOAPMessage
            SOAPHeader sh = soapEnvelope.getHeader();
             if (sh != null) {
              Iterator it = sh.examineHeaderElements("com.mycompany.actor");
              while (it.hasNext()) {
                 SOAPHeaderElement element =
                          (SOAPHeaderElement)it.next();
                Name name = element.getElementName();
                String headerEntryName = name.getLocalName();
                                        if (headerEntryName.equals(“metadata”)) {
                
      // retrieve each metadata element and set metadata 
                        entryInfo.setTimeLimit(timeLimit);
                      entryInfo.setPriority(priority);
                  }
              }
          }
      
          
      //builds invalidation ids using SOAP header. 
          public String[] getInvalidationIds(javax.xml.rpc.handler.soap.SOAPMessageContext 
            messageContext) {      ....
            
      // retrieve SOAP header entries from SOAPMessage
                      String[] invalidationIds = new String[1];
            SOAPHeader sh = soapEnvelope.getHeader();
             if (sh != null) {
              Iterator it = sh.examineHeaderElements("com.mycompany.actor");
              while (it.hasNext()) {
                 SOAPHeaderElement element =
                          (SOAPHeaderElement)it.next();
                Name name = element.getElementName();
                String headerEntryName = name.getLocalName();
                                        if (headerEntryName.equals("invalidation")) {
                String sNamespace = element.getNamespaceURI("");
                if (sNamespace != null && !sNamespace.equals("")) {
                    headerEntryName = sNamespace + ":symbol";
                  String quotes = element.getValue();
                }
                ...
                ...
                
      // create a method "parseAndSort" to parse and sort quotes
                
      // By parsing and sorting quotes, you avoid duplicate cache 
                
      // entries.
                
      // quotes e.g. SUNW,NT
                
      // to return a cache key "urn:stock:symbol=NT,SUNW"
                String sortQuotes = parseAndSort(quotes); 
                invalidationIds[0] = headerEntryName + "=" sortQuotes;
                   }
             }
          return invalidationIds;
          }
      }
      
      
      
      The invalidation id for this sample is generated as:

      http://TradeSample.com:9082/service/getquote:urn:stock:symbol=NT,SUNW
      

      An example of the SOAP request generated by the client when using custom Java code follows:

      POST /wsgwsoap1/soaprpcrouter HTTP/1.1 SOAPAction: "" Context-type: text/xml, charset=utf-8 User-Agent: Java /1.4.1 Host: localhost Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2 Connection: keep-alive Content-Length:645
      
      <?xml version="1.0" encoding="UTF-8"?>
      <soapenv:Envelope
      
          xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
          
          xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
          
          xmlns:xsd="http://www.w3.org/2001/XMLSchema"
          
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <soapenv:Header>
        <getQuote soapenv:actor="com.mycompany.actor"
            
          xmlns="urn:stock">IBM,CSCO,MSFT,INTC</getQuote>
          <metaData soapenv:actor="com.mycompany.actor" 
          xmlns="urn:stock">
            <priority>10</priority>
            <timeLimit>30000</timeLimit>
          </metaData>
          <invalidation soapenv:actor="com.mycompany.actor" 
            
          xmlns="urn:stock">SUNW, NT</invalidation>
      </soapenv:Header>
      <soapenv:Body soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding">
      <getQuote 
          xmlns="urn:ibmwsgw#GetQuoteSample">
        <symbol 
          xsi:type="xsd:string">IBM,CSCO,MSFT,INTC</symbol>
      </getQuote>
      </soapenv:Body>
      </soapenv:Envelope>
      

  4. Save the cache policy to the appropriate directory.

    • If using the Web Services Gateway on SOAP channel 1, the directory is: APP_ROOT\installedApps\wsgwsoap1.servername.nodename.ear/wsgwsoap.war/WEB-INF

    • For a simple JAX-RPC client in the application to invoke remote Web services, save the cache policy in the Web module WEB-INF of the JAX-RPC application.

 

Results

We can monitor the results of the Web services client cache policy by using the dynamic cache monitor. See Displaying cache information for more information.

 

Related tasks


Task overview: Using the dynamic cache service to improve performance

 

Related


cachespec.xml file