4.4 Smart Client with HTTP Front EndThe managed GUI bundle uses only a fraction of the power provided by the OSGi container. Through its services, the OSGi container supports external applications and devices over the network. To use a separate program to render the UI, we can more effectively separate the business and presentation layers.The "pizza order" example application distributed with the SMF illustrates the use of HTTP services in the OSGi framework. After starting the bundle from the SMF console, we can launch the device's built-in HTML browser (Internet Explorer for PocketPC or the Opera browser for Embedded Linux) and point the URL to http://localhost/pizza. An HTML page of a dummy pizza store appears. We can fill out the pizza order form, submit the form, and get response from a servlet running inside the bundle. The screen flow is shown in Figure 4.6. Figure 4.6. The pizza order application in action.![]() This design allows us to build a simple UI very quickly, using HTML without messaging with complex event handlers in AWT code. It also allows the vast majority of serverside Java developers to transfer their skills and make use of their familiar patterns, such as the Model-Viewer-Controller pattern. The overall architecture of the smart client with HTTP front end is illustrated in Figure 4.7. Figure 4.7. The smart client with HTTP front end.![]() 4.4.1 The Pizza Order BundleThe PizzaBundle class (Listing 4.8) implements the BundleActivator interface. This bundle does not register or provide any new services. It customizes the container HTTP service to serve pizza order HTML content at a specified URL. It also uses the container logging services to record activities inside the bundle. If no logging service has been registered for this bundle, it logs to the standard output. The bundle start() method instantiates trackers for LogService and HttpService. The bundle then invokes their open() methods.When the ServiceTracker for the HttpService is opened, it obtains all registered HttpService references from the container, adds them into the tracker, and invokes the corresponding ServiceTrackerCustomizer's addingService() method for each added reference.The addingService() method obtains the HTTP service object from the container and customizes it with the pizza order servlet and other resources.When the bundle stops, its stop() method calls the close() methods of the two ServiceTrackers. The HttpService tracker in turn calls the removedService() method, which unplugs the servlet from the HTTP service. Listing 4.8. The PizzaBundle class
4.4.2 The Pizza Order ServletIn the addingService() method, we use a servlet Pizza (Listing 4.9) to provide the custom HTTP service (the application logic). This is just a standard Java servlet that reads from HttpRequest and writes HTML data to HttpResponse objects. Those HTTP context objects are provided by the container. Listing 4.9. The Pizza servlet
4.4.3 The Logging ServiceA container can have multiple logging services. For example, one service implementation could log messages to a disk file while another could send the critical message as Instant Message alerts to administrators. The OSGi framework provides a common LogService interface for all logging services. Implementations of the LogService interface are provided and shared by individual bundles. In our pizza example, the LogTracker (Listing 4.10) object is a ServiceTracker object that tracks all available logging services from the container registry and makes sure each message is logged by all services. The LogTracker.open() method is invoked in the bundle start() method to initiate the tracker.LogTracker.open() calls its base class's open() method, which obtains all LogService references in the container.When the bundle needs to log a message, it calls the LogTracker.log() method, which iterates through the current list of tracked LogService references. It obtains the service object for each reference and pushes the message to all available logging services.If the container does not have any registered logging service (the reference list size is zero), the LogTracker object will call its noLogService() method to log to the standard output. NoteThe LogTracker class does not register any new LogService to the container.Listing 4.10. The LogTracker class
4.4.4 Rich UI Clients for the HTTP ServiceAlthough the pizza order example supports clearly separated application layers, the drawback is that it does not really take advantage of the rich UI capability of smart clients. There are several ways to create rich UI clients for the HTTP service.Rich browsers: Instead of plain HTML content, the servlet can provide rich content such as Java Applet and Flash for capable browsers.Standalone GUI: We can also replace the browser completely with a standalone GUI application. The OSGi HTTP service can serve binary or XUL (XML User Interface) content and allow the standalone GUI front end to decide how to render it. |