The Generic Connection Framework

by C. Enrique Ortiz August 2003

Introduction

This article provides an overview of the Generic Connection Framework (GCF), a J2ME API that provides broad support for connection types.

GCF was originally defined to rely on the J2ME platform's Connected Limited Device Configuration (CLDC), version 1.0, because the familiar J2SE java.net and java.io APIs were considered too large to fit into the constrained memory available in mobile devices.

Today you can find the GCF not only in CLDC-based profiles, such as the Mobile Information Device Profile (MIDP) and the Information Module Profile (IMP), but also in Connected Device Configuration (CDC)-based profiles, such as the Foundation Profile and its relatives the Personal Basis Profile and Personal Profile - and now, with JSR 197, on the J2SE platform as well. You can also find the GCF in an increasing number of optional packages, including those that provide Bluetooth support and access to files and smart cards.

A Generic Approach to Connectivity

The GCF is a straightforward hierarchy of interfaces and classes to create connections (such as HTTP, datagram, or streams) and perform I/O.

As the name implies, the GCF provides a generic approach to connectivity. It is generic because it provides a common foundation API for all the basic connection types - for packet-based (data blocks) and stream-based (contiguous or sequence of data) input and output.

This generalization is possible through the use of:

  • An interface hierarchy that is extensible
  • A connection factory
  • Standard Uniform Resource Locators (URLs) to indicate the connection types to create

The base CLDC 1.0 GCF is illustrated in Figure 1:

The CLDC Generic Connection Framework Interface Hierarchy and Related Classes

Figure 1: The CLDC Generic Connection Framework Interface Hierarchy and Related Classes

(Click to Enlarge)

At the top of the interface hierarchy is the Connection interface, the most basic type of connection - all other connection types extend Connection. As you move down the hierarchy, connections become more complex and functional.

For packet-based I/O the GCF defines DatagramConnection, and for stream-based I/O InputConnection, OutputConnection, StreamConnection, and ContentConnection. Note how StreamConnection extends both InputConnection and OutputConnection, making it a two-way stream connection. At the bottom of the hierarchy is the ContentConnection, a special type of StreamConnection that provides content-specific information such as data length, content type, and data encoding. Finally, the StreamConnectionNotifier enables an application to wait for incoming stream connections, asynchronously.

In addition to the connection hierarchy, the GCF provides the Connector class, which is the connection factory, and the ConnectionNotFoundException that is used to indicate when a connection type can't be created. For packet-based connections, the GCF defines the Datagram interface, which represents a datagram packet.

Not defined by the GCF but related to it are InputStream, DataInputStream, OutputStream, and DataOutputStream, familiar to users of the java.io package, for stream-based connections.

The GCF is so practical and flexible that it is used across J2ME profiles and optional packages, and now on the J2SE platform as well. The relationship between the base CLDC GCF and the GCF for profiles and platforms is illustrated in Figure 2:

Relationships Between Base GCF and GCF for MIDP, FP, and J2SE

Figure 2: Relationships Between Base GCF and GCF for MIDP, FP, and J2SE

MIDP and the Foundation Profile extend the base CLDC 1.0 GCF, while the J2SE version of GCF comes directly from the GCF for Foundation Profile.

The GCF - An Extensible Framework for Not-So-Generic Connections

The GCF, which is defined in the javax.microedition.io package, defines a lowest-common-denominator framework - a pretty high-level generalization. It is up to profiles and optional packages to extend the base GCF, and define and provide the actual low-level connection types, and the network and I/O protocol implementations.

When we look closely at a typical connection and its related I/O protocol we see that these are not generic. For example, HTTP connections have peculiarities that reflect their request/response nature, while a Bluetooth connection exposes the dynamic (ad hoc) nature of its protocol, and a socket connection exposes low-level networking methods for timeouts and keep-alive options.

Fortunately, the GCF is extensible. New connection types, which are defined and standardized via the Java Community Process (JCP), can be added by defining a new Connection subtype and supporting classes, providing a Connector factory class that supports the newly defined connection type, and defining a new URL scheme that identifies the new connection type. Figure 3 illustrates how a particular profile or optional package could extend the GCF:

Extending the Generic Connection Framework

Figure 3: Extending the Generic Connection Framework

(Click to Enlarge)

A new connection type can extend the basic Connection interface or one of its subtypes.

A Rich Set of Connection Types

The GCF supports a large number of connection types, across profiles and platforms, all in a consistent manner.

URLs play a very important role in the GCF. One of the most widely used inventions of the Internet, URLs describe the location and access method for a resource on the Internet using a hierarchical notation. In the GCF, URLs identify connection types and endpoints.

The general format of a URL, as defined in RFC 1738 (and later in RFC 2396) is as follows:

scheme://user:password@host:port/url-path;parameters, where:

  • scheme specifies the access method or protocol, such as FTP or HTTPS. In the GCF, it describes the connection type to use, which maps to an underlying connection or I/O protocol.
  • user is an optional user name.
  • password is an optional password.
  • host is the fully qualified name or the IP address of the host where the resource is located.
  • port is an optional port to use. Its interpretation depends on the scheme.
  • url-path is the "path" to the resource. Its format and interpretation depend on the scheme. The url-path may define optional parameters.

Note that the delimiters are literal, and required as appropriate. For example, parameters are optional, but if supplied must be preceded by a semi-colon.

Of special importance is the scheme, which in the GCF describes the connection type to create. Table 1 summarizes some of the GCF URL schemes and connection types that are currently defined by the JCP:

Table 1. GCF URL Schemes and Connection Types

URL Scheme Connectivity GCF Connection Type Defined By...
btl2cap Bluetooth L2CAPConnection JSR 82. Support is optional.
datagram Datagram DatagramConnection All CLDC- and CDC-based profiles, such as MIDP, Foundation and related profiles, and with JSR 197, J2SE. Support is optional.
file File Access FileConnection, InputConnection JSR 75. Support is optional.
http HyperText Transport Protocol HttpConnection MIDP 1.0, MIDP 2.0, Foundation Profile, J2SE (JSR 197). Support is required.
https Secure HTTP HttpsConnection MIDP 2.0. Support is required.
comm Serial I/O CommConnection MIDP 2.0. Support is optional.
sms mms cbs Short Messaging Service Multimedia Messaging Service Cell Broadcast SMS MessageConnection JSR 120, JSR 205. Support is optional.
apdu jcrmi Security Element APDUConnection, JavaCardRMIConnection JSR 177. Support is optional.
socket serversocket Socket SocketConnection, ServerSocketConnection JSR118 (MIDP 2.0). Support is optional.
datagram UDP Datagram UDPDatagramConnection JSR118 (MIDP 2.0). Support is optional.

Note that most of the connection types are optional (device manufacturers are not required to support them) and defined by an optional package. Before using an API make sure the devices you are targeting incorporate the appropriate JSR.

Table 2 summarizes some of the currently defined core GCF connection types, by profile:

Table 2. Summary of Core GCF Connection Types, By Profile

GCF Interfaces, Classes, Exceptions Vendors Must Support? CLDC 1.0, 1.1 MIDP 1.0 MIDP 2.0 Foundation and Related Profiles GCF for J2SE (JSR 197)
CommConnection N     X    
Connection (base connection) Y X X X X X
Content Connection Y X X X X X
Datagram Connection N X X X X X
HttpConnection Y   X X X X
HttpsConnection Y     X    
InputConnection Y X X X X* X*
OutputConnection Y X X X X X
SecureConnection N     X    
ServerSocket Connection N     X    
SocketConnection N     X    
StreamConnection Y X X X X X
StreamConnection Notifier Y X X X X X
UDPDatagram Connection N     X    

* A URL scheme of "file:" returns an InputConnection.

The MIDP 2.0 GCF provides the most connection types, while the other profiles and J2SE just support HttpConnection, in addition to the basic CDLC GCF types.

Support: Required Versus Optional

It is important to realize that even though all core interfaces and classes must be present, as defined by the specification, the actual implementations may be optional. See the "Vendors Must Support?" column in Table 2. For example, the MIDP 1.0 specification mandates support only for HttpConnection, and even though MIDP 2.0 defines additional connection types, HTTP is the only connection type vendors must support.

Using the Generic Connection Framework

Using the GCF is very simple. To create a connection you use the Connector factory class and a URL. To close it, you use the created Connection subtype object. Using a connection can be easy or more involved, depending on the connection type, because each connection type has its own peculiarities.

Opening a Connection - Using The Connector Class

The Connector class is the connection factory. It creates and opens an instance of the appropriate subtype of Connection based on the URL you specify, if that type is supported.

To create a connection, call the Connection.open() method as in the following code snippet:



...
String url = "socket://www.j2medeveloper.com:80";
...
SocketConnection c = null;
InputStream s = null;
try {
    c = (SocketConnection)Connector.open(url);
    s = c.openInputStream();
    ...
    // Read from the input stream, handle input data.
    ...
} catch (ConnectionNotFoundException cne) {
    // Connection specified in URL can't be created.
    // Handle exception, throw exception or return error.
} catch (IllegalArgumentException iae) {
    // One of the arguments is in error.  In this example, the 
    // only argument to open is URL, so the only expected 
    // exceptions are ConnectionNotFoundException or IOException.
    // Handle exception, throw exception or return error.
} catch (IOException ioe) {
    // Handle exception, throw exception or return error.
} finally {
    try {
        if (s != null) s.close();
        if (c != null) c.close();
    } catch (Exception e) {
        // Handle exception, throw exception or return error.
    } 
}
...

The Connector class defines three open() methods:

  • open(String url)
  • open(String url, int mode)
  • open(String url, int mode, boolean timeouts)

...where:

  • url is the URL that describes the connection type to create (examples follow).
  • mode is the connection mode to use - READ, WRITE, or READ_WRITE (the default).
  • timeouts is a flag to indicate that the caller wants to be notified about timeout exceptions ( InterruptedIOException), if the underlying connection implements notification. (The default is false.)

The simple form, open(String url), is the most widely used:

...

// Create a SocketConnection and InputStream
String url = "socket://www.j2medeveloper.com:80";
c = (SocketConnection)Connector.open(url);
s = c.openInputStream();
...

The Connector class contains convenience methods for creating streams of various types:

  • static DataInputStream  openDataInputStream(String name)
  • static DataOutputStream openDataOutputStream(String name)
  • static InputStream      openInputStream(String name)
  • static OutputStream     openOutputStream(String name)

Because these helper methods are static, you can get the input or output streams directly, as follows:

...

// Create an InputStream
String url = "socket://www.j2medeveloper.com:80";
s = (InputConnection)Connector.openInputStream(url);
...

This method of opening streams is discouraged, however, because you don't get a reference to the connection itself, and thus don't have access to connection-specific methods or attributes. For example, if you pass to openInputStream() a URL that specifies http, you won't have access to any of the HttpConnection methods to manipulate the HTTP headers and return codes.

Next are some examples of how to create various connection types:

  • Creating a SocketConnection:
    ...
    
    String url = "socket://www.j2medeveloper.com:80";
    SocketConnection c = (SocketConnection)Connector.open(url);
    ...
    
  • Creating an HttpConnection:
    
    
    ...
    String url = "http://www.j2medeveloper:80/com/myServlet";
    HttpConnection c = (HttpConnection)Connector.open(url);
    ...
    
  • Creating an InputConnection (Foundation Profile and J2SE):
    ...
    
    String url = "file:///myResourceFile.res";
    InputConnection c = (InputConnection)Connector.open(url);
    ...
    
  • Creating a FileConnection (JSR 75):
    ...
    
    String url = "file:///myResourceFile.res";
    FileConnection c = (FileConnection)Connector.open(url);
    ...
    
  • Creating a DatagramConnection:
    String url = "datagram://www.j2medeveloper.com:7001";
    
    UDPDatagramConnection c = (UDPDatagramConnection)Connector.open(url);
    

    Closing a Connection - Using the Connection Interface

    The Connection interface defines the most basic connection type. Its only method is close(). Assuming you have a connection named conn, the following snippet shows how to use this method to close the connection:

    
    
    	try {
        // Here close any open streans
        conn.close();
    } catch (IOException ioe) {
        // Handle the exception.
        // Throw the exception, ignore it, or return an error.
    }
    

    Using a Connection

    Covering all the different connection types supported by the GCF is outside the scope of this article, but you can find other GCF-related articles on this site:

    Conclusion:

    This article introduced the Generic Connection Framework, a very flexible and extensible API for network, file, serial, and other kinds of I/O. The GCF started as the I/O API for CLDC-based platforms, but due to its flexibility it has been incorporated into CDC-based profiles and the J2SE platform as well. This article also showed the wide variety of connection types that GCF makes readily available to applications based on CLDC, CDC, and J2SE.

    Acknowledgments

    Thanks to Roger Riggs and James Allen for their contributions to this article. And many thanks to Brian Christeson, for making this article just better.

    About the Author: C. Enrique Ortiz, Director of Engineering, Mobile Applications for corrigo. He is an active participant in the wireless Java community, and is the co-author of the Mobile Information Device Profile for J2ME published by John Wiley and Sons. Enrique holds a B.S. in Computer Science from the University of Puerto Rico and has over 13 years of industry experience.