Download
FAQ History |
API
Search Feedback |
JAX-RPC Coffee Supplier Service
The Coffee Break servers are clients of the JAX-RPC coffee supplier service. The service code consists of the service interface, the 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 the JavaBeans components listed in the preceding section.The source code for the
SupplierIF
interface, which follows, resides in the<
INSTALL
>/j2eetutorial14/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 would 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. The source code for theplaceOrder
method follows:public ConfirmationBean placeOrder(OrderBean order) { Date tomorrow = DateHelper.addDays(new Date(), 1); ConfirmationBean confirmation = new ConfirmationBean(order.getId(), DateHelper.dateToCalendar(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(DateHelper.dateToCalendar(today), DateHelper.dateToCalendar(endDate), priceItems); return priceList; }Publishing the Service in the Registry
Because we want customers to find our service, we publish it in a registry. When the JAX-RPC Web application is started and stopped, the context listener object
ContextListener
publishes and removes the service in thecontextInitialized
andcontextDestroyed
methods respectively.The
contextInitialized
method begins by retrieving the registry and endpoint URLs and coffee registry properties. Both the context initializer and destroyer call themakeConnection
method, which 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 registry URL retrieved from a context parameter. 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 a connection factory it looks up using JNDI:context = new InitialContext(); factory = (ConnectionFactory) context.lookup("java:comp/env/eis/JAXR"); factory.setProperties(props); connection = factory.createConnection();
Next, the program instantiates a utility class named
JAXRPublisher
. To publish the service,the
contextInitialized
method invokes theexecutePublish
method, which accepts as inputconnection
,username
,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.The
contextInitialized
method saves this key in a text file namedorgkey.txt
. ThecontextDestroyed
method reads the key fromorgkey.txt
so that it can delete the service. See Deleting the Service From the Registry. The source code for thecontextInitialized
method follows.public void contextInitialized(ServletContextEvent event) { String registryURL = context.getInitParameter("registryURL"); String endpoint = URLHelper.getEndpointURL(); ResourceBundle registryBundle = ResourceBundle.getBundle(" com.sun.cb.CoffeeRegistry"); String username = registryBundle.getString("registry.username"); String password = registryBundle.getString("registry.password"); String keyFile = registryBundle.getString("key.file"); Connection connection = makeConnection(registryURL, registryURL); if (connection != null) { String key = publisher.executePublish(connection, username, password, endpoint); try { FileWriter out = new FileWriter(keyFile); out.write(key); out.flush(); out.close(); } catch (IOException ex) { System.out.println(ex.getMessage()); } try { connection.close(); } catch (Exception je) {} } }The
JAXRPublisher
class is almost identical to the sample programJAXRPublish.java
, which is described in Managing Registry Data.The
executePublish
method takes four arguments: the connection to the registry server, a user name, a password, and an endpoint. It begins by obtaining aRegistryService
object and 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, the
executePublish
method then uses theusername
andpassword
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 nameJAXRPCCoffeeSupplier
, and aUser
object that will serve as the primary contact. This code is almost identical to the code in the JAXR examples.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);The
executePublish
method adds a telephone number and email address for the user, then makes the user the primary contact:It gives
JAXRPCCoffeeSupplier
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 URL for the service binding contains the endpoint URL that remote clients will use to contact our service:http://localhost:8080
/jaxrpc-coffee-supplier/jaxrpc 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); binding.setValidateURI(false); binding.setAccessURI(endpoint); 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 that 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
contextDestroyed
method deletes the service from the Registry Server. Like thecontextInitialized
method, thecontextDestroyed
method starts by fetching the registry URL and other values from theCoffeeRegistry.properties
file. One these values,keyFile
, is the name of the file that contains the key that uniquely identifies the service.The
contextDestroyed
method 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 thecontextDestroyed
method:public void contextDestroyed(ServletContextEvent event) { String keyStr = null; String registryURL = context.getInitParameter("registryURL"); ResourceBundle registryBundle = ResourceBundle.getBundle("com.sun.cb.CoffeeRegistry"); 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(); Connection connection = makeConnection(registryURL, registryURL); if (connection != null) { javax.xml.registry.infomodel.Key modelKey = null; modelKey = remover.createOrgKey(connection, keyStr); remover.executeRemove(connection, modelKey, username, password); try { connection.close(); } catch (Exception je) {} } }Instantiated by the
contextDestroyed
method, theJAXRRemover
class contains thecreateOrgKey
andexecuteRemove
methods. It is almost identical to the sample programJAXRDelete.java
, which is described in Removing Data from the Registry.The
createOrgKey
utility method takes two arguments; the connection to the registry server and the string value extracted from the key file. It obtains theRegistryService
object and theBusinessLifeCycleManager
object, and then creates aKey
object from the string value.The
executeRemove
method takes four arguments: a connection, a user name, a password, and theKey
object returned by thecreateOrgKey
method. It uses theusername
andpassword
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.
Download
FAQ History |
API
Search Feedback |
All of the material in The J2EE(TM) 1.4 Tutorial is copyright-protected and may not be published in other works without express written permission from Sun Microsystems.