Scott Wahl, Manager, Software Documentation, RIM

The Hypertext Transfer Protocol (HTTP, or the "core" of the World Wide Web), has been around since 1990. It is based on a model of requests and responses between clients and servers.

In form it works with a client opening a connection then sending an HTTP request message to a server. The server then sends a response message, which usually contains the requested resource.

Topics within this section include:

Format for HTTP Requests

<method> <resource_path><version>
    Header1: value1
    Header2: value2
    Header3: value3
<optional message>
  

The following table defines the HTTP request variables:

Variable Definition
method Method names indicate an action, such as GET, HEAD, or POST. The commonly used method is GET, meaning "give me this resource."
resource_path The path that points to the requested resource is the part of the URL that appears after the host name. This is also called the Request URL.
version The version of HTTP that you are running is noted as "HTTP/x.x". The BlackBerry Enterprise Server (BES) supports both version 1.0 and 1.1.
header The header provides information about the request or about any object that is sent in the message body.
optional message The HTTP message can contain data. In a request, this is where user-entered data or uploaded files are sent to the server. When an object accompanies the message, the request usually also includes headers that define its properties.

Format for HTTP Responses

<HTTP version><status_code><reason>
    Header1: value1
    Header2: value2
    Header3: value3
<message>

The following table defines the HTTP response variables:

Variable Definition
HTTP_version The version of HTTP that you are running is noted as "HTTP/x.x". The BlackBerry Enterprise Server software supports both version 1.0 and 1.1.
status_code The status code is a numerical value that reflects the results of the client's initial request. For example, 200 (OK) indicates successful transmission; 404 (Not Found) indicates the requested URL could not be found.
reason The reason is the text message that is associated with the status code.
header The header provides information about the response and about the object that is being sent in the message body.
message The HTTP message contains data. In a response, this message provides content that was requested by the client; the response also includes headers that define its properties.

Tip: Applications should check the status code in HTTP response messages. Any code other than 200 (OK) indicates that an error might have occurred in establishing the HTTP connection. For example, if an application receives an HTTP response with a status code 401 (Unauthorized), the application should retry the request with the appropriate authorization information.

HTTP Programming

The BlackBerry handhelds support network communication using HTTP. Network programming is abstracted, so in your applications you need to set up an HTTP connection to send and receive data over the wireless network, regardless of the underlying protocols or network technology.

Opening an HTTP Connection

When you open an HTTP connection, by default the handheld establishes the connection using the BlackBerry Enterprise Server Software, which resides behind the corporate firewall. Communication is encrypted between the BlackBerry Enterprise Server and the BlackBerry Wireless Handheld using the same Triple DES encryption that is used for BlackBerry email. The BlackBerry service maintains the connection for the handheld, so you do not need to specify the IP address of the BlackBerry Enterprise Server to set up an HTTP connection.

Note: HTTP connections are supported by the BlackBerry Enterprise Server Software for Microsoft Exchange, version 3.5 or later, and the BlackBerry Enterprise Server Software for Lotus Domino, version 2.2 or later. The Mobile Data Service must be enabled.

Perform the following steps to open an HTTP connection.

  1. Create an HTTPConnection object then define a URL:
    HttpConnection conn = null;
    String URL = "http://www.myServer.com/myContent";
      
  2. Invoke the Connector.open method and cast this object as an HTTPConnection.<
    conn = (HttpConnection)Connector.open(URL);
      
  3. Use methods on the HttpConnection class to set the HTTP request method (GET, PUT or POST) and to set or retrieve header fields for HTTP request or HTTP response messages.
    conn.setRequestMethod(HttpConnection.POST);
    conn.setRequestProperty("User-Agent", "BlackBerry/3.2.1");
    conn.setRequestProperty("Content-Language", "en-US");
      
  4. Acquire input and output streams, using the openInputStream() and openOutputStream() methods, to send and receive data.
    InputStream in = conn.openInputStream();
      

Using HTTPS

In addition to the standard HTTP support required by MIDP, the BlackBerry handheld also supports HTTP connections over SSL/TLS, for end-to-end data security in addition to the Triple DES encryption. You would typically use HTTPS for applications to communicate with servers on the public Internet, outside of the corporate firewall.

To open an HTTPS connection, you specify https instead of http as the protocol; for example:

HttpConnection stream =
  (HttpConnection)Connector.open("https://www.test.com:443/");

If the Mobile Data Service has been configured to allow unauthenticated connections, an application can connect using HTTPS without authenticating the server by adding the trustAll parameter:

HttpConnection stream =
  (HttpConnection)Connector.open("https://www.test.com:443/;trustAll");

The Mobile Data Service can handle HTTPS to HTTPS or HTTPS to HTTP redirection automatically to minimize communication with the handheld. To enable automatic forwarding, use the RdHTTPS parameter:

HttpConnection stream =
  (HttpConnection)Connector.open( "https://www.test.com:443/;RdHTTPS");

Mobile Data Service adds the x-rim-redirect-https header to the HTTP response to indicate that redirection occurred.

Automatic redirection is disabled by default, which means that if redirection occurs, the Mobile Data Service sends the request back to the handheld to establish another HTTP connection.

Using the Mobile Data Service Simulator

If you want to test applications that require an HTTP network connection, you must start the Mobile Data Service simulator, which is included in the BlackBerry JDE. On the Windows Start menu, select:

Programs->Research In Motion->BlackBerry Java Development Environment Version 3.x->BlackBerry Mobile Data Service

A DOS window appears to indicate that the process is running.

Tip: You can configure the IDE to start the Mobile Data Service automatically for simulations. On the Edit menu, click Preferences. Click the Simulator tab. Select Launch Mobile Data Service (MDS) with simulator.

Connecting Using a WAP Gateway

You can also set up an HTTP connection using a WAP gateway hosted by a network operator or service provider. The handheld supports WAP 1.1 features. WAP push applications are not supported.

Note: WAP may not be supported on all wireless networks. Contact your network operator or service provider for information prior to starting development, and information on how to connect to their WAP gateway.

To set up an HTTP connection using WAP, you must include the WAPGatewayIP and WapGatewayAPN parameters in the Connector.open method, at the end of the URL. For example, you can use the following method:

Connector.open("http://wap.yahoo.com;
  WAPGatewayIP=127.0.0.1;WAPGatewayAPN=carrier.com.gprs");

WAP parameters are separated by a semi-colon (;). Spaces are not allowed.

The following table describes WAP parameters that you can include for a WAP connection.

ParameterDescriptionDefault
WapGatewayIP IP address of the gateway  
WapGatewayAPN Access Point Node (for GPRS networks only); for testing purposes, you can use rim.net.gprs  
WapGatewayPort Gateway port value (if port 9203 is specified, WTLS is used unless WapEnableWTLS=false is specified) 9201
WapSourceIP IP address of the source 127.0.0.1
WapSourcePort Source port value 8205
TunnelAuthUsername User name for APN session, when PAP or CHAP authentication is used none
TunnelAuthPassword Password for APN session, when PAP or CHAP authentication is used none
WapEnableWTLS Explicitly enables or disables WTLS (if this parameter is not specified, WTLS is used by default for connections to port 9203) none

Note: When testing applications that require a WAP connection in the RIM simulator, use the following command line switch: /rport=<wap_source_port>

In the IDE on the Edit menu, click Preferences. Click the Simulator tab and then the Advanced sub-tab. In the Simulator Command line field, add the command line switch.

Handheld Security

The BlackBerry Wireless Handheld includes built-in security to help prevent third-party applications from sending or receiving data without the user‘s knowledge.

When an unsigned application attempts to open a connection, the handheld user is presented with a dialog asking them if they want to allow the connection.

Warning message for network connections

The user must choose to allow or deny the connection. The user can also select one of the options to allow connections of this type or connections to the destination in the future without prompting. These options apply only to the specific application.

The user can change these settings later in handheld, under Options then Firewall.

HTTP Authentication

Many web sites require HTTP authentication, such as a user name and password. The Mobile Data Service supports Basic Authentication only. Refer to RFC 2617 for more information.

The Mobile Data Service can store user names and passwords locally, which reduces network traffic to and from the handheld and enables users to avoid having to retype their password each time they visit the same site.

In the case of an authentication failure, in which no valid name and password pair is found for a particular domain, the authentication failure is sent to the handheld. This failure notice alerts the handheld user that the name and password pair could not be found.

If the authentication failure occurs, the Mobile Data Service sends the HTTP authentication challenge to the handheld. If the user is using the Browser, a login prompt appears. Custom applications must include code to handle these authentication challenges if they connect to a server that requires a password.

On the Mobile Data Service, the system administrator can enable and disable HTTP authentication storage and set a timeout value. This timeout value determines the length of time that HTTP authentication information is stored on the proxy before being purged. By default, HTTP authentication is disabled on the Mobile Data Service. The handheld user must enter HTTP authentication information when prompted. The handheld then sends this information to the Mobile Data Service.

Cookie Support

Many web sites generate a cookie, which is a condensed record of user information, formed during an exchange between the user and an external web page.

The handheld browser automatically stores cookies that it receives and sends them back to the appropriate server when a new request is made. In custom Java applications, you can write code to maintain a server session ID by checking for a cookie in HTTP response then sending it back to the server when you send a new HTTP request.

By default, cookie storage is disabled on the Mobile Data Service and all cookies are sent to the handheld. To reduce this load, you can configure the Mobile Data Service to store cookies on behalf of the handheld.

Transaction Management

Given the intermittent nature of wireless network connections, you should consider the extent to which your application requires reliable delivery and synchronization of data between the client and server.

The Mobile Data Service does not provide transaction management. When your application sends data, you cannot assume that it has been received and processed correctly.

If reliable delivery of data is important, your application must implement some form of acknowledgement mechanism to verify that data is received and processed. The following are two approaches you might consider:

  • Use global identifiers for each transaction with an acknowledgment implementation. Global transaction identifiers enable an application to determine which transactions are still outstanding, and to resend data as necessary.
  • Display to the user, which transactions completed successfully and which failed. The user can then resend failed transactions.

Writing a Network Application Using HTTP

This section explains how to write an application that uses an HTTP connection to retrieve data. You perform the following tasks:

  • create a connection thread
  • define a method to retrieve data
  • define a method to display data to the user
  • define a method to exit the application
  • create the application constructor

The main class for this application extends BaseApp, which implements common UI functionality.

Note: The following example requires that you create resource files in the application project and define the required resource keys.

Creating a Connection Thread

You should always create a separate thread to send and receive data so that you do not block the application‘s event thread while data is being sent or received, which would lock the application user interface. The BlackBerry handheld support for multithreading assists you in writing effective network applications.

Create a thread class to manage the HTTP connection. In this example, HTTP get operations are not queued; however, if a call is active and another call is made, the second request stalls until the previous request completes.

private class ConnectionThread extends Thread {

Define Variables

Define variables to maintain the state of the connection thread:

private volatile boolean _start = false;
private volatile boolean _stop = false;
  

The volatile keyword indicates that, because the data is shared, the value of each variable must always be read and written from memory, instead of cached by the VM. Reading and writing a single boolean is considered an atomic action. This technique is equivalent to wrapping the shared data in a synchronized block, but it produces less overhead.

Define a Method to Fetch a Page

Define a method to retrieve data from a specified URL. Initialize _theURL to the parameter that is passed into the method, and set _start to true.

The fetch method is invoked on the connection thread by the fetchPage method, which you define later. The fetchPage method is invoked in the application constructor.

public void fetch(String url)
{
  _start  = true;
  _theUrl = url;
}

Define a stop() Method

Define a method to close the connection thread. This method sets the _stop variable to true. This method is invoked when the application exits.

public void stop()
{
    _stop = true;
}

Define the run() Method

Override the Thread.run() method to open an input stream and extract data. The run() method synchronizes the thread so that only one connection is open at a time. The run() method is invoked when the thread is started.

  1. Control the thread to avoid looping continuously. When no connections are open for fetch requests (_start == false), but the thread has not been stopped (_stop == false), invoke the sleep method to pause the thread for 500 milliseconds. This action reduces the CPU load to a negligible level. If the thread is not running (_stop == false), exit the method.
    public void run()
    {
      for(;;)
      {
        while( !_start && !_stop)
        {
          try
          {
            sleep(500);
          } catch (InterruptedException e)
          {
            System.err.println(e.toString());
          }
        }
        //exit condition
        if ( _stop )
          return;
        
  2. Use a synchronized block to wrap the code for opening the connection and retrieving data. This action is not necessary for this example, but it is good practice in most applications to ensure that subsequent fetch requests are not missed while received data is processed.
  3. Create a StreamConnection object. Invoke the Connector.open method, using the getUrl() method to pass in the URL that the user entered. Cast the returned object as a StreamConnection.
    synchronized(this)
    {
      //open connection and extract the data
      StreamConnection s = null;
    
      try
      {
        s = (StreamConnection)Connector.open(getUrl());
        

    Note: In some cases, you might want to cast the object returned by Connector.open as an HttpConnection object instead. HttpConnection is a StreamConnection that provides access to specific HTTP functionality, including headers and other HTTP Resources. Other types of objects can be returned by the Connector.open() method, depending on the type of protocol specified in the URL. A URL that starts with http returns an HttpConnection object.

  4. Invoke openInputStream() on the StreamConnection object to open and return an input stream for the connection. Store this input stream in a variable called input.
    InputStream input = s.openInputStream();
        
  5. Extract data from the input stream in 256-byte chunks and write it into a string buffer.
    byte[] data = new byte[256];
    int len = 0;
    StringBuffer raw = new StringBuffer();
    
    while ( -1 != (len = input.read(data)) )
    {
        raw.append(new String(data, 0, len));
    }
       
  6. Convert the received text to a String and then invoke the updateContent method to display the text on screen. Then you can close the input stream (input) and the HTTP connection (s).
        String text = raw.toString();
        updateContent(text);
        input.close();
        s.close();
    } catch (IOException e){
        System.err.println(e.toString());
    }
        
  7. Reset the start state to indicate that the connection is finished.
                _start = false;
            }
        }
    }
        

Retrieving Web Content

Define a method to retrieve data from the URL (which is hard-coded in this example).

  1. Perform basic validation of the URL. Set all characters to lowercase and add the http:// string if it is not present. This prefix string is defined in the HTTP_PROTOCOL constant.
    private static final String[] HTTP_PROTOCOL = {"http://", "http:\\"}
    ...
    
    private void fetchPage(String url)
    {
        String lcase = url.toLowerCase();
        boolean validHeader = false;
        int i = 0;
    
        for (i=HTTP_PROTOCOL.length-1;i>= 0;--i)
        {
            if(-1!=lcase.indexOf(HTTP_PROTOCOL[i]))
            {
                validHeader = true;
                break;
            }
        }
    
        if ( !validHeader )
        {
            //add protocol specifier
            url = HTTP_PROTOCOL[0] + url;
        }
        
  2. Invoke the fetch method to start a new thread for the connection. Note that you cannot open a connection on the event thread.
        _connectionThread.fetch(url);
    }
    

Displaying the Content

Define a method that updates the _content field on the main screen. This method is invoked by the connection thread to display text that has been retrieved.

private void updateContent(final String text) {
    UiApplication.getUiApplication().invokeLater(new Runnable()
    {
        public void run()
        {
            _content.setText(text);
        }
    });
}

Exiting the Application

Implement the abstract onExit() method that you defined in the base class to shut down the status and connection threads. This method is invoked when the user closes the application.

public void onExit()
{
    _connectionThread.stop();
}
  

Writing the application constructor

Create a new thread object and define variables for UI components. A RichTextField is a read-only field that supports a variety of text formatting.

The constructor for your class must create the main UI components (including a main screen, a title, and display fields), start the connection thread, and then push the main screen onto the UI stack. Invoke the fetchPage method to retrieve the URL.

private static final String[] HTTP_PROTOCOL = {"http://", "http:\\"}
private static final String SAMPLE_PAGE = "http://www.blackberry.com"

ConnectionThread _connectionThread = new ConnectionThread();

private MainScreen _mainScreen;
private RichTextField _content;
...

public HTTPDemo()
{
    _mainScreen = new MainScreen();
    _mainScreen.setTitle( new LabelField(
      _resources.getString(APPLICATION_TITLE),
        LabelField.ELLIPSIS | LabelField.USE_ALL_WIDTH));
    _mainScreen.add(new SeparatorField());
    _content = new RichTextField(
      _resources.getString(HTTPDEMO_CONTENT_DEFAULT));
    _mainScreen.add(_content);

    //implemented by super
    _mainScreen.addKeyListener(this);

    //implemented by super
    _mainScreen.addTrackwheelListener(this);

    //start the helper threads
    _connectionThread.start();

    pushScreen(_mainScreen);
    fetchPage(SAMPLE_PAGE);
}
  

Working With Socket Connections

This section explains how to exchange data with a remote server using a socket connection.

The BlackBerry handheld supports low-level socket connections, which are not a required part of MIDP. You can open socket connections from your handheld application to a server across the wireless network.

Although you can implement HTTP over a socket connection, many of the features of the Mobile Data Service are not supported for socket connections. Such an application would likely require significantly more bandwidth to perform a similar operation. You should use caution when sending data streams over the wireless network given that actual available bandwidth often remains quite low and network coverage can be intermittent.

Tip: If you use sockets, you should design your application to accommodate intermittent connections to the wireless network. For example, your application should re-open the connection if an error occurs, such as the handheld moving outside an area of network coverage.

Open a Connection

To open a socket connection, invoke the Connector.open method but specify socket rather than http as the protocol.

private static String URL = "socket://localhost:4444";
StreamConnection conn = null;
conn=(StreamConnection)Connector.open(URL);

Note: Socket connections require that you use the BlackBerry Enterprise Server Software as your network gateway. You cannot use socket connections with a WAP gateway.

Send Data

To send data on a socket connection, you can acquire input and output streams using the openInputStream() and openOutputStream() methods. Working with input and output streams is not much different than in J2SE.

private OutputStreamWriter _out;
  ...
_out = new OutputStreamWriter(conn.openOutputStream());

String data = "This is a test";
int length = data.length();
_out.write(data, 0, length);
  

Receive Data

Use an InputStreamReader to receive data on a socket connection. In the following example, each character is read into the input array.

private InputStreamReader _in;
  ...
_in = new InputStreamReader(conn.openInputStream());

int length = data.length();
char[] input = new char[length];

for ( int i = 0; i < length; ++i )
{
    input[i] = (char)_in.read();
}

Close the Connection

As with all connections in the MIDP framework, invoke the close() method on input and output streams to close them, and then invoke close() on the socket connection to close it.

_in.close();
_out.close();
conn.close();

Configuring the Mobile Data Service

In a production environment, the BlackBerry Enterprise Server system administrator can configure Mobile Data Service parameters using the BlackBerry Enterprise Server Management console.

In the BlackBerry Java Development Environment, you can configure the Mobile Data Service simulator using text configuration files in the MDS\config folder:

  • configure Mobile Data Service properties (rimpublic.property)
  • configure email to PIN mappings (system.property)

Configuring Mobile Data Service Properties

The rimpublic.property configuration file is located in the MDS\config folder in the JDE installation folder. Edit this file in a text editor. You must restart the MDS simulator for changes to take effect.

The following subsections describe parameters that you might need to change.

HTTP Parameters

The following parameters configure how the Mobile Data Service manages HTTP connections.

Parameter Description Default
application.handler.http.
AuthenticationSupport
Set to TRUE or FALSE to enable or disable storage of user authentication information. FALSE
application.handler.http.
AuthenticationTimeout
If HTTP authentication is set to TRUE, this time frame determines the length of time (in milliseconds) before the authentication information becomes invalid. This timer resets whenever the user issues a request that invokes the authentication information for a particular domain. 3600000
application.handler.http.
CookieSupport
Set to TRUE or FALSE to enable or disable cookie storage. If you select TRUE, the Mobile Data Service manages cookie storage instead of the handheld. This reduces the load on the handheld significantly. FALSE

HTTPS Parameters

The following parameter specifies whether the handheld can establish an HTTPS connection with an untrusted server.

application.handler.https.allowUntrustedServer = false

If you set this parameter to TRUE, the Mobile Data Service accepts outbound HTTPS connections to servers for which no certificate is stored. If this parameter is set to FALSE, users are prompted before establishing a connection to an untrusted server.

TLS Parameters

The following parameter specifies whether the handheld can establish a TLS connection with an untrusted server.

application.handler.tls.allowUntrustedServer = false

If you set this parameter to TRUE, the Mobile Data Service accepts outbound HTTPS connections to servers for which no certificate is stored. If this parameter is set to FALSE, users are prompted before establishing a connection to an untrusted server.

IPPP Parameters

The following parameters control how the Mobile Data Service manages the underlying connection with the handheld, which uses the RIM IP Proxy Protocol (IPPP). You should not have to change these parameters, unless the port specified by the IPPP.queue.flow.control.timeout parameter is already in use.

Parameter Description Default
IPPP.connection.
MaxNumberOfKBytesToSend
This parameter defines the maximum number of kilobytes that can be sent to the handheld per connection. 1024
IPPP.logging Set to TRUE or FALSE to enable or disable IPPP logging. If you select TRUE, the Mobile Data Service logs all packets that are sent and received using IPPP. TRUE
IPPP.push.listen.
tcp.port
This parameter specifies the port on which the Mobile Data Service listens to open server connections. 81
IPPP.queue.flow control.
timeout
If the handheld does not send an acknowledgement within the time frame specified here, the Mobile Data Service discards all content pending to the handheld. This parameter is measured in milliseconds. 60000
IPPP.queue.flow control.
window.size
This parameter specifies the size of the flow control window per handheld. The flow control window dictates the number of waiting packets that can be sent to a destination at one time. A value of -1 disables flow control. This is acceptable when using the simulator. -1

SRP Parameters

The following parameter specifies the SRP UID to assign to the Mobile Data Service.

SRP.UID = SV000000

This parameter does not apply to the simulator. Do not change this parameter.

Web Server Parameters

The following parameters control the operation of the Web Server that is included in the Mobile Data Service. You typically should not have to change these parameters unless the specified ports are already in use.

Parameter Description Default
MonitorAgent.listen.
port
This parameter is not applicable to the simulator. 8070
WebServer.listen.
port
This parameter is not applicable to the simulator. 8088
WebServer.servlet.
monitor.host
This parameter is not applicable to the simulator. localhost
WebServer.servlet.
monitor.port
This parameter is not applicable to the simulator. 8070
WebServer.servlet.
push.host
This parameter indicates to the push servlet the host name on which the Mobile Data Service runs. This parameter must be set to localhost. localhost
WebServer.servlet.
push.port
This parameter indicates to the push servlet the port on which the Mobile Data Service listens to open server connections. This port number must match that of the variable IPPP.push.listen.tcp.port 81

Configuring Email to PIN Mappings

The BlackBerry Enterprise Server automatically handles the mapping between users' email addresses and their handheld personal identification numbers (PINs).

The mapping between email address and PINs can be simulated in the BlackBerry JDE by creating or editing the system.property file in the MDS\config folder.

Add one line for each mapping, in the following format:

<EMAIL>  <PIN>

For example:

asmith@work.com 11111111
bsmith@work.com 22222222