Sun Java Solaris Communities My SDN Account Join SDN
 
Article

MIDP Inter-Communication with CGI and Servlets

 



Communications 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
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.

Choose
One Final
Grades
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.

Choose
One Final
Grade
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.

Choose
One Add a
User First
Name Second
Servlet
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




Reader Feedback
Excellent   Good   Fair   Poor  

If you have other comments or ideas for future technical tips, please type them here:

Comments:
If you would like a reply to your comment, please submit your email address:
Note: We may not respond to all submitted comments.

Have a question about Java programming? Use Java Online Support.



Back To Top