Build database-powered mobile applications on the Java platform

Use JavaServer Pages as a gateway between MIDP applications and databases

Internet-connected mobile devices are important tools in our daily lives. The ability to access information in realtime and in real-life circumstances has enabled us to work more efficiently. To fully harness mobile commerce's potential, we need to integrate wireless devices with the rest of the Internet. In particular, wireless devices should be able to access the vast amounts of data on Internet backend databases and utilize data processing power from enterprise-level database applications.

To achieve that functionality, Java is our best bet. It offers the ideal platform for developing complex mobile commerce applications. Java programs can deploy on both the wireless device and the application server, independent of host hardware and operation systems. Client-side and server-side Java applications can integrate seamlessly under consistent API designs.

In this article, we explore ways to access Internet backend databases from Java-enabled mobile devices. We use a simplified example to illustrate our approach and explain the design and implementation decisions we made.

The Java platform for small mobile devices

The standard Java APIs and virtual machine (VM) are feature rich. But standard Java applications are simply too big and too slow to run directly on resource-constrained mobile devices. Small runtime memory footprint and fast execution speed prove essential for mobile commerce developers. In response to this need, Sun created a small-footprint edition of Java: J2ME (Java 2 Platform, Micro Edition).

J2ME is divided into configurations and profiles. You can use different combinations for different memory and processing power requirements. The Connected Limited Device Configuration (CLDC) and Mobile Information Device Profile (MIDP) combination is designed specially for resource-constrained mobile devices, such as wireless phones and personal digital assistants. CLDC provides class libraries to support a limited set of Java core language APIs; MIDP provides device-specific implementations for application-level APIs, such as GUI components, network connection, and persistent storage. CLDC and MIDP work together to provide a complete development and runtime environment for mobile devices. Each MIDP-supported mobile device has a MIDP VM that can run compiled MIDP byte code. Thus, MIDP applications run on all MIDP devices.

Unlike applications built around browser-based technologies such as WML (Wireless Markup Language) and other HTML variants, MIDP applications are real programs that can handle interactive user interfaces, manipulate data, and allow offline user interaction. In contrast with platform-native applications, MIDP applications are portable across all mobile platforms and can deploy over the Internet. MIDP developers can take advantage of Java's sound object-oriented design and the many third-party libraries/components available for the Java platform.

A MIDP application's basic component is the MIDlet. A MIDlet can have its own event handlers and user interface. Several MIDlets and their supporting classes work together in a MIDlet suite to provide a MIDP application's complete functionalities (for more information about MIDP development, see Resources). However, MIDP lacks a crucial functionality for database-powered applications: Java Database Connectivity (JDBC). In the next section, we discuss how to access databases from MIDP applications.

J2EE middleware

In theory, MIDP applications on wireless devices can directly communicate with backend databases using raw TCP/IP network sockets. However, the mobile application must therefore handle all database-dependent communication, resulting in an application that cannot be ported across different backend database servers. On top of that, the mobile application needs to process both the business logic and the presentation logic -- a huge burden for resource-constrained mobile devices, thus producing inefficient, unexpandable, nonportable applications. In a sound design, the mobile application should handle only the interaction with the user (presentation logic) and leave everything else to the server.

The server-side requirements necessitate another server-side layer between the databases and MIDP applications. J2EE (Java 2 Platform, Enterprise Edition) provides the perfect tools for such server-side middleware. JavaServer Pages (JSPs) can communicate with MIDP applications via the standard HTTP protocol; JSPs can also interact directly with databases through database-independent JDBC APIs or integrate with other J2EE components, such as Enterprise JavaBeans (EJBs). For more information on JSP, JDBC, and EJB development, please refer to Resources.

Architecture

Figure 1 shows the basic architecture discussed above. The MIDP application runs on mobile devices. MIDlets communicate with JSPs through the HTTP protocol using data formatted as XML (more on this later). The JSP then passes the MIDlet request to a middle layer of application software that handles business logic and communicates with databases through JDBC. The middle layer can be a set of helper classes in the JSP container or a separate EJB server. Since the focus of this article is MIDlet-JSP communication, in our simplified example, we combine middle-layer business-logic handling and database access functions into JSPs.

Figure 1. The architecture of a database-powered mobile Java application

Example

This article's example is a notes/comments collection program. We want to gather user feedback on a new product. First, the user needs to log in and start a session. Then, on the mobile device, he records any notes/comments he has on that product during realtime usage. At any time, the user can send the time-stamped notes to a central database for further processing. In this example, the central database has only one table, Notes. The SQL listing below shows the table schema:

CREATE TABLE Notes (
  Notes.NoteID    BIGINT(20) NOT NULL AUTO_INCREMENT PRIMARY KEY,
  Notes.UserName  TEXT,
  Notes.Time      DATETIME,
  Notes.Note      TEXT
);

Note: You can download the source code for both the client- and server-side Java example programs from Resources. The MIDlets directory contains all the MIDlets, and the jsp directory contains all the JSPs. The support directory contains supporting Java classes that need to be deployed on both MIDP and JSP server sides. See the sidebar below, "Deploy the Example MIDP Application on Palm OS Devices," for more information.

The application works as follows:

  1. The MIDlet Session manages the HTTP session information through the JSPs updateSession.jsp and getSession.jsp. In the example, for illustration purposes, only one string variable, username, is stored with the session. No password check or username validation is performed. Real user authentication reaches beyond this article's scope.
  2. The MIDlet Record receives user notes in realtime and stores them in a record management system (RMS) record store (database) with time stamps.
  3. The MIDlet SendData reads the notes from the record store, sends them to updateDB.jsp -- which stores the notes -- and time-stamps them with username in a backend relational database.

Figure 2 shows the screen shots of a complete session on the MIDP side, from login to upload of all notes to a database.

Figure 2. The example application's complete user session. Click on thumbnail to view full-size image.

Figure 3 shows the content in the backend database after the session completes.

Figure 3. Contents in the backend database after the session shown in Figure 2

We want to emphasize that this is only a simplified example to illustrate our approach. In the real world, a mobile application should avoid any lengthy user input. You could replace the note-taking process with interactive multiple-choice questionnaires. The questions and choices could be generated dynamically from databases and sent to MIDlets via JSPs as well.

We developed and tested the example system with the following toolkits/environments:

  • On the MIDP client side: CLDC 1.0, MIDP 1.03, MIDP4Palm 1.0 on a Palm V running Palm OS 3.5
  • On the server side: J2EE 1.3, Jakarta Tomcat 4.0.1, MySQL 3.23.44, and the MM.MySQL JDBC driver 2.0.4

We compiled and packaged the Java programs using standard Java 2 1.3.1 tools.

To follow the rest of this article, you should have a basic understanding of how to implement standalone MIDP or JSP applications. For an earlier JavaWorld series that can help you get started with MIDP, see Resources below. In the following sections, we will address some implementation issues and show you how to make client- and server-side Java applications work together.

Persistent storage on MIDP

One of the most important features of MIDP is its ability to store data in on-device databases. It facilitates client-server communication by providing a data cache. That cache allows the wireless application to work on its own for a period of time without assistance from the server side (JSPs). It drastically improves mobile applications' flexibility and speed. In this section, we discuss how to implement persistent storage in our example application.

We use RMS record stores to store user notes and associated time stamps in the MIDlet Record. RMS record stores resemble files on filesystems. They can be opened and accessed by their names and can survive soft resets (reboots). A record store can store a number of Records. Each record has a unique RecordID as the primary key, and the record itself contains data in binary format.

The MIDP API offers many methods to manipulate stores and records. The following method opens a record store:

RecordStore noteStore = RecordStore.openRecordStore("JWTestStore", true);

The first parameter in openRecordStore() is a name that uniquely identifies the record store. The second parameter indicates whether or not a new store should be created if the named store does not exist.

To add a new record containing the string note to the record store, we use the addRecord() method:

noteStore.addRecord( note.getBytes(), 0, note.length() );

After we gather a few notes, we can send them to the database using SendData. In the MIDlet SendData, we transverse all the records in a store using the enumeration object and then delete the processed records:

RecordEnumeration re = noteStore.enumerateRecords(null, null, false);
while ( re.hasNextElement() ) {
  int id = re.nextRecordId();
  byte [] b = noteStore.getRecord(id);
  // Do something about the data in array b.
  // Assemble it into the XML document to be send to server.
  noteStore.deleteRecord(id);
}

The first parameter in method enumerateRecords() is a RecordFilter, which decides which records to include in the returned enumeration. The second parameter is a RecordComparator, which specifies the order in which the records are returned. In the above example, we used the null value for both parameters, so the enumeration contains all records in the store in no particular order. The third parameter indicates whether the enumeration should be kept up-to-date with changes in the record store.

The above name-based record-store access methods are convenient. However, there is a problem: you can install multiple MIDlets suites on the same device, and chances are that some suites might choose to use the same record store names. To avoid that confusion, the MIDP RecordStore class has a built-in security model. Any MIDlet in a suite can access only RMS databases created by MIDlets in the same suite. The static method RecordStore.listRecordStores() returns an array of record store names accessible to the current MIDlet.

Data connections and session management

In this section, we look at how to establish data connections on both the client and the server side. On the MIDP client side, open a new connection to a specific URL with the following code:

HttpConnection conn = (HttpConnection) Connector.open(url);

To send data over HTTP, use conn.setRequestMethod(HttpConnection.POST) for the POST method or conn.setRequestMethod(HttpConnection.GET) for the GET method.

Now we can send data to the server using the output stream from the connection object:

DataOutputStream os = conn.openDataOutputStream();
os.write(StringToPost.getBytes());

Finally, we can retrieve the server response data from the input stream:

DataInputStream is = conn.openDataInputStream();

On the JSP server side, the client's request data can be retrieved in the input stream reader:

Reader reader = request.getReader();

The server talks with the database through JDBC connections (Do not confuse JDBC connection objects with HTTP connection objects!):

Connection conn = DriverManager.getConnection("jdbc:mysql://computer/DB", DBusername, passwd);

Then, the server can send response data back to the MIDP client through the output stream. In a JSP, any text outside the scriptlet (embedded Java code) sections automatically writes to the output stream.

Session management

Since our server application needs to support simultaneous multiple users, we must track each user's state information to store notes with the appropriate usernames. However, HTTP is a stateless protocol, and each HTTP connection conducts a separate transaction with no knowledge of the context. A standard way to solve this problem is to have the server group relevant connections into sessions and store persistent state information with the sessions. Every MIDlet and JSP in our example application uses the technique discussed in this section to manage sessions.

1 2 3 Page
Recommended
Join the discussion
Be the first to comment on this article. Our Commenting Policies
See more