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
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
- Write the Java code.
- 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; } }
- 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; } }
- Write the code for the business object
- Deploy the user .jar file.
For more information, see Deploying a third party or custom user .jar file.
- Register the web service in Product Master.
- Access your Product Master instance
and log in. For example:
http://yourWPCserver:yourWPCport/utils/enterLogin.jsp
. - Click Collaboration Manager > Web Services > Web Service Console > New.
- 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 .
- 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.
- Access your Product Master instance
and log in.
- Test starting your web service. Your web service is now
deployed and ready for use. Type: 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.
http://YourWPCServer:YourWPCPort/services/ServiceName?method=getListOfMatchingItems&attributeName=YourAttributeName&attributeValue=YourAttributeValue
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".
- 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.
- Open Rational Software
Architect and open a new Java project.
Call it
ItemFinderClient
. - 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. - Import the
ItemFinderService.wsdl
file into your Java project. - Ensure that you have the following capabilities that
are enabled in your workspace preferences:
- Web Service Developer
- XML Developer
- Advanced Java Platform, Enterprise Edition
- Right-click the WSDL file and select Web Services > Generate Client.
- 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.
- Click Finish. You have now generated the files that provide the methods that you need to access the web service from your Java code.
- 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); } } }
- 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.
- 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
- Open Rational Software
Architect and open a new Java project.
Call it