Java Technology Home Page
A-Z Index

Java Developer Connection(SM)
Technical Tips

Downloads, APIs, Documentation
Java Developer Connection
Tutorials, Tech Articles, Training
Online Support
Community Discussion
News & Events from Everywhere
Products from Everywhere
How Java Technology is Used Worldwide
Print Button

Members Only Requires login

Early Access Members Only

Downloads

Bug Database Members Only
Submit a Bug
View Database

Newsletters
Back Issues
Subscribe

Learning Centers
Articles
Bookshelf
Code Samples
New to Java
Question of the Week
Quizzes
Tech Tips
Tutorials

Forums

Technology Centers
Tech Tips archive

J2ME Tech Tips

December 18, 2000

WELCOME to the Java Developer ConnectionSM (JDC) J2ME Tech Tips, December 18, 2000. This issue covers:

This issue of the JDC J2ME Tech Tips is written by Eric Giguere (http://www.ericgiguere.com), an engineer at iAnywhere Solutions, inc, and author of the book "Java 2 Micro Edition: Professional Developer's Guide."


THE J2ME DEVELOPMENT CYCLE

Java 2 Platform, Micro Edition (J2ME) is a set of technologies and specifications that enable Java applications to run on devices such as cell phones, Personal Digital Assistants, or set top boxes, that are unable to accommodate the JavaTM 2 Platform, Standard Edition (J2SE(tm)) runtime environment. These devices have severe resource constraints when compared to desktop or server computers, limitations that kept the Java Platform off these devices until now.

Central to J2ME are the concepts of configurations and profiles. A configuration defines the core runtime environment for J2ME implementations. It specifies the capabilities of the Java Virtual Machine*, a supported subset of J2SE classes, and additional J2ME-specific classes. A profile builds on the configuration by adding classes and specifying behaviors in support of families of specific devices or types of applications. A profile can also build on another profile.

How do configurations and profiles affect the normal Java development cycle? In some ways there is little change: you still use the same tools as before (such as, javac, jar, and javadoc). In fact, you need a Java 2 SDK (formerly known as a JDK), in order to build J2ME applications. The J2SE 1.3 SDK is the currently recommended SDK, although you can use a Java 2 SDK such as JDK 1.2.2. Configurations accept standard Java class files and JAR files as input to the virtual machine, which is why the J2SE tools can be used.

What's different are the options you use when invoking the Java compiler. Placing the configuration classes in the compiler's class path won't work, because the compiler automatically searches the J2SE core classes first, regardless of what's in the class path. This means that the compiler won't catch any references to classes or methods that are missing from a particular J2ME configuration, leading to runtime errors when you deploy your application.

The solution is simple: use the -bootclasspath option to replace the J2SE classes with the J2ME classes. As an example, you can apply this to the Connected Limited Device Configuration (CLDC). Assuming that you've installed the CLDC reference implementation on your machine, and defined a CLDC_HOME environment variable, you compile a CLDC application like this under Windows:

  javac -bootclasspath %CLDC_HOME%\bin\api\classes *.java

On Solaris, you use:

  javac -bootclasspath $CLDC_HOME/bin/api/classes *.java

To keep the class files as small as possible, you normally also use the -g:none option to remove all debugging information.

If you compile your J2ME application to use the Connected Device Configuration (CDC) instead of the CLDC, use the CDC classes, instead of the CLDC classes, with the -bootclasspath option. If you compile against a particular profile, just add the profile's classes to the boot class path.

For CLDC-based applications, there is an additional step to follow after compiling your Java source code. The CLDC includes a new Java virtual machine (VM) called the K Virtual Machine or KVM for short. The KVM is a completely new implementation of a Java virtual machine, designed from the start to work on resource-constrained devices. One of the things it does is change how classes are verified, or checked for correctness. Instead of running the complete verification process on the device, most of it is done offline, using a tool called a preverifier. The preverifier does the actual verification and inserts extra information into the class files. (Note that the modifications are transparent to non-KVM virtual machines.) The KVM looks for this information and uses it to perform a much simpler verification based on the data collected by the preverifier.

You can find the preverifier in the bin of the CLDC reference implementation. On Windows you invoke the preverifier (on a single line, of course) like this:

  %CLDC_HOME%\bin\preverify -classpath %CLDC_HOME%\bin\api\classes
    -d verified dir-or-class-list

The syntax for Solaris is similar, just adjust the paths and the environment variable expansion. The options are similar to those of javac:

  • The -classpath option lists the directories (note that the current version of the preverifier doesn't handle JAR files) in which to find referenced classes.
  • The -d option defines the output directory for the preverified classes.
  • The dir-or-class-list argument is the set of directory and/or class names to preverify. Directories are searched recursively for any class files.

When preverifying classes, be sure to keep the unverified and the preverified classes separate. It's usually best to keep them in separate directories. For example, say you define a simple HelloWorld.java source file:

  public class HelloWorld {
    public static void main( String[] args ){
      System.out.println( "Hello, world!" );
    }
  }

You could compile and preverify it in Windows as follows, assuming that the CLDC's bin directory is in your path:

  javac -g:none -bootclasspath 
    %CLDC_HOME%\bin\api\classes 
        -d unverified HelloWorld.java
    
  preverify -classpath %CLDC_HOME%\bin\api\classes 
        -d preverified unverified

In Solaris:

  javac -g:none -bootclasspath 
    $CLDC_HOME/bin/api/classes 
        -d unverified HelloWorld.java

  preverify -classpath $CLDC_HOME/bin/api/classes
        -d preverified unverified

The HelloWorld.class in the preverified directory is the one you actually want to run:

In Windows:

  kvm -classpath 
    preverified;%CLDC_HOME%\bin\api\classes HelloWorld
In Solaris:
  kvm -classpath 
    preverified:$CLDC_HOME/bin/api/classes HelloWorld

Apart from these few changes, developing in J2ME is almost the same as developing in J2SE, making the transition to Java programming for small devices relatively simple.

There is also a toolkit, called the J2ME Wireless Toolkit, that can further simplify the J2ME development process. For more information about the J2ME Wireless Toolkit, see http://java.sun.com/products/j2mewtoolkit/.

For further information on the J2ME development cycle, see the white paper Java 2 Micro Edition (J2ME) Technology for Creating Mobile Devices (http://java.sun.com/products/cldc/wp/KVMwp.pdf).

For further information about the Connected Limited Device Configuration (CLDC), see http://java.sun.com/products/cldc/.

Also visit the Consumer & Embedded Technology Center (http://java.sun.com/jdc/products/j2me/) for articles, tutorials, and other resources on J2ME technologies.


MAKING HTTP CONNECTIONS WITH MIDP

HTTP connectivity is one of the requirements of the Mobile Information Device Profile (MIDP). A MIDP-enabled device must be able to interact with a web server through conventional HTTP requests. If the network doesn't directly support HTTP, then the device must route its requests through a gateway. But this is all transparent to the application developer.

In the MIDP, you interact with the network using the Generic Connection framework. (This is true for any profile built on top of the Connected Limited Device Configuration (CLDC)). The framework is a set of classes and interfaces defined by the CLDC that replaces most of the java.io and java.net classes defined by J2SE.

To make an HTTP request, use the Connector.open method and a conventional URL, casting the result to an HttpConnection:

  import javax.microedition.io.*;
    
  HttpConnection conn = Connector.open( 
                      "http://www.java.sun.com/jdc" );

The HttpConnection interface defines all the usual methods you would expect to see for making HTTP requests and processing the replies. This includes setRequestMethod, getHeaderField and openInputStream. The HttpConnection interface makes it simple to interact with any web site on the Internet.

One thing you will soon discover is that you won't always get the response you expect when you connect to a web site. In particular, many web sites redirect you to another URL. The Java Developer Connection web site does this, for example, when you attempt to open the page at http://www.java.sun.com/jdc -- it redirects you to http://developer.java.sun.com/developer/. Sometimes a site redirects you because the resource you are asking for has moved. Or else the site wants you to login first. If you are accessing a web site that's not under your control, you have to be prepared to handle redirections. You need to follow the redirections to obtain the data you really want.

Here's a simple class called HttpConnectionHelper that uses the HttpConnection interface. You can use the class to automatically follow web site redirections:

  import java.io.*;
  import javax.microedition.io.*;
    
  public class HttpConnectionHelper {
  
    public interface Callback {
      void prepareRequest( String originalURL, 
                           HttpConnection conn ) 
           throws IOException;
    }
    
    public static HttpConnection connect( String url ) 
                                   throws IOException {
      return connect( url, null );
    }
    
    public static HttpConnection connect(
            String url, Callback callback ) 
                         throws IOException {
      HttpConnection conn = null;
      String         originalURL = url;
    
      while( url != null ){
        HttpConnection conn = (HttpConnection) 
                          Connector.open( url );
    
        if( callback != null ){
          callback.prepareRequest( originalURL,
					 conn );
        }
    
        int rc = conn.getResponseCode();
   
        switch( rc ){
            case HttpConnection.HTTP_MOVED_PERM:
            case HttpConnection.HTTP_MOVED_TEMP:
            case HttpConnection.HTTP_SEE_OTHER:
            case HttpConnection.HTTP_TEMP_REDIRECT:
              url = conn.getHeaderField( "Location" );
              if( url != null && url.startsWith( 
                                            "/*" ) ){
                StringBuffer b = new StringBuffer();
                b.append( "http://" );
                b.append( conn.getHost() );
                b.append( ':' );
                b.append( conn.getPort() );
                b.append( url );
                url = b.toString();
              }
              conn.close();
              break;
            default:
              url = null;
              break;
        }
      }
    
      return conn;
   }
 }

To use this class, call the connect method, passing it the original URL:

  HttpConnection conn = HttpConnectionHelper.connect( 
                           "http://java.sun.com/jdc" );
  int            rc = conn.getResponseCode();
    
  if( rc == HttpConnection.HTTP_OK ){
    InputStream in = conn.openInputStream();
    // do something with the response....
  } else {
    // unexpected response code
  }

When invoked, the connect method connects to the original URL and gets the HTTP response code. If the response code is the redirection code HTTP_TEMP_REDIRECT, the connect method gets the new URL from the Location response header and connects to that URL. The method loops until a non-redirection response code is returned. At that point, the method returns an HttpConnection to the final destination.

For special cases, such as when you want to make a Post request instead of a Get request, you can use the two-parameter form of the connect method. Here you pass in the URL as the first parameter, and an object implementing the HttpConnectionHelper.Callback interface as the second parameter:

  class MyCallback implements 
      HttpConnectionHelper.Callback {
    public void prepareRequest( String originalURL, 
                               HttpConnection conn ) 
                                throws IOException {
      conn.setRequestMethod( HttpConnection.POST );
      conn.setRequestProperty( "User-Agent",
        "Profile/MIDP-1.0 Configuration/CLDC-1.0" );
      conn.setRequestProperty( 
                       "Content-Language", "en-US" );
    }
  }
    
  HttpConnection conn = HttpConnection.connect( 
       "http://java.sun.com/jdc", new MyCallback() );

If you define a callback, it's called each time a connection is made, that is, before the response code is obtained. This lets you modify the HTTP request before it's actually made.

For further information about the Mobile Information Device Profile (MIDP), see http://java.sun.com/products/midp.

For more information about the HTTP 1.1 protocol, refer to ftp://ftp.isi.edu/in-notes/rfc2616.txt.


— Note —

Sun respects your online time and privacy. The Java Developer Connection mailing lists are used for internal Sun MicrosystemsTM purposes only. You have received this email because you elected to subscribe. To unsubscribe, go to the Subscriptions page (http://developer.java.sun.com/subscription/), uncheck the appropriate checkbox, and click the Update button.

— Subscribe —

To subscribe to a JDC newsletter mailing list, go to the Subscriptions page (http://developer.java.sun.com/subscription/), choose the newsletters you want to subscribe to, and click Update.

— Feedback —

Comments? Send your feedback on the JDC Tech Tips to: jdc-webmaster@sun.com

— Archives —

You'll find the J2ME Tech Tips archives at:

http://java.sun.com/jdc/J2METechTips/index.html

— Copyright —

Copyright 2000 Sun Microsystems, Inc. All rights reserved.
901 San Antonio Road, Palo Alto, California 94303 USA.

This Document is protected by copyright. For more information, see:

http://java.sun.com/jdc/copyright.html

J2ME Tech Tips December 18, 2000


*As used in this document, the terms "Java virtual machine" or "JVM" mean a virtual machine for the Java platform.

Print Button
[ This page was updated: 4-Jun-2001 ]
Products & APIs | Developer Connection | Docs & Training | Online Support
Community Discussion | Industry News | Solutions Marketplace | Case Studies
Glossary | Feedback | A-Z Index
For more information on Java technology
and other software from Sun Microsystems, call:
(800) 786-7638
Outside the U.S. and Canada, dial your country's AT&T Direct Access Number first.
Sun Microsystems, Inc.
Copyright © 1995-2001 Sun Microsystems, Inc.
All Rights Reserved. Terms of Use. Privacy Policy.