Example of creating a web service that uses a business object and complex logic

This example shows a more sizeable Java™ API application that uses a business object to provide backend function. This example also illustrates how to create your own Java client to call your web service.

About this task

The functionality that is offered is to search all catalogs and return a list of items that meet a specified attribute=value criteria. This example is a more realistic example, involving a business object that is used by the web service to look through all catalogs for any items with the specified attribute value.

Procedure

  1. Write the Java code.
    1. Write the code for the business object CatalogQuery. Here is a sample:
      public class CatalogQuery
      {
      
          /**
           * All catalogs are queried for any items with the attribute name/value pair
           * provided.
           * 
           * @return an array of strings containing either matching item names or the
           *         result of the query if no match was found
           * 
           */
          public String[] getListOfItems(String attributeName, String attributeValue)
          {
      
              Collection<String> matchInfo = getItems(attributeName, attributeValue);
              int size = matchInfo.size();
      
              String[] list = new String[size];
      
              Iterator<String> listIterator = matchInfo.iterator();
      
              int i = 0;
              while (listIterator.hasNext())
              {
                  String string = (String) listIterator.next();
                  list[i++] = string;
              }
              return list;
          }
      
      
          /**
           * getItems
           * 
           * @return an ArrayList containing either matching item names or the result
           *         of the query if no match was found
           * 
           */
          public Collection<String> getItems(String attributeName, String attributeValue)
          {
              Collection<String> result = new ArrayList<String>();
      
              Collection<Catalog> wpcCatalogs = getCatalogs();
              if (wpcCatalogs == null)
              {
                  String noCatalogs = " There are no matching Items: No Catalogs found ";
                  result.add(noCatalogs);
                  return result;
              }
              else
              {
                  Collection<String> matchingItemsOrResult = getItemsMatchingCriteria(wpcCatalogs, attributeName, attributeValue);
                  return matchingItemsOrResult;
              }
          }
      
          /**
           * getCatalogs uses a sequence of javaapi calls for accessing catalogs in a
           * IBM® InfoSphere Master Data Management Server for Product Information
           * Management instance from a webservice
           * 
           * @return a PIMCollection containing objects representing the catalogs
           *         found.
           * 
           */
          private Collection<Catalog> getCatalogs()
          {
              Collection<Catalog> catalogs = null;
              String errorMsg = null;
              Context ctx = null;
              try
              {
                  ctx = PIMContextFactory.getContext("Admin", "trinitron", "BadWolf");
      
              }
              catch (Exception e)
              {
                  errorMsg = "Error obtaining Context" + e.getMessage();
                  e.printStackTrace();
              }
              CatalogManager catalog_manager = null;
              try
              {
                  catalog_manager = ctx.getCatalogManager();
              }
              catch (Exception e)
              {
                  errorMsg = "Error retrieving Catalog manager" + e.getMessage();
                  e.printStackTrace();
              }
              try
              {
                  catalogs = catalog_manager.getCatalogs();
                  if (null != catalogs)
                  {
                      errorMsg = "No Catalogs found";
                  }
                  return catalogs;
              }
              catch (Exception e)
              {
                  errorMsg = "Error retrieving Catalogs. " + e.getMessage();
                  e.printStackTrace();
              }
              String result = null;
              if (null == errorMsg)
              {
                  result = "Successfully completed Catalog interrogation";
              }
              else
              {
                  result = errorMsg;
              }
              System.out.println(result);
              return catalogs;
      
          }
      
          /**
           * getItemsMatchingCriteria queries each catalog for items with a matching
           * attribute name/value pair
           * 
           * @return an ArrayList containing either matching item names or the result
           *         of the query if no match was found
           * 
           */
          private Collection<String> getItemsMatchingCriteria(Collection<Catalog> wpcCatalogs, String attributeName, String attributeValue)
          {
              // this Collection will be returned if the result is an error
              Collection<String> result = new ArrayList<String>();
              // fa separate Collection to return if the result is good
              Collection<String> listOfMatchingItemNames = new ArrayList<String>();
      
              Iterator<Catalog> catalogIterator = wpcCatalogs.iterator();
              // iterate through the Catalogs looking for items with the matching
              // attributes
              while (catalogIterator.hasNext())
              {
                  Catalog wpcCatalog = catalogIterator.next();
      
                  if (wpcCatalog == null)
                  {
                      String catalogAltered = "System alterations have been made by another application: Catalog not found. ";
                      result.add(catalogAltered);
                      return result;
                  }
                  else
                  {
                      try
                      {
                          String specName = wpcCatalog.getSpec().getName();
      
                          if (hasItems(wpcCatalog))
                          {
                              PIMCollection<Item> wpcItems = wpcCatalog.getItems();
      
                              // iterate through the items for matching attributes
                              Iterator<Item> itemsIterator = wpcItems.iterator();
                              while (itemsIterator.hasNext())
                              {
                                  Item wpcItem = itemsIterator.next();
                                  if (wpcItem == null)
                                  {
                                      String itemAltered = "System alterations have been made by another application: Item not found. ";
                                      result.add(itemAltered);
                                      return result;
                                  }
                                  else if (attributeMatch(wpcItem, specName, attributeName, attributeValue))
                                  {
                                      String itemName = wpcItem.getDisplayName();
                                      listOfMatchingItemNames.add(itemName);
                                  }
      
                              }
                          }
                      }
                      catch (Exception e)
                      {
                          e.printStackTrace();
                      }
                  }
              } // end of the Catalog iterator 'while'
      
              // after we iterate through all the catalogs and build a list of
              // matching items
              // we return the list of matching items
              // first check to see whether there are any items in the Collection
              if (listOfMatchingItemNames.isEmpty())
              {
                  String noMatches = "No items that matched the criteria were found. ";
                  result.add(noMatches);
                  return result;
              }
              else
              {
                  return listOfMatchingItemNames;
              }
          }
      
          /**
           * hasItems determines whether a catalog contains items
           * 
           * @return boolean
           * 
           */
          private boolean hasItems(Catalog wpcCatalog)
          {
              try
              {
                  PIMCollection<Item> items = wpcCatalog.getItems();
                  if (items == null)
                  {
                      return false;
                  }
                  else
                  {
                      return true;
                  }
              }
              catch (Exception e)
              {
                  e.printStackTrace();
              }
              return false;
      
          }
      
          /**
           * attributeMatch determines whether the item has a matching attribute and
           * value
           * 
           * @return boolean
           * 
           */
          private boolean attributeMatch(Item wpcItem, String specName, String attributeName, String attributeValue)
          {
      
              // first establish whether the attribute exists for the item
              try
              {
                  String valueRetrieved = (String) wpcItem.getAttributeValue(specName + "/" + attributeName);
                  if (valueRetrieved == null)
                  {
                      // attribute is not there, so there will be no match
                      return false;
                  }
                  else
                  {
                      // check whether the attribute found has a value match
                      if (valueRetrieved.equals(attributeValue))
                      {
                          return true;
                      }
                  }
              }
              catch (Exception e)
              {
                  e.printStackTrace();
              }
              return false;
          }
      }
      
    2. Write the code for the web service, ItemFinderService, which uses the previous business object. Here is a sample:
      /**
       * This class is intended to be exposed as the Web service that drives
       * CatalogQuery
       *
       * An attribute name/value pair is provided, and a list of items that contain
       * this attribute name/value pair is returned.
       *
       * @return an array of string containing the primary keys (PKs) of items containing the
       *         attribute name/value pair.
       *
       */
      public class ItemFinderService
      {
      
          /**
           * getListOfMatchingItems queries all catalogs for any items with the
           * attribute name/value pair provided.
           *
           * @param String
           *            attributeName: search for this attribute name
           * @param String
           *            attributeValue: if the attributeName exists, search for
           *            instances of that name with this value
           *
           * @return an array of strings containing either item names with matching
           *         attribute name/value or the result of the query if no match was
           *         found
           */
          public String[] getListOfMatchingItems(String attributeName, String attributeValue)
          {
              CatalogQuery catalogQuery = new CatalogQuery();
              String[] matchInfo = catalogQuery.getListOfItems(attributeName, attributeValue);
              return matchInfo;
          }
      
      }
  2. Deploy the user .jar file.
  3. Register the web service in Product Master.
    1. Access your Product Master instance and log in.
      For example: http://yourWPCserver:yourWPCport/utils/enterLogin.jsp.
    2. Click Collaboration Manager > Web Services > Web Service Console > New.
    3. Provide the following values:
      • Web Service Name: Provide a name. For example, ItemFinderService.
      • WSDL: Type:
        <?xml version="1.0" encoding="UTF-8"?>
         <wsdl:definitions targetNamespace="http://javawbs.acme.com"
         xmlns="http://schemas.xmlsoap.org/wsdl/"
         xmlns:apachesoap="http://xml.apache.org/xml-soap"
         xmlns:impl="http://javawbs.acme.com"
         xmlns:intf="http://javawbs.acme.com"
         xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
         xmlns:tnsl="http://javawbs.acme.com"
         xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
         xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"
         xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
         xmlns:xsd="http://www.w3.org/2001/XMLSchema">
            <wsdl:types>
               <schema targetNamespace="http://javawbs.acme.com"
         xmlns="http://www.w3.org/2001/XMLSchema">
                  <element name="getListOfMatchingItems">
                     <complexType>
                        <sequence>
                           <element name="attributeName"
         type="xsd:string"/>
                           <element name="attributeValue"
         type="xsd:string"/>
                        </sequence>
                     </complexType>
                  </element>
                  <element name="getListOfMatchingItemsResponse">
                     <complexType>
                        <sequence>
                           <element maxOccurs="unbounded" minOccurs="0"
         name="getListOfMatchingItemsReturn" type="xsd:string"/>
                        </sequence>
                     </complexType>
                  </element>
               </schema>
            </wsdl:types>
            <wsdl:message name="getListOfMatchingItemsResponse">
               <wsdl:part element="tnsl:getListOfMatchingItemsResponse"
         name="parameters"/>
            </wsdl:message>
            <wsdl:message name="getListOfMatchingItemsRequest">
               <wsdl:part element="tnsl:getListOfMatchingItems"
         name="parameters"/>
            </wsdl:message>
            <wsdl:portType name="ItemFinderService">
               <wsdl:operation name="getListOfMatchingItems">
                  <wsdl:input
         message="impl:getListOfMatchingItemsRequest"
         name="getListOfMatchingItemsRequest"/>
                  <wsdl:output
         message="impl:getListOfMatchingItemsResponse"
         name="getListOfMatchingItemsResponse"/>
               </wsdl:operation>
            </wsdl:portType>
            <wsdl:binding name="ItemFinderServiceSoapBinding"
         type="impl:ItemFinderService">
               <wsdlsoap:binding style="document"
         transport="http://schemas.xmlsoap.org/soap/http"/>
           <soap12:binding
         transport="http://schemas.xmlsoap.org/soap/http"/>
               <wsdl:operation name="getListOfMatchingItems">
                  <wsdlsoap:operation
         soapAction="getListOfMatchingItems"/>
                  <wsdl:input name="getListOfMatchingItemsRequest">
                     <wsdlsoap:body namespace="http://javawbs.acme.com"
         use="literal"/>
                  </wsdl:input>
                  <wsdl:output name="getListOfMatchingItemsResponse">
                     <wsdlsoap:body namespace="http://javawbs.acme.com"
         use="literal"/>
                  </wsdl:output>
               </wsdl:operation>
            </wsdl:binding>
            <wsdl:service name="ItemFinderServiceService">
               <wsdl:port binding="impl:ItemFinderServiceSoapBinding"
         name="ItemFinderService_PORT">
                  <wsdlsoap:address
         location="http://<your-WPC-server>:<your-WPC-port>/services/Item
         FinderService"/>
               </wsdl:port>
            </wsdl:service>
         </wsdl:definitions>
        
      • Web Service Implementation: Select Java.
      • Java Implementation Class: Type the Java class of your web service. For the previous example, type com.acme.javawbs.ItemFinderService.
      • WSDD: Type:
        <deployment
        			xmlns="http://xml.apache.org/axis/wsdd/"
        			xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
        		<!--Services from ItemFinderService WSDL service-->
        		<service name="ItemFinderService" provider="java:WPCDocument" style="wrapped"use="literal">
        				<parameter name="wsdlTargetNamespace" value="http://javawbs.acme.com"/>
        				<parameter name="wsdlServiceElement" value="ItemFinderService"/>
        				<parameter name="wsdlServicePort" value="ItemFinderService"/>
        				<parameter name="className" value="com.acme.javawbs.ItemFinderService"/>
        				<parameter name="wsdlPortType" value="ItemFinderService"/>
        				<operation name="getListOfMatchingItems" qname="operNS:getListOfMatchingItems"xmlns:operNS="http://javawbs.acme.com" returnQName="getListOfMatchingItemsReturn" returnType="rtns:string"xmlns:rtns="http://www.w3.org/2001/XMLSchema">
        					<parameter name="attributeName" type="tns.string" xmlns:tns="http://www.w3.org/2001/XMLSchema"/>
        					<parameter name="attributeValue" type="tns:string" xmlns:tns="http://www.w3.org/2001/XMLSchema"/>
        			<operation>
        			<parameter name="allowedMethods" value="getListOfMatchingItems"/>
        			<parameter name="scope" value="Session"/>
        	</service>
        </deployment>
      • Deployed: Select this checkbox. Clearing this selection enables you to store web services in an inactive (unusable) state.
      • Authenticated: Do not select this checkbox .
    4. Click Save. If you get an error similar to: Unable to verify Java implementation class, and you have no typographical errors in your fully qualified Java class name, then you did not successfully deploy your Java class through the user .jar mechanism. Return to Step 2 and check whether your user .jar appears in your class path.
      For example, ps -ef | grep java and check the Java process for Product Master.
  4. Test starting your web service. Your web service is now deployed and ready for use. Type:
    http://YourWPCServer:YourWPCPort/services/ServiceName?method=getListOfMatchingItems&attributeName=YourAttributeName&attributeValue=YourAttributeValue
    Where YourWPCServer and YourWPCPort is the URL for accessing your Product Master system, ServiceName is the name that you gave the web service when you deployed it to Product Master, YourAttributeName is the name of the attribute that you want to examine, and YourAttributeValue is the value of that attribute that you want to look for.

    The output in the browser window returns two matching items from any Product Master catalog that contains a field that is called "color" with a value of "red".

  5. Create a client application to call the web service. The following instructions apply to Rational® Software Architect, but you can use different tools for writing SOAP web service clients.
    1. Open Rational Software Architect and open a new Java project. Call it ItemFinderClient.
    2. Go to the URL that appeared in the WSDL URL field when you saved the ItemFinderService web service (or copy the WSDL from the WSDL text box). After you obtain the WSDL, save it to a file.
      For example, ItemFinderService.wsdl. Your client needs the web service WSDL definition to know how to interact with the web service.
    3. Import the ItemFinderService.wsdl file into your Java project.
    4. Ensure that you have the following capabilities that are enabled in your workspace preferences:
      • Web Service Developer
      • XML Developer
      • Advanced Java Platform, Enterprise Edition
    5. Right-click the WSDL file and select Web Services > Generate Client.
    6. Select the default options for the web service. Do not select Test web service because this runs a separate application server within Rational Software Architect and will not work for Product Master.
    7. Click Finish. You have now generated the files that provide the methods that you need to access the web service from your Java code.
    8. Create a Java class that is called ItemFinderServiceClient.java with the following code:
      public class ItemFinderServiceClient 
      {
      	public static void main(String args[]) throws RemoteException
      	{
      		// test the ItemFinderService Web Service
      		ItemFinderServiceProxy proxy = new ItemFinderServiceProxy();
      		ItemFinderService service = proxy.getItemFinderService();
      		
      		// call the web service and return matching items
      		String[] returnedItems = service.getListOfMatchingItems("color","red");
      
      		// report number of matches
                      System.out.println("ItemFinderService.getItems("color",\"red\") returned "+returnedItems.length+" matching items:");
      		
                      // print details
      		for (int i=0; i < returnedItems.length; i++)
      		{
      			String itemString = (String) returnedItems[i];
      			int itemNo = i+1;
      			System.out.println("Item "+itemNo+": "+itemString);
      		}
      	}
      }
    9. Ensure that Product Master is started, your user .jar with the current version of the web service class is deployed, and the web service is registered and saved as deployed in Product Master.
    10. In Rational Software Architect, run the ItemFinderServiceClient class. If everything is set up correctly, you see the output from calling the web Service in the Rational Software Architect console view.
      ItemFinderService.getItems("color",
      "red") returned 2 matching items:
      Item 1: Item27
      Item 2: Item43