Download PDF Home History |  | API Search Feedback FAQ

> ## 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 the `placeOrder` and `getPriceList` methods, which are defined by the `SupplierIF` 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, the `placeOrder` method confirms every order and sets the ship date in the confirmation to the next day. The source code for the `placeOrder` 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 a `PriceListBean` object, which lists the name and price of each type of coffee that can be ordered from this service. The `getPriceList` method creates the `PriceListBean` object by invoking a private method named `loadPrices`. In a production application, the `loadPrices` method would fetch the prices from a database. However, our `loadPrices` method takes a shortcut by getting the prices from the `SupplierPrices.properties` file. Here are the `getPriceList` and `loadPrices` 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 the `contextInitialized` and `contextDestroyed` methods respectively.

> The `c` `ontextInitialized` method begins by retrieving the registry and endpoint URLs and coffee registry properties. Both the context initializer and destroyer call the `makeConnection` 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 URLs retrieved from a resource bundle.

>     Properties props = new Properties();
>     props.setProperty("javax.xml.registry.queryManagerURL",
>       queryUrl);
>     props.setProperty("javax.xml.registry.lifeCycleManagerURL",
>       publishUrl);
>     props.setProperty("com.sun.xml.registry.http.proxyHost",
>       httpProxyHost);
>     props.setProperty("com.sun.xml.registry.http.proxyPort",
>       httpProxyPort);
>     props.setProperty("com.sun.xml.registry.https.proxyHost",
>       httpsProxyHost);
>     props.setProperty("com.sun.xml.registry.https.proxyPort",
>       httpsProxyPort);

> 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 the `executePublish` method, which accepts as input `connection`, `username`, `password`, and `endpoint`. The `username` and `password` values are required by the registry server. The `endpoint` value is the URL that remote clients will use to contact our JAX-RPC service. The `executePublish` method of `JAXRPublisher` returns a key that uniquely identifies the service in the registry. `The` `contextInitialized` method saves this key in a text file named `orgkey.txt`. The `contextDestroyed` method reads the key from `orgkey.txt` so that it can delete the service. See Deleting the Service From the Registry. The source code for the `contextInitialized` method follows.

>     public void contextInitialized(ServletContextEvent event) {
>       ResourceBundle registryBundle =
>         ResourceBundle.getBundle("com.sun.cb.CoffeeBreak");

>       String queryURL = registryBundle.getString("query.url");
>       String publishURL = registryBundle.getString("publish.url");
>       System.out.println(queryURL);
>       System.out.println(publishURL);

>       String username =
>         registryBundle.getString("registry.username");
>       String password =
>         registryBundle.getString("registry.password");
>       String keyFile = registryBundle.getString("key.file");

>       JAXRPublisher publisher = new JAXRPublisher();
>       ServletContext context = event.getServletContext();

>       String endpointURL = URLHelper.getEndpointURL();

>       Connection connection =
>         makeConnection(queryURL, publishURL);

>       if (connection != null) {
>         String key = publisher.executePublish(connection,
>           username, password, endpointURL);
>         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 program `JAXRPublish.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 a `RegistryService` object and then a `BusinessQueryManager` object and a `BusinessLifeCycleManager` 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 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 `JAXRPCCoffeeSupplier`, and a `User` 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.CoffeeBreak");

>     // 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:

>     org.setPrimaryContact(primaryContact);

> 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 by `saveOrganizations` includes the `Key` object containing the unique key value for the organization. The `executePublish` method first checks to make sure that the `saveOrganizations` 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 the `contextInitialized` method can save it in a file for use by the `contextDestroyed` method.

> ### Deleting the Service From the Registry

> The `contextDestroyed` method deletes the service from the Registry Server. Like the `contextInitialized` method, the `contextDestroyed` method starts by fetching the registry URL and other values from the `CoffeeBreak.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 invoking `makeConnection`, and then deletes the service from the registry by calling `executeRemove`. Here is the source code for the `contextDestroyed` method:

>     public void contextDestroyed(ServletContextEvent event) {
>       String keyStr = null;

>       ResourceBundle registryBundle =
>         ResourceBundle.getBundle("com.sun.cb.CoffeeBreak");

>       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();
>       Connection connection = makeConnection(queryURL,
>         publishURL);
>       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, the `JAXRRemover` class contains the `createOrgKey` and `executeRemove` methods. It is almost identical to the sample program `JAXRDelete.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 the `RegistryService` object and the `BusinessLifeCycleManager` object, and then creates a `Key` object from the string value.

> The `executeRemove` method takes four arguments: a connection, a user name, a password, and the `Key` object returned by the `createOrgKey` method. It uses the `username` and `password` arguments to establish its security credentials with the registry server, just as the `executePublish` method does.

> The method then wraps the `Key` object in a `Collection` and uses the `BusinessLifeCycleManager` object's `deleteOrganizations` 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 the `executeRemove` 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);
>     }

Download PDF Home History |  | API Search Feedback FAQ

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.