|
|
 |
February 2005
Networked J2ME Applications
Table of Contents - Introduction
- The Problem
- A Solution
- Pros and Cons of Cell Phones
- Why J2ME
-
Overall Architecture
-
Technology Stack
-
Client Technology
-
The Server Side
-
Development Tools
-
Rolling Out The Application
-
Jar file size
-
Scalability
-
In Conclusion
-
References
-
Thank You
Introduction
This paper explores the various facets of building a J2ME application.
It assumes a working knowledge of Java. The focus is on a MIDP 1.0/CLDC
1.0 application that depends heavily on network access.
I have been working with Java for the past four years, primarily in web
application development. For the past year and a half, I have worked on a team
developing a J2ME
application; most of the information presented here has been gained in
that experience.
The Problem
Imagine you are commuting in traffic. There is a long line of cars ahead
of you on the interstate; there is a line at the next exit.
It looks like a wait either way. Luckily,
you subscribe to a traffic congestion service.
If you use your cell phone to enter your location, the service can return high congestion
areas close to you. Hitting the brakes in frustration, you
enter the cross streets just ahead. The traffic service queries a
database of
current traffic in your city, and informs you that
there is congestion on the cross street ahead, making the interstate a
better choice. You turn up the radio
and leave the other cars on the exit ramp behind.
This problem has some salient characteristics: users need information, and
may not be in front of their computer. Data only needs to be queried,
not entered, and does not require complex presentation. In addition, the immediacy
of access is more important than depth of information.
Other characteristics of this type of problem include: users may be non
technical, more than one remote system may be involved, and control over
such systems may
be distributed--there may be one or more traffic congestion reporting
databases in a given city.
To sum up, the problem that this paper will examine is: what is the best way to allow real time, read only
access, for remote, possibly non-technical users, to an information system, or set of
systems. In this paper,
I explain why cell phones clients are a good answer to this type of problem.
In addition, I also show how Java 2 Micro Edition
(J2ME) is a good platform for such a client. I also outline some
of the design choices and technical issues faced when
building a J2ME client to access a system like the traffic congestion
service.
A Solution
Cell phones are increasingly powerful and available computing platforms.
They differ from desktop and higher end mobile clients in a number of ways.
Relative to most other computing devices (embedded systems are a notable
exception), cell phones have slower persistent storage, less memory, smaller screens, slower
processors, and more limited user interfaces.[1] However, while by no
means perfect, there are a number of compelling reasons to use
cell phones to
solve this type of problem.
Pros and Cons of Cell Phones
Advantages of Cell Phones
Cellular phones allow access to the Internet in a wider area
and at a lower cost than competing technologies. Wi-fi is cheaper
and faster, but does not have the broad coverage. Satellite based
networks have greater coverage, but can not compete on price (see
Iridium).
Cell phones are widely available and familiar to most people.
Users have or can easily purchase cell phones, and cell phones are more
common than other wireless Internet solutions (such as laptops with
wireless phone cards or wi-fi). Many people are likely to be
comfortable with cell phone applications because of this familiarity.
Cell phones are a reasonably sophisticated platform. There are a number of
options when deciding how to develop a mobile application, all offering
significant functionality.
More and more cellular phones will allow an application to retrieve the location
of the phone. Such knowledge, combined with GIS data, can allow for
unique and valuable applications. Imagine pushing traffic jam
locations as a subscriber approached them. (Positing the
existence of the back end systems, such a service is possible today, on
some higher end phones.)
Of course, cell phones are not a panacea. The technology has
limitations.
When not to use cell phones
For a complicated user interface, or one where a user needs to
input significant amounts of data, cell phones are a poor
choice. Since they typically have only the familiar twelve number buttons
and two programmable softbuttons, the input interface is limited. Even a
small amount of data entry can make a cell phone application
tedious.
In contrast to the web browser, which has a relatively forgiving
and well known interface, some users might not be comfortable running
programs on their cell phones. I expect this to change as cell phones
become more accepted as a computing platform by normal people.
If users need permanent access to remote data, cellular phones
are not the right client. Cell phone networks are not renowned for their
reliability.
(Of course, no wireless technology can promise uninterrupted network access, but
others may come closer.)
There is a mishmash of competing solutions when it comes to cell phone
development. Both the device manufacturers and the cell phone service
providers, also known as carriers, play a role in the availability of APIs
and platforms. For an application that needs to run uniformly
everywhere, cell phones might be too diverse a platform.
It is clear that sometimes cell phones are not the best solution for
networked data access, especially if there are extensive connectivity or
user interface requirements. However, for a significant set of problems,
like the traffic congestion service, they can be a cost effective
solution. For read only, real time access to a remote database, cell
phones work. They deal with users' remote locations, immediate need to
query data and money concerns.[2] Why J2ME
There are five major cell phone platforms available today: Symbian,
Windows Mobile, BREW, WAP and J2ME.[3] Each is worth investigating;
depending on the nature of the problem to be solved and the resources
and people available, a particular platform may stand out. Frankly, J2ME
was chosen to solve my problem not only because it was a good technical
fit, but also because the developers were familiar with Java.
Cell phone platform options
Symbian
is an operating system for cell phones. Later versions of Symbian do
support J2ME.[4]
Windows
Mobile is Microsoft's mobile solution. This platform is aimed at
relatively high-end devices and developers with Windows expertise.
BREW is a C++ based
framework that has support from Verizon. Developers for this platform can
rely upon the phone carrier for billing and deployment. However, the
certification process required for such support is an obstacle
for small companies. IBM has built a JVM for BREW.[5]
WAP is an excellent cell
phone platform. Some form of it is
supported on almost all modern phones; this is a strong selling point.
The markup which sits on top of WAP 2.0 is
XHTML.[6] Due to that fact,
there is very little caching or data validation that can be done on the client.
J2ME is a Java based platform
for cell phones. It includes everything
needed to solve the traffic congestion service problem set: a GUI, persistent
data storage, and network access. It is supported by a majority of cell
phone carriers in the US, has no licensing issues, and is well
documented.
J2ME is not without its warts, including a large
number of specifications and technologies. Features that many
Java developers consider fundamental (RMI, for example) are implemented at the
discretion of the device manufacturer. Early versions
of the platform are well supported among newer phones, including less
expensive models, but later versions of J2ME are supported by
far fewer phones.
One benefit of choosing J2ME is the widespread
support for this platform. In addition to the Symbian and BREW support
mentioned above, there are implementations for PalmOS and methods of
turning J2ME applications into native Blackberry
applications.[7] J2ME applications are also
relatively easy to deploy initially, especially when compared to BREW
applications.
Overall Architecture
In this section I examine the possible architectural choices and some of
their benefits.
The J2ME application living on the cell phone will need to communicate
with the remote systems.
Using the traffic congestion service as an example, there are two
alternative designs for this kind of system.
Architectural Options
Each cell phone could communicate with every required city traffic system.
This solution distributes the networking and processing load
onto many clients, but also means that each client needs to know how to
communicate with each remote system (assuming the remote systems do not
share the exact same protocol and implementation).
There could be a single intermediary server which would communicate with
each of the cell phones and each of the city traffic systems. This means the
intermediate server is a single point of failure (unless made redundant,
perhaps via clustering) but also that each
client only needs to be able to communicate with one server (via one
protocol).
The second solution, illustrated below, is better. By keeping the client
simple and pushing complexity to the server, the complexity becomes easier
to manage. Mitigating the weaknesses of cell phones--a slow processor,
weak user interface, slow and intermittent network access--is a secondary
benefit.
 The intermediary server architecture. The cell phone
communicates via the carrier's network to the intermediary server, which
processes requests and dispatches them to other systems, as needed. Other benefits of the intermediary server architecture
Though cell phones are constantly improving, they are still low powered
consumer devices.
There are certain activities that, while perhaps achievable on a cell
phone, are easier done on a server. If the traffic congestion service
offloads complicated tasks, such as email notifications to family or friends regarding late
arrival or map generation for route finding, to the server, more
functionality can be offered without complicating the client.
It is possible to cache information retrieved from the city traffic
systems at the intermediary server. Therefore, when everyone is stuck at
one interchange, the city traffic database is not queried
repeatedly, and users will see better performance.
For development purposes, the intermediary server offers fewer interactions
to manage and debug. Rather than M x N interactions caused by
M clients talking to N systems, there are M+N interactions.
Authentication and access control become easier; the single server can
handle these sometimes complicated tasks. The traffic congestion service
can easily make sure users have paid and if there are premium features added,
one point of authorization makes controlling access easier.
When the protocol to access the city traffic systems change there is
no need to track down and persuade users to upgrade the application
on their cell phone; instead the intermediary server can be easily upgraded.
Clients can use whatever protocol is best for communicating over the
wireless network, rather than being forced to understand the (perhaps
different) protocols of the remote systems.
However, an intermediary server means more testing and more
code to maintain, and if that server fails, the application is
inaccessible. However, the alternative architecture, each client
talking to each remote system, is a protocol management nightmare,
requiring complex J2ME clients.
Technology Stack
In this section I examine the technologies used to roll out a
network application based on the J2ME platform.
Client Technology
Before examining implementation details of a
networked J2ME client, it is worth exploring the basics
of the J2ME platform and the applications written for it,
known as midlets.
Basics of J2ME
Pieces of the J2ME platform
CLDC stands for Connected Limited Device Configuration. In J2ME, a
“configuration specification defines the minimum
required complement of
Java technology components and libraries for small connected
devices”[8], including almost all of the supported classes in the
java.lang package.
Most cell phones will use this configuration.
(There is another configuration, the Connected Device Configuration,
for higher end devices.) At the time of writing, there are two
versions of the CLDC: 1.0 and 1.1.
MIDP stands for Mobile Information Device Profile. This is a
higher level API with which most developers will interact, and includes
classes for the
user interface, persistent data storage and other functionality.[9] Currently, there are two versions of this API:
1.0 and 2.0.
Optional packages are a crucial part of the J2ME platform, even though
they seem to lack the requisite acronym.
There is functionality that has been
standardized by the JCP and that is a defined part of the J2ME platform:
APIs such as JDBC, RMI and location based services (LBS).
However, it may not be appropriate to have this functionality on every
device. Therefore, it is not part of a profile or configuration, the
implementation of which are mandatory. For example, if a device does
not have the processor speed to support RMI marshalling and
unmarshalling, the manufacturer may choose not to implement that package.
But if they do, they must conform to the specification.
Optional packages must be implemented by the phone manufacturer; they are
not simple libraries that a developer can include with his midlet.
The J2ME platform on a given device consists of a device configuration (for example, CLDC) and a device
profile (for example, MIDP), plus optional packages. In general,
the configuration sits below the profile, and different versions of each
may be paired. The configuration handles lower level interactions with
the device, whereas the profile handles user interface and other higher level
abstractions. Separating these allows them to evolve at different paces.
The J2ME API intersects with J2SE. Depending on the versions of the
profile and configuration chosen, the java.io,
java.lang, and
java.util packages will be present (the red area below). In addition,
there are some J2ME specific classes, in the javax.microedition package
(the green area below). This package includes sub-packages which hold user interface,
lifecycle, I/O and other J2ME specific classes.
 Intersection between J2SE and J2ME
platforms
If a class is present in both J2ME and J2SE, there is an attempt to make the
classes compatible. However, it is an attempt, not a promise. From section
6.1.2 of the CLDC 1.0a spec: “The majority of the libraries included in CLDC are a subset of
the larger Java editions (J2SE and J2EE) to ensure upward compatibility
and portability of applications. While upward compatibility is a
very desirable goal, J2SE and J2EE libraries have strong internal
dependencies that make subsetting of them difficult in important areas
such as security, input/output, user interface definition, networking
and storage. These dependencies are a natural consequence of design
evolution and reuse that has taken place during the development of
Java libraries over time. Unfortunately, these dependencies make it
very difficult to take just one part of the libraries without including
several others. For this reason, we have redesigned some of the libraries,
especially in the areas of networking and I/O.”
This “subsetting” is evident in many places. The
String
class in JDK 1.3 has 47 non deprecated methods, not including those
inherited from
Object, including compareToIgnoreCase and
intern. These methods are not among the 34 included in the
CLDC 1.0 implementation of the String class. And when
compared with the more feature-laden JDK 1.4 String class,
J2ME omits many more methods.
Entire classes are missing (the white area area above), including such
useful classes as java.util.Collections and java.util.Properties.
Most of the differences are outlined in section 5 of the CLDC 1.0a
specification.
Sometimes the differences are subtler. Just as in J2SE,
the Thread class should not be stopped via the
stop method. Where the J2SE Thread class
has a deprecated stop()
method [10],
J2ME simply does not have the stop
method [11].
Note that differences outlined above are configuration and profile dependent.
Differences in the library classes are the obvious incompatibilities, but
there are also language feature
differences between J2ME and J2SE. In J2ME, JNI is disallowed and
asserts are not supported.
I was unable to track down exactly what version of the java language J2ME
supports, but my experience has been that it supports the language features
of JDK 1.3 and has a library similar to JDK 1.1 (Vectors and
Hashtables). The bytecode is similar to that of J2SE,
with a few differences.[12]
In short, J2ME is similar enough to J2SE to allow use of many of the same
tools, and a developer competent in one can pick up the other quickly.
There are two files needed for a J2ME application. One is the jar file,
the typical zipped archive of
classes and resources. The other is the
jad file (see Example 1, “Sample jad File”), which is very similar in purpose, if not in format, to the
web.xml descriptor used in java web applications. The jad file contains information
about the midlet which is used by the phone on installation.
Example 1. Sample jad File
1 MIDlet-1: SampleMidlet, , com.foo.SampleMidlet
2 MIDlet-Jar-Size: 74274
3 MIDlet-Jar-URL: SampleMidlet.jar
4 MIDlet-Name: SampleMidlet
5 MIDlet-Vendor: SampleMidletVendor
6 MIDlet-Version: 1.0
7 MicroEdition-Configuration: CLDC-1.0
8 MicroEdition-Profile: MIDP-1.0
(Line numbers are not part of the file.) There must be a entry similar to
line 1 for each midlet
in the jar file, including the name of the midlet,
an optional icon filename, and the full name of the midlet class (which must extend
javax.microedition.midlet.MIDlet). The
jar file listed on line 3 must be the size listed on line 2. For this
reason, jad files are often generated.
Lines 4 and 5 are shown during the application installation process. Line 6 is
used for versioning during the installation process--some phones
prompt the user during midlet install if there exists on the phone a midlet
of the same name and version number.
Lines 7 and 8 indicate the versions of the configuration and profile
that this application requires.
Client Specifics
Applications aiming for a wide user base of consumers, such as the traffic
congestion service, would be best served by
supporting the CLDC 1.0 and MIDP 1.0 specifications because these
are the earliest mature specifications; both were released in 2000.
They are also the most widely supported of the J2ME specifications.
Different problem sets may require different API choices, though.
For example, an application may need to perform floating point
calculations or access the location of the phone. In such cases, later
specifications may be worth looking at: CLDC 1.1 supports
java.lang.Float[13] and has support for LBS.
In the next sections,
I will explore some of the basic ingredients of a J2ME application,
including user interface, navigation, and networking.
User Interface
J2ME user interface development is similar to Swing
development. Applications are structured around a series of
screens. The main user interface elements are strings and images to convey
information, and text input fields and choice groups (similar to radio buttons) to gather information. All
of these elements are placed on a Form, a class similar to
JPanel. Unlike
Swing, where there are several different
layout managers, in MIDP, there is exactly one. This layout adds
elements to the screen, each in their own row.
If absolute control over drawing the screen is important, the
Canvas and Graphics classes, which according to
the MIDP 1.0 specification, are “designed for applications that
need precise placement and control of graphic elements and access to
low-level input events.”
Since the user interface is limited, it is a good idea to ease information
entry whenever possible. Do not use a text field, which forces users
to enter letters and numbers using the keypad, when a choice
group, which lets users
select one option among many, will work. Do not present a
choice group when there is only one valid choice.
Specify constraints for text fields when possible.[14]
Do not make the screens too large, as then users will have to scroll.
However, balance this against the number of screens needed to
collect data and try to attain a happy medium.
Provide sane defaults whenever possible--commonly
selected options or example values can make the application easier to use.
Find out what parts of the application are most important to the user
and make them prominent.
 Softbuttons with multiple actions associated
A typical cell phone has two soft buttons, used to handle high
level actions (as opposed to low level events like keypad button releases).
More than one action can be associated with a softbutton,
but doing so means a more complex navigation, as shown above.
Use softbuttons wisely--minimize the number of actions associated with them.
J2ME user interface issues are similar to those of other software
environments, but requirements are more stringent. The MIDP 1.0 spec
suggests a screen size of at least 96x54 pixels, which does not give
application developers
much room for mistakes. In addition, the “consumer device”
nature of most
cell phones means that usability expectations of installed applications
are high--unlike a computer, where training is the expectation, I feel
that most people expect to pick up a cell phone and be able to use
installed programs.
Application Navigation
In order to flow from one screen to another and
enable users to return to previous states in the application, a stack
can be used. Whenever a user chooses
to go to a different state, the current form is pushed on to the stack.
If the user returns to the previous state, the
application pops the stack and brings back the previous form.
This design is Model 1.
Each screen knows the transitions available to the user.
This architecture is a simple solution, easy
to understand, and keeps the client small. Having a central
configuration and controller, like many web frameworks, is overkill for a
typical J2ME application.
Networking
Since applications like the traffic congestion application depend so
heavily on real time data access, networking is important.
Networking access in J2ME
requires understanding threads.
As in Swing, in J2ME there is a system thread responsible for
redrawing the screen. This thread should not block for
any reason, including waiting for I/O or network access. In some
emulators, the blocking behavior is not emulated
correctly, but the flaw is apparent when an application is running on
a real phone: the phone locks up. Why? Many phones require user
permission for an application to access the network--and if the system thread is busy trying to access
said network, it cannot respond to the user's permission granting;
deadlock ensues.
Separate threads access the network but what will the communication between
the cell phone and the intermediary server look like?
Options for Data Transfer Between Server and Client
A proprietary scheme over sockets is the fastest method of data
transfer, but will be brittle if data requirements change. In addition,
MIDP 1.0/CLDC 1.0 do not support sockets.
A proprietary scheme, such as fixed width fields or key value pairs,
over HTTP is another option. HTTP is supported, but such a scheme will,
again, be brittle in the face of change.
RMI is the best of all worlds--since the application is so
dependent on network access anyway, why not have it be
transparent and just ship objects back and forth between the server and the
client? Unfortunately, RMI is an optional
package.[15] Requiring RMI will thus limit the number
of devices on which the application can run.
SOAP is a great option. However, it can be a bit heavyweight at
times[16].
XML over HTTP is easy to build, can be used for different clients fairly
trivially, can be debugged in a browser, and can leverage all of the
tools available for testing websites.
In the end, a custom XML format was chosen. When processing
the XML, a third party library was used[17], and the strings were decoded into
java objects. These java objects were then passed on to the user interface.
Javabeans with synchronized getters and setters and the producer
consumer pattern were used to
ensure that the user interface did not display information until it
had been retrieved from the network. Below is s a sample network interaction
explained in the context of the traffic congestion service.
 Sequence Diagram for Retrieving And Displaying Information
From the Network
First, the user enters an address.
The User Input Form object creates the Wait object, which displays a
'Waiting for Data' message to the user. The Wait object starts a new
thread, the Logic object, that is responsible for retrieving and processing the
data, and passes itself to the Logic object as a reference. The Wait object is
pushed onto the display stack maintained by the Controller object, by the
User Input Form, which then
causes the Wait object to be drawn on the screen. Meanwhile, in the Logic
object,
network access is deferred to yet another thread, the Network
Worker. The Logic object communicates with the Network Worker through one or
more Transfer objects, which are simply beans with synchronized get and set
methods to which both the Logic and Network Worker objects have
references. The Network Worker
connects to the network, and receives an XML input
stream containing information regarding the traffic jams around the address
the user entered, which it puts in the Transfer object (see Example 2, “Network Connection Code” for code). The Logic object has been
waiting for this input stream, and processes it by parsing the
XML into domain objects (see Example 3, “XML Parsing Code” for code). These objects are then passed back to the Wait state,
which then creates a new Form object, passing the retrieved data to the new
Form in its constructor. Then the Wait object passes control to the new
Form by pushing it onto the stack.
This then
causes the Form to be drawn on the device, displaying whatever data has been
retrieved from the network and perhaps prompting the user for more data.
Example 2. Network Connection Code
1 hc = (HttpConnection) Connector.open(urlst);
2 if (null != sessionCookie) {
3 hc.setRequestProperty("cookie", sessionCookie);
4 }
5 if (post) {
6 hc.setRequestMethod(HttpConnection.POST);
7 hc.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
8 hc.setRequestProperty("Content-Length", Integer.toString(message.length()));
9 out=hc.openOutputStream();
10 if (null != out){
11 out.write(message.getBytes());
12 }else{
13 Log.logError("couldn't write post data to output stream");
14 }
15 } else {
16 hc.setRequestMethod(HttpConnection.GET);
17 }
18 hc.setRequestProperty("Connection", "close");
19 is = hc.openInputStream();
20 t1.setPayload(is);
This is a section of the Network Worker object's run() method.
It opens up a network connection on line 1, attaches a cookie to the
request on lines 2-4, sets appropriate properties depending on
whether the HTTP request is a POST or a GET on lines 5-18, and retrieves
the input stream containing the server's response on line 19. The input
stream is then passed to a transfer object on line 20.
Example 3. XML Parsing Code
1 while ((event = parser.read()).getType() != Xml.END_DOCUMENT) {
2 int type = event.getType();
3 if ( (type == Xml.START_TAG) && (event.getName().equals("INTERSECTION"))) {
4 String name = event.getName();
5 IdDescriptionPair intersection = new IdDescriptionPair();
6 intersection.id = event.getValue("code");
7 intersection.desc = event.getValue("description");
8 returnVector.addElement(intersection);
9 }
10 }
XML input is parsed by checking for start tags on line 3. The scenario
here is that the traffic service application does not have enough
information based on the address entered, so a set of suggested intersections
is returned. Intersection
data, as represented by the INTERSECTION tag, has two attributes,
code and description. The values of those attributes are placed
into a domain value object on lines 6 and 7. There will likely be more
than one, so a Vector is used on line 8 to hold all of them
for iteration and display on the screen.
Networking code has some phone specific peculiarities. In particular,
the header handling has been different between phones.
On some Motorola phones, when there is more than one cookie, the
later ones are not seen. In addition, handling cancel events
means communicating back to the network accessing thread; this
communication can only happen at certain times (not when
the thread is blocking on network access). Also, most phones ask users if
an application can access the network, since doing so costs the user money.
If the user says no, a security exception is thrown, and must be
handled by the application.
These issues, as well as the deadlock issue mentioned above, make it
clear that testing on as many real phones and emulators as possible helps
smoke out non standard behavior that will adversely affect the user experience.
Cell phone applications exhibit decent network performance. The user
experience has depended greatly upon the cell phone network--some
carriers simply have higher data transfer rates than others. This is not
a rigorous analysis, but while demoing applications, I have
never seen it take more than ten seconds or so to download ten KB
of information from the network.
Security
Mobile phones are lost, stolen or
misplaced more easily than laptops. Anything that needs
to be secure should not be on a cell phone; if data needs to be secure and
must reside on the cell phone, look at encrypting
it. In the case of the traffic congestion client, sensitive
data, including authentication tokens to remote databases, could be kept on the server.
Permanent storage
Cell phones have static memory which J2ME exposes via the recordstore API,
using classes in the javax.microedition.rms package.
Recordstores are an
array of byte arrays. The store is easier to work with if
treated as a persistent hashtable.[18]
Images that are downloaded from the network and then displayed can be
cached in the recordstore for a performance increase. However, doing so
requires storing the raw byte[] array before displaying the
image.
Such a a byte[] array can be easily turned into an
javax.microedition.lcdui.Image
object, displayable on a screen. However, there is no way to turn an
Image object into a byte[] array after it has been
created.
The Server Side
The server that the J2ME application will communicate with need not be
complex.
A typical open source J2EE application will suffice:
Apache, fronting a tomcat servlet engine, with struts as the MVC framework,
and using mysql as a datastore. I am only going to address a few points
where the nature of the J2ME client influences the intermediary server.
The struts framework can be used in two separate
scenarios: to build a typical web application, allowing users to sign
up and pay for the
traffic congestion service as well as other account management activities
best done with a browser, and also to generate XML for the cell phone
application. In the second case, not all
the features of struts need to be used--client side validation
and action forms are both superfluous, for example. Since all that is
communicated between the the cell phone and the server application
are sets of XML messages, the main benefit of
the action form, validation and error messages, is not useful.
When transmitting binary data such as images, a
simple custom servlet streamed the data as a
java.io.ByteArrayOutputStream over HTTP.[19]
JSPs can be used to generate XML. Since WAP supports a subset
of XHTML, adding another view layer to the server application is easy.
(This took about 6 hours for our application
and not a single Java class was touched.)
However, limitations of WAP mean advanced features
are not available to the WAP browser client--in particular, information
collection for a given
request can (and should) be spread over multiple screens with the rich
client, while it must be gathered on one screen with the WAP browser.
In order to generate and manipulate images, JAI
was used. It is poorly
documented; the main form of documentation, javadoc,
does not provide much help for beginners, and the tutorial is a few versions
behind. However, the mailing
list is very useful. The JAI library can be used to transform GIFs
and JPGs into PNGs.[20]
JAI can be used to flatten images from 24 to 8 bit color. Since images are
shown on cell phone
displays of such small resolution, trading color depth for download
speed can be acceptable.
Development Tools
J2ME development is similar to J2EE and J2SE development in many ways.
Developers write
classes that fit within frameworks like Swing and struts. However, due to
the limitations of the cell phone platform, there are several J2ME specific
tools.
Useful J2ME tools
J2ME emulators mock up the J2ME runtime environment on a desktop PC,
allowing development to occur on a device that has more memory, a faster
network connection, and a keyboard. Emulators are available from many
sources: Sun, IBM, most device manufacturers and even a few carriers.
The Sun Wireless
Tool Kit (WTK) has an excellent emulator. IBM's WebSphere Device
Developer (WSDD) has an emulator integrated with an IDE; this made for a
great development environment, but the version I used did not handle the network
threading deadlock appropriately and cost money.
Both of these emulators support Windows and Linux. However, most cell phone
emulators only run on Windows.
Other emulators can be downloaded from device manufacturers' or
carriers' websites.
Be aware that when developing using emulators, the advantages gained can
also lead to user experience issues: for example, it may make sense to download a logo for
the traffic service every time if a fast reliable network connection is
available, but this is not the case if the application is using the cell
phone network, which is neither fast nor reliable. Be aware of such non
functional problems and test on real phones as often as possible.
Building midlets take more steps than building a normal web or java application, including preverification of
classes[21]
and jad file generation. WSDD and WTK can take care of the additional
steps,
but then development has to take place in that context.
antenna, on the other hand,
is a set of ant tasks that leverage existing WTK classes to enable command
line midlet builds. In addition, antenna also provides the ability
to build midlets for other platforms and create automated builds.
The size of the application jar file can be important, if for no other
reason than application download time. Obfuscators are
java programs that can be used with any class file; they twiddle with byte
code and rename classes and variables to make decompilation more difficult.
As a happy side effect, however, they also decrease the size of class files.
proguard is one such
obfuscater. Easy to use and feature rich, it also integrates with the
WTK. Jode has also been
recommended, but I found it difficult to use.
Rolling Out The Application
Actually rolling out a J2ME application to cell phones is easy.
Buy a J2ME capable phone; there are lists of compatible phones on the web.
[22] Get a data plan--4MB a month has been ample for
me.
Place the jad and jar files on a web server.
Modify the web server's mime types to assign the correct content
types to the .jad and .jar extensions:
Example 4. Addition to web server mime types for Apache
...
application/java-archive jar
text/vnd.sun.j2me.app-descriptor jad
...
Every phone capable of running a midlet will have a browser. To install,
download the jad file; the midlet support
infrastructure asks the user for permission to install the
application, deals with versioning issues, and downloads
and actually installs the application. In some cases, browsing directly to the jad
file triggers the installation process; however, in one or two cases
bizarre behavior prevented installation in this manner.
The solution is to browse to an XHTML file that has a link to the jad file;
such an XHTML document need not be complex
(see Example 5, “XHTML File Used to Install a Midlet”).
Example 5. XHTML File Used to Install a Midlet
<a href='file.jad'>Application</a>
For an application such as the traffic congestion service, licensing and
piracy are not huge issues.
This is the case for most networking midlets, since the value comes
from remote data delivered at the appropriate time, rather than the application
itself. Delivery takes place after authentication,
so if a user is not recognized or has not paid for the service, access can
be easily denied.
Some aspects of J2ME deployments are not in the developer's control.
For example, one source of frustration for
me has been Verizon. This carrier, the largest in the USA, simply does not
support J2ME.[23] Optional package implementation is similar--if a
device manufacturer has not implemented an API needed, the application
simply cannot run on that device. Contrast this with the J2EE world, where
the server is under the application developer's control, or at least
influence. In addition, J2EE's typical delivered product, HTML,
has a fairly standard feature set; with J2ME, clients differ in their
capabilities.
Jar file size
In addition to speedy download as a reason to decrease jar file size, some
phones, particularly inexpensive Nokia models, simply do not accept
jar files larger than 64KB.
Obfuscation tools such as proguard help, but even with obfuscation and
elimination of unused classes, jar files might be too large. Other means
of decreasing the size include design compromises and removing logging
statements.
Often, value objects on the client side have, in good javabeans style, get and
set methods. To decrease the size of the class files, these can be replaced
by
public variables (see lines 6 and 7 of Example 3, “XML Parsing Code”).
Commenting out logging statements, which
generate a large number of String objects, decreases the size
of the jar file significantly, as commented out
Strings are not included in the class files.
This optimization experience was something new to the development team.
After all, in the world of J2SE and J2EE, there are a different set of
constraints--programmer time, database access, execution speed. How many
developers
ever really pay attention to the size of their class files?
Scalability
If an application has not been widely rolled out, scalability is difficult
to ascertain. The traffic congestion service does have usage scenarios: a
user will login, enter some data, and receive an answer. Perhaps they will
check for traffic jams once or twice during the commute, but most users
will not be using the service all day. Therefore, the application should
be built to handle spikes during rush hours. One tool that can be used
to gain an idea of performance is The Grinder.
Of course, requests from a PC or set of PCs are not entirely reliable emulations of
the real usage scenarios, but it is a starting point.
One concern is, though the MIDP 1.0 profile supports HTTP 1.1,[24] clients with slow network connections require
the server to have a larger number of sockets open for a given number of
clients over a specified period of time, when compared to speedier clients. Ten clients that each take ten
seconds to read a given amount of data, starting in one second intervals,
will require a maximum of ten sockets, whereas ten clients that each take
one second to read the same amount of data, starting in one second
intervals, will require one socket.
I am not sure at what point such behavior will have a negative effect on
performance, but it should be considered when thinking of the number of
supportable clients.
In Conclusion
In this paper, I have examined the kind of problems that rich client
applications residing on cell phones solve.
Cell phone platforms were examined, and I
explained why J2ME was a good choice for an application like the traffic
congestion service, where data was needed quickly while away from the
desktop computer and little user data entry was required.
I also covered the basics of J2ME and discussed some of the quirks that I
have encountered, including device discrepancies.
Even in the
J2ME world, it is important to realize that, while MIDP 1.0/CLDC 1.0
gives a firm base from which to build, APIs for carriers and device makers
will vary. I also looked at the different types of client/server
solutions available to
solve the problem, and some of the tools that made building midlets easier.
For many problems, J2ME can be a good solution with a low barrier
to entry. As more and more phones can support more
and more complex functionality, J2ME will continue to grow in promise.
The variety of functionality available now reminds me of the web browser
market in the mid 1990s; exciting things are in the works, even if many of
the bugs have not been shaken out yet.
References
Thank You
Thanks to Brian Rook, who brought me into his J2ME project.
Much thanks to my reviewers, who caught many mistakes and made some great
suggestions. Any errors still present are of course my responsibility.
-
Dion Almaer
-
Bryan Buus
-
Aprille Jordan
-
Michael Yuan
-
Corey Snipes
-
Andy Pai
-
Pat Meyers
-
Jeff Barry
-
Mike Mahon
|