Implementing the Connector Pattern with Web Services


The event service demonstrated in the previous chapter is an excellent place to demonstrate the usefulness of the Connector pattern. You will use the event service as is but with a new event subscriber. The event subscriber is part of a larger application that receives events from the remote event service and posts them immediately to the user through a simple Java Swing user interface. The pattern implementation, shown in Figure 13-6, adds an application subscriber and the components that enable it to be a remote object.

click to expand
Figure 13-6: Event subscriber class diagram

As mentioned in the "Understanding the Structure of the Connector Pattern" section, the class diagram does not belie the nature of the deployment or some of the details inherent in actual implementation. In this case, the subscriber service implementation that resides in the Web tier uses an instance of the ApplicationSubscriberImpl_Stub instance to communicate with the ApplicationSubscriberImpl instance that resides in the application's process, as shown in Figure 13-7.

click to expand
Figure 13-7: Event forwarding through the physical tiers by the connector

The interface, ApplicationSubscriber , abstracts away the actual concrete class that the subscriber holds, which is simply a good practice employed by RMI users. Using the interface model, the service implementation, Subscriber , can look up an ApplicationSubscriber interface in the naming service and not worry about the implementation returned to them. In this case, the subscriber receives the stub.

Defining the Interface to the Implementation Side

To leverage RMI, you will first define the interface that both the concrete implementation class and the proxy to the implementation class implement. The service implementation could use the interface as well, though the signatures to the methods do not have to match between the service implementation and the remote implementation class. Listing 13-1 contains the interface implementation.

Listing 13-1: Interface to the Remote Implementation Class
start example
 public interface ApplicationSubscriber extends Remote {    public void update(String eventId, String data) throws RemoteException; } 
end example
 

There should be nothing too interesting in the interface. To implement the class as a remote object, the class extends java.rmi.Remote and the methods in the class throw the java.rmi.RemoteException exception.

Building the Implementation Class

The class for the application subscriber implements the interface in Listing 13-1 and extends the java.rmi.server.UnicastRemoteObject class. This class extension makes your object remoteable and gives it the ability to be registered with the naming service from RMI and subsequently receive method calls from outside of the process.

The class is a part of a larger Swing-based application. Its responsibilities include the following:

  • Receiving events from a remote target ”in this case the service implementation subscriber that serves as a bridge to an external event service

  • Posting the events directly to a text area for the application user to see

To fulfill the second responsibility, the application passes a reference to the JTextArea graphic component on the constructor that this class instance uses to post messages for the user. Listing 13-2 illustrates the application-side subscriber that serves as the implementation class.

Listing 13-2: Application-Side Event Subscriber
start example
 public class ApplicationSubscriberImpl    extends java.rmi.server.UnicastRemoteObject    implements ApplicationSubscriber {    JTextArea ivTextArea = null;    public ApplicationSubscriberImpl(JTextArea textArea) throws RemoteException {     super();     ivTextArea = textArea;    }    public ApplicationSubscriberImpl(int port, JTextArea textArea)      throws RemoteException {      super(port);      ivTextArea = textArea;    }    public void update(String eventId, String data) throws RemoteException {      ivTextArea.append("Event ID: "+eventId);      ivTextArea.append("Event Data: "+data);    } } 
end example
 

The service implementation (the subscriber that serves as the Web Service) calls the update method on this class. This class, in turn , writes the data from the event to the application's text area by simply appending the event data to the text area. In reality, you would have a more user-centric mechanism for notifying the user of an important event that needs their attention.

This class requires special handling on instantiation. To facilitate communication between the service implementation deployed through Apache Axis and this application-side implementation class, the class must register with RMI's component registry, the Naming service. The service implementation can then use Naming to look up the class from an outside process and communicate through the proxy.

Building Remote Stubs

J2SE comes with an RMI compiler, rmic , that handles the details of building the application-side implementation stub generation. The stub is subsequently instantiated into the same process that runs the service implementation; thus, the interface must at least be in the class path for the Apache Axis engine.

Your build process ”in this case, the Apache Ant build process that comes with the source code for the book ”automatically builds the stubs when the code is recompiled.

Implementing the Web Service

The previous classes and the interface concerned themselves with the concrete behavior of the application that the service implementation calls upon receiving a request. Also in the previous sections, you built the mechanisms that the service implementation uses to have a conversation with the application-side (or logic tier) components.

This section enhances the subscriber from the event service built in the Publish/Subscribe pattern to forward messages to the application with an interest in the events published by the event service. The difference in the implementation code from the previous chapter occurs in the update method, shown in Listing 13-3. You no longer print information to the System.out stream in the body of the update method. Instead, you retrieve a proxy to the implementation, through RMI's Naming service, and call methods against the proxy.

Listing 13-3: Subscriber Web Service Implementation
start example
 public class Subscriber {   private static String topic =     "com.servicefoundry.books.events.ProductOrderUpdate";   ApplicationSubscriber appSubscriber = null;   public Subscriber() {   }   public void update(String eventId, String data){     try {       ApplicationSubscriber appSubscriber =       (ApplicationSubscriber)Naming.lookup("ApplicationSubscriberImpl");       if(appSubscriber!=null){          appSubscriber.update(eventId, data);       }     } catch (Exception e) {       e.printStackTrace();     }   } } 
end example
 

Listing 13-3 retrieves the proxy from RMI's Naming every time Apache Axis calls the update method. This allows the application to start and stop at will without impacting the Web Service. The Web Service continues to receive events from the remote event service when the user application is not available, but it stops delivering events to the user application. One of the nice attributes of splitting the logic and Web tiers in terms of the process that contains them is the additional ability to leverage code and classes independently of the containers. For example, users can continue to use applications when the Web Service environment is not available.

This service implementation deploys to Apache Axis in the same manner as the subscriber in the previous chapter. The same Web Services Description Language (WSDL) created in the previous chapter describes the interface to this subscriber, and the event service has no realization that this implementation differs from the previous chapter's implementation.

Seeing the Event Service in Action with the New Subscriber

Putting the new subscriber Web Service into action requires several steps worth noting. The steps described here do not necessarily have to occur in the order described; however, exceptions to the step order accompany the description:

  1. Start the event service built in the previous chapter. This Web Service runs unmodified from the previous chapter.

  2. Start the stand-alone application. By starting the stand-alone application, you also start the subscriber implementation class that resides within the application. Further, the application registers the RMI object with the RMI Naming service, with the application code shown in Listing 13-4, in the local RMI registry. After this step, other processes can download the remote stub class from Naming and communicate with the application's subscriber implementation. Recall that this step does not have to occur before the Web Service subscriber implementation starts because the Web Service will simply ignore events that post to it if an appropriate subscriber cannot be located.

  3. Start the subscription Web Service built in this chapter and register it with the event service started in step 1. This step can occur before or after step 2. After the subscription Web Service starts, register its target Uniform Resource Locator (URL) with the event service started in step 1. At this point, events delivered to the event service, started in step 1, with the appropriate topic post to the event subscriber started in this step. The event subscriber started in this step then forwards the event to the application subscriber started in step 2.

  4. Next, post an event to the Web Service with the client from the previous chapter.

  5. Finally, view the results of the post to the Web Service in the stand-alone application's graphical text area.

Listing 13-4 contains a method run by the stand-alone application to register its subscriber to RMI's Naming component. The application uses this code as described in step 2 after initialization of the user interface but before clients can interact with the application.

Listing 13-4: Registering the Application's Subscriber with RMI's Naming Service
start example
 public static void registerToRegistry(     String name, Remote obj, boolean create)     throws RemoteException, MalformedURLException{     if (name == null)         throw new IllegalArgumentException(         "registration name can not be null"         );     try {        Naming.rebind(name, obj);     } catch (RemoteException ex){       if (create) {         Registry r =           LocateRegistry.createRegistry(Registry.REGISTRY_PORT);         r.rebind(name, obj);       } else throw ex;     } } 
end example
 

The client creates the application subscriber and registers it with the code shown in Listing 13-5. The ivTextArea instance variable refers to a JTextArea graphical component created earlier in the application.

Listing 13-5: Creating the Application-Side Subscriber and Registering the Subscriber
start example
 ApplicationSubscriberImpl obj = new ApplicationSubscriberImpl(ivTextArea); ApplicationSubscriberImpl.registerToRegistry(  "ApplicationSubscriberImpl", obj, true); 
end example
 

In Listing 13-5, you registered the application subscriber using the name ApplicationSubscriberImpl . The Web Service implementation uses this name to locate the proxy to the application in RMI's Naming service, as shown previously in Listing 13-3. Once the service implementation in the Web tier has a reference to the proxy, the proxy facilitates the remote communication with the logic tier and the concrete implementation of the application subscriber logic.




Web Service Patterns
Web Services Patterns: Java Edition
ISBN: 1590590848
EAN: 2147483647
Year: 2003
Pages: 190

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net