By Qusay Mahmoud
Release 1.0
February 2001
Source: FirstMidletServlet.java, HelloServlet.java, PostMidlet.java, RequestServlet.java, SecondMidletServlet.java
When using a wireless device for Internet browsing, such as a cell phone,
one of the most frequent actions a user performs is to submit data in a form,
such as a login box. There are several ways to implement this functionality with
Common Gateway Interface (CGI) scripts and servlets as the most popular.
The Connected Limited Device Configuration (CLDC) provides a generic
Connection framework that you can use to develop network-based
applications. In addition, the Mobile Information Device Profile (MIDP) provides
the HttpConnection interface, which is part of the
javax.microedition.io package, that defines the necessary methods and constants for an HTTP connection. The CLDC generic connection framework and MIDP HttpConnection
interface are discussed in detail in MIDP Network Programming.
This article presents a brief overview of the HTTP GET and
POST operations, explains how to handle them, and includes examples that show you how to
invoke Common Gateway Interface (CGI) scripts and Servlets from MIDlets using the GET and
POST operations. This article also covers different techniques you can use for
session tracking in a wireless environment.
The HTTP Programming Model
The HTTP protocol is a request-response application protocol
in which the parameters of the request must be set before the
request is sent. For example, the input values in a fill-out form
are sent as part of the request when the user clicks the
Submit button.
Request Methods
There are two methods to send data from a fill-out form (or MIDlet,
for example) to a CGI script or a servlet hosted by the HTTP server:
GET and POST. These methods
determine how the data is sent to the server.
- For the
GET method, the input values are sent as part of the URL in the QUERY_STRING environment variable.
- For the
POST method, data is sent as an input stream and its length is saved in the CONTENT_LENGTH environment variable.
The POST method is more secure, and you can send more data using it.
Example: the GET method
As an example, consider the following HTML code for the form shown in
Figure 1:
<form
action="http://www.somesite.com/cgi-bin/getgrade.cgi"
method="GET">
Student#:
<input type="text" name="idnum" size=30>
<input type="submit">
</form>
|

Figure 1: Form with one field (GET Method)
This form is to be handled by the script:
http://www.somesite.com/cgi-bin/getgrade.cgi,
so when the user enters a student number, such as 123333, and clicks the
Retrieve Marks button, the form data is sent to the CGI script
as part of the URL because the form uses the GET method. In other
words, the encoded URL is:
http://www.somesite.com/cgi-bin/gergrade.cgi?idnum=123333.
In the case of POST, however, input values are not sent as part of the
URL. They are sent as an input stream in a separate message.
If the user enters a string with spaces, all spaces are replaced by
pluses (+). Also, if the form requires multiple input values for different
fields, the fields are separated by an ampersand (&). For more details
about the HTTP GET and POST operations, see
More Information.
Servlet Programming Model
Similar to CGI, servlets support a request and response programming
model. When a client sends a request to the server, the server sends the
request to the servlet. The servlet then constructs a response that the server
sends back to the client. Unlike CGI scripts, however, Servlets run
within the same process as the HTTP server.
When a client request is made, the service method is called
and passed a request and response object. The servlet first
determines whether the request is a GET or POST
operation, then calls either the HttpServlet.doGet or
HttpServlet.doPost method as appropriate. Both the doGet
and doPost methods take request (HttpServletRequest) and
response (HttpServletResponse) objects as parameters.
Invoking a CGI Script from a MIDlet
After you understand the basics of HTTP GET, POST,
CGI, and servlets, take a look at some examples. This first example shows how
to invoke a CGI script from a MIDlet using the POST method. In this
example, a script is invoked and the input sent to the script in a message.
The url variable specifies where the pgrade.cgi
CGI script is located. In this example, an HTTP connection is opened to the CGI
script, followed by opening output and input streams on the connection. Input to
the script is sent through the output stream, and the response is received through
the input stream. The CGI script in this example, which is written in Perl, takes a
student number input value. If the student number is found in the database file,
the script retrieves the corresponding final grade and returns the grade to the
calling client. In the case of MIDlets, there are no HTML forms, so here the
message name=163748 is sent to the CGI script. The source code for
this example is shown in Listing 1.
Example 1 Listing 1:
PostMidlet.java
import java.io.*;
import javax.microedition.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
/**
* An example MIDlet to invoke a CGI script
* using the POST method.
**/
public class PostMidlet extends MIDlet {
private Display display;
String url =
"http://somesite.com/cgi-bin/pgrade.cgi";
public PostMidlet() {
display = Display.getDisplay(this);
}
//Initialization. Invoked the MIDlet activates.
public void startApp() {
try {
getGrade(url);
} catch (IOException e) {
System.out.println("IOException " + e);
e.printStackTrace();
}
}
//Pause, discontinue ....
public void pauseApp() { }
//Destroy must cleanup everything.
public void destroyApp(boolean unconditional) { }
//Retrieve a grade.
void getGrade(String url) throws IOException {
HttpConnection c = null;
InputStream is = null;
OutputStream os = null;
StringBuffer b = new StringBuffer();
TextBox t = null;
try {
c = (HttpConnection)Connector.open(url);
c.setRequestMethod(HttpConnection.POST);
c.setRequestProperty("IF-Modified-Since",
"20 Jan 2001 16:19:14 GMT");
c.setRequestProperty("User-Agent",
"Profile/MIDP-1.0 Configuration/CLDC-1.0");
c.setRequestProperty("Content-Language", "en-CA");
os = c.openOutputStream();
// send request to the CGI script
String str = "name=163748";
byte postmsg[] = str.getBytes();
for(int i=0; < postmsg.length;i++) {
os.write(postmsg[i]);
}
os.flush();
//receive response and display in a text box.
is = c.openDataInputStream();
int ch;
while((ch = is.read()) != -1) {
b.append((char) ch);
System.out.println((char)ch);
}
t = new TextBox("Final Grades",
b.toString(), 1024, 0);
} finally {
if(is!= null) {
is.close();
}
if(os != null) {
os.close();
}
if(c != null) {
c.close();
}
}
display.setCurrent(t);
}
}
|
When you run and activate PostMidlet, you see something similar to
Figure 2.
 |
 |
| Figure 2: PostMidlet
Output |
To see how a CGI script can be invoked from a MIDlet where the GET
method is used, see MIDP Network Programming.
Invoking a Servlet from a MIDlet
You can invoke a servlet from a MIDlet the same way you invoke a CGI
script: by opening an HTTP connection and input/output streams on the
connection. This section presents two examples:
- The first example invokes a servlet using the
GET operation, and
collects and
displays the results.
- In the second example, the servlet accepts input obtained from the user of
the handset and
is invoked with the
POST method.
Example 2: Invoking a Servlet
In this example, a FirstMidletServlet is invoked
with the GET method and the response is received and
displayed on the handset. No input is sent to the servlet. When
invoked the servlet sends the "Servlet Invoked" string
and the date back to the client. The source code for
FirstMidletServlet is in Listing 2.1.
Listing 2.1:
FirstMidletServlet.java
import java.io.*;
import javax.microedition.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
/**
* An example MIDlet to invoke a CGI script.
*/
public class FirstMidletServlet extends MIDlet {
private Display display;
String url =
"http://somesite.com/servlet/HelloServlet";
public FirstMidletServlet() {
display = Display.getDisplay(this);
}
//Initialization. Invoked when MIDlet activates
public void startApp() {
try {
invokeServlet(url);
} catch (IOException e) {
System.out.println("IOException " + e);
e.printStackTrace();
}
}
//Pause, discontinue ....
public void pauseApp() { }
//Destroy must cleanup everything.
public void destroyApp(boolean unconditional) { }
//Prepare connection and streams then invoke servlet.
void invokeServlet(String url) throws IOException {
HttpConnection c = null;
InputStream is = null;
StringBuffer b = new StringBuffer();
TextBox t = null;
try {
c = (HttpConnection)Connector.open(url);
c.setRequestMethod(HttpConnection.GET);
c.setRequestProperty("IF-Modified-Since",
"20 Jan 2001 16:19:14 GMT");
c.setRequestProperty("User-Agent",
"Profile/MIDP-1.0 Configuration/CLDC-1.0");
c.setRequestProperty("Content-Language", "en-CA");
is = c.openDataInputStream();
int ch;
// receive response and display it in a textbox.
while ((ch = is.read()) != -1) {
b.append((char) ch);
}
t = new TextBox("First Servlet",
b.toString(), 1024, 0);
} finally {
if(is!= null) {
is.close();
}
if(c != null) {
c.close();
}
}
display.setCurrent(t);
}
}
|
Listing 2.2:
The source code for the HelloServlet, which sends
the message "Servlet Invoked!" and the date
to the client, is shown in Listing 2.2.
HelloServlet.java
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
/**
* The simplest possible servlet.
*/
public class HelloServlet extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
response.setContentType("text/plain");
PrintWriter out = response.getWriter();
out.println("Servlet invoked!");
out.println(new Date());
}
}
|
When you run and activate the FirstMidletServlet, you
see something similar to the output shown in Figure 3.
 |
 |
| Figure 3: FirstMidletServlet
Output |
Example 3: Invoking a Servlet with Input Values
Now, let's see how to invoke a servlet that expects input with the
POST operation method. This is a more sophisticated example
than Example 2. In this example, the SecondMidletServlet prompts
the user to enter a value (the first name). When the user presses the key that
corresponds to the Submit command, the RequestServlet
is invoked. RequestServlet retrieves the input values of the request
from the buffer and returns them back to the client showing that the servlet
receives the POST request. The source code for the
SecondMidletServlet
is shown in Listing 3.1.
Listing 3.1
SecondMidletServlet.java
import javax.microedition.rms.*;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
import javax.microedition.io.*;
import java.io.*;
import java.util.Vector;
public class SecondMidletServlet
extends MIDlet
implements CommandListener {
Display display = null;
List menu = null;
TextBox input = null;
String user = null;
String url =
"http://somesite.com/servlet/RequestServlet";
static final Command backCommand = new Command(
"Back", Command.BACK, 0);
static final Command submitCommand = new Command("
Submit", Command.OK, 2);
static final Command exitCommand = new Command(
"Exit", Command.STOP, 3);
String currentMenu = null;
public SecondMidletServlet() { }
public void startApp()
throws MIDletStateChangeException {
display = Display.getDisplay(this);
menu = new List("Invoke Servlet", Choice.IMPLICIT);
menu.append("Add a user", null);
menu.addCommand(exitCommand);
menu.setCommandListener(this);
mainMenu();
}
public void pauseApp() { }
public void destroyApp(boolean unconditional) {
notifyDestroyed();
}
void mainMenu() {
display.setCurrent(menu);
}
//Prompt the user to input his/her name.
public void addName() {
input = new TextBox("Enter first name:",
"", 5, TextField.ANY);
input.addCommand(submitCommand);
input.addCommand(backCommand);
input.setCommandListener(this);
input.setString("");
display.setCurrent(input);
}
//Prepare connection and streams invoke servlet.
void invokeServlet(String url)
throws IOException {
HttpConnection c = null;
InputStream is = null;
OutputStream os = null;
StringBuffer b = new StringBuffer();
TextBox t = null;
try {
c = (HttpConnection)Connector.open(url);
c.setRequestMethod(HttpConnection.POST);
c.setRequestProperty("IF-Modified-Since",
"20 Jan 2001 16:19:14 GMT");
c.setRequestProperty("User-Agent",
"Profile/MIDP-1.0 Configuration/CLDC-1.0");
c.setRequestProperty("Content-Language", "en-CA");
// send request to the servlet.
os = c.openOutputStream();
String str = "name="+user;
byte postmsg[] = str.getBytes();
System.out.println("Length: "+str.getBytes());
for(int i=0;i |
The source code for the RequestServlet, which retrieves
the POST request from the buffer and sends the input values
back to the client, is shown in Listing 3.2.
Listing 3.2:
RequestServlet.java
import java.io.*;
import java.text.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
/**
* Example servlet showing request headers
*/
public class RequestServlet extends HttpServlet {
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
response.setContentType("text/plain");
PrintWriter out = response.getWriter();
BufferedReader br = request.getReader();
String buf = br.readLine();
out.print("Rec: "+buf);
}
}
|
When you run SecondMidletServlet and activate it by
entering your name, you see something similar to the output shown in
Figure 4.
 |
 |
 |
 |
| Figure 4:
SecondMidletServlet Output |
 |
 |
 |
 |
 |
Note: If you want to use the method ServletRequest.getParameter(String
name)
to retrieve the input values from the MIDlet in Example 3, then you need to set the
CONTENT_TYPE header to application/x-www-form-encoded as
follows:
HttpConnection.setRequestProperty("CONTENT-TYPE",
"application/x-www-form-encoded");
|
 |
 |
 |
Wireless Session Tracking
Session tracking means maintaining state information about a series
of requests from the same client. Maintaining such information for clients
that use HTTP is a problem. HTTP is a request-response protocol, which means
the connection between the client and server is not maintained for the duration of
the conversation. In other words, HTTP is a stateless protocol. This means
you can not depend on the underlying connection protocol to maintain state
information. Therefore, you must find other ways to maintain this information.
The two most widely used techniques for session tracking are cookies and
URL rewriting. A cookie is a piece of data that a Web server sends to the
client. This piece of data is stored by the client and used the next time the
client makes a request from that server. But if cookies are disabled by the
browser, or more importantly, if the browser itself does not support them (as is
the case with most wireless devices), then cookies are not of much use.
The other technique for session tracking is URL rewriting. This technique is
ideal for clients that do not support cookies or have cookies disabled. In this
technique, the session information is encoded into URLs that the server generates.
This means, instead of returning this URL:
http://www.somesite.com/servlet/shop/catalog.html
The server generates this URL (or something similar) instead:
http://www.somesite.com/servlet/shop/catalog.html;
jsessionid=cl98373673At
The information that would otherwise be stored in a cookie is appended to
the URL. The server looks for this information when a request is made from
the client. The exact syntax of the encoded URL depends on the underlying
server environment.
The Servlet API provides facilities (such as
response.encodeURL(String)
and response.encodeRedirectURL(String)) that you can use for
session tracking.
Conclusion
All MIDP implementations must support the HttpConnection
interface, which allows your application to be portable across all mobile
information devices. The examples in this article show how CGI scripts and
servlets can be invoked from a MIDlet using the HttpConnection
interface. Notice that the content type in these examples is set to
text/plain
as opposed to text/html. If your MIDlet invokes a CGI script or a
servlet where the content type is set to text/html, all HTML tags are sent
to the handset!
URL rewriting is an ideal session tracking technique for clients that do
not support cookies. However, as this technology develops, there might be
other techniques where the device can contain some unique information that
can be used for session tracking.
More Information
About the Author: Qusay H. Mahmoud provides Java consulting and training services. He has published dozens of articles on Java, and is the author of Distributed Programming with Java (Manning Publications, 1999) and Learning Wireless Java (O'Reilly & Associates, 2002).
Back To Top
|
|