★ wanayoo — archive 1999 http://developer.java.sun.com/developer/community/chat/CodeClinic/1997/cc0821.htmlNouvelle recherche | Portail wanayoo
Java Technology Home Page
A-Z Index

Java Developer Connection(SM)
Chat

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
 

Code Clinic
includes questions on JDBCTM, Custom Class Loaders, AWT, and RMI
August 21, 1997

Guest-Speaker (SPK): spk-jaz

SPK-rohaly: Hi everyone. I'm Tim Rohaly from the MageLang Institute, and I will be answering your code questions today.

ljarratt: I am getting errors trying to connect to SQL Server 6.5 with the JDBC/ODBC bridge.

-------------------------------
I get the following warnings in Netscape 4:

Properties: java.lang.NullPointerException
Get Meta Data: java.lang.NullPointerException
Warning: sun.jdbc.odbc.JdbcOdbcSQLWarning: [Microsoft]
   [ODBC SQL Server Driver][SQL Server]Changed database 
   context to 'PlatTest'.
Warning: sun.jdbc.odbc.JdbcOdbcSQLWarning: [Microsoft]
   [ODBC SQL Server Driver][SQL Server]Changed language 
   setting to 'us_english'.
Warning: sun.jdbc.odbc.JdbcOdbcSQLWarning: [Microsoft]
   [ODBC SQL Server Driver]Access to database configured 
   in the DSN has been denied. Default used.
I still get the data with Netscape 4. It does query the database and retrieves the data
accurately.
--------------------------------
I get the following errors in Internet Explorer 3:
Properties: java.lang.NullPointerException
Get Meta Data: java.lang.NullPointerException
java.lang.UnsatisfiedLinkError
at sun/jdbc/odbc/JdbcOdbc.allocEnv
at sun/jdbc/odbc/JdbcOdbc.SQLAllocEnv
at sun/jdbc/odbc/JdbcOdbcDriver.initialize
at sun/jdbc/odbc/JdbcOdbcDriver.connect
at java/sql/DriverManager.getConnection
at java/sql/DriverManager.getConnection
at AccountAdmin/SignupClient.init
at com/ms/applet/BrowserAppletFrame.run
at java/lang/Thread.run

-----------------------------
I get the following errors in Netscape 3:
Driver: java.lang.ClassNotFoundException: 
   sun/jdbc/odbc/JdbcOdbcDriver
Properties: java.lang.NullPointerException
Get Meta Data: java.lang.NullPointerException
Connection: java.sql.SQLException: No suitable driver
Warning: java.lang.NullPointerException
java.lang.NullPointerException
java.lang.NullPointerException
java.lang.NullPointerException
I have verified the paths and they are correct.
-----------------------------
This is my code:
public class SignupClient extends Applet {
   public static final int PORT = 2000;
   Socket           socket;
   DataInputStream  inStream;
   PrintStream      outStream;
    TextArea         resultsTextArea;
   StreamListener   listenerStream;
   int              numberNewAccounts = 0;
   TitlePanel       titlePanel;
   String username;
   String entity;
   String password;
   String ccnumber;
   String fullname;

	
   String driverName;
   String dataSourceName;
   String dataSourceUsername;
   String dataSourcePassword;
   java.sql.Connection dbConnection = null;

   public void init() {
   
   // This was removed because of a 
   //      security error in Netscape 4.
   //
   //   try {
   //	   java.io.OutputStream outFile = new 
   //         java.io.FileOutputStream("jdbc.out");
   //      java.io.PrintStream  outStream = new 
   //         java.io.PrintStream(outFile, true);
   //   } catch (IOException e) {
   //       System.out.println("Log: " + e);
   //     }
   
        //   DriverManager.setLogStream( outStream );
        
        // These should be read in from a configuration 
        // file later.
        //
        
   driverName = "sun.jdbc.odbc.JdbcOdbcDriver";
   dataSourceName = "jdbc:odbc:TestDB";
   dataSourceUsername = "test";
   dataSourcePassword = "test";
      
   try {
      Driver d=(Driver)Class.forName( 
            driverName ).newInstance();
   } catch (Exception e) {
        System.out.println("Driver: " + e);
     }
        
   // GET PROPERTIES
   boolean autoCommit;
   boolean isReadOnly;
   String  catalogName;
   int     transIsolation;
    
   try {
      isReadOnly = dbConnection.isReadOnly();
      catalogName = dbConnection.getCatalog();
      transIsolation = 
            dbConnection.getTransactionIsolation();
   } catch (Exception e) {
        System.out.println("Properties: " + e);
     }
     
   // GET DB META DATA
   DatabaseMetaData dmd;
   try {
      dmd = dbConnection.getMetaData();
   } catch (Exception e) {
        System.out.println("Get Meta Data: " + e);
     }
    
   try {
      dbConnection = 
         DriverManager.getConnection( dataSourceName,
         dataSourceUsername, dataSourcePassword );
   } catch (Exception e) {
        System.out.println("Connection: " + e);
     }
    
   // Get SQL Warnings
   SQLWarning warning = null;
   try {
      warning = dbConnection.getWarnings();
      if (warning == null) {
         System.out.println( "No Warnings" );
         return;
      }
      
      while (warning != null) {	
         System.out.println( "Warning: " + warning);
         warning = warning.getNextWarning();
      }
   } catch (Exception e) {
        System.out.println("Warning: " + e);
     }
     
  // EXECUTE SQL
  boolean ret = false;
  ResultSet results = null;
  int updateCount = 0;
  try {
     ret = stmt.execute("select entity, state, 
        domain from domains");
     if (ret == true){
        results = stmt.getResultSet();
     }
     else{
        updateCount = stmt.getUpdateCount();
     }
   } catch(Exception e){
       System.out.println(e);
     }
    
   StringBuffer buffer = new StringBuffer();
   try {
      ResultSetMetaData rsmd = results.getMetaData();
      int numCols = rsmd.getColumnCount();
      int i, rowcount = 0;
      
      for ( i=1; i<= numCols; i++ ) {
         if ( i > 1 ) buffer.append("\t\t\t");
         buffer.append(rsmd.getColumnLabel(i));
      }
      buffer.append("\n");
      
      while (results.next() && 
         rowcount < 100) {
         for ( i=1; i<= numCols; i++ ) {
            if ( i > 1 ) buffer.append("\t");
            buffer.append(results.getString(i));
         }      
         buffer.append("\n");
         rowcount++;
      } 
      results.close();
   } catch (Exception e) {
        System.out.println(e);
        return;
     }

   // CLOSE CONNECTION
   try {
      dbConnection.close();
   } catch (Exception e) {
        System.out.println("Close Connection: " + e);
     }
     
   // IS CONNECTION CLOSED
   boolean b;
   try {
      b = dbConnection.isClosed();
   } catch (Exception e) {
        System.out.println(
            "Is Connection Closed: " + e);
     }
     
   // Do screen stuff here
   }
}

SPK-rohaly: Well, I'm having technical difficulties testing your code--this window doesn't allow cut and paste! But I am looking through it to see if you've done anything obviously wrong.

The first thing to note is that DatabaseMetaData doesn't work with a lot of drivers. I personally don't have any experience with SQL Server, so I don't know if this is one of your problems. Are you trying to connect to a local database (local to client), or is the database on the HTTP server machine.
ljarrat asked about a piece of code he posted at the beginning of the session having to do with the JDBC. After receiving the entire code from him by email after the session ended, I responded to him like this:

I moved the following block of code up to before you invoke methods on dbConnection--you will get a NullPointerException otherwise since dbConnection has not been initialized when you try to use it.

  try {
       dbConnection = DriverManager.getConnection( 
             dataSourceName,
       dataSourceUsername, dataSourcePassword );
  } catch (Exception e) {
       System.out.println("Connection: " + e);
  }
(This block should be moved to just before your "GET PROPERTIES" comment) Second, in the following block of code:
  if (warning == null) {
      System.out.println( "No Warnings" );
       return;
   }
You probably don't want "return" here--your code never puts the contents of your ResultSet into your TextArea since you return! Removing the return will make the results show up.

Your code now works for me. I think the operative error you were seeing was the NullPointerException from not having the Connection initialized. The other errors indicate to me that your ODBC Driver Manager maybe doesn't have the datasource set up properly. Check to make sure that the driver manager on your client machine is set up so that TestDB is defined with the username/password "test"/"test", and that it really points to your SQL Server database on the right machine with the right permissions.

You might want to try a much simpler program to get your datasource set up. The JDBCTest program is good for this. JDBCTest is written by Intersolv, and can be found at http://www.intersolv.com/products/data-jdbc_test.html

This and other useful hints can be found in our online short course on the JDBC (http://developer.java.sun.com/developer/onlineTraining/jdbc/index.html)

amer_h: I have a question about porting AWT components to a local platform. I understand that I have to create my own toolkit class, extending the abstract toolkit provided with the JDKTM. Within the toolkit, I will implement my own component peer classes that talk to the local operating system.

My question is: by extending the abstract toolkit, I have to implement all the methods and all the peer classes before even testing the app. It seems there is a missing link somewhere. Do you have any hints? Also any pointers to resources and documentation on this matter will be greatly appreciated.

SPK-rohaly: If you're going to try this, you're more brave than I am! What you say is essentially correct--you have to implement all the methods in the peer classes before you can test your application. Of course, you can have null implementations for those methods you aren't using right away, and that will help you to incrementally implement your peers. There is a mailing list devoted to porting the JDK, which you can find at http://java.miningco.com/

amer_h: Thanks for the URL, rohaly. It definitely seems like a nontrivial task to say the least! There also used to be a link on java.sun.com called Porting.html, but somehow this link can no longer be found.

I have another related question. The toolkit class provided with the JDK is an abstract class--that is what it looks like from Toolkit.java as well as from the disassembly of Toolkit.class. The interesting thing is there is no class that
seems to extend toolkit, and since abstract classes cannot be instantiated,
then it seems that the toolkit class is not instantiated. Now this cannot be since
toolkit.class is the place where all display objects are implemented/created.
Obviously, something does not add up. Sorry if this seems to be a repetition, but
at this stage, I am more or less fishing for hints.

SPK-rohaly: You're right that toolkit is abstract and cannot be instantiated. However, no class is actually giving you an instance of toolkit. For example, getDefaultToolkit() returns a subclass of toolkit that is specific to the platform--this is how all the peer code gets invoked.

There is a subclass for Windows, a subclass for SolarisTM, and so on--the one that gets used is the one for your platform. This way, the application programmer deals only with the public methods of toolkit (same on every platform), but the implementation is different on different platforms.

amer_h: Theoretically, as a proof of concept, I could extend the Windows subclass of toolkit and override one or more of the peers. If this is true, do you know where this Windows subclass is?

SPK-rohaly: True, you should be able to do this. You would have to do a little more than just subclass, because you would want your subclass to be returned as the implementation. But yes, you can do this to override just a small portion of the platform-specific behavior.

The first thing you need to do is get yourself a copy of the JDK source code--sign up at the java.sun.com web site. To see the specific implementation for your platform, you can look in the Java source release at the following files:
<install_dir>/src/solaris/sun/sun/awt/motif/MToolkit.java
<install_dir>/src/win32/sun/sun/awt/windows/WToolkit.java

These are the Java source files that implement the Toolkit class. It is these
classes that actually return the platform-specific peers.

Most of their methods as native; the native source can be found at:
<install_dir>/src/solaris/sun/awt_MToolkit.c
<install_dir>/src/win32/sun/mfc/awt.cpp
<install_dir>/src/win32/sun/windows/awt/awt_Toolkit.cpp

(Of course, there's a lot more code involved, but these routines are a good starting point).

kagur: If I am in the directory C:\ken\ and type "java trywindow" this works. However, if I type "java c:\ken\trywindow" this does not work. What I want to do is set my computer so that if I click on a class file it runs. I'm using winNT and "associate file" always passes the full path of the file clicked. I did try the JRE and it does not work at all. When I'm in the above dir, I type "jre trywindow" it says "can't find class trywindow." Any help would be great.

SPK-rohaly: I'm not an NT person myself, so I don't know the specifics. I have heard that such a capability exists, but I thought it was by using the Microsoft tools that came with MS's JDK, and not by making an association. Does anyone here have an answer for kagur?

stevey: Kagur: if your class is in your classpath, then you can type "java <class"> no matter where you are in the file system.

Also, someone has written a Java shell called "jsh" that lets you type in the name of a class; it loads it and runs it for you as if it had a main.

ljarratt: Kagur: This may work. I am not sure yet, since I haven't rebooted. Once the file is associated, go to the registry. Add a new Key under .class with the name ShellNew. Then under that, add a new String Value with the name command and the value jdkhome\bin\java.exe "%1". I think you will have to reboot for the changes to take effect. Also, all the class file directories must be in the classpath. Let me know if this works.

stevey: My question is about custom class loaders, and reloading classes into the system. I just bought a book called Advanced Java: Idioms, Pitfalls, Styles and Programming Tips (Laffra, PrenticeHall) that describes a method for dynamically loading a class that has already been loaded, by using a ClassLoader with no class cache.

When I tried it, defineClass tells me "name already in use." I find this a bit surprising. If it's caching the names for me internally, why do the ClassLoader docs say I should cache the classes myself?

In any case, I would really like to be able to change the behavior of an existing class by reloading it, SmallTalk-style. Can you tell me if this is even possible?

SPK-rohaly: There's a good article on ClassLoaders by Chuck McManis. It can be found on www.javaworld.com. Have you looked at that one yet? I haven't tried Chris Laffra's code but I have run Chuck's, so I know that one works.

The problem with doing what you want is that there is currently no way to unload a class. Each ClassLoader has it's own namespace, and you can't reload the same class in the same namespace.

stevey: I went and read the Java World articles by Chuck McManis and Bill Venners. The two articles had everything I needed to know. Thanks for the pointer!

SPK-rohaly: Glad to hear that!

mhilpert: How can I save a (simple text) file from an applet to the server? It works in the
appletviewer, but in a browser, I get a security exception.

SPK-rohaly: This is hard to do, since your browser controls what an applet can or cannot do. In particular, your browser doesn't allow you to connect a socket back to any machine other that the host it was downloaded from.

So, if your fileserver and HTTP server are the same machine, this can be done. Or if you are using a browser like HotJavaTM, which has a user-configurable security model, this can be done. What you have to do is write a little server application to run on your file/HTTP server, which accepts a socket connection, defines a protocol for talking to the client, and returns the file requested. Or you can take advantage of the new HTTP command (I think it's called PUT) to deliver the file directly to your HTTP server for writing. I don't know of any HTTP servers that will currently let you do this, however.

mhilpert: But the security model says that if I access the same computer (IP address) where the applet is loaded from, I should be able to access this computer's file system--meaning I should be able to read/write. Is this right?

SPK-rohaly: What do you mean by read/write? As I said, you can connect a socket back and read/write that way (you rely on your little server application to interact with the file system on the server).

But Java doesn't, give you any direct access to the file system, which you don't have through any other means.

archie: I need some sample code for reading/writing text to/from ASCII files. Most examples I've seen don't treat the subject of converting from strings to bytes.

SPK-rohaly: Just look at the javadocs for PrintWriter and BufferedReader. These io classes will properly handle your text-based IO to and from a stream.

I will post a little example here:

out = new PrintWriter(new FileWriter("junk.txt"));
in = new BufferedReader(new FileReader("junk.txt"));

out.println("Write this to a file!");
String input = in.readln();
(You can't do the read and write on the same file at the same time, this is just for instance...)

Penumbra: Archie, another good place to look is www.digitalfocus.com/digitalfocus/faq/howdoi.html

peteroblenis: Does anyone happen to know of a way to override Frame so that you don't have the title bar (or at least don't see it). Since this has a peer I don't know if this is even possible.

SPK-rohaly: What you want is a "window"--this is a frame without the window decoration.

peteroblenis: Actually, what I'm trying to do is rewrite AWT Frame (for my own purposes), so that apps using my version will create frames with no title bars. I don't want to have to touch the source of these apps (and change frame to window). So I guess what I'm really trying to do is create a class derived from Window that does everything a Frame does with no title bar (I still want menu capabilites).

SPK-rohaly: peterobl: Yes, it looks like you want to subclass Window. As you have noticed, Window doesn't implement MenuContainer, so you will have to do a little work here to reimplement the stuff that is done within Frame.

peteroblenis: Yep. I guess I'll try the route of adding MenuContainer functionality to Window.

BigDi: I would like to know how to make a text label blink using the JDK1.1

SPK-rohaly: BigDi: You will have to be creative. Alternating the value of the label
foreground color within a thread would be one way.

BigDi: OK, thanks. I have one more question, is there a way to make a beeping sound occur, at a certain point in a standalone application, using the JDK 1.1 on a SunTM workstation.

SPK-rohaly: Toolkit.getDefaultToolkit().beep()

dearing: I have an AWT question. I'm trying to specify a gridbag layout to start in the northwest portion of my container. How do I do it?

SPK-rohaly: It depends on what look you are trying to achieve. If you really want an arbitrary component placed in the northwest, then writing your own layout manager is the best way to go about it. See http://developer.java.sun.com/developer/javaInDepth/layout-mgrs-10-96.html for an article describing how to write your own LayoutManager.

If you just want to force something into the northwest location on the GridBagLayout, then you have to set your constraints so that the fill, gridwidth, gridheight, gridx, gridy, weightx, and weighty are right. I don't think I can really give you a more specific answer because the "right" way really depends on your application.

lalitendu: Is there any way I can lock/unlock the keyboard using Java?

SPK-rohaly: Meaning? You can certainly capture the keyboard events and discard them before they do anything, but that only works for events within your applet.

lalitendu: How do I reset the mouse pointer to default? If I use setcursor (WAIT_CURSOR), then use set setcursor (DEFAULT_CURSOR), then the mouse pointer does not change back to default. The mouse pointer changes only if I move the mouse physically. I know this is a problem with 1.0.2 in the win95 environment. Is there any way to work around this?

SPK-rohaly: lalitend: You're right that it's a "feature." I think a work-around may be to validate() the container. I don't see that behavior on my platform--but then again, I don't do Windows :-)

lalitendu: What I meant by keyboard lock is: suppose my applet is executing an event in response to a mouse click/keyboard, and I don't want users to fire the event again. (Like clicking a button twice fires two events). So do I prevent the user from clicking twice? One way is to disable the button, but that will not help me, because I want to disable all the components in that frame. I should not allow the user to have the control until the click event is over.

SPK-rohaly: It seems to me that your problem is best solved by designing your classes so that your event handler gets all the events, sets a flag when it starts processing, and throws away all events while that flag is set. Then upon the end of processing, your event handler can reset the flag and be responsive once more. If your event processing takes any significant time at all, you should probably do it in its own thread, then you have to worry about synchronization issues. Delegate the handling out of your main event handler, then your main event handler can select which events to deal with.

lalitendu: Thanks, rohaly. That is exactly what I have done, but I am looking for an alternate solution.

muraliM: I'm facing a typical problem while using Java applets and accepting the values from different AWT components. The problem is that I accepted some values from the user. When I tried to implement the same components in the next row, it gave this error: "exception occurred during event dispatching." So, I made the entire row components comments, and then it worked. Is there any way out for this problem?

SPK-rohaly: There is not enough information here for me to figure out what is happening. Can you post a brief code fragment, give the exact error, mention what components you are using, etc.? It could be anything.

Offline, muraliM sent me his source code via email. After looking at it, I was able to determine his problem. Since it is a common mistake, let me include it here in the transcript. The following is part of my email response to him:

This is not a problem with too many components. The problem is that you define an instance variable "c7" in your bcd2 class, then you declare a separate, distinct, local variable also named c7 within your init() method. The local variable shadows the instance variable definition, so that the c7 instance variable (which you use in your event handler) never gets initialzed. This leads to your NullPointerExceptions.

When I fixed this, it worked. I have inserted my remarks and fixes as comments in your code fragment below:

public class bcd2 extends Applet {

...

    Choice c,c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12;
    //                         ^^
    //                       this is an instance variable
    //                       can refer to it as this.c7

    public void init() {

...

        Choice c7 = new Choice() ;
        //     ^^
        //      this is a *local* variable, since you 
        //      re-declare it here.
        //     in this case,   (this.c7 != c7)
        //     this.c7 is still == null
        //
        //      Fix is to change this line to read 
        //      "c7 = new Choice();"
        //
        c7.addItem("Monday");
        c7.addItem("Tuesday");
        c7.addItem("Wednesday");
        c7.addItem("Thursday");
        c7.addItem("Friday");
        c7.addItem("Saturday");
        c7.addItem("Sunday");
        gridbag.setConstraints(c7,constraints) ;
        add(c7) ;

...

    }

// So when you get to the event handler,
// c7 refers to this.c7, which was never initialized.
// So when you invoke getSelectedItem() you get 
// the null pointer exception.
   
    public boolean action(Event e,Object arg) {
        if(e.target instanceof Button) {

...
            names[11]=c7.getSelectedItem();
            //        ^^^
            //        this.c7 = null

            // you get a NullPointerException here.

crighi: I'm having a problem with RMI. When I try to pass back an array of Remote Object in the client applet, I create a (Remote) Ipdiscovery Object and than ask it to return the list of (Remote) Host Object.

FactoryInterface Mfactory = (FactoryInterface)Naming.lookup(
   "//Hostname/object"); 
//First Remote
Object IpDiscoveryInterface Mdiscovery = (IpDiscovery)

Mfactory.createIpDiscovery(
      "194.177.121.0","255.255.255.252");
//Second Remote Object

// The IpDiscovery Thread inizialize and start correctly

HostInterface[] arry=(
       HostInterface[])Mdiscovery.getHostList();  
// ERROR
 
AppletViewer gives me this error:
--------------------------------
Applet exception: Unexpected exception; nested exception is:
  java.lang.ArrayStoreException:
  java.rmi.UnexpectedException: Unexpected exception; 
     nested exception is:
        
  java.lang.ArrayStoreException:
  at netmanager.net.IpDiscovery_Stub.getHostList(
     IpDiscovery_Stub.java:47)
  at netmanager.net.HostApplet.init(HostApplet.java:45)
  at sun.applet.AppletPanel.run(AppletPanel.java:287)
  at java.lang.Thread.run(Thread.java:474)
  
The remote Interface for the IpDiscovery class:
---------------------------
package netmanager.net;

public interface IpDiscoveryInterface 
      extends java.rmi.Remote {
   public int totalElements() throws
      java.rmi.RemoteException;
      
   public HostInterface[] getHostList() throws
      java.rmi.RemoteException;
}

The implementation fot IpDiscovery  getHostList Method :
------------------------------

public HostInterface[] getHostList() throws 
      RemoteException {
   return(hostarry);
};
I've tried different variations to this code but they all throw the same error. If I return only one Host Object from the getHostList method, it all works fine. I'm using JDK 1.1.2 under WindowsNT.

SPK-rohaly: crighi posted a problem with some RMI code. We exchanged email and private posts. This is what I responded to him:

I don't see anything wrong with what you have posted. You can return an array from a remote method. But you have to understand what is happening. During the chat, we talked about how Java built-in types are passed by copy using the serialization mechanism. This is true of any object that is not a Remote object. In particular, an array will be passed by copy using serialization. This means that the datatype stored in the array must implement Serializable, and any data members referenced by your datatype must also implement Serializable--that is the only requirement.

If your datatype is not Serializable, it should throw a java.io.NotSerializableException. What you are getting is a java.lang.ArrayStoreException, which means that you are trying to store the wrong datatype in an array. This is what I can't understand, and I can't figure it out without seeing all your code.

It is difficult to figure what is wrong without seeing how you define HostInterface, Host, lpDiscovery, and all the other objects you are using.

My guess is that if you changed to returning an array of Objects, then it should work. But that is not a solution--the solution is to figure out why the type assignment is wrong so you can pass an array of your datatype.

cringhi: Do you know some good reference about RMI? (except RMI Tutorial and Specification)

SPK-rohaly: There is an RMI-users mailing list--see the instructions at the bottom of http://chatsubo.javasoft.com/current/

I have not seen any good books on RMI yet--but there is one book that has a good chapter on RMI called Client/Server Programming with Java and CORBA by Robert Orfali and Dan Harkey. The book mostly talks about CORBA, but many of the concepts are the same as in RMI.

There is another book called RMI: Developing Distributed Java Applications With Remote Method Invocation and Object Serialization by Troy Bryan Downing, but I haven't seen it yet so I don't know how good it is.

I'm afraid we're out of time now. But we will be having these code clinics every week for a while, so if you have any questions, please come back next week!



Print Button
[ This page was updated: 30-Mar-2000 ]
Products & APIs | Developer Connection | Docs & Training | Online Support
Community Discussion | Industry News | Solutions Marketplace | Case Studies
Glossary - Applets - Tutorial - Employment - Business & Licensing - Java Store - Java in the Real World
FAQ | Feedback | Map | 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-2000 Sun Microsystems, Inc.
All Rights Reserved. Terms of Use. Privacy Policy.