J2ME  Networking
Peter Komisar ©  Conestoga College  version  1.2 /  2009


reference: Networking with J2ME, Soma Ghosh, IBM
http://www.ibm.com/developerworks/java/library/wi-jio/
'Learning Wireless Java', Qusay H. Mahmoud, O'Reilley
MIDP Inter-Communication with CGI and Servlets,Qusay Mahmoud
http://developers.sun.com/mobility/midp/articles/servlets/




J2ME networking features extend the reach of the
hand held device into the mobile space. The hand
held device becomes an Internet browser.

MIDP supports a subset of the HTTP protocol which
can make use of IP protocols like TCP/IP and non-IP
protocols such as WAP and i-Mode via gateways
that provide access to HTTP servers on the Internet.

// a gateway may be used as a bridge between a
// wireless network and the wired Internet.



The java.io Package


The Microedition's java.io package is a subset of
the standard edition's java.io package. It works in
a similar way for J2ME supplying input and output
streams for the transfer of data.


A Little Review

Following is a code sample that uses the standard
java.io package.



IO Example from the Standard Edition

import java.io.*; 

class ReadLoop {
public static void main(String[]args){
int symbol=0;
FileInputStream fis=null;
 try{
    fis=new FileInputStream("Zee.txt");
    while( (symbol=fis.read( ))!= -1){
      System.out.print((char)symbol + "-");
      }
    }
  catch(FileNotFoundException fnfe){}
  catch(IOException io){}
  }
}


We will see the streaming mechanics are essentially
the same in the micro edition although the basic
approach is quite different.  For instance, you might
decide to open a Reader on a file only to find out that
in the MicroEdition version of java.io none of the
classes can open on a target file. We will see, in
J2ME everything is initially channeled through the
Connector class.


The javax.microedition.io Package


The javax.microedition.io classes and interfaces
provide networking capability for the MIDP platform.
It supplies sockets and HTTP Classes. On first glance
it seems to be that the micro edition combines aspects
of java.io and the java.net packages from the standard
edition of Java. 


The Key Link


The key connectivity point that is addressed in J2ME's
networking API is the communication between the mobile
device and Web server. Once this connection is established
it is an easy matter to interface with other network objects
like intranets, databases and the Internet.


Three networking categories are described in the IBM
reference noted above.


Three Categories of Networking

Low Level IP Networking


TCP/IP

This is the socket level of connection where a TCP/IP
socket that negotiates this protocol is created. When
using the TCP/IP protocol, a virtual connection is made
which includes an acknowledgment  mechanism that
ensures data is received by the recipient.

// In TCP/IP source and destination addresses are included


UDP

The API also supplies a datagram communication based
on UDP where data is broadcasted without any assurance
that the data has been received. This is often used to send
multi-media data, like a video where a few dropped frames
is acceptable.

// In UDP only the destination address is needed for it's use


A Quick Look at the javax.microedition.io Package

A quick look the microedition.io package shows it
contains almost all interfaces and just a few classes.
The two classes of the package are Connector and
PushRegistry.


Interfaces of the javax.microedition.io Package



Classes of the javax.microedition.io Package

     // one exception class
The Connector class, is clearly the main player
in attaining a connection.

The Connector Class   //  'the main player'

The Connector class uses all static methods
and so does not require any constructors. It
defines the following three static fields.

The static fields signal the creation of connections
that exclusively read or write, or do both, read and
write.


Static Fields of the Connector Class
// static ints

Following is a quick summary of Connector's static
methods. The set offers several options for returning
different objects useful for different functions.

Static Methods of the Connector Class

The open( ) methods all return Connection objects
which encapsulate Socket connections.  The mode
argument in the open( ) methods refers to READ,
WRITE or READ_WRITE constants. The boolean
flag indicates the caller wants a timeout notification.

The openDataInputStream( ) and openDataOutputStream( )
methods are useful for reading and writing Java primitive
types, their associated wrapper classes or Unicode strings.

The generic Input and Output stream objects define
variations on read( )  and write( ) methods.


Generic Connection Framework

We back up a step here to consider the architecture
that binds these classes and interfaces together.

To provide the different sorts of connections that can
be made, the Micro API uses a set of classes called
the 'Generic Connection Framework'.

Practically speaking, this is the set of Java interfaces
that define the methods needed to make the different
sorts of network connections.

Following are the key interfaces.

Generic Connection Framework Interfaces
// all found in the javax.microedition.io package

The following depiction shows how the interfaces
are structured. Interesting to note is that, though
Java doesn't support multiple inheritance for it's
classes, Java's interfaces can participate in multiple
inheritance as is evidenced by StreamConnection's
dual parenthood.


Generic Connection Framework Hierarchy

                     Connection
            _____________|___________
           |             |           |
StreamConnectionNotifier |   DatagramConnection

                  
___________|___________
             |                       |
        InputConnection       OutputConnection
             |_______________________|
                         |
                  StreamConnection
                         |
                  ContentConnection
                _________|_________
               |                   |
          HttpConnection     HttpsConnection             
                    


Connecting


Making a connection involves opening a connection
to a Web server from the mobile device. Once a
connection is established an exchange of data can
occur.

The following states of connection are described:
It is only during setup that request parameters can
be set. We will example this shortly.


The Connector Class

The Connector class provides static methods to create
various connection objects. This is done dynamically
based on the platform name and the protocol that is
being requested.

Notice how the open( ) method determines the type
of connection it will return based on the arguments
supplied to the open( ) method.


Connector.open( ) Examples



Example: Invoking HTTP-based communication

Connection conn = Connector.open("http://www.yahoo.com");


Example: Invoking stream-based socket communication

Connection conn = Connector.open("socket://localhost:9000");


Example: Invoking datagram-based socket communication

Connection conn = Connector.open("datagram://:9000");


Example: Invoking serial port communication

Connection conn = Connector.open("comm:0;baudrate=9000");


Example: Invoking file I/O communication

Connection conn = Connector.open("file://myfile.dat");


Note Regarding the above Examples

'Learning Java' supplies a very similar set of examples
as shown above.


Qusay Mahmoud, in 'Learning Java' points out that
the above sorts of examples are useful for illustration
only. The CLDC does not mandate how protocols are
implemented at the configuration level. Sun's MIDP
profile provides an implementation for the HTTP protocol
but not for socket or datagram connection.


HTTP a 'Must Support' So It's Use is Encouraged

Because MIDP 1.0 must support HTTP, developers
are encouraged to use this protocol in their applications
so that they are portable across mobile devices.


Secure Connections


IF the URL provided to the open( ) method is of the
form  ' https://  '  an HttpsConnection is returned. 

A SecureConnection is returned when open( ) is
provided with an argument that has a url of the form,
 ' ssl:// ' .


Reading and Writing Streams of Bytes

The following snippet from 'Networking with J2ME' by
Soma Ghosh shows how an InputStream is opened
on a connection in order to read bytes of data from
the stream.


Example of Opening an InputStream

//
code extract from
Networking with J2ME, Soma Ghosh,
http://www.ibm.com/developerworks/java/library/wi-jio/


// . . .
  HttpConnection c = null;
         InputStream is = null;
              StringBuffer str = new StringBuffer();

              try {
                  c = (HttpConnection)Connector.open(url);

                // Getting the InputStream will open the connection
                // and read the HTTP headers. They are stored until
                // requested.

                is = c.openInputStream( );
 
               // Get the length and process the data
             int len = (int)c.getLength();
             int ch;
             while ((ch = is.read()) != -1) {
                 str.append((char)ch);
// . . .


A First Example

The following code is an adaption of code supplied in
the above referenced IBM article. The original was an
elaborate work that parsed out a sample of currency
exchange from a site on the web.

We short circuited the code to open on a simple file
at www.sentex.net/~pkomisar/Sea.txt.

Note the emulation asks if you will accept charges.
This would happen with a real mobile device but I
think it is safe to say yes when using the emulation!
You won't be charged!


Sample Adapted from Currency Exchange
// based on CurrencyExchange.java from Networking with J2ME,
Soma Ghosh,
http://www.ibm.com/developerworks/java/library/wi-jio/


import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.io.*;
import java.io.*;

public class NetPage extends MIDlet
               implements CommandListener

  private Command exitCommand;
  private Display display;     
  Form displayForm;
 
 public NetPage() {
    display = Display.getDisplay(this);
    exitCommand =
    new Command("Exit", Command.SCREEN, 1);
   }

 public void startApp()
  {
   displayForm = new Form("Local");
   displayForm.addCommand(exitCommand);
   displayForm.setCommandListener(this);
 
 try
   {
   String result = getViaHttpConnection
   ("http://www.sentex.net/~pkomisar/Sea.txt");
    displayForm.append(" " + result);
   }
 catch (Exception exc)
   {
   exc.printStackTrace();
   }
   display.setCurrent(displayForm);
  }
 
   public void pauseApp() { }
   public void destroyApp(boolean unconditional) { }

  public void commandAction(
   Command c, Displayable s) {
    if (c == exitCommand) {
     destroyApp(false);
     notifyDestroyed();
    }
  }
 
// this method is in the IBM article and in Quasay Mahmoud's
// Learning Wireless Java book
so I am thinking there is a Q,
// that is supplying a general pattern that is applied, depending
// on the stream choice that is used. It is modified here to suit
// our purposes


String getViaHttpConnection(String url) throws IOException {
         HttpConnection c = null;
         InputStream is = null;
         StringBuffer str = new StringBuffer( );

         try {
             c = (HttpConnection)Connector.open(url);
             // get the ContentType
            // not used in this code but could be handy
             // outputs text/plain for this sample
             String type = c.getType( );
             System.out.println(type);
 
             // Getting the InputStream will open the connection
             // and read the HTTP headers. They are stored until
             // requested.
             is = c.openInputStream( );
 
           
 
             // Get the length and process the data
             int len = (int)c.getLength( );
             int ch;
             while ((ch = is.read( )) != -1) {
                    str.append((char)ch);
                 }
            
         } finally {
             if (is != null)
                 is.close();
             if (c != null)
                 c.close();
         }
     return str.toString( );
     }
  }


No HTML Rendering?

Note if we open on a web page with the above code
the HTML code is shown. Seeing a bunch of HTML
source code on screen makes you think J2ME might
supply a HTML renderer something like the JTextPane
class in the javax.swing package, but apparently not.

Mobile vendors like Nokia or RIM provide browser
capabilities for their cell phones. Still we would like to
have some control on rendering from inside the J2ME
API. Maybe it will come later.

Various projects have been started to achieve this goal
of supplying browser capabilities for the J2ME API.
Following are a few to investigate.

To Investigate



Some Midlet IO Examples

A similar format is used to reference a file url with
important differences.

When opening on the local file system the J2ME
context also asks if you wish to connect to the
local file system in addition to asking if you accept
charges.

// this is reminiscent of issues surrounding applets

The following example is example was migrated
from the earlier example and now is essentially the
same as the MIDlet, 'FetchPageMidlet' found in
 'Learning Java' by Qusay Mahmoud.

Here you can see the key method, has it's name
modified to indicate the sort of stream that is being
used. It is called getViaStreamConnection( ).

IN this code, the attributes ContentType and Length,
characteristic of the HTTP protocol are not used.

Another variation, instead of capturing the output
as a String object, the StringBuffer issues it's output
to a TextBox which is made the current display.

// the text file target needs to be created, but see
// the Fix below after running the code


Reading from Local File URL Sample

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.io.*;
import java.io.*;

public class LocalFile extends MIDlet
              

  private Display display;     
 
 
 public LocalFile() {
    display = Display.getDisplay(this);
    }

 public void startApp()
  {
  
 try
   {
   getViaStreamConnection("file:///root1/Know.txt");
   }
 catch (Exception exc)
   {
   exc.printStackTrace();
   }
 }
 
   public void pauseApp() { }
   public void destroyApp(boolean unconditional) { }

 

void getViaStreamConnection(String url) throws IOException {
     
         StreamConnection c = null;
         InputStream s = null;
         StringBuffer str = new StringBuffer();
         TextBox t=null;
  

         try {
   
             c = (StreamConnection)Connector.open(url);
             s = c.openInputStream();
             int ch;
             while ((ch = s.read()) != -1) {
                    str.append((char)ch);
             System.out.println(str.toString());
             
             }
           t = new TextBox("Local File", str.toString(),1024,0);
      
            
         } finally {
             if (s != null)
                 s.close();
             if (c != null)
                 c.close();
         }
     display.setCurrent(t);
     }
  }


Problem Houston!

We dutifully put a Know.txt file under C. We compile
the code. The code compiles fine. We run it and get
the following exception.


Exception Thrown When Code is Run.


java.io.IOException: Root is not accessible
    at com.sun.midp.io.j2me.file.Protocol.ensureConnected(+47)
 

The Fix


The issue seems to be that the WTK 2.52 sees itself as
the center of the universe and doesn't regard C: (speaking
about Windows) as the root of the file system.

// this may have changed in WTK 3.0 which is just out at
// the time of this writing

We need to create the folders filesystem\root1 and put
our code there. Another words, the meaning of the root
directory for the file system is defined locally in the WTK.

Here is the location to put your target text file.

Location of Root in the WTK2.5.2  Context // Windows

C:\Documents and Settings\Peter\j2mewtk\2.5.2\appdb\DefaultColorPhone\filesystem\root1


If you are using version 3.0 the following is the location
you would use.


Location of Root for the Default Phone in WTK3.0 // Windows

C:\Documents and Settings\User\javame-sdk\3.0_ea\work\1\appdb\filesystem\root1

Now when the code above is run the text is shown to
screen.


Form Data

HTML with a Simple Form

Following is an HTML page that allows a user to
enter some text and press a submit button to have
it processed. The process is set to send the data
to the Hello_Form servlet. In this form a GET method
is specified.
 
Notice we would need to set the servlet up to run
somewhere to test this code in practice.

HTML Page with a FORM Element Using the GET Form

<HTML>
<HEAD>
<TITLE>Hello Form</TITLE>
</HEAD>
<BODY>
<H2>Hello!</H2>
<HR/>
<FORM METHOD=GET ACTION="Hello_Form">
Hello! May I ask, who are you?
<INPUT TYPE=TEXT NAME="name"<P>
<INPUT TYPE=SUBMIT>
</FORM>


Data Transfer With Get The GET Form

Because the GET method is used the data is
appended to the URL that will be sent to the
server. If we are running local host the url that
is sent will be something like the following.


Example of a URL sent with a GET

http://localhost:8080/examples/servlet/Hello_Form?name=Billy+the+Kid


Back to HelloWorld To Capture Data

The HelloWorld Servlet can be enhanced to provide a
dynamic response to the form submission. The only
consequential changes are highlighted. The key
call is getParameter( ) which retrieves the parameter
that was appended to the client's GET request.
 

Hello_Form,  A Servlet With a Response to a Form Submission

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class Hello_Form  extends HttpServlet{

public void doGet(HttpServletRequest req, HttpServletResponse res)
                           throws ServletException, IOException{

      res.setContentType("text/html");
      PrintWriter out=res.getWriter( );

    String name=req.getParameter("name");

      out.println("<HTML>");
      out.println("<HEAD><TITLE>Hello_Form</TITLE></HEAD>");
      out.println("<BODY>");
      out.println("<BIG>Hello " + name +  "! </BIG>");
      out.println("</BODY></HTML>");
      }
  }


Back to the Mobile Device

The Mobile Device can also be used to send and
receive data over the HTTP protocol. Recall there
were three phases to a connection ,set, connect
and close. Parameters are put in place before the
connection is established.

The first example we show will be theoretical and
used for study as we do not have the corresponding
CGI script and / or a servlet set up to reply to it.

This example was first pubished by Quasay Mahmoud
at the Sun Developer's web site.

Notice the code does some important set up relating
to using CGI scripts by way of the the setRequestMethod( )
and setRequestProperty( )  methods.


Code Snippet

     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");


Again the author sets the result into the current
display via a TextBox.


Midlet Example That Invokes a CGI Script

MIDP Inter-Communication with CGI and Servlets,Qusay Mahmoud
http://developers.sun.com/mobility/midp/articles/servlets/


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);
}
}


Note in the following code is sent to a Servlet that does
not process an parameters. The
setRequestMethod( ) is used to set the HTTP
action type to a GET.

Example
c.setRequestMethod(HttpConnection.GET);

Note in the following code you can adapt the
url to some real page. If one doesn't like to
see HTML tags the Servlet is quite happily
adapted to just send text.

A Midlet That Sends a GET Command

MIDP Inter-Communication with CGI and Servlets,Qusay Mahmoud
http://developers.sun.com/mobility/midp/articles/servlets/


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 { // GET called ed.
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);
}
}

A MIDlet That Specifies the POST Command

Perhaps more interesting is an example that Q.
Mahmoud offers which we can adapt it to get a
response from a servlet we can pre-load.

This example processes a POST method.

A look at this MIDlet shows again that parameters
and properties are set in advance.


A MIDLet Example That Processes a POST Command
'Learning Wireless Java', Qusay H. Mahmoud, O'Reilley

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://localhost:8080/WebStore/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 { // POST called ed.
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<postmsg.length;i++){
os.write(postmsg[i]);
}
// or you can easily do
// os.write(("name="+user).getBytes());
// os.flush( )

is = c.openDataInputStream();
int ch;
while ((ch = is.read()) != -1) {
b.append((char) ch);
}
t = new TextBox("First Servlet", b.toString(), 1024, 0);
t.addCommand(backCommand);
t.setCommandListener(this);
}

finally
{
if(is!= null) {
is.close();
}
if(c != null) {
c.close();
}
}
display.setCurrent(t);
}

public void commandAction(Command c,Displayable d){
String label =c.getLabel();
if (label.equals("Exit")){
destroyApp(true);
}
else if (label.equals("Back")){
mainMenu( );
}
else if (label.equals("Submit")){
user=input.getString( );
try{
invokeServlet(url);
}
catch(IOException e) { }
}
else{
addName();
}
}
}



Following is the Servlet which does the POST
for the above MIDlet.


RequestServlet.java

MIDP Inter-Communication with CGI and Servlets,Qusay Mahmoud
http://developers.sun.com/mobility/midp/articles/servlets/


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);
}
}



Servlets and Java Server Pages are Enterprise Topics

One way to implement this might be to download
Apache's Tomcat, run it as 'localhost' and load the
servlet into the examples folder. You might also just
adapt the above code to one of the existing servlets
in Tomcat.

Another option is to build and test the Servlet in
Eclipse or Netbeans.

This is left to you as a supplemental as Servlets
and Java Server Pages are a major topic onto
themselves, now normally covered with the
context of an Enterprise Java course.
 


Assignment


1) Adapt the first code sample above to discover
the contents of a text file called AZ.txt at:

 www.sentex.net/~pkomisar/AZ.txt

Show your code and a screen shot of the text.

2 ) Find a short poem or saying, put it in a file
located in what the WTK thinks is the root directory.
Adapt the code above to output the contents of the
file.
Screenshot the output, the code and the path to
the file from the operating systems point of view.


Optional 

3) For those who are familiar with servlets or
something that runs on a server, create a MIDlet
that sends three parameters to a server and is
returned a confirmation that those three parameters
are correct by restating them to the mobile device.