The Generic Connection Framework (GCF)
provides an extensible, generic I/O framework for resource constrained
devices. In this final installment in the J2ME 101 series,
author John Muchow walks you through the GCF interfaces, showing you how
they facilitate the development and support of various types of network
and file I/O on MIDP.

This article is the final piece in the four-part J2ME 101 series, which
consists of a two-part tutorial and two follow-up articles. In this last
installment, we'll explore network communication on MIDP, using the
Generic Connection Framework (GCF).

As in the previous content in this series, we'll start with the basics
(in this case, how to open a connection to a remote resource), but quickly
move into more complex territory. Our first MIDlet will demonstrate how to
download and display an image that is stored on a server; our second one
will use an HTTP connection to download and display a text file from a
server; and our final MIDlet will get you started with passing date and
time parameters to a servlet.

Please note that this article assumes that you are familiar with MIDlet
development in the J2ME environment. You will need to have a J2ME
development environment installed on your system in order to compile the
code examples. See the Resources section for
links to the first three installments in the J2ME 101 series, as well
as installation instructions for the J2ME Wireless Toolkit (WTK).

What is GCF?GCF is
a set of interfaces defined within the javax.microedition.io
package. Figure 1 shows the GCF class hierarchy.

A total of seven interfaces are defined in GCF, with
Connection at the root. Notice that both datagram (packet)
and stream connections are supported. As you would assume, working your
way down the hierarchy you'll find interfaces that provide additional
functionality. For example, StreamConnection supports both
input and output streams, and ContentConnection extends
StreamConnection with support for determining the content
type, data length, and encoding format of a stream.

The Connector class is used to open every type of
connection in GCF. Here you can see the format for the open()
method inside the Connector
class:

Connector.Open("protocol:address;parameters");

Connection protocol
supportGCF is exceptionally flexible in its support for
different connection protocols. When a request is made to open a
connection, the Connector class uses its
Class.forName() method to search for a class that implements
the requested protocol. If found, an object is returned that implements
the Connection interface, as shown in Figure 1.

The ContentConnection class isn't the only option we have
for creating a connection. We could also choose to create an
InputStream directly. In Listing 4, you can see what might
happen if we needed to download an image over a network connection and
create an Image based on the downloaded contents.

As you may have noticed, bypassing the ContentConnection
leaves us no method to determine the length of the incoming data. This
isn't much of a problem, however, because we can use the
ByteArrayOutputStream to read and transfer the data to our
destination array.

Image supportPortable Network
Graphics (PNG) is the only image format required for any MIDP device
implementation. See Resources to learn
more about the PNG format.

The DownloadImage
MIDletLet's write a short MIDlet that builds on the code
shown in Listing 4. The DownloadImage MIDlet will demonstrate the steps to
download and display an image in an MIDP application. The MIDlet will use
a ByteArrayOutputStream to download the remote data and then
display the resulting image on a Form using an
ImageItem.

Take a look at the complete code for the DownloadImage MIDlet and
then we'll discuss it in more detail.

Once the MIDlet is running the main user interface should appear in
your WTK device emulator, as shown in the figures below. Figure 2 shows a
TextBox that prompts for the URL of image. Clicking the View command initiates
the download.

HTTP support in
MIDPNow that you've seen how GCF supports various types of
connections and we've developed our first networking MIDlet, it's time to
take a closer look at HTTP support in MIDP. We'll start with an updated
hierarchy diagram that indicates which class provides support for HTTP
connections.

The original MIDP 1.0 specification only required that devices support
the HTTP connection protocol, whereas the more recent MIDP 2.0 spec
requires support for both HTTP and HTTPS, with the latter offering support
for more secure network connections. The APIs to work with these protocols
are HttpConnection and HttpConnections,
respectively. In addition to these mandated protocols, a device
manufacturer can choose to support additional communication protocols such
as datagrams or sockets. While at times convenient, you should know that
using vendor-specific protocols could affect your application's
portability to other devices.

Request and response
protocolsBoth HTTP and HTTPS are request/response
protocols. A client sends a request and a server sends a response. We'll
look at the stages of both the client request and the server response
before we move on.

Client requestThe
client request,
sometimes called the request entity, consists of the following three
sections:

Request method

Header

Body

We'll look at each of these sections in some detail.

Request method

The request method
determines how data will be sent to a remote resource. The three methods
available are GET, POST, and
HEADER. When using GET, data is sent as part of
the URL. With POST, any client data is sent in a separate
stream, distinct from the request to establish a connection.
HEADER requests do not send any data to a server. Instead,
HEADER requests only meta information about the remote
resource.

Listing 5 shows how we would open an HTTP connection with a specified
request method of GET, passing a parameter with the name
size and a value of large.

Header fields let us
pass parameters, if you will, from the client to the server. Common fields
are If-Modified-Since, Accept, and User
Agent. You set header fields as key-value pairs, using
the setRequestProperty() method. Listing 6 shows a header
request specifying that only data that has been modified since November
11, 2003 be sent back from the server.

Oftentimes you will not need to specify any additional information
beyond the request method and header fields. If you do need to specify
additional information you will include the data in the body.

GET versus POSTGET
and POST are two similar request methods that yield
different results. When a GET request is used, the data
will be sent as part of a URL (via URL encoding), which poses a
limit on the amount of data that can be transferred. When we use a
request method of POST, the data is sent over a stream,
so there is no limit on the amount of data that can be
retrieved.

Server
responseAfter the server has received and processed the
client request, it must package and send a response. As with the client
request, three sections are associated with the server response:

Status line

Header

Body

Status line

As the name implies, the server status line
informs the client of the outcome of its request. HTTP classifies the
status line codes into the following broad categories:

1xx is informational

2xx is success

3xx is redirection

4xx is client error

5xx is server error

The server status line includes the protocol version number running on
the server, the status code, and a text message representing the return
code. Below are several examples of valid status lines:

"HTTP/1.1 200 OK"

"HTTP/1.1 400 Bad Request"

"HTTP/1.1 500 Internal Server Error"

Header

Not unlike the client, the
server can send information through header fields. Three of the most
common methods for retrieving header information sent from a server are
shown in Listing 8.

String getHeaderField(int n) Get header field value looking up by index
String getHeaderField(String name) Get header field value
looking up by name
String getHeaderFieldKey(int n) Get header field key using index

A server could potentially return more than one header field. In this
case, the first method would obtain the value of the header field by
specifying its index in the result set and the next one would retrieve a
header field value by looking up its key by name. Should you need to get
the header field key, you could pass a parameter to the final method
representing the index of the entry in the result set you were interested
in.

Custom header fieldsIf the header
fields defined in the HTTP specification aren't sufficient to your
needs, you can also retrieve custom headers, which you define and
return from the server. Custom headers are commonly used for session
management when using URL-rewriting.

Table 1 shows what each of the three methods in Listing 8 would return
if the response in a server header contained the content "content-type=text/plain".
Assume for this example that the server results set contains only one
entry.

Like the client, the server
sends the bulk of information in the body of its response. Along similar
lines as Listing 7 (which shows a
client sending its body through an output stream), the client would read
the server response using an input stream.

The HttpConnection
APIAs previously mentioned, we use the
HttpConnection API to establish connections on MIDP. Table 2
shows all the methods available in the HttpConnection
class.

The FileViewer
MIDletOur next MIDlet will use an
HttpConnection to download and view the contents of a text
file. This short example will give you some insight into how we send
client information and interpret a server response. The MIDlet also
includes calls to various methods within the HttpConnection
class, which help us to gather information about the host server, the
port, and the content type returned.

Take a look at the complete code for the FileViewer MIDlet and
then we'll discuss it in more detail.

Now, let's view the output of our MIDlet. The left screen shot in
Figure 5 shows the interface upon startup. After you select the View command, the file
will be downloaded and displayed on the device, as shown on the right
screen shot in Figure 5.

Note that the status line (message and code) and all the header field
key-value pairs are
displayed. HttpConnection also includes the methods shown in
Listing 9 to obtain server information, including the host, port, and
content type returned. These values for the FileViewer MIDlet
are shown near the bottom of Figure 6.

Accessing a Java
servletWe're going to develop one last MIDlet together
before we close the J2ME 101 series. The
DateFormat MIDlet (see the complete source code) will
demonstrate the steps necessary to access a Java servlet from within a
MIDlet. This is a fairly complex operation compared to the others you've
learned so far, but we'll walk through it together in the sections that
follow.

We'll start by passing parameters to a servlet requesting a specified
date and time format to be returned. The servlet will create a properly
formatted string based on the parameters and send the result to the
client, where it will be displayed on the WTK device emulator. Table 3
lists the available parameters and their meanings, along with a brief
example.

The servlet is hosted at http://www.mycgiserver.com.
This is a free hosting service based in Austria, so you shouldn't be
surprised if the date format isn't familiar to your native language. For
example, in Figure 7, the time zone is shown as CET, Central European
Time, which we requested by specifying a time zone parameter of "zzz". However, if we
change the time zone parameter to "zzzz" to get the
full-text version of the time zone, the output may no longer be what you
expect, as shown in Figure 9.

Eye on the clockCET is used only
during winter months in Austria. If you run the example shown in
Figure 7 at another time of the year, the time zone may be CEST. See
Resources to learn
more about the CET and CEST time zones.

The code for callServlet is shown in Listing 11. Notice
the code for the client side consists only of setting the request method
to GET. No header or body information is necessary for this
MIDlet. You'll learn how to interpret the server response in just a moment
from Listing 11 below.

The two lines of code that specify the URL show how to call our
DateFormatServlet servlet from within the MIDlet. Simply looking at how
the servlet is invoked gives us a hint that we will be using a
GET request method, because all parameters are passed as part
of the URL rather than being sent in a separate stream.

In Listing 12 you can see how we pass a parameter with the name format from the client
to the server. The servlet will extract the value of this parameter to
determine how to format the requested date.

The servlet codeThe
servlet code is quite trivial. The bulk of what we are after is inside the
method doPost(). We first store the format requested by the
client in the variable format. Next, we call
SimpleDateFormat to create an instance of our preferred date
formatting object and follow this with a call to create a new
Date object. We create a PrintWriter object as
our output stream, set the content type to text/html and
output the date in the requested format, as shown in Listing 13.

Parsing servlet
resultsThe code for interpreting the server response is
shown in Listing 14. The first check is to determine if the status line
indicates the client request was successfully processed and a result
returned (HTTP_OK). There is no header information, so we
move directly to reading the server data from an input stream, storing the
results in the variable serverMsg.

For our next step we need to head back to the code inside
commandAction(). After a successful call to
callServlet() we append the saved string returned from the
server onto the Form (our primary user interface component),
which in turn displays the results on the device, as shown in Listing
15.

ConclusionIn this
final article in the J2ME 101 series, you've
had a chance to explore network communication support in MIDP. We began
with an introduction to the Generic Connection Framework, the foundation
for creating networked applications in MIDP. This was followed by a
discussion of HTTP support, including how to package a client request, as
well as interpret a server response. To demonstrate the concepts presented
up to this point, we wrote a file-viewer MIDlet that downloaded and
displayed a text file.

In the final section of this article we wrote a comprehensive MIDlet to
access a Java servlet. This included a broad range of network
communication operations, such as passing parameters to the servlet,
interpreting and processing the parameters on the server side and,
finally, retrieving and displaying the server response on the client.

In this four-part series, we've had a chance to take a close look at
all the primary components of MIDP, namely, high-level and low-level user
interface components, persistent storage, and network support. With the
completion of this comprehensive overview, you now have a baseline of
information to begin exploring and developing your own J2ME
applications!

Learn more about getting Java applications to network on small
devices, with Soma Ghosh's "Networking with J2ME"
(developerWorks,
September 2002).

Keep on learning about J2ME, with the latest tutorial, "Work with sprites in
J2ME" (developerWorks,
December 2003), where you'll learn how to spice up your applications
with more complex, malleable images.

The KVM mailing list is an
excellent resource for J2ME developers, offering a searchable archive
and an active email discussion area.

Core J2ME (Prentice
Hall PTR, 2002) by John W. Muchow is a comprehensive guide to J2ME
development. You can also visit the Core J2ME Web site for
additional articles, tutorials and developer resources.

The alphaWorks Web Services Toolkit for
Mobile Devices provides tools and a runtime environments for
developing applications that use Web services on small mobile devices,
gateway devices, and intelligent controllers.

John Muchow,
author of Core J2ME technology
and MIDP, is a freelance technical writer and developer, with
extensive experience in J2ME, Java technology, JSP, C, and
ColdFusion. Visit Core J2ME for
additional source code, articles, and developer resources. Send John
an e-mail for
additional information about writing or software development
projects.