Enabling the Wireless Enterprise with Java 2 Micro Edition

Enabling the Wireless Enterprise with Java 2 Micro Edition

By Mark Balbes, Ph.D., OCI Senior Software Engineer

November 2001


Introduction

In a previous article, Java 2 Micro Edition: Java for Small and Embedded Systems, we explored how Java 2 Micro Edition (J2ME) can be used to program Palm devices. A lot has changed on the J2ME landscape since then.

In this article, I will give you an update on the current state of J2ME. We will then explore how J2ME can be used to extend your enterprise applications to wireless devices.

The Mobile Information Device Profile

The Mobile Information Device Profile (MIDP) is the first J2ME profile to be available on multiple devices.

Currently, MIDP is supported on:

During 2002, we will see other mobile phone networks support MIDP, including Sprint, which recently announced support by mid-2002.

One obvious omission is the current lack of MIDP support on PocketPC. However, PersonalJava implementations with more capabilities than MIDP are available, and the J9 VM from IBM should soon support MIDP.

MIDP provides four major additions to the Connected Limited Device Configuration (CLDC) we discussed in the previous article:

  1. A well-defined lifecycle for the application
  2. A GUI toolkit
  3. Persistent storage
  4. HTTP networking capabilities

1. MIDlets – Controlling the Lifecycle of a MIDP Application

The entry point to any MIDP application is the MIDlet class defined in the javax.microedition.midlet package.

Just as the Applet class contains methods that allow a browser to control the lifecycle of an applet, the MIDlet contains similar methods, which are manipulated by a device-dependent application manager. However, unlike an applet, a MIDlet is not a GUI component.

The MIDlet class defines the methods startApp(), pauseApp(), and destroyApp(), which can be called either by the MIDlet itself or by an application manager on the device.

The application manager is responsible for creating the MIDlet and starting it. It will also pause the MIDlet when necessary, such as when a phone call comes in, and it will destroy the MIDlet if there is an uncaught exception (see Figure 1).

Figure 1: MIDlet Lifecycle

Fig 1: MIDlet Lifecycle

Here is a simple HelloMIDlet that shows how to use these methods.

  1. import javax.microedition.midlet.*;
  2.  
  3. public class HelloMIDlet extends MIDlet {
  4.  
  5. public void startApp() {
  6. System.out.println("Hello MIDlet");
  7. }
  8.  
  9. public void pauseApp() {}
  10. public void destroyApp(boolean unconditional) {}
  11. }

Since the MIDlet class is not a GUI component, the above code has no screen presence. Depending on the device, you may not even see "Hello MIDlet" printed out. On most emulators, standard out is redirected to a console window.

Each time the user invokes the MIDlet, "Hello MIDlet" will be sent to standard out. Since we don't have to do anything special when the MIDlet is paused or destroyed, these methods are empty.

Typically, pauseApp() and destroyApp() would contain any code needed to free resources that were grabbed by startApp(). It is important to remember that startApp() can be called multiple times during the lifetime of the MIDlet.

If you need to perform a task only when the application is first started, for example showing a splash screen, it will be necessary to set an appropriate flag in the startApp() method.

2. Building User Interfaces with MIDP

Building a GUI in MIDP is very different from the Java 2 Standard Edition (J2SE).

In J2SE, we have a rich set of visual components that we can place in our application using layout managers. In MIDP, the assumption is that the screen is not large enough to display a lot of components at once.

It is also desirable to display the application in a way that is natural for the device it is running on. Just as AWT applications look different on different computer systems, MIDP applications may look different on different devices.

MIDP specifies both high-level and low-level user interface APIs in the javax.microedition.lcdui package.

The high-level API specifies a small set of Screen objects, only one of which can be shown at a time. Because of the limited size of the devices, we leave behind the notion of layout managers. When the object is shown, it takes up all of the screen real estate available to MIDP (note that some of the screen may be reserved for device-specific information, as well).

High-level objects include an AlertListTextBox and Form. See the table below for a description of each.

High Level GUI Components

We can now improve our HelloWorld MIDlet so that it displays "Hello World" on the device's screen.

  1. import javax.microedition.midlet.*;
  2. import javax.microedition.lcdui.*;
  3.  
  4. public class HelloMIDlet extends MIDlet implements CommandListener {
  5. private Command exitCommand;
  6. private Display display;
  7.  
  8. public HelloMIDlet() {
  9. this.exitCommand = new Command("Exit", Command.SCREEN, 2);
  10. }
  11.  
  12. public void startApp() {
  13. this.display = Display.getDisplay(this);
  14. TextBox textBox = new TextBox("Hello MIDlet", "Hello World!", 256,
  15. TextField.ANY);
  16. textBox.addCommand(this.exitCommand);
  17. textBox.setCommandListener(this);
  18. this.display.setCurrent(textBox);
  19. }
  20.  
  21. public void pauseApp() {}
  22. public void destroyApp(boolean unconditional) {}
  23.  
  24. public void commandAction(Command command, Displayable displayable) {
  25. if (command == this.exitCommand) {
  26. destroyApp(false);
  27. notifyDestroyed();
  28. }
  29. }
  30. }

Note that if a phone call is received while HelloMIDlet is running, the MIDlet is paused. When the user resumes HelloMIDletstartApp() is called again, and the GUI is recreated from scratch.

In a more sophisticated application, you may instead test if display is null to determine if the GUI needs to be built.

The HelloMIDlet class above is built using the high-level GUI components. It also uses a Command to indicate that the user has the option to exit the application.

Commands can be associated with any Screen component except an Alert; unfortunately, adding a Command to an Alert will produce a runtime error, not a compiler error.

The same command can be associated with multiple screens. Depending on the type of command (as defined by constants in the Command class), the command may be mapped to a hardware key or a soft key on the device. For example, an exit command may be mapped to the "hang up" key on a phone.

It is up to the device manufacturers to map the commands appropriately. MIDP gives no direct control to the developer for the placement of the commands. Indirectly, we can affect the placement by manipulating the command's type and priority.

In addition to the high-level API, the lcdui package also defines a Canvas class, which provides similar drawing functionality to the AWT Canvas.

The Canvas class also provides methods to access pointer and keyboard events. This allows the developer to create interactive games or custom components. However, cross-device compatibility may be compromised.

For example, a game that relies on pointer-based events may not work on a phone. On the other hand, a game that only uses key events will be awkward – but possible – to use on a Palm device.

Thankfully, Canvas gives us methods like hasPointerEvents(), so we can write code that works in either environment.

3. Persistent Storage

MIDP provides the ability to persistently store data on a device. The javax.microedition.rms package defines classes to support data persistence across different invocations of the MIDlet and across device power outs.

Only one concrete class, RecordStore, is defined. It has static methods to create and destroy data stores, as well as instance methods to manipulate the contents of a record store. A single record is stored as an array of bytes.

Having persistent data on the device itself allows network-dependent MIDP applications to run, even when the network is inaccessible. For example, an application could store data on the device when no network is available and then send that data to a server at a later time.

A full exploration of the capabilities of the MIDP persistent storage mechanism will be the subject of a future article.

4. HTTP Networking

The CLDC defines a Connector framework to support networking. The framework is much smaller than the J2SE network-support classes; however, it is very flexible and easy to use.

The CLDC itself does not require support for any specific protocols. MIDP requires that HTTP support is available.

Creating an HTTP connection on a MIDP device is quite easy. The following code opens an HTTP connection, sends a GET request, and reads some text from the response.

  1. /**
  2.   * Use an HTTP GET request to retrieve the contents of the URL as a string.
  3.   * @param url location of the desired information
  4.   * @return the contents of the URL.
  5.   */
  6. public static String get(String url) throws IOException {
  7. HttpConnection httpConnection = null;
  8. InputStream inputStream = null;
  9. String content;
  10. try {
  11. httpConnection = (HttpConnection) Connector.open(url);
  12. httpConnection.setRequestProperty("User-Agent",
  13. "Profile/MIDP-1.0 Configuration/CLDC-1.0");
  14. httpConnection.setRequestProperty("Content-Language", "en-US");
  15.  
  16. // Check that everything is OK
  17. int status = httpConnection.getResponseCode();
  18. if (status != HttpConnection.HTTP_OK) {
  19. // we could choose to handle redirects here by looking
  20. // for a status of HttpConnection.HTTP_TEMP_REDIRECT,
  21. // HttpConnection.HTTP_MOVED_TEMP, or
  22. // HttpConnection.HTTP_MOVED_PERM
  23. throw new IOException("Server response not OK");
  24. }
  25.  
  26. // Get the response back from the server
  27. inputStream = httpConnection.openInputStream();
  28.  
  29. String type = httpConnection.getType(); // Get the ContentType
  30. int length = (int) httpConnection.getLength();
  31. if (length > 0) {
  32. byte[] responseData = new byte[length];
  33. int actual = inputStream.read(responseData);
  34. content = new String(responseData);
  35. } else {
  36. StringBuffer stringBuffer = new StringBuffer();
  37. int ch = inputStream.read();
  38. while (ch != -1) {
  39. stringBuffer.append((char) ch);
  40. ch = inputStream.read();
  41. }
  42. content = stringBuffer.toString();
  43. }
  44. } finally {
  45. if (inputStream != null) {
  46. inputStream.close();
  47. }
  48. if (httpConnection != null) {
  49. httpConnection.close();
  50. }
  51. }
  52.  
  53. return content;
  54. }

Extending the Enterprise

One of the most exciting aspects of J2ME is that it enables us to extend our network infrastructures into the wireless world. Using the networking classes described above, we can write software for wireless devices that interact with a server.

In order to demonstrate how to wirelessly enable an enterprise application, we will create a small client-server system that consists of:

Tools

As with any job, it is important to have the right tools.

There are several tools available on the market today for J2ME development. Sun has the J2ME Wireless Toolkit, which can run in stand-alone mode or as an integrated piece of Forte for Java. JBuilder 5 includes integration with the Nokia toolkit. Motorola and Nokia offer tools through their developer web sites designed to work with their phones.

See the References below for links to these sites.

Building the Servlet

We will write a simple servlet that simply echoes the data sent to it by the client (for more about servlets, see the previous SETT article What is a Servlet?).

The servlet will do all of the following:

The code for the servlet, named EchoServlet, can be found here.

You can access the servlet directly by typing its URL into your browser and appending some request parameters:

www.example.com/J2ME/echo?myParam=Test+Param.

In the URL above, "myParam" is the parameter name and "Test+Param" is the parameter value, where the "+" is used to represent a space between the two words.

Building the HTML Browser Client

Now we will create an HTML front end to our application. Don't get too excited, though. We will create a simple web page that lets us test our Servlet.

Simply type in a parameter value and click the GET or POST button. This will send the text to the servlet in a GET or POST request, respectively.

Building the MIDP Client

Now that we have our servlet working, and we've tested it with our web browser, we can begin the much more interesting task of creating a MIDP client.

The client consists of the WirelessMIDlet class and the HTTPHelper class. The MIDlet builds the user interface, and HTTPHelper contains utility functions to send HTTP GET and POST requests to a given URL and retrieve the responses as text.

The application itself consists of four screens (see the images below):

  1. Initially, a splash screen is shown.
  2. Next, the user can type in the URL for the servlet. For convenience, the URL of our servlet is the default value.
  3. Next, the user can enter in two name/value pairs and choose to either use GET or POST to send the data.
  4. Once the servlet sends back a response, it is displayed in an Alert.

Splash Screen

URL Entry Screen

Parameter Entry Screen

GET/POST Options

Results Screen

Summary

We have explored how J2ME MIDP can break the tether of the wired connection, gaining us access to enterprise functionality in the wireless world. Using the simple and well-understood HTTP protocol, MIDlets can access data anywhere on the Internet.

It is important to remember that, although we have access to all of the information on the Internet, MIDP applications should not be modeled after the familiar web browser paradigm to which we have all become accustomed.

Because of the limited screen size, awkward input mechanisms, low computing power, and slow connection speeds of these wireless devices, the browsing paradigm of the Web does not work. Instead, MIDP applications must be small, targeted applications that solve a single problem quickly and easily with a minimum of user involvement.

References



Software Engineering Tech Trends (SETT) is a regular publication featuring emerging trends in software engineering.