|
Home
TOC Index |
|
JAX-RPC Distributor Service
The Coffee Break server is also a client-- it makes remote calls on the JAX-RPC distributor service. The service code consists of the service interface, service implementation class, and several JavaBeans components that are used for method parameters and return types.
Service Interface
The service interface,
SupplierIF, defines the methods that can be called by remote clients. The parameters and return types of these methods are JavaBeans components:
AddressBean- shipping information for customerConfirmationBean- order id and ship dateCustomerBean- customer contact informationLineItemBean- order itemOrderBean- order id, customer, address, list of line items, total pricePriceItemBean- price list entry (coffee name and wholesale price)PriceListBean- price listBecause these components are shared by other programs, their source code resides in the <
JWSDP_HOME>/docs/tutorial/examples/cb/common/srcdirectory. The source code for theSupplierIFinterface, which follows, resides in the <JWSDP_HOME>/docs/tutorial/examples/cb/jaxrpc/srcdirectory.package com.sun.cb; import java.rmi.Remote; import java.rmi.RemoteException; public interface SupplierIF extends Remote { public ConfirmationBean placeOrder(OrderBean order) throws RemoteException; public PriceListBean getPriceList() throws RemoteException; }Service Implementation
The
SupplierImplclass implements theplaceOrderandgetPriceListmethods, which are defined by theSupplierIFinterface. So that you can focus on the code related to JAX-RPC, these methods are short and simplistic. In a real-world application, these methods would access databases and interact with other services, such as shipping, accounting, and inventory.The
placeOrdermethod accepts as input a coffee order and returns a confirmation for the order. To keep things simple, theplaceOrdermethod confirms every order and sets the ship date in the confirmation to the next day. (This date is calculated byDateHelper, a utility class that resides in the cb/commonsubdirectory.) The source code for theplaceOrdermethod follows:public ConfirmationBean placeOrder(OrderBean order) { Date tomorrow = com.sun.cb.DateHelper.addDays(new Date(), 1); ConfirmationBean confirmation = new ConfirmationBean(order.getId(), tomorrow); return confirmation; }The
getPriceListmethod returns aPriceListBeanobject, which lists the name and price of each type of coffee that can be ordered from this service. ThegetPriceListmethod creates thePriceListBeanobject by invoking a private method namedloadPrices. In a production application, theloadPricesmethod would fetch the prices from a database. However, ourloadPricesmethod takes a shortcut by getting the prices from theSupplierPrices.propertiesfile. Here are thegetPriceListandloadPricesmethods:public PriceListBean getPriceList() { PriceListBean priceList = loadPrices(); return priceList; } private PriceListBean loadPrices() { String propsName = "com.sun.cb.SupplierPrices"; Date today = new Date(); Date endDate = DateHelper.addDays(today, 30); PriceItemBean[] priceItems = PriceLoader.loadItems(propsName); PriceListBean priceList = new PriceListBean(today, endDate, priceItems); return priceList; }Publishing the Service in the Registry
Because we want customers to find our service, we will to publish it in a registry. The programs that publish and remove our service are called
OrgPublisherandOrgRemover. These programs are not part of the service's Web application. They are stand-alone programs that are run by theantset-up-servicecommand. (See Building and Installing the JAX-RPC Service.) Immediately after the service is installed, it's published in the registry. And in like manner, right before the service is removed, it's removed from the registry.The
OrgPublisherprogram begins by loadingStringvalues from theCoffeeRegistry.propertiesfile. Next, the program instantiates a utility class namedJAXRPublisher.OrgPublisherconnects to the registry by invoking themakeConnectionmethod ofJAXRPublisher. To publish the service,OrgPublisherinvokes theexecutePublishmethod, which accepts as inputusername,password, andendpoint. Theusernameandpasswordvalues are required by the Registry Server. Theendpointvalue is the URL that remote clients will use to contact our JAX-RPC service. TheexecutePublishmethod ofJAXRPublisherreturns a key that uniquely identifies the service in the registry.OrgPublishersaves this key in a text file namedorgkey.txt. TheOrgRemoverprogram will read the key fromorgkey.txtso that it can delete the service. (See Deleting the Service From the Registry.) The source code for theOrgPublisherprogram follows.package com.sun.cb; import javax.xml.registry.*; import java.util.ResourceBundle; import java.io.*; public class OrgPublisher { public static void main(String[] args) { ResourceBundle registryBundle = ResourceBundle.getBundle ("com.sun.cb.CoffeeRegistry"); String queryURL = registryBundle.getString("query.url"); String publishURL = registryBundle.getString("publish.url"); String username = registryBundle.getString("registry.username"); String password = registryBundle.getString("registry.password"); String endpoint = registryBundle.getString("endpoint"); String keyFile = registryBundle.getString("key.file"); JAXRPublisher publisher = new JAXRPublisher(); publisher.makeConnection(queryURL, publishURL); String key = publisher.executePublish (username, password, endpoint); try { FileWriter out = new FileWriter(keyFile); out.write(key); out.flush(); out.close(); } catch (IOException ex) { System.out.println(ex.getMessage()); } } }The
JAXRPublisherclass is almost identical to the sample programJAXRPublish.java, which is described in Managing Registry Data.First, the
makeConnectionmethod creates a connection to the Registry Server. See Establishing a Connection for more information. To do this, it first specifies a set of connection properties using the query and publish URLs passed in from theCoffeeRegistry.propertiesfile. For the Registry Server, the query and publish URLs are actually the same.Properties props = new Properties(); props.setProperty("javax.xml.registry.queryManagerURL", queryUrl); props.setProperty("javax.xml.registry.lifeCycleManagerURL", publishUrl);Next, the
makeConnectionmethod creates the connection, using the connection properties:ConnectionFactory factory = ConnectionFactory.newInstance(); factory.setProperties(props); connection = factory.createConnection();The
executePublishmethod takes three arguments: a username, a password, and an endpoint. It begins by obtaining aRegistryServiceobject, then aBusinessQueryManagerobject and aBusinessLifeCycleManagerobject, which enable it to perform queries and manage data:rs = connection.getRegistryService(); blcm = rs.getBusinessLifeCycleManager(); bqm = rs.getBusinessQueryManager();Because it needs password authentication in order to publish data, it then uses the username and password arguments to establish its security credentials:
PasswordAuthentication passwdAuth = new PasswordAuthentication(username, password.toCharArray()); Set creds = new HashSet(); creds.add(passwdAuth); connection.setCredentials(creds);It then creates an
Organizationobject with the name "JAXRPCCoffeeDistributor," then aUserobject that will serve as the primary contact. It gets the data from the resource bundle instead of hardcoding it as strings, but otherwise this code is almost identical to that shown in the JAXR chapter.ResourceBundle bundle = ResourceBundle.getBundle("com.sun.cb.CoffeeRegistry"); // Create organization name and description Organization org = blcm.createOrganization(bundle.getString("org.name")); InternationalString s = blcm.createInternationalString (bundle.getString("org.description")); org.setDescription(s); // Create primary contact, set name User primaryContact = blcm.createUser(); PersonName pName = blcm.createPersonName(bundle.getString("person.name")); primaryContact.setPersonName(pName);It adds a telephone number and email address for the user, then makes the user the primary contact:
org.setPrimaryContact(primaryContact);It gives JAXRPCCoffeeDistributor a classification using the North American Industry Classification System (NAICS). In this case it uses the classification "Other Grocery and Related Products Wholesalers".
Classification classification = (Classification) blcm.createClassification(cScheme, bundle.getString("classification.name"), bundle.getString("classification.value")); Collection classifications = new ArrayList(); classifications.add(classification); org.addClassifications(classifications);Next, it adds the JAX-RPC service, called "JAXRPCCoffee Service," and its service binding. The access URI for the service binding contains the endpoint URL that remote clients will use to contact our service:
http://localhost:8080/jaxrpc-coffee-supplier/jaxrpc/SupplierIFJAXR validates each URI, so an exception is thrown if the service was not installed before you ran this program.
Collection services = new ArrayList(); Service service = blcm.createService(bundle.getString("service.name")); InternationalString is = blcm.createInternationalString (bundle.getString("service.description")); service.setDescription(is); // Create service bindings Collection serviceBindings = new ArrayList(); ServiceBinding binding = blcm.createServiceBinding(); is = blcm.createInternationalString (bundle.getString("service.binding")); binding.setDescription(is); try { binding.setAccessURI(endpoint); } catch (JAXRException je) { throw new JAXRException("Error: Publishing this " + "service in the registry has failed because " + "the service has not been installed on Tomcat."); } serviceBindings.add(binding); // Add service bindings to service service.addServiceBindings(serviceBindings); // Add service to services, then add services to organization services.add(service); org.addServices(services);Then it saves the organization to the registry:
Collection orgs = new ArrayList(); orgs.add(org); BulkResponse response = blcm.saveOrganizations(orgs);The
BulkResponseobject returned bysaveOrganizationsincludes theKeyobject containing the unique key value for the organization. TheexecutePublishmethod first checks to make sure thesaveOrganizationscall succeeded.If the call succeeded, the method extracts the value from the
Keyobject and displays it:Collection keys = response.getCollection(); Iterator keyIter = keys.iterator(); if (keyIter.hasNext()) { javax.xml.registry.infomodel.Key orgKey = (javax.xml.registry.infomodel.Key) keyIter.next(); id = orgKey.getId(); System.out.println("Organization key is " + id); }Finally, the method returns the string
idso that theOrgPublisherprogram can save it in a file for use by theOrgRemoverprogram.Deleting the Service From the Registry
The
OrgRemoverprogram deletes the service from the Registry Server immediately before the service is removed. Like theOrgPublisherprogram, theOrgRemoverprogram starts by fetching values from theCoffeeRegistry.propertiesfile. One these values,keyFile, is the name of the file that contains the key that uniquely identifies the service.OrgPublisherreads the key from the file, connects to the Registry Server by invokingmakeConnection, and then deletes the service from the registry by callingexecuteRemove. Here is the source code for theOrgRemoverprogram:package com.sun.cb; import java.util.ResourceBundle; import javax.xml.registry.*; import javax.xml.registry.infomodel.Key; import java.io.*; public class OrgRemover { Connection connection = null; public static void main(String[] args) { String keyStr = null; ResourceBundle registryBundle = ResourceBundle.getBundle ("com.sun.cb.CoffeeRegistry"); String queryURL = registryBundle.getString("query.url"); String publishURL = registryBundle.getString("publish.url"); String username = registryBundle.getString("registry.username"); String password = registryBundle.getString("registry.password"); String keyFile = registryBundle.getString("key.file"); try { FileReader in = new FileReader(keyFile); char[] buf = new char[512]; while (in.read(buf, 0, 512) >= 0) { } in.close(); keyStr = new String(buf).trim(); } catch (IOException ex) { System.out.println(ex.getMessage()); } JAXRRemover remover = new JAXRRemover(); remover.makeConnection(queryURL, publishURL); javax.xml.registry.infomodel.Key modelKey = null; modelKey = remover.createOrgKey(keyStr); remover.executeRemove(modelKey, username, password); } }Instantiated by the
OrgRemoverprogram, theJAXRRemoverclass contains themakeConnection,createOrgKey, andexecuteRemovemethods. It is almost identical to the sample programJAXRDelete.java, which is described in Removing Data from the Registry.The
makeConnectionmethod is identical to theJAXRPublishermethod of the same name.The
createOrgKeymethod is a utility method that takes one argument, the string value extracted from the key file. It obtains theRegistryServiceobject and theBusinessLifeCycleManagerobject, then creates aKeyobject from the string value.The
executeRemovemethod takes three arguments: a username, a password, and theKeyobject returned by thecreateOrgKeymethod. It uses the username and password arguments to establish its security credentials with the Registry Server, just as theexecutePublishmethod does.The method then wraps the
Keyobject in aCollectionand uses theBusinessLifeCycleManagerobject'sdeleteOrganizationsmethod to delete the organization.Collection keys = new ArrayList(); keys.add(key); BulkResponse response = blcm.deleteOrganizations(keys);The
deleteOrganizationsmethod returns the keys of the organizations it deleted, so theexecuteRemovemethod then verifies that the correct operation was performed and displays the key for the deleted organization.Collection retKeys = response.getCollection(); Iterator keyIter = retKeys.iterator(); javax.xml.registry.infomodel.Key orgKey = null; if (keyIter.hasNext()) { orgKey = (javax.xml.registry.infomodel.Key) keyIter.next(); id = orgKey.getId(); System.out.println("Organization key was " + id); }
|
Home
TOC Index |
|
This tutorial contains information on the 1.0 version of the Java Web Services Developer Pack.
All of the material in The Java Web Services Tutorial is copyright-protected and may not be published in other works without express written permission from Sun Microsystems.