New York University

Computer Science Department

Courant Institute of Mathematical Sciences

 

Session 6: MIDP Extensions and MIDlets

 

Course Title: Application Servers    Course Number: g22.3033-011

Instructor: Jean-Claude Franchitti                                                        Session: 6

 

 

I. Mobile Enterprise Application Features

 

 

Application Features

Characteristics

Standalone applications

* Small footprint versions of application logic and local processing: thick, intelligent, client/server or smart client applications.

* Applications can run on devices with intermittent network coverage.

* Intelligent use of wireless bandwidth.

Rich user interface

High and low level UI APIs allow for simple but richer user interfaces (when compared to WML) for mobile business applications and games

Network aware

* Support for HTTP/XML and other web standards

* Direct device-to-device network communications

* Client/Server and distributed applications

* Occasionally connected

Reliable messaging

Guaranteed message delivery ensures transactions are not lost due to lost of network coverage.

Local persistence

Local data store allows for persistence at the device. Key to offline functionality and caching and guaranteed message delivery and better utilization of wireless bandwidth.

End-to-End security

Small footprint TLS implementation allows for end-to-end security without translations at the network provider

Data synchronization

Synchronize data when/as needed

Notifications

Real-time asynchronous notifications

Multi language support

Target application to different languages

Cross platform and low cost of development and ownership

Develop 'once' deploy to any J2ME device w/ appropriate profile

Access to corporate servers


Integrate and interoperate with existing corporate servers

 

 

II. HTTP for networking (MIDP)

 

HTTP is a text-based stateless request/response protocol with messages with the following format:

 

HTTP message = start-line (request or status line) CRLF

message-header(a set of name&values)CRLF

CRLF (empty line)

Optional message-body

 

1. To open an HTTP connection invoke javax.microedition.io.Connector class:

 

 

import javax.microedition.io;

HttpConnection hc;

hc = (HttpConnection)Connector.open(targetURL);

 

where targetURL follows the a standard URL format as defined by RFC 2396:

 

<SCHEME>:<SCHEME-SPECIFIC-PART>, where <SCHEME> indicates to the implementation the type of Connection object that must be created/returned and the <SCHEME-SPECIFIC-PART> indicates the hostname, port and query-string.

 

For example:


http://www.j2medeveloper.com:8080/emailController?user=enrique&pwd=8dfje3

datagram://www.j2medeveloper.com:7001

 

2. To set HTTP request headers before sending the request use setRequestProperty():

 

hc.setRequestProperty("User-Agent",

    "Profile/MIDP-1.0 Configuration/CLDC-1.0" );

 

The MIDP specification recommends that User-Agent is set to indicate MIDP/CLDC as shown above.

 

3. To retrieve HTTP response headers use getHeaderField():

 

String cookie = hc.getHeaderField( "Set-Cookie" );

 

4. One possible way to send an HTTP request:

/*

 *  Set HTTP request method to POST.

 *    It is good practice to always set:

 *    Content Length, Type, Language, Accept.

 *    Send body

 */

hc.setRequestMethod(HttpConnection.POST);

 

hc.setRequestProperty

    ("Content-Length", ""+ messageBody.length() );

hc.setRequestProperty(

    "Content-Type",

    "application/x-www-form-urlencoded");

hc.setRequestProperty("Content-Language", "en-US"); // should be config.

hc.setRequestProperty("Accept", "text/xml");

hc.setRequestProperty("Connection", "close");

 

os = hc.openOutputStream();

os.write(messageBody.getBytes());

 

5. One possible way to receive an HTTP response:

 

InputStream is  = hc.openInputStream(); // get response

int len = (int) hc.getLength();

StringBuffer receivebuffer = new StringBuffer();

 

if( len != -1) {

    // Read exactly Content-Length bytes

    for(int i = 0; i < len; i++) {

        if((ch = is.read()) != -1) {

           receivebuffer.append((char) ch);

        }

    }

}

else {

   //Read until the connection is closed.

   while ((ch = is.read()) != -1) {

        len = is.available() ;

        receivebuffer.append((char)ch);

   }

}

response = receivebuffer.toString();

 

III. Leveraging XML on the MIDP (see http://www.ericgiguere.com/microjava/cldc_xml.html)

 

Leveraging XML for data exchange allows for easy integration with existing systems. There are a number of small, open source XML parsers available to us including NanoXML, kXML and TinyXML.

 

The NanoXML (http://nanoxml.sourceforge.net/) and TinyXML http://www.gibaradunn.srac.org/tiny/index.shtml are both natively tree-based parsers while kXML (http://kxml.enhydra.org/) is a more sophisticated pull/event-based parser.

 

kXML is much larger than NanoXML and TinyXML.

 

All these parsers are becoming more complete over time with features such as DTD validation and Java interfaces for both tree and event-based parsing; of course all these goodies come at a price: memory footprint.

 

As a side-note, kSOAP, a small implementation of SOAP for J2ME is written on top of kXML, meaning that if you are targeting SOAP you should consider using kXML instead. From the licensing perspective, the NanoXML licensing is the less restrictive one. Please refer to the individual web-sites for more information.

 

The following is a snippet of code that uses the NanoXML:

 

EmailMessage em = null;

 

kXMLElement parser = new kXMLElement();

parser.parseString(xml); // xml is an input String

 

Enumeration children = parser.enumerateChildren();

 

// For each element, get tag and contents

while (children.hasMoreElements()) {

 

    // allocate an email message object

    em = new EmailMessage();

 

    kXMLElement child = (kXMLElement)(children.nextElement());

 

    String tag      = child.getTagName();

    String contents = child.getContents();   

 

    ...... // other code

 

    if ("msgid".equals(tag)) {

        em.setId(contents); // get contents Into object

    }

    ...... // test for other tags and retrieve the content

}

if (em != null) return em;

 

IV. Local data persistence

 

The MIDP defines javax.microedition.io.rms for local data persistence. RMS stands for Record Management System, a simple record store that allows MIDlets to store records that that persists across MIDlet executions.

 

RMS records are stored as array of bytes. Developers can use java.io.DataInputStream, DataOutputStream to read/write primitive types and ByteArrayInputStream and ByteArrayOutputStream to manipulate RMS record streams.

 

The following is a snippet of code that opens a record store and reads three fields:

 

import javax.microedition.rms.*

recordStore = RecordStore.openRecordStore("userDB", true);

..... // other code

 

// create Input streams

ByteArrayInputStream bais = new

       ByteArrayInputStream(recordStore.getRecord(id));

DataInputStream inputStream = new DataInputStream(bais);

 

// read Individual fields as appropriate

String name = inputStream.readUTF();

String text = inputStream.readUTF();

String int = inputStream.readInt();

The RMS also provides the means to list, delete, enumerate, and filter (sort) records and to keep track (get notified) of changes to the record store.

 

V. Deploying a MIDlet

 

MIDlets are distributed using standard JAR files as per the documentation at http://java.sun.com/docs/books/tutorial/jar/basics/index.html.

 

In addition to the JAR file, a new file called the Java Application Description File or JAD is used to describe the JAR file. Knowing the characteristics of the JAR file before download is important because the JAR might be to big to fit on the device or you do not want to download huge JAR files over the air (OTA) or there might be some security concerns. Lets look at an example of a JAD file:

 

GatewayPort: 80

GatewayURL: www.j2medeveloper.com

MIDlet-1: Email,, com.j2medeveloper.email.Email

MIDlet-Jar-Size: 34435

MIDlet-Jar-URL: email.jar

MIDlet-Name: Email

MIDlet-Vendor: J2MEDEVELOPER.COM

MIDlet-Version: 1.0

UserEmail: xyz@j2medeveloper.com

UserName: xyz

 

Also, you can use the JAD to store any configuration information you need (for example web-server or a user name or an email address). Use the method javax.microedition.midlet.getAppProperties() to access properties or configuration information stored in JAD (vs. hard coding any values on your code).

 

Building and Running your MIDlet

 

How to build and run your MIDlet will all depend on the Java environment that you are using. You should consult your IDE or development environment documentation as needed.

 

You can package more than one MIDlet within a JAR file into what is call a MIDlet suite. Once you have created the JAD file, you must also create a MANIFEST file for your JAR file. The MANIFEST looks very similar to the JAD file, for example:

 

MIDlet-1: Email,, com.j2medeveloper.email.Email

MIDlet-Name: Email

MIDlet-Vendor: XYZ

MIDlet-Version: 1.0

MicroEdition-Configuration: CLDC-1.0

MicroEdition-Profile: MIDP-1.0

 

To build and run under the J2ME Wireless toolkit (J2MEWTK) from Sun Microsystems, you need to be aware of the directory structure used by the J2MEWTK. That structure contains two important directories for the following classes:

 

1)      tmpclasses, containing compiled classes that have not being verified

2)      2) classes which contains the pre-verified classes.

 

Building steps are as follows:

 

1. Compile - use javac tool but override J2SE classes to use MIDP ones

 

set MIDP_HOME=c:\midp

javac -g:none -bootclasspath %MIDP_HOME%\classes -d tmpclasses src\*.java

 

2. Preverify

 

preverify -d classes -classpath %MIDP_HOME%\classes tmpclasses

 

3. Create JAR file

 

jar cfm bin\myMidletSuite.jar bin\manifest.mf -C res . -C classes .

 

4. Running your MIDlet suite

 

emulator.exe -Xdescriptor: myMidletSuite.jad -classpath myMidletSuite.jar

 

-OR-

 

midp -classpath bin\ myMidletSuite.jar -descriptor bin\ myMidletSuite.jad