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/src
directory. The source code for theSupplierIF
interface, which follows, resides in the <JWSDP_HOME
>/docs/tutorial/examples/cb/jaxrpc/src
directory.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
SupplierImpl
class implements theplaceOrder
andgetPriceList
methods, which are defined by theSupplierIF
interface. 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
placeOrder
method accepts as input a coffee order and returns a confirmation for the order. To keep things simple, theplaceOrder
method 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/common
subdirectory.) The source code for theplaceOrder
method 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
getPriceList
method returns aPriceListBean
object, which lists the name and price of each type of coffee that can be ordered from this service. ThegetPriceList
method creates thePriceListBean
object by invoking a private method namedloadPrices
. In a production application, theloadPrices
method would fetch the prices from a database. However, ourloadPrices
method takes a shortcut by getting the prices from theSupplierPrices.properties
file. Here are thegetPriceList
andloadPrices
methods: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
OrgPublisher
andOrgRemover
. These programs are not part of the service's Web application. They are stand-alone programs that are run by theant
set-up-service
command. (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
OrgPublisher
program begins by loadingString
values from theCoffeeRegistry.properties
file. Next, the program instantiates a utility class namedJAXRPublisher
.OrgPublisher
connects to the registry by invoking themakeConnection
method ofJAXRPublisher
. To publish the service,OrgPublisher
invokes theexecutePublish
method, which accepts as inputusername
,password
, andendpoint
. Theusername
andpassword
values are required by the Registry Server. Theendpoint
value is the URL that remote clients will use to contact our JAX-RPC service. TheexecutePublish
method ofJAXRPublisher
returns a key that uniquely identifies the service in the registry.OrgPublisher
saves this key in a text file namedorgkey.txt
. TheOrgRemover
program will read the key fromorgkey.txt
so that it can delete the service. (See Deleting the Service From the Registry.) The source code for theOrgPublisher
program 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
JAXRPublisher
class is almost identical to the sample programJAXRPublish.java
, which is described in Managing Registry Data.First, the
makeConnection
method 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.properties
file. 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
makeConnection
method creates the connection, using the connection properties:ConnectionFactory factory = ConnectionFactory.newInstance(); factory.setProperties(props); connection = factory.createConnection();The
executePublish
method takes three arguments: a username, a password, and an endpoint. It begins by obtaining aRegistryService
object, then aBusinessQueryManager
object and aBusinessLifeCycleManager
object, 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
Organization
object with the name "JAXRPCCoffeeDistributor," then aUser
object 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
BulkResponse
object returned bysaveOrganizations
includes theKey
object containing the unique key value for the organization. TheexecutePublish
method first checks to make sure thesaveOrganizations
call succeeded.If the call succeeded, the method extracts the value from the
Key
object 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
id
so that theOrgPublisher
program can save it in a file for use by theOrgRemover
program.Deleting the Service From the Registry
The
OrgRemover
program deletes the service from the Registry Server immediately before the service is removed. Like theOrgPublisher
program, theOrgRemover
program starts by fetching values from theCoffeeRegistry.properties
file. One these values,keyFile
, is the name of the file that contains the key that uniquely identifies the service.OrgPublisher
reads 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 theOrgRemover
program: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
OrgRemover
program, theJAXRRemover
class contains themakeConnection
,createOrgKey
, andexecuteRemove
methods. It is almost identical to the sample programJAXRDelete.java
, which is described in Removing Data from the Registry.The
makeConnection
method is identical to theJAXRPublisher
method of the same name.The
createOrgKey
method is a utility method that takes one argument, the string value extracted from the key file. It obtains theRegistryService
object and theBusinessLifeCycleManager
object, then creates aKey
object from the string value.The
executeRemove
method takes three arguments: a username, a password, and theKey
object returned by thecreateOrgKey
method. It uses the username and password arguments to establish its security credentials with the Registry Server, just as theexecutePublish
method does.The method then wraps the
Key
object in aCollection
and uses theBusinessLifeCycleManager
object'sdeleteOrganizations
method to delete the organization.Collection keys = new ArrayList(); keys.add(key); BulkResponse response = blcm.deleteOrganizations(keys);The
deleteOrganizations
method returns the keys of the organizations it deleted, so theexecuteRemove
method 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.