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

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

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

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

Michael Juntao Yuan

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

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

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



4.3 A Simple Echo Service Example


In this section, we first introduce a J2ME-compatible OSGi implementation from IBM. Using a simple echo example, we demonstrate how to implement bundles and share services among them.


4.3.1 The IBM Service Management Framework


The IBM SMF is a readily available OSGi implementation. It has a memory footprint of 3 MB and runs on both execution environments defined in the OSGi Service Platform Release 3 specification. IBM supports the J2ME environments through WME (WebSphere Micro Environment JVM) and the minimum execution environment through WCE (WebSphere Custom Environment JVM) products. It can be tightly integrated into IBM's WebSphere Studio Device Developer IDE. The SMF product versions we cover in this book are v3.1 for OSGi R2 and v3.5 for OSGi R3.

The SMF installation process varies among devices. It generally involves the following steps.


Download and unpack the SMF toolkit from IBM.

Copy the following directories and files to the target device (or to a local execution directory, if you want to run SMF on a desktop computer). For my PocketPC device, I put all four items under the device root directory.

The jarbundles directory contains installed bundles.

The smf.jar file provides implementation classes for the OSGi specification.

The smfconsole.jar file provides a command-line management console for the container.

The smf.properties file specifies the runtime configuration.


Make sure that the com.ibm.osg.smf.bundledir property in the smf.properties file points to the correct bundle directory. For example,


com.ibm.osg.smf.bundledir=jarbundles

Now we can start the SMF console using the following command (in one line) or its equivalent on the device platform.


java -classpath "smf.jar:smfconsole.jar"
com.ibm.osg.smf.SMFLauncher -console "launch"

For my PocketPC device with IBM WebSphere Micro Environment preinstalled, I use the following command (in one line). Please refer to the Appendix B for the steps to install the IBM J2ME runtimes on PDA devices.


"\WSDD\j9.exe" -jcl:foun
"-Xbootclasspath:\WSDD\lib\jclFoundation\classes.zip;
\smf.jar;\smfconsole.jar" "com.ibm.osg.smf.SMFLauncher"
-console "Launch"


After the SMF console is started, it loads all currently installed bundles into the container and presents the user a command-line interface for management tasks. For a complete list of management commands, please refer to the SMF manual. Figure 4.2 shows the command-line console on desktop and PocketPC devices. Table 4.3 lists some of the most frequently used commands.


Figure 4.2. The SMF console on desktop and PocketPC devices.


Table 4.3. Common Commands Available in the SMF Console

Command

Description

install url

Installs a bundle from a URL and returns a bundle ID. The URL could point to files on the local file system, such as file:/path/bundle.jar.

update id

Updates the package from the same URL as specified by the install command.

uninstall id

Uninstalls the bundle.

start id

Starts the bundle.

stop id

Stops the bundle.

bundle id

Displays information about an installed bundle.

status

Displays all installed bundles and registered services.

packages

Displays the imported and exported packages for each bundle.

close

Shuts down the container and exits the console.

In the next two sections, we describe how to create and deploy two OSGi bundles: The EchoService bundle exposes an echo service; the EchoUIConsumer bundle presents a simple GUI client and uses the EchoService in the container to echo user input. Figures 4.3 and 4.4 show the two bundles in action in J2SE and J2ME OSGi containers. Figure 4.5 shows user interactive OSGi bundles.


Figure 4.3. The echo bundles in action in J2SE.



Figure 4.4. The echo bundles in action in J2ME.



Figure 4.5. OSGi bundles with UIs.



4.3.2 The EchoService Bundle


The EchoService bundle demonstrates how to implement and register a service in an OSGi bundle. The service itself is extremely simple: It only defines one method that does nothing more than echo a string input. The steps to create the bundle are as follows.


Define the service interface as a Java interface (Interface EchoService, Listing 4.1).

Create an implementation class for the interface (Class EchoserviceImpI, Listing 4.2).

Create a BundleActivator, class that implements the required OSGi life-cycle methods and registers the service with the container upon startup (Class EchoActivator, Listing 4.3).

Create a manifest file that specifies the BundleActivator class for this bundle and exports the service interface package (Listing 4.4). The OSGi container uses the manifest to find the entry point of the bundle and collect necessary configuration data.

Package the compiled classes and manifest file into a standard Jar file.


Listing 4.1. The EchoService interface


package com.enterprisej2me.osgi.echoservice;
public interface EchoService {
public String echo (String s);
}

Listing 4.2. The EchoServiceImpI class


package com.enterprisej2me.osgi.echoserviceimpl;
import com.enterprisej2me.osgi.echoservice.*;
public class EchoServiceImpl implements EchoService {
EchoServiceImpl () { }
public String echo (String s) {
return s;
}
}

Listing 4.3. The EchoActivator class


package com.enterprisej2me.osgi.echoserviceimpl;
import org.osgi.framework.*;
import com.enterprisej2me.osgi.echoservice.*;
public class EchoActivator implements BundleActivator {
private ServiceRegistration reg;
public EchoActivator () { }
public void start (BundleContext context) throws Exception {
EchoServiceImpl impl = new EchoServiceImpl ();
reg = context.registerService (
EchoService.class.getName(), impl, null);
}
public void stop (BundleContext context) throws Exception {
reg.unregister ();
}
}

Listing 4.4. The JAR manifest for the echo service bundle


Manifest-Version: 1.0
Bundle-Name: Echo service
Bundle-Description: Echo the input
Bundle-Activator: com.enterprisej2me.osgi.echoserviceimpl.EchoActivator
Import-Package: org.osgi.framework; specification-version=1.1
Export-Package: com.enterprisej2me.osgi.echoservice
Export-Service: com.enterprisej2me.osgi.echoservice.EchoSerivce

Now, we can install and start the package in our SMF console.


4.3.3 The EchoUIConsumer Bundle


The EchoUIConsumer bundle is created to demonstrate how to use the echo service through the framework:


Create a BundleActivator implementation as the entry point to the bundle (Class EchoUIConsumer, Listing 4.5).

In the EchoUIConsumer.start() method, create and open a ServiceTracker object to track the echo service we started.

Create the UI frame class EchoFrame (Listing 4.6) and pass the ServiceTracker object and the current bundle (i.e., the echo consumer bundle) to EchoFrame.

The EchoFrame object obtains the EchoService object from the ServiceTracker and uses the EchoService to echo any user input. When we hit the Exit button in the UI frame, the AWT event handler calls the bundle's stop() method and triggers the container to invoke the EchoUIConsumer.stop() method. For more details, refer to method actionPerformed() in Listing 4.6.

In the EchoUIConsumer.stop() method, dispose the UI frame and close the ServiceTracker (Listing 4.5).

Create the manifest file (Listing 4.7). We import the package containing the EchoService interface here.

Package and deploy the JAR bundle.



Tracking the Services


In the service consumer bundles, we could manually look up the service objects from the framework. Then, we would have to register event listener and callback methods to handle situations when other bundles or the container itself changes those services (e.g., removes the service). This could be a tedious task. Instead, we take a shortcut and use a pair of ServiceTracker objects to automatically track those services.

The ServiceTracker object tracks a list of services meeting certain criteria passed to it in the constructor. It provides default event handlers for the services it tracks.

The ServiceTracker object can be instantiated with a ServiceTrackerCustomizer object. When a service in the tracker is added, modified, or deleted, the appropriate method in its associated ServiceTrackerCustomizer is called. For more usage examples of the ServiceTracker class, please refer to Section 4.4.

Listing 4.5. The EchoUIConsumer class


package com.enterprisej2me.osgi.echouiconsumer;
import org.osgi.framework.*;
import org.osgi.util.tracker.*;
import com.enterprisej2me.osgi.echoservice.*;
public class EchoUIConsumer implements BundleActivator {
ServiceTracker echoTracker;
EchoFrame frame;
public EchoUIConsumer () { }
public void start (BundleContext context) {
echoTracker = new ServiceTracker (context,
EchoService.class.getName(), null );
echoTracker.open ();
frame = new EchoFrame(250, 250, echoTracker, context.getBundle());
}
public void stop (BundleContext context) {
frame.dispose ();
echoTracker.close();
}
}

Listing 4.6. The EchoFrame class


package com.enterprisej2me.osgi.echouiconsumer;
import java.awt.*;
import java.awt.event.*;
import org.osgi.framework.*;
import org.osgi.util.tracker.*;
import com.enterprisej2me.osgi.echoservice.*;
public class EchoFrame extends Frame
implements WindowListener, ActionListener {
private TextField entryText;
private Label echoedText;
private Button submit;
private Button exit;
private Panel content, top, bottom, middle;
private ServiceTracker echoTracker;
private Bundle echoUIConsumerBundle;
public EchoFrame (int width, int height,
ServiceTracker t, Bundle b) {
super ("Echo UI");
setBounds(0, 0, width, height);
echoTracker = t;
echoUIConsumerBundle = b;
entryText = new TextField (20);
echoedText = new Label (" ");
submit = new Button ("Echo");
exit = new Button ("Exit");
submit.addActionListener (this);
exit.addActionListener (this);
top = new Panel ();
middle = new Panel ();
bottom = new Panel ();
top.setLayout(new FlowLayout(FlowLayout.LEFT));
top.add(new Label("Echo: "));
top.add(echoedText);
middle.setLayout(new FlowLayout(FlowLayout.LEFT));
middle.add(new Label("Input: "));
middle.add(entryText);
bottom.setLayout(new FlowLayout(FlowLayout.CENTER));
bottom.add(submit);
bottom.add(exit);
content = new Panel ();
content.setLayout(new GridLayout(3, 1));
content.add(top);
content.add(middle);
content.add(bottom);
add (content);
addWindowListener(this);
pack ();
setVisible (true);
}
public void actionPerformed (ActionEvent e) {
if ( e.getSource() == submit ) {
top.remove (echoedText);
// Obtain the echo service object
EchoService echoObj = (EchoService) echoTracker.getService();
// Use the echo service to echo a string
echoedText = new Label ( echoObj.echo(entryText.getText()) );
top.add (echoedText);
entryText.setText(");
setVisible (true);
} else if ( e.getSource() == exit ) {
// see note
// echoUIConsumerBundle.stop();
dispose ();
}
}
public void windowClosing(WindowEvent e) {}
public void windowOpened(WindowEvent e) {}
public void windowClosed(WindowEvent e) {}
public void windowIconified(WindowEvent e) {}
public void windowDeiconified(WindowEvent e) {}
public void windowActivated(WindowEvent e) {}
public void windowDeactivated(WindowEvent e) {}
}

Listing 4.7. The manifest file for the echo consumer bundle


Manifest-Version: 1.0
Bundle-Name: Echo UI consumer
Bundle-Description: Consume the echo service
Bundle-Activator: com.enterprisej2me.osgi.echouiconsumer.EchoUIConsumer
Import-Package: com.enterprisej2me.osgi.echoservice,
org.osgi.framework; specification-version=1.1,
org.osgi.util.tracker; specification-version=1.1
Import-Service: com.enterprisej2me.osgi.echoservice.EchoSerivce


Limitations of the Bundle State-Change APIs


Note that when we exit the EchoFrame UI, it merely disposes the UI window but does not stop the underlying bundle. That is because the synchronous state-change APIs in the current OSGi specification do not allow a bundle to change its own state safely. This limitation is being addressed by the OSGi expert group. When it is resolved in a future OSGi edition, the EchoFrame exit event handler can simply call the echoUIConsumerBundle.stop() method to dispose the window and stop the bundle.


The Espial DeviceTop


The Espial DeviceTop is an OSGi implementation running on PersonalJava platforms. In addition to standard OSGi services, it provides an application service that supports bundles with GUIs. The bundle's BundleActivator class can extend the espial.devicetop.refui.Application class, which automatically takes care of the interactions between the UI frame and the bundle itself. With Espial's proprietary Espresso UI library, we can create sophisticated mobile UI applications on the DeviceTop framework.


/ 204