Enterprise J2ME Developing Mobile Java Applications [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Enterprise J2ME Developing Mobile Java Applications [Electronic resources] - نسخه متنی

Michael Juntao Yuan

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید



4.4 Smart Client with HTTP Front End


The 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 Bundle


The 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


public class PizzaBundle implements
BundleActivator, ServiceTrackerCustomizer {
/** BundleContext for this bundle */
protected BundleContext context;
/** Log Service wrapper object */
protected LogTracker log;
/** Http Service tracker object */
protected ServiceTracker tracker;
/** HttpContext for HTTP registrations */
protected HttpContext httpContext;
// ... ...
public PizzaBundle() { }
// Methods in BundleActivator
public void start(BundleContext context) throws Exception {
this.context = context;
httpContext = new HttpContext() { ... ... };
log = new LogTracker(context, System.err);
tracker = new ServiceTracker(context,
HttpService.class.getName(), this);
tracker.open();
}
public void stop(BundleContext context) throws Exception {
tracker.close();
log.close();
}
// Methods for ServiceTrackerCustomizer
public Object addingService(ServiceReference reference) {
HttpService http = (HttpService)context.getService(reference);
if (http != null) {
try {
http.registerServlet(servletURI,
new Pizza(), null, httpContext);
http.registerResources(servletURI+imagesURI,
imagesURI, httpContext);
log.log(log.LOG_INFO, "Pizza Servlet registered");
} catch (Exception e) {
// handle the exception
}
}
return http;
}
public void modifiedService(ServiceReference
reference, Object service) {
}
public void removedService(ServiceReference
reference, Object service) {
HttpService http = (HttpService) service;
http.unregister(servletURI);
http.unregister(servletURI+imagesURI);
context.ungetService(reference);
log.log(log.LOG_INFO, "Pizza Servlet unregistered");
}
}


4.4.2 The Pizza Order Servlet


In 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



import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
public class Pizza extends HttpServlet {
protected void doGet(HttpServletRequest req,
HttpServletResponse res)
throws ServletException, IOException {
// Generate some output
res.setContentType("text/html;" + "charset=iso-8859-1");
PrintWriter out = res.getWriter();
out.print(" ... ... ");
// Get query parameters
String queryString = req.getQueryString();
// any pizza order logic
// ... ...
out.println("</body></html>");
}
}


4.4.3 The Logging Service


A 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.


Note

The LogTracker class does not register any new LogService to the container.

Listing 4.10. The LogTracker class


public class LogTracker
extends ServiceTracker implements LogService {
protected final static String clazz =
"org.osgi.service.log.LogService";
protected PrintStream out;
public LogTracker(BundleContext context, PrintStream out) {
super(context, clazz, null);
this.out = out;
open();
}
// Implements various log() messages with
// different signatures.
// ... ...
public synchronized void log(ServiceReference reference,
int level, String message, Throwable exception) {
ServiceReference[] references = getServiceReferences();
if (references != null) {
int size = references.length;
for (int i = 0; i < size; i++) {
LogService service = (LogService) getService(references[i]);
if (service != null) {
try {
service.log(reference, level, message, exception);
} catch (Exception e) { }
}
}
return;
}
noLogService(level, message, exception, reference);
}
protected void noLogService(int level, String message,
Throwable throwable, ServiceReference reference) {
if (out != null) {
synchronized (out) {
switch (level) {
case LOG_DEBUG: {
out.print("Debug: ");
break;
}
case LOG_INFO: {
out.print("Info: ");
break;
}
case LOG_WARNING: {
out.print("Warning: ");
break;
}
case LOG_ERROR: {
out.print("Error: ");
break;
}
default: {
out.print("Unknown Log level[");
out.print(level);
out.print("]: ");
break;
}
}
out.println(message);
if (reference != null) {
out.println(reference);
}
if (throwable != null) {
throwable.printStackTrace(out);
}
}
}
}
}


4.4.4 Rich UI Clients for the HTTP Service


Although 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.



/ 204